From 24827fdf0d21bdd3237ef7c582c40052e1b8ed46 Mon Sep 17 00:00:00 2001 From: sdolgin Date: Wed, 13 Dec 2023 18:40:39 +0000 Subject: [PATCH] [create-pull-request] automated change --- checklists/checklist.en.master.json | 13842 ++++++++-------- checklists/sql_checklist.en.json | 1515 +- checklists/sql_checklist.es.json | 759 + checklists/sql_checklist.ja.json | 759 + checklists/sql_checklist.ko.json | 759 + checklists/sql_checklist.pt.json | 759 + checklists/sql_checklist.zh-Hant.json | 759 + .../macrofree/checklist.en.master.xlsx | Bin 294225 -> 297125 bytes spreadsheet/macrofree/sql_checklist.en.xlsx | Bin 0 -> 31084 bytes spreadsheet/macrofree/sql_checklist.es.xlsx | Bin 0 -> 32109 bytes spreadsheet/macrofree/sql_checklist.ja.xlsx | Bin 0 -> 34481 bytes spreadsheet/macrofree/sql_checklist.ko.xlsx | Bin 0 -> 33564 bytes spreadsheet/macrofree/sql_checklist.pt.xlsx | Bin 0 -> 32275 bytes .../macrofree/sql_checklist.zh-Hant.xlsx | Bin 0 -> 32915 bytes .../alz_checklist.en_network_counters.json | 454 +- ...hecklist.en_network_counters_template.json | 2 +- .../alz_checklist.en_network_tabcounters.json | 1628 +- ...klist.en_network_tabcounters_template.json | 2 +- .../alz_checklist.en_network_workbook.json | 400 +- ...hecklist.en_network_workbook_template.json | 2 +- 20 files changed, 12578 insertions(+), 9062 deletions(-) create mode 100644 checklists/sql_checklist.es.json create mode 100644 checklists/sql_checklist.ja.json create mode 100644 checklists/sql_checklist.ko.json create mode 100644 checklists/sql_checklist.pt.json create mode 100644 checklists/sql_checklist.zh-Hant.json create mode 100644 spreadsheet/macrofree/sql_checklist.en.xlsx create mode 100644 spreadsheet/macrofree/sql_checklist.es.xlsx create mode 100644 spreadsheet/macrofree/sql_checklist.ja.xlsx create mode 100644 spreadsheet/macrofree/sql_checklist.ko.xlsx create mode 100644 spreadsheet/macrofree/sql_checklist.pt.xlsx create mode 100644 spreadsheet/macrofree/sql_checklist.zh-Hant.xlsx diff --git a/checklists/checklist.en.master.json b/checklists/checklist.en.master.json index cac58d14c..408e52838 100644 --- a/checklists/checklist.en.master.json +++ b/checklists/checklist.en.master.json @@ -942,8 +942,8 @@ "guid": "c851fd44-7cf1-459c-95a4-f6455d75a981", "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/cost-management-allocation", "services": [ - "Monitor", - "Cost" + "Cost", + "Monitor" ], "severity": "Medium", "subcategory": "Cost Optimization", @@ -1069,8 +1069,8 @@ "guid": "54174158-33fb-43ae-9c2d-e743165c3acb", "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", "services": [ - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Pricing & Settings", @@ -1082,8 +1082,8 @@ "guid": "349f0364-d28d-442e-abbb-c868255abc91", "link": "https://learn.microsoft.com/azure/security-center/enable-azure-defender", "services": [ - "Monitor", - "Defender" + "Defender", + "Monitor" ], "severity": "High", "subcategory": "Pricing & Settings", @@ -1169,8 +1169,8 @@ "guid": "05675c5e-985b-4859-a774-f7e371623b87", "link": "https://learn.microsoft.com/azure/security-center/continuous-export?tabs=azure-portal", "services": [ - "EventHubs", - "Defender" + "Defender", + "EventHubs" ], "severity": "High", "subcategory": "Pricing & Settings", @@ -1182,9 +1182,9 @@ "guid": "5a917e1f-349f-4036-9d28-d42e8bbbc868", "link": "https://learn.microsoft.com/azure/security-center/continuous-export?tabs=azure-portal", "services": [ - "Monitor", + "Defender", "Sentinel", - "Defender" + "Monitor" ], "severity": "Medium", "subcategory": "Pricing & Settings", @@ -1220,9 +1220,9 @@ "guid": "cce9bdf6-b483-45a0-85ec-c8232b230652", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy-integrate-with-microsoft-cloud-application-security", "services": [ + "Defender", "Entra", - "Monitor", - "Defender" + "Monitor" ], "severity": "Low", "subcategory": "Pricing & Settings", @@ -1259,8 +1259,8 @@ "guid": "50259226-4429-42bb-9285-37a55119bf8e", "link": "https://learn.microsoft.com/azure/defender-for-cloud/tutorial-security-incident", "services": [ - "Monitor", - "Defender" + "Defender", + "Monitor" ], "severity": "Medium", "subcategory": "Security Alerts", @@ -1297,8 +1297,8 @@ "guid": "93846da9-7cc3-4923-856b-22586f4a1641", "link": "https://learn.microsoft.com/azure/defender-for-cloud/enable-enhanced-security", "services": [ - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Secure Score", @@ -1323,8 +1323,8 @@ "guid": "65e8d9a3-aec2-418e-9436-b0736db55f57", "link": "https://learn.microsoft.com/azure/defender-for-cloud/remediate-vulnerability-findings-vm", "services": [ - "VM", - "Defender" + "Defender", + "VM" ], "severity": "High", "subcategory": "Azure Defender", @@ -1336,8 +1336,8 @@ "guid": "9603334b-df9c-4c23-918d-b61171265f4b", "link": "https://techcommunity.microsoft.com/t5/azure-network-security/azure-firewall-manager-is-now-integrated-with-azure-security/ba-p/2228679", "services": [ - "Firewall", - "Defender" + "Defender", + "Firewall" ], "severity": "Medium", "subcategory": "Firewall Manager", @@ -1350,9 +1350,9 @@ "guid": "b47a393a-0803-4272-a479-8b1578a219a4", "link": "https://learn.microsoft.com/azure/security/fundamentals/network-best-practices", "services": [ + "Defender", "VNet", - "Firewall", - "Defender" + "Firewall" ], "severity": "Medium", "subcategory": "Firewall Manager", @@ -1364,9 +1364,9 @@ "guid": "6ceb5443-5025-4922-9442-92bb628537a5", "link": "https://azure.microsoft.com/blog/how-azure-security-center-detects-ddos-attack-using-cyber-threat-intelligence/", "services": [ + "Defender", "Firewall", - "DDoS", - "Defender" + "DDoS" ], "severity": "Medium", "subcategory": "Firewall Manager", @@ -1378,8 +1378,8 @@ "guid": "5119bf8e-8f58-4542-a7d9-cdc166cd072a", "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started?WT.mc_id=Portal-Microsoft_Azure_Security", "services": [ - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Coverage", @@ -1391,8 +1391,8 @@ "guid": "4df585ec-dce9-4793-a7bc-db3b51eb2eb0", "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses", "services": [ - "VNet", - "VM" + "VM", + "VNet" ], "severity": "High", "subcategory": "Public IPs", @@ -1405,8 +1405,8 @@ "guid": "3dda6e59-d7c8-4a2e-bb11-7d6769af669c", "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses", "services": [ - "EventHubs", "Firewall", + "EventHubs", "VM" ], "severity": "High", @@ -1624,8 +1624,8 @@ "guid": "2055b29b-ade4-4aad-8e8c-39ec94666731", "link": "https://learn.microsoft.com/azure/virtual-network/kubernetes-network-policies", "services": [ - "VNet", "AzurePolicy", + "VNet", "AKS" ], "severity": "High", @@ -1652,8 +1652,8 @@ "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", "services": [ "VNet", - "Monitor", - "Sentinel" + "Sentinel", + "Monitor" ], "severity": "High", "subcategory": "Virtual Networks", @@ -1691,8 +1691,8 @@ "guid": "718d1dca-1f62-4565-aee5-580a38249c93", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-global-transit-network-architecture", "services": [ - "Monitor", - "VWAN" + "VWAN", + "Monitor" ], "severity": "High", "subcategory": "Virtual WAN", @@ -1757,8 +1757,8 @@ "guid": "f2e8bbbc-4681-455a-ac91-64e9909aed8c", "link": "https://learn.microsoft.com/azure/frontdoor/", "services": [ - "RBAC", - "FrontDoor" + "FrontDoor", + "RBAC" ], "severity": "High", "subcategory": "FrontDoor", @@ -1770,9 +1770,9 @@ "guid": "44cf3b2b-3818-4baf-a2cf-2149d013a923", "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/front-door-security-baseline?toc=/azure/frontdoor/TOC.json", "services": [ - "WAF", + "AzurePolicy", "FrontDoor", - "AzurePolicy" + "WAF" ], "severity": "High", "subcategory": "FrontDoor", @@ -1784,8 +1784,8 @@ "guid": "ce574dcc-bd8a-4c2a-aebc-a2a44da1dbf3", "link": "https://learn.microsoft.com/azure/frontdoor/front-door-custom-domain-https", "services": [ - "FrontDoor", - "AzurePolicy" + "AzurePolicy", + "FrontDoor" ], "severity": "High", "subcategory": "FrontDoor", @@ -1809,8 +1809,8 @@ "guid": "38249c93-1213-4dbd-9fb0-12f70943f630", "link": "https://learn.microsoft.com/azure/frontdoor/front-door-diagnostics", "services": [ - "FrontDoor", - "Sentinel" + "Sentinel", + "FrontDoor" ], "severity": "High", "subcategory": "FrontDoor", @@ -1931,8 +1931,8 @@ "guid": "00350863-4df6-4050-9cf1-cbaa6d58283e", "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-admins#managed-accounts-for-admins", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Privileged administration", @@ -2078,8 +2078,8 @@ "guid": "4c1e945b-459c-4373-b7ed-71623b375a91", "link": "https://learn.microsoft.com/azure/active-directory/authentication/tutorial-enable-sspr", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Password Reset", @@ -2152,8 +2152,8 @@ "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-monitoring", "services": [ "Entra", - "Monitor", - "Sentinel" + "Sentinel", + "Monitor" ], "severity": "High", "subcategory": "Diagnostic Settings", @@ -2189,8 +2189,8 @@ "guid": "6e6a8dc4-a20e-427b-9e29-711b1352beee", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/concept-conditional-access-policy-common", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Conditional Access Policies", @@ -2202,8 +2202,8 @@ "guid": "079b588d-efc4-4972-ac3c-d21bf77036e5", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/location-condition", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "Medium", "subcategory": "Conditional Access Policies", @@ -2215,8 +2215,8 @@ "guid": "e6b4bed3-d5f3-4547-a134-7dc56028a71f", "link": "https://learn.microsoft.com/azure/active-directory/authentication/tutorial-enable-azure-mfa", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Conditional Access Policies", @@ -2228,8 +2228,8 @@ "guid": "fe1bd15d-d2f0-4d5e-972d-41e3611cc57b", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-admin-mfa", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "Medium", "subcategory": "Conditional Access Policies", @@ -2241,8 +2241,8 @@ "guid": "4a4b1410-d439-4589-ac22-89b3d6b57cfc", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-azure-management", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Conditional Access Policies", @@ -2254,8 +2254,8 @@ "guid": "645461e1-a3e3-4453-a3c8-639637a552d6", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-block-legacy", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Conditional Access Policies", @@ -2267,8 +2267,8 @@ "guid": "7ae9eab4-0fd3-4290-998b-c178bdc5a06c", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/require-managed-devices", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "High", "subcategory": "Conditional Access Policies", @@ -2281,8 +2281,8 @@ "guid": "a7144351-e19d-4d34-929e-b7228137a151", "link": "https://devblogs.microsoft.com/premier-developer/azure-active-directory-automating-guest-user-management/", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "Medium", "subcategory": "Guest users", @@ -2306,8 +2306,8 @@ "guid": "bcfc6998-a135-4e33-9897-e31c67d68cb6", "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "Medium", "subcategory": "Break Glass Accounts", @@ -2319,8 +2319,8 @@ "guid": "0ac252b9-99a6-48af-a7c9-a8f821b8eb8c", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "VM", - "AzurePolicy" + "AzurePolicy", + "VM" ], "severity": "High", "subcategory": "Access Control", @@ -2429,8 +2429,8 @@ "guid": "650c3fc1-4eeb-4b36-a382-9e3eec218368", "link": "https://learn.microsoft.com/azure/security-center/security-center-partner-integration", "services": [ - "VM", - "Defender" + "Defender", + "VM" ], "severity": "High", "subcategory": "Protect against malware", @@ -2466,8 +2466,8 @@ "guid": "02145901-465d-438e-9309-ccbd979266bc", "link": "https://learn.microsoft.com/azure/security-center/asset-inventory", "services": [ - "VM", - "Defender" + "Defender", + "VM" ], "severity": "High", "subcategory": "Manage VM Updates", @@ -2503,8 +2503,8 @@ "guid": "012f7b95-e06e-4154-b2aa-3592828e6e20", "link": "https://learn.microsoft.com/azure/virtual-machines/windows/snapshot-copy-managed-disk", "services": [ - "LoadBalancer", - "VM" + "VM", + "LoadBalancer" ], "severity": "Medium", "subcategory": "Encrypt your VHDs", @@ -2529,8 +2529,8 @@ "guid": "10523081-a941-4741-9833-ff7ad7c6d373", "link": "https://learn.microsoft.com/azure/security-center/security-center-partner-integration", "services": [ - "Entra", - "VM" + "VM", + "Entra" ], "severity": "High", "subcategory": "Restrict direct internet connection ", @@ -2566,8 +2566,8 @@ "guid": "1cbafe6c-4658-49d4-98a9-27c3974d1102", "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-forced-tunneling", "services": [ - "VPN", - "VM" + "VM", + "VPN" ], "severity": "High", "subcategory": "Restrict direct internet connection ", @@ -2592,8 +2592,8 @@ "guid": "cd5d1e54-a297-459e-9968-0e78289c9356", "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "services": [ - "Monitor", - "Sentinel" + "Sentinel", + "Monitor" ], "severity": "High", "subcategory": "Architecture ", @@ -2617,9 +2617,9 @@ "guid": "e8f5c586-c7d9-4cdc-86ac-c075ef9b141a", "link": "https://learn.microsoft.com/azure/sentinel/multiple-workspace-view", "services": [ + "Sentinel", "ACR", - "Monitor", - "Sentinel" + "Monitor" ], "severity": "Medium", "subcategory": "Architecture ", @@ -2705,8 +2705,8 @@ "guid": "8e13f9cc-bd46-4826-9abc-a264f9a19bfe", "link": "https://learn.microsoft.com/azure/sentinel/connect-defender-for-cloud", "services": [ - "Sentinel", - "Defender" + "Defender", + "Sentinel" ], "severity": "High", "subcategory": "Data Connectors", @@ -2890,9 +2890,9 @@ "guid": "f0d5a73d-d4de-436c-8c81-770afbc4c0e4", "link": "https://techcommunity.microsoft.com/t5/azure-network-security/role-based-access-control-for-azure-firewall/ba-p/2245598", "services": [ + "AzurePolicy", "Firewall", - "RBAC", - "AzurePolicy" + "RBAC" ], "severity": "High", "subcategory": "Firewall Manager", @@ -2904,8 +2904,8 @@ "guid": "5c3a87af-4a79-41f8-a39b-da47768e14c1", "link": "https://learn.microsoft.com/azure/firewall-manager/policy-overview", "services": [ - "Firewall", - "AzurePolicy" + "AzurePolicy", + "Firewall" ], "severity": "High", "subcategory": "Firewall Manager", @@ -2917,8 +2917,8 @@ "guid": "15675c1e-a55b-446a-a48f-f8ae7d7e4b47", "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "Firewall", - "AzurePolicy" + "AzurePolicy", + "Firewall" ], "severity": "High", "subcategory": "Firewall Manager", @@ -2930,8 +2930,8 @@ "guid": "5b6c8bcb-f59b-4ce6-9de8-a03f97879468", "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "Firewall", - "AzurePolicy" + "AzurePolicy", + "Firewall" ], "severity": "High", "subcategory": "Firewall Manager", @@ -2943,8 +2943,8 @@ "guid": "d66a786d-60e9-46c9-9ad8-855d04c2b39c", "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "Firewall", - "AzurePolicy" + "AzurePolicy", + "Firewall" ], "severity": "High", "subcategory": "Firewall Manager", @@ -2956,8 +2956,8 @@ "guid": "986bb2c1-2149-4a11-9b5e-3df574ecccd9", "link": "https://learn.microsoft.com/azure/firewall/features", "services": [ - "Firewall", - "AzurePolicy" + "AzurePolicy", + "Firewall" ], "severity": "High", "subcategory": "Firewall Manager", @@ -2969,8 +2969,8 @@ "guid": "793a6bcd-a3b5-40eb-8eb0-3dd95d58d7c8", "link": "https://learn.microsoft.com/azure/firewall/dns-details", "services": [ - "Firewall", - "DNS" + "DNS", + "Firewall" ], "severity": "Medium", "subcategory": "Firewall Manager", @@ -3057,9 +3057,9 @@ "id": "A01.01", "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-2-encrypt-backup-data", "services": [ + "AKV", "SQL", - "Backup", - "AKV" + "Backup" ], "severity": "Medium", "subcategory": "Azure Key Vault", @@ -3075,8 +3075,8 @@ "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-1-ensure-regular-automated-backups", "services": [ "SQL", - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "Medium", "subcategory": "Backup", @@ -3092,8 +3092,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/automated-backups-overview?tabs=single-database&view=azuresql#backup-storage-redundancy", "services": [ "SQL", - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "Low", "subcategory": "Backup", @@ -3171,8 +3171,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/azure-defender-for-sql?view=azuresql#enable-microsoft-defender-for-sql ", "services": [ "SQL", - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Defender for Azure SQL", @@ -3188,8 +3188,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-configure", "services": [ "SQL", - "Monitor", - "Defender" + "Defender", + "Monitor" ], "severity": "High", "subcategory": "Defender for Azure SQL", @@ -3205,8 +3205,8 @@ "link": "https://learn.microsoft.com/azure/defender-for-cloud/sql-azure-vulnerability-assessment-overview", "services": [ "SQL", - "Monitor", - "Defender" + "Defender", + "Monitor" ], "severity": "High", "subcategory": "Vulnerability Assessment", @@ -3252,9 +3252,9 @@ "id": "F02.01", "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#control-access-of-application-users-to-sensitive-data-through-encryption", "services": [ + "AKV", "SQL", - "Storage", - "AKV" + "Storage" ], "severity": "Low", "subcategory": "Column Encryption", @@ -3270,8 +3270,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-create-server", "services": [ "SQL", - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "High", "subcategory": "Transparent Data Encryption", @@ -3286,8 +3286,8 @@ "id": "F03.02", "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-overview", "services": [ - "SQL", - "AKV" + "AKV", + "SQL" ], "severity": "Medium", "subcategory": "Transparent Data Encryption", @@ -3334,8 +3334,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#central-management-for-identities", "services": [ "SQL", - "Monitor", - "Entra" + "Entra", + "Monitor" ], "severity": "Medium", "subcategory": "Azure Active Directory", @@ -3366,10 +3366,10 @@ "id": "G02.01", "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", "services": [ - "Entra", "SQL", "ACR", "AKV", + "Entra", "RBAC" ], "severity": "Low", @@ -3417,9 +3417,9 @@ "id": "H01.02", "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-digest-management", "services": [ + "AzurePolicy", "SQL", - "Storage", - "AzurePolicy" + "Storage" ], "severity": "Medium", "subcategory": "Database Digest", @@ -3480,9 +3480,9 @@ "id": "I01.01", "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", "services": [ + "AzurePolicy", "SQL", - "Storage", - "AzurePolicy" + "Storage" ], "severity": "Medium", "subcategory": "Auditing", @@ -3497,12 +3497,12 @@ "id": "I01.02", "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", "services": [ - "Entra", + "Storage", "Monitor", "SQL", "EventHubs", - "Backup", - "Storage" + "Entra", + "Backup" ], "severity": "Low", "subcategory": "Auditing", @@ -3517,11 +3517,11 @@ "id": "I01.03", "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", "services": [ - "EventHubs", + "Storage", "Monitor", "SQL", - "Subscriptions", - "Storage" + "EventHubs", + "Subscriptions" ], "severity": "Medium", "subcategory": "Auditing", @@ -3600,9 +3600,9 @@ "id": "J01.02", "link": "https://learn.microsoft.com/azure/azure-sql/database/connectivity-architecture", "services": [ + "AzurePolicy", "SQL", - "PrivateLink", - "AzurePolicy" + "PrivateLink" ], "severity": "Low", "subcategory": "Connectivity", @@ -3666,10 +3666,10 @@ "id": "J03.01", "link": "https://learn.microsoft.com/azure/azure-sql/database/private-endpoint-overview?view=azuresql#disable-public-access-to-your-logical-server", "services": [ - "Firewall", "PrivateLink", "Monitor", "SQL", + "Firewall", "VNet" ], "severity": "Medium", @@ -3686,8 +3686,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/private-endpoint-overview?view=azuresql#disable-public-access-to-your-logical-server", "services": [ "SQL", - "PrivateLink", - "VNet" + "VNet", + "PrivateLink" ], "severity": "High", "subcategory": "Private Access", @@ -3736,9 +3736,9 @@ "id": "J04.01", "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview?view=azuresql#ip-vs-virtual-network-firewall-rules", "services": [ + "AzurePolicy", "SQL", - "VNet", - "AzurePolicy" + "VNet" ], "severity": "High", "subcategory": "Public Access", @@ -3785,9 +3785,9 @@ "id": "J04.04", "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/public-endpoint-overview", "services": [ + "AzurePolicy", "SQL", - "VNet", - "AzurePolicy" + "VNet" ], "severity": "High", "subcategory": "Public Access", @@ -3935,8 +3935,8 @@ "id": "A01.06", "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "services": [ - "Entra", - "AKV" + "AKV", + "Entra" ], "severity": "Medium", "subcategory": "Identity", @@ -3965,12 +3965,12 @@ "id": "B01.01", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "services": [ - "Entra", "Firewall", "DDoS", - "VNet", "WAF", - "Subscriptions" + "Subscriptions", + "Entra", + "VNet" ], "severity": "Low", "subcategory": "DDoS", @@ -3996,8 +3996,8 @@ "id": "B03.01", "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", "services": [ - "WAF", - "FrontDoor" + "FrontDoor", + "WAF" ], "severity": "Medium", "subcategory": "Internet", @@ -4011,8 +4011,8 @@ "id": "B03.02", "link": "https://learn.microsoft.com/azure/openshift/howto-secure-openshift-with-front-door", "services": [ - "PrivateLink", - "FrontDoor" + "FrontDoor", + "PrivateLink" ], "severity": "Medium", "subcategory": "Internet", @@ -4026,8 +4026,8 @@ "id": "B03.03", "link": "https://learn.microsoft.com/azure/openshift/howto-restrict-egress", "services": [ - "Firewall", "AzurePolicy", + "Firewall", "NVA" ], "severity": "Medium", @@ -4056,8 +4056,8 @@ "id": "B04.02", "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", "services": [ - "PrivateLink", - "ACR" + "ACR", + "PrivateLink" ], "severity": "Medium", "subcategory": "Private access", @@ -4406,8 +4406,8 @@ "id": "E03.01", "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", "services": [ - "Arc", "Defender", + "Arc", "AKS" ], "severity": "Medium", @@ -4450,8 +4450,8 @@ "id": "E05.02", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes#install-azure-policy-extension-for-azure-arc-enabled-kubernetes", "services": [ - "Monitor", - "AzurePolicy" + "AzurePolicy", + "Monitor" ], "severity": "Medium", "subcategory": "Workload", @@ -4479,8 +4479,8 @@ "id": "E05.04", "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", "services": [ - "Subscriptions", - "ACR" + "ACR", + "Subscriptions" ], "severity": "Low", "subcategory": "Workload", @@ -4508,8 +4508,8 @@ "id": "01.01.02", "link": "https://learn.microsoft.com/azure-stack/hci/concepts/drive-symmetry-considerations#understand-capacity-imbalance", "services": [ - "ACR", - "Storage" + "Storage", + "ACR" ], "severity": "Medium", "subcategory": "Physical", @@ -4523,8 +4523,8 @@ "id": "01.02.01", "link": "https://learn.microsoft.com/azure-stack/hci/concepts/fault-tolerance#parity", "services": [ - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "Medium", "subcategory": "S2D", @@ -4701,8 +4701,8 @@ "id": "02.01.05", "link": "https://learn.microsoft.com/azure-stack/hci/concepts/host-network-requirements", "services": [ - "VNet", - "Storage" + "Storage", + "VNet" ], "severity": "Medium", "subcategory": "Host", @@ -4918,8 +4918,8 @@ "id": "05.01.01", "link": "https://learn.microsoft.com/azure/backup/back-up-azure-stack-hyperconverged-infrastructure-virtual-machines", "services": [ - "Backup", "VM", + "Backup", "ASR" ], "severity": "High", @@ -5045,8 +5045,8 @@ "guid": "3277558e-3155-4088-b49a-78594cb4ce1a", "id": "07.01.02", "services": [ - "VNet", - "Storage" + "Storage", + "VNet" ], "severity": "High", "subcategory": "Stretch Clustering", @@ -5183,9699 +5183,9421 @@ "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "32e42e36-11c8-418b-8a0b-c510e43a18a9", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "a95b86ad-8840-48e3-9273-4b875ba18f20", "id": "A01.01", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", "services": [ - "Entra", - "AVS", - "Subscriptions" + "Cost", + "Monitor" ], - "severity": "High", - "subcategory": "Identity", - "text": "Ensure ADDS domain controller(s) are deployed in the identity subscription in native Azure", - "waf": "Security" + "subcategory": "Azure Monitor - enforce data collection rules", + "text": "Data collection rules in Azure Monitor -https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-rule-overview", + "training": "https://azure.microsoft.com/pricing/reservations/" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", - "id": "A01.02", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "45901365-d38e-443f-abcb-d868266abca2", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", "services": [ - "Entra", - "AVS" + "Cost", + "Backup" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Ensure ADDS sites and services is configured to keep authentication requests from Azure-based resources (including Azure VMware Solution) local to Azure", - "waf": "Security" + "subcategory": "Backup", + "text": "check backup instances with the underlying datasource not found" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "de3aad1e-7c28-4ec9-9666-b7570449aa80", - "id": "A01.03", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "64f9a19a-f29c-495d-94c6-c7919ca0f6c5", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", "services": [ - "Entra", - "AVS" + "Cost" ], - "severity": "High", - "subcategory": "Identity", - "text": "Ensure that vCenter is connected to ADDS to enable authentication based on 'named user accounts'", - "waf": "Security" + "subcategory": "delete/archive", + "text": "delete or archive unassociated services (disks, nics, ip addresses etc)" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "cd289ced-6b17-4db8-8554-61e2aee3553a", - "id": "A01.04", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "659d3958-fd77-4289-a835-556df2bfe456", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "AVS" + "Cost" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Ensure that the connection from vCenter to ADDS is using a secure protocol (LDAPS)", - "waf": "Security" + "subcategory": "delete/archive", + "text": "consider snooze and stop technique (snooze a service after x days, stop after 2x, delete/deallocate after 3x)" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "b9d37dac-43bc-46cd-8d79-a9b24604489a", - "id": "A01.05", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "3b0d834a-3487-426d-b69c-6b5c2a26494b", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "AVS" + "Cost", + "Storage", + "Backup" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", - "waf": "Security" + "subcategory": "delete/archive", + "text": "delete or archive unused resources (old backups, logs, storage accounts, etc...)" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "53d88e89-d17b-473b-82a5-a67e7a9ed5b3", - "id": "A01.06", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "69bad37a-ad53-4cc7-ae1d-76667357c449", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "AVS" + "Cost", + "Storage", + "Backup", + "ASR" ], - "severity": "High", - "subcategory": "Identity", - "text": "Ensure that NSX-Manager is integrated with an external Identity provider", - "waf": "Security" + "subcategory": "delete/archive", + "text": "consider a good balance between site recovery storage and backup for non mission critical applications" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "ae0e37ce-e297-411b-b352-caaab79b198d", - "id": "A01.07", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "674b5ed8-5a85-49c7-933b-e2a1a27b765a", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "services": [ - "Entra", - "AVS", - "RBAC" + "Cost", + "Monitor" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Has an RBAC model been created for use within VMware vSphere", - "waf": "Security" + "subcategory": "Log Analytics retention for workspaces", + "text": "check spending and savings opportunities among the 40 different log analytics workspaces- use different retention and data collection for nonprod workspaces-create daily cap for awareness and tier sizing - If you do set a daily cap, in addition to creating an alert when the cap is reached,ensure that you also create an alert rule to be notified when some percentage has been reached (90% for example). - consider workspace transformation if possible - https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-transformations#workspace-transformation-dcr ", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/understand-work-scopes" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "ab81932c-9fc9-4d1b-a780-36f5e6bfbb9e", - "id": "A01.08", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "91be1f38-8ef3-494c-8bd4-63cbbac75819", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "Entra", - "AVS", - "RBAC" + "AzurePolicy", + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "RBAC permissions should be granted on ADDS groups and not on specific users", - "waf": "Security" + "subcategory": "Policy", + "text": "enforce a purging log policy and automation (if needed, logs can be moved to cold storage)", + "training": "https://www.youtube.com/watch?v=nHQYcYGKuyw" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "d503547c-c447-4e82-9128-a71f0f1cac6d", - "id": "A01.09", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "59bb91a3-ed90-4cae-8cc8-4c37b6b780cb", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "Entra", - "AVS", - "RBAC" + "Cost" ], - "severity": "High", - "subcategory": "Identity", - "text": "RBAC permissions on the Azure VMware Solution resource in Azure are 'locked down' to a limited set of owners only", - "waf": "Security" + "subcategory": "run orphaned resources workbook - delete or snooze ghost items", + "text": "https://github.com/dolevshor/azure-orphan-resources", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "9ef1d5e8-32e4-42e3-911c-818b0a0bc510", - "id": "B01.01", - "link": "https://github.com/Azure/AzureCAT-AVS/tree/main/networking", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "9fe5c464-89d4-457a-a27c-3874d0102cac", + "id": "A07.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "AVS" + "Cost" ], - "severity": "High", - "subcategory": "Architecture", - "text": "Is the correct Azure VMware Solution connectivity model selected for the customer use case at hand", - "waf": "Performance" + "subcategory": "shutdown/deallocate", + "text": "shutdown underutilized instances", + "training": "https://learn.microsoft.com/azure/cost-management-billing/understand/analyze-unexpected-charges" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", - "id": "B02.01", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "6aae01e6-a84d-4e5d-b36d-1d92881a1bd5", + "id": "A08.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "ExpressRoute", - "Monitor", - "AVS", - "VPN", - "NetworkWatcher" + "Cost", + "Storage", + "Backup", + "VM" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure ExpressRoute or VPN connections from on-premises to Azure are monitored using 'connection monitor'", - "waf": "Operations" - }, - { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", - "id": "B02.02", - "services": [ - "ExpressRoute", - "Monitor", - "AVS", - "NetworkWatcher", - "VM" - ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Ensure a connection monitor is created from an Azure native resource to an Azure VMware Solution virtual machine to monitor the Azure VMware Solution back-end ExpressRoute connection", - "waf": "Operations" + "subcategory": "stopped/deallocated VMs: check disks", + "text": "check that the disks are really needed, if not: delete. If they are needed, find lower storage tiers or use backup -", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/manage-automation" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "25659d35-58fd-4772-99c9-31112d027fe4", - "id": "B02.03", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "d1e44a19-659d-4395-afd7-7289b835556d", + "id": "A09.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "AVS", - "NetworkWatcher", - "VM", - "Monitor" + "AzurePolicy", + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Ensure a connection monitor is created from an on-premises resource to an Azure VMware Solution virtual machine to monitor end-2-end connectivity", - "waf": "Operations" + "subcategory": "storage accounts lifecycle policy", + "text": "consider moving unused storage to lower tier, with customized rule - https://learn.microsoft.com/azure/storage/blobs/lifecycle-management-policy-configure ", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "563b4dc7-4a74-48b6-933a-d1a0916a6649", - "id": "B03.01", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "f2bfe456-3b0d-4834-a348-726de69c6b5c", + "id": "A10.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "AVS", - "ARS" + "Cost" ], - "severity": "High", - "subcategory": "Routing", - "text": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", - "waf": "Operations" + "subcategory": "Tagging", + "text": "use specific tags for temporary items with 'delete by DATE' format - and automate monthly cleanup" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "6128a71f-0f1c-4ac6-b9ef-1d5e832e42e3", - "id": "C01.01", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "2a26494b-69ba-4d37-aad5-3cc78e1d7666", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "services": [ - "Entra", - "AVS", - "RBAC" + "Cost" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Is Privileged Identity Management implemented for roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", - "waf": "Security" + "subcategory": "db optimization", + "text": "plan for db optimization with the intent of downsizing the related services (and improve performance)" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "c4e2436b-b336-4d71-9f17-960eee0b9b5c", - "id": "C01.02", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "7357c449-674b-45ed-a5a8-59c7733be2a1", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "AVS", - "RBAC" + "Cost" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Is Privileged Identity Management audit reporting implemented for the Azure VMware Solution PIM roles", - "waf": "Security" + "subcategory": "app modernization", + "text": "modernizing the app towards a microservices architecture will have the effect of letting the app scale according to the single service and not the entire stack" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "8defc4d7-21d3-41d2-90fb-707ae9eab40e", - "id": "C01.03", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "a27b765a-91be-41f3-a8ef-394c2bd463cb", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "AVS" + "Cost", + "Storage", + "VM" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Limit use of CloudAdmin account to emergency access only", - "waf": "Security" + "subcategory": "db optimization", + "text": "optimizing the DB queries will increase performance and allow better right-sizing of storage and VMs" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "d329f798-bc17-48bd-a5a0-6ca7144351d1", - "id": "C01.04", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "bac75819-59bb-491a-9ed9-0cae2cc84c37", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Entra", - "AVS", - "RBAC" + "Cost" ], - "severity": "Medium", - "subcategory": "Security (identity)", - "text": "Create custom RBAC roles in vCenter to implement a least-privilege model inside vCenter", - "waf": "Security" + "subcategory": "demand shaping", + "text": "using demand shaping on PaaS services will optimize costs and performances" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "9dd24429-eb72-4281-97a1-51c5bb4e4f18", - "id": "C01.05", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "b6b780cb-9fe5-4c46-989d-457a927c3874", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", "services": [ - "Entra", - "AVS" + "Cost", + "Entra" ], - "severity": "Medium", - "subcategory": "Security (identity)", - "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", - "waf": "Security" + "subcategory": "Advisor", + "text": "Start from the Azure Advisor page suggestions." }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "586cb291-ec16-4a1d-876e-f9f141acdce5", - "id": "C01.06", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "d0102cac-6aae-401e-9a84-de5de36d1d92", + "id": "C01.02", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Entra", - "AVS", + "Cost", "VM" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Use a centralized identity provider to be used for workloads (VM's) running on Azure VMware Solution", - "waf": "Security" + "subcategory": "Advisor", + "text": "make sure advisor is configured for VM right sizing " }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "79377bcd-b375-41ab-8ab0-ead66e15d3d4", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "881a1bd5-d1e4-44a1-a659-d3958fd77289", "id": "C02.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS" + "Cost" ], - "severity": "Medium", - "subcategory": "Security (network)", - "text": "Is East-West traffic filtering implemented within NSX-T", - "waf": "Security" + "subcategory": "Automation", + "text": "consider implementing IAC scripts or devops pipelines to match the cost governance process" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "a2adb1c3-d232-46af-825c-a44e1695fddd", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "b835556d-f2bf-4e45-93b0-d834a348726d", "id": "C02.02", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Firewall", - "AVS", - "AppGW" + "Cost", + "Monitor" ], - "severity": "High", - "subcategory": "Security (network)", - "text": "Workloads on Azure VMware Solution are not directly exposed to the internet. Traffic is filtered and inspected by Azure Application Gateway, Azure Firewall or 3rd party solutions", - "waf": "Security" + "subcategory": "Automation", + "text": "set up cost alerts for applications that have variable costs (ideally for all of them)" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "eace4cb1-deb4-4c65-8c3f-c14eeab36938", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "e69c6b5c-2a26-4494-a69b-ad37aad53cc7", "id": "C02.03", + "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "services": [ - "AVS" + "Cost" ], - "severity": "High", - "subcategory": "Security (network)", - "text": "Auditing and logging is implemented for inbound internet requests to Azure VMware Solution and Azure VMware Solution based workloads", - "waf": "Security" + "subcategory": "Automation", + "text": "Use Azure Automation: Automate repetitive tasks can help you save time and resources, reducing costs in the process. " }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "29e3eec2-1836-487a-8077-a2b5945bda43", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "8e1d7666-7357-4c44-a674-b5ed85a859c7", "id": "C02.04", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS", - "Monitor" + "Cost" ], - "severity": "Medium", - "subcategory": "Security (network)", - "text": "Session monitoring is implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", - "waf": "Security" + "subcategory": "Automation", + "text": "run orphaned resources workbook" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "334fdf91-c234-4182-a652-75269440b4be", - "id": "C02.05", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "733be2a1-a27b-4765-a91b-e1f388ef394c", + "id": "C03.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "services": [ - "ExpressRoute", - "DDoS", - "VNet", - "AVS", - "VPN" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Security (network)", - "text": "Is DDoS standard protection enabled on ExR/VPN Gateway subnet in Azure", - "waf": "Security" + "subcategory": "Baseline", + "text": "try and establish a baseline of monthly spending and an acceptable saving target against the baseline (new services will not be optimized at this stage)" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "3d3e0843-276d-44bd-a015-bcf219e4a1eb", - "id": "C02.06", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "2bd463cb-bac7-4581-a59b-b91a3ed90cae", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS" + "AzurePolicy", + "Cost" ], - "severity": "Medium", - "subcategory": "Security (network)", - "text": "Use a dedicated privileged access workstation (PAW) to manage Azure VMware Solution, vCenter, NSX manager and HCX manager", - "waf": "Security" + "subcategory": "Baseline", + "text": "establish a cost optimization baseline by using a policy that tags every new resource as #NEW" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "9ccbd869-266a-4cca-874f-aa19bf39d95d", - "id": "C03.01", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "2cc84c37-b6b7-480c-a9fe-5c46489d457a", + "id": "C03.03", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "services": [ - "AVS", - "Defender" + "Cost" ], - "severity": "Medium", - "subcategory": "Security (guest/VM)", - "text": "Enable Advanced Threat Detection (Microsoft Defender for Cloud aka ASC) for workloads running on Azure VMware Solution", - "waf": "Security" + "subcategory": "Baseline", + "text": "Organize resources to maximize cost insights and accountability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "44c7c891-9ca1-4f6d-9315-ae524ba34d45", - "id": "C03.02", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "927c3874-d010-42ca-a6aa-e01e6a84de5d", + "id": "C04.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", "services": [ - "AVS", - "Arc" + "Cost" ], - "severity": "Medium", - "subcategory": "Security (guest/VM)", - "text": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", - "waf": "Security" + "subcategory": "Budgets", + "text": "Create budgets" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "85e12139-bd7b-4b01-8f7b-95ef6e043e2a", - "id": "C03.03", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "e36d1d92-881a-41bd-9d1e-44a19659d395", + "id": "C05.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", "services": [ - "SQL", - "AVS" + "Cost" ], - "severity": "Low", - "subcategory": "Security (guest/VM)", - "text": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", - "waf": "Security" + "subcategory": "Cost Analysis", + "text": "in cost analysis - use daily granularity, grouped by service name to analyze the spending of the past 3 months and identify the top 3 spenders" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "a3592718-e6e2-4051-9267-6ae46691e883", - "id": "C03.04", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "8fd77289-b835-4556-bf2b-fe4563b0d834", + "id": "C05.02", + "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "services": [ - "AVS", - "AKV" + "Cost" ], - "severity": "Low", - "subcategory": "Security (guest/VM)", - "text": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", - "waf": "Security" + "subcategory": "Cost Analysis", + "text": "check daily for cost spikes and anomalies (ideally with automatic billing exports)" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "5ac94222-3e13-4810-9230-81a941741583", - "id": "C03.05", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "a348726d-e69c-46b5-a2a2-6494b69bad37", + "id": "C05.03", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "services": [ - "AVS" + "Cost" ], - "severity": "High", - "subcategory": "Security (guest/VM)", - "text": "Ensure extended security update support is configured for workloads running on Azure VMware Solution (Azure VMware Solution is eligible for ESU)", - "waf": "Security" + "subcategory": "Cost Analysis", + "text": "automate cost retrieval for deep analysis or integration" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "3ef7ad7c-6d37-4331-95c7-acbe44bbe609", - "id": "C04.01", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "aad53cc7-8e1d-4766-9735-7c449674b5ed", + "id": "C06.01", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "services": [ - "AVS", - "Storage", - "VM", - "AzurePolicy" + "Cost", + "ACR" ], - "severity": "High", - "subcategory": "Governance (platform)", - "text": "Ensure that the appropriate VM template storage policy is used", - "waf": "Performance" + "subcategory": "free services", + "text": "Take advantage of Azure free services: Azure offers a number of free services, such as DevOps, Azure Container Registry, and Azure Logic Apps, that can help you save costs on development and operations. " }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "d89f2e87-7784-424d-9167-85c6fa95b96a", - "id": "C04.02", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "96c96ad8-844c-4f3b-8b38-c886ba2c0214", + "id": "C07.01", + "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "services": [ - "AVS", - "ASR" + "Cost" ], - "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", - "waf": "Reliability" + "subcategory": "Tagging", + "text": "Tag shared resources" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "d88408f3-7273-44c8-96ba-280214590146", - "id": "C04.03", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "99014a5d-3ce5-474d-acbd-9792a6bcca2b", + "id": "C07.02", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "services": [ - "AVS", - "Storage", - "AzurePolicy" + "Cost" ], - "severity": "High", - "subcategory": "Governance (platform)", - "text": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", - "waf": "Reliability" + "subcategory": "Tagging", + "text": "consider using tags to all services for cost allocation" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "5d38e53f-9ccb-4d86-a266-acca274faa19", - "id": "C04.04", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "4fea1dbf-3dd9-45d4-ac7c-891dcb1f7d57", + "id": "D01.01", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "services": [ - "AVS" + "Cost" ], - "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", - "waf": "Operations" + "subcategory": "automation", + "text": "consider Reservation automation to track and promptly react to changes" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "bf39d95d-44c7-4c89-89ca-1f6d5315ae52", - "id": "C04.05", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "description": "check by searching the Meter Category Licenses in the Cost analysys", + "guid": "59ae568b-a38d-4498-9e22-13dbd7bb012f", + "id": "D02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "services": [ - "AVS", - "AzurePolicy" + "AzurePolicy", + "Cost", + "VM", + "SQL" ], - "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Ensure that you have a policy around ESXi host density and efficiency, keeping in mind the lead time for requesting new nodes", - "waf": "Operations" + "subcategory": "check AHUB is applied to all Windows VMs, RHEL and SQL", + "text": "run the script on all windows VMs https://learn.microsoft.com/azure/virtual-machines/windows/hybrid-use-benefit-licensing?ref=andrewmatveychuk.com#convert-an-existing-vm-using-azure-hybrid-benefit-for-windows-server- consider implementing a policy if windows VMs are created frequently" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "4ba34d45-85e1-4213-abd7-bb012f7b95ef", - "id": "C04.06", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "7b95e06e-158e-42ea-9992-c2de6e2065b3", + "id": "D03.01", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "AVS", - "Cost" + "Cost", + "LoadBalancer" ], - "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Ensure a good cost management process is in place for Azure VMware Solution - Azure Cost Management can be used", - "waf": "Cost" + "subcategory": "check Red Hat Licences if applicable", + "text": " this can be also put under AHUB if you already have licenses https://learn.microsoft.com/azure/virtual-machines/linux/azure-hybrid-benefit-linux?tabs=rhelpayg%2Crhelbyos%2CrhelEnablebyos%2Crhelcompliance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "6e043e2a-a359-4271-ae6e-205172676ae4", - "id": "C04.07", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "a76af4a6-91e8-4839-ada4-6667e13c1056", + "id": "D04.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts", "services": [ - "AVS", - "Cost" + "Cost", + "AppSvc" ], - "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Are Azure reserved instances used to optimize cost for using Azure VMware Solution", - "waf": "Cost" + "subcategory": "Functions", + "text": "saving plans will provide 17% on select app service plans" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "6691e883-5ac9-4422-83e1-3810523081a9", - "id": "C04.08", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "75c1e945-b459-4837-bf7a-e7c6d3b475a5", + "id": "D05.01", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "services": [ - "AVS" + "Cost", + "VM" ], - "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Consider the use of Azure Private-Link when using other Azure Native Services", - "waf": "Security" + "subcategory": "planning", + "text": "consolidate reserved VM families with flexibility option (no more than 4-5 families)", + "training": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "48b262d6-cc5f-4512-a253-98e6db9d37da", - "id": "C05.01", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "c7acbe49-bbe6-44dd-a9f2-e87778468d55", + "id": "D06.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "services": [ - "AVS", + "Cost", "VM", - "Defender" + "ARS" ], - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Enable Microsoft Defender for Cloud for Azure VMware Solution guest VM workloads", - "waf": "Security" + "subcategory": "reservations/savings plans", + "text": "Utilize Azure Reserved Instances: This feature allows you to reserve VMs for a period of 1 or 3 years, providing significant cost savings compared to PAYG prices." }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "41741583-3ef7-4ad7-a6d3-733165c7acbe", - "id": "C05.02", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "a785c6fe-96c9-46ad-a844-cf3b2b38c886", + "id": "D06.02", + "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "services": [ - "AVS", - "VM", - "Arc" + "Cost" ], - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Use Azure Arc enabled servers to manage your Azure VMware Solution guest VM workloads", - "waf": "Security" + "subcategory": "reservations/savings plans", + "text": "plan for Azure Savings Plans for all the workloads that are dynamic and need maximum flexibility" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "88f03a4d-2cd4-463c-abbc-868295abc91a", - "id": "C05.03", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "ba2c0214-9901-44a5-b3ce-574dccbd9792", + "id": "D06.03", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "services": [ - "AVS" + "Cost" ], - "severity": "High", - "subcategory": "Governance (guest/VM)", - "text": "Enable Diagnostic and metric logging on Azure VMware Solution", - "waf": "Operations" + "subcategory": "reservations/savings plans", + "text": "plan for Azure Reservations for all the workloads that are less dynamic and won't change much" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "4ed90dae-2cc8-44c4-9b6b-781cbafe6c46", - "id": "C05.04", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "a6bcca2b-4fea-41db-b3dd-95d48c7c891d", + "id": "D07.01", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "services": [ - "AVS", - "VM", - "Monitor" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Deploy the Log Analytics Agents to Azure VMware Solution guest VM workloads", - "waf": "Operations" + "subcategory": "reserve storage", + "text": "only larger disks can be reserved =>1TiB -" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "589d457a-927c-4397-9d11-02cad6aae11e", - "id": "C05.05", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "cb1f7d57-59ae-4568-aa38-d4985e2213db", + "id": "D08.01", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "services": [ - "AVS", - "VM", - "AzurePolicy", - "Backup" + "Cost", + "VM" ], - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", - "waf": "Operations" + "subcategory": "reserve VMs with normalized and rationalized sizes", + "text": "after the right-sizing optimization" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "ee29711b-d352-4caa-ab79-b198dab81932", - "id": "C06.01", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "d7bb012f-7b95-4e06-b158-e2ea3992c2de", + "id": "D09.01", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "services": [ - "AVS", - "Monitor", - "Defender" + "AzurePolicy", + "Cost", + "SQL" ], - "severity": "Medium", - "subcategory": "Compliance", - "text": "Use Microsoft Defender for Cloud for compliance monitoring of workloads running on Azure VMware Solution", - "waf": "Security" + "subcategory": "SQL Database AHUB", + "text": "check if applicable and enforce policy/change https://learn.microsoft.com/azure/azure-sql/azure-hybrid-benefit?view=azuresql&tabs=azure-portalhttps://learn.microsoft.com/azure/cost-management-billing/scope-level/create-sql-license-assignments?source=recommendations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "c9fc9d1b-b780-436f-9e6b-fbb9ed503547", - "id": "C06.02", - "services": [ - "AVS", - "Defender" + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "6e2065b3-a76a-4f4a-991e-8839ada46667", + "id": "D10.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", + "services": [ + "Cost", + "VM", + "SQL" ], - "severity": "Medium", - "subcategory": "Compliance", - "text": "Are the applicable compliance baselines added to Microsoft Defender for Cloud", - "waf": "Security" + "subcategory": "SQL Database Reservations", + "text": "the VM + licence part discount (ahub+3YRI) is around 70% discount" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "cc447e82-6128-4a71-b0f1-cac6d9ef1d5e", - "id": "C06.03", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "e13c1056-75c1-4e94-9b45-9837ff7ae7c6", + "id": "D11.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "services": [ - "AVS" + "Cost" ], - "severity": "High", - "subcategory": "Compliance", - "text": "Was data residency evaluated when selecting Azure regions to use for Azure VMware Solution deployment", - "waf": "Security" + "subcategory": "tracking", + "text": "Make sure you Azure Reservations and Savings plans are close to 100% utilization or make the necessary changes to reach it." }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "832e42e3-611c-4818-a0a0-bc510e43a18a", - "id": "C06.04", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "d3b475a5-c7ac-4be4-abbe-64dd89f2e877", + "id": "D11.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "services": [ - "AVS" + "AzurePolicy", + "Cost" ], - "severity": "High", - "subcategory": "Compliance", - "text": "Are data processing implications (service provider / service consumer model) clear and documented", - "waf": "Security" + "subcategory": "tracking", + "text": "make sure that your reservations usage is close to 100%. If not, either enforce an allowed SKU policy or exchange the reservation" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "e43a18a9-cd28-49ce-b6b1-7db8255461e2", - "id": "D01.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "78468d55-a785-4c6f-b96c-96ad8844cf3b", + "id": "E01.01", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "services": [ - "AVS", - "Monitor" + "AzurePolicy", + "Cost" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Create dashboards to enable core Azure VMware Solution monitoring insights", - "waf": "Operations" + "subcategory": "Automation", + "text": "plan and enforce a ON/OFF policy for production services, where possible" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "6b84ee5d-f47d-42d9-8881-b1cd5d1e54a2", - "id": "D01.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "2b38c886-ba2c-4021-9990-14a5d3ce574d", + "id": "E01.02", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "services": [ - "AVS", - "Monitor" + "AzurePolicy", + "Cost" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Create warning alerts for critical thresholds for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", - "waf": "Operations" + "subcategory": "Automation", + "text": "plan and enforce a ON-DEMAND policy with auto-shutdown for non-production services, where possible" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "9659e396-80e7-4828-ac93-5657d02bff45", - "id": "D01.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "ccbd9792-a6bc-4ca2-a4fe-a1dbf3dd95d4", + "id": "E02.01", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "services": [ - "AVS", - "Monitor" + "Cost", + "VM" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure critical alert is created to monitor if vSAN consumption is below 75% as this is a support threshold from VMware", - "waf": "Operations" + "subcategory": "Autoscale", + "text": "consider using a VMSS to match demand rather than flat sizing" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "64b0d934-a348-4726-be79-d6b5c3a36495", - "id": "D01.04", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "c1b1cd52-1e54-4a29-a9de-39ac0e7c28dc", + "id": "E02.02", + "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "services": [ - "AVS", - "Monitor" + "Cost", + "AKS" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure alerts are configured for Azure Service Health alerts and notifications", - "waf": "Operations" + "subcategory": "Autoscale", + "text": "use AKS autoscaler to match your clusters usage (make sure the pods requirements match the scaler)" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "b6abad38-aad5-43cc-99e1-d86667357c54", - "id": "D01.05", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "93665720-2bff-4456-9b0d-934a359c363e", + "id": "E02.03", + "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "services": [ - "AVS", - "Storage", - "Monitor" + "Cost" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Configure Azure VMware Solution logging to be send to an Azure Storage account or Azure EventHub for processing", - "waf": "Operations" + "subcategory": "Autoscale", + "text": "right-size PaaS service according to average use and accomodate spikes with auto or manual scaling" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "9674c5ed-85b8-459c-9733-be2b1a27b775", - "id": "D01.06", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "7dd61623-a364-4a90-9eba-e38ead53cc7d", + "id": "E02.04", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AVS", - "Monitor" + "Cost" ], - "severity": "Low", - "subcategory": "Monitoring", - "text": "If deep insight in VMware vSphere is required: Is vRealize Operations and/or vRealize Network Insights used in the solution?", - "waf": "Operations" + "subcategory": "Autoscale", + "text": "plan for demand shaping where applicable" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "a91be1f3-88f0-43a4-b2cd-463cbbbc8682", - "id": "D02.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "e2e8aaab-3571-4549-ab91-53d89f89dc7b", + "id": "E02.05", "services": [ - "AVS", - "Storage", - "VM", - "AzurePolicy" + "Cost" ], - "severity": "High", - "subcategory": "Operations", - "text": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning", - "waf": "Operations" + "subcategory": "Autoscale", + "text": "consider implementing a service re-scaling logic within the application", + "training": "https://learn.microsoft.com/azure/cost-management-billing/savings-plan/" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "d9ef1d5e-832d-442e-9611-c818b0afbc51", - "id": "D02.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "44be3b1a-27f8-4b9e-a1be-1f38df03a822", + "id": "E03.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "services": [ - "AVS" + "Cost", + "Backup" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure vSphere content libraries are not placed on vSAN as vSAN is a finite resource", - "waf": "Operations" + "subcategory": "Backup", + "text": "Move recovery points to vault-archive where applicable (Validate)", + "training": "https://azure.microsoft.com/pricing/reservations/" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "0e43a18a-9cd2-489b-bd6b-17db8255461e", - "id": "D02.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "cd463cbb-bc8a-4c29-aebc-91a43da1dae2", + "id": "E04.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AVS", - "Storage", - "Backup" + "Cost", + "VM", + "LoadBalancer" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", - "waf": "Operations" + "subcategory": "databricks", + "text": "consider using Spot VMs with fallback where possibleconsider autotermination of clusters https://learn.microsoft.com/azure/databricks/clusters/cluster-config-best-practices#automatic-termination ", + "training": "https://andrewmatveychuk.com/how-to-audit-azure-hybrid-benefit-usage-with-azure-workbooks/" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "2aee3453-aec8-4339-848b-262d6cc5f512", - "id": "D02.04", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "cc881470-607c-41cc-a0e6-14658dd458e9", + "id": "E05.01", + "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "services": [ - "AVS", - "Arc" + "Cost" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure workloads running on Azure VMware Solution are hybrid managed using Azure Arc for Servers (Arc for Azure VMware Solution is in preview)", - "waf": "Operations" + "subcategory": "Functions", + "text": "Functions - Reuse connections", + "training": "https://learn.microsoft.com/azure/cost-management-billing/reservations/reservation-apis?toc=%2Fazure%2Fcost-management-billing%2Ftoc.json" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "925398e6-da9d-437d-ac43-bc6cd1d79a9b", - "id": "D02.05", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "27139b82-1102-4dbd-9eaf-11e6f843e52f", + "id": "E05.02", + "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "services": [ - "AVS", - "Monitor" + "Cost" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", - "waf": "Operations" + "subcategory": "Functions", + "text": "functions -Cache data locally", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "24604489-a8f4-42d7-ae78-cb6a33bd2a09", - "id": "D02.06", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "4722d928-c1b1-4cd5-81e5-4a29b9de39ac", + "id": "E05.03", + "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "services": [ - "AVS" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Include workloads running on Azure VMware Solution in existing update management tooling or in Azure Update Management", - "waf": "Operations" + "subcategory": "Functions", + "text": "functions - Cold starts-Use the 'Run from package' functionality. This way, the code is downloaded as a single zip file. This can, for example, result in significant improvements with Javascript functions, which have a lot of node modules.Use language specific tools to reduce the package size, for example, tree shaking Javascript applications.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "17e7a8d9-0ae0-4e27-aee2-9711bd352caa", - "id": "D02.07", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "0e7c28dc-9366-4572-82bf-f4564b0d934a", + "id": "E05.04", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "services": [ - "AVS", - "Monitor", - "AzurePolicy" + "Cost" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", - "waf": "Operations" + "subcategory": "Functions", + "text": "Functions -Keep your functions warm", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "ab79b188-dab8-4193-8c9f-c9d1bb77036f", - "id": "D02.08", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "359c363e-7dd6-4162-9a36-4a907ebae38e", + "id": "E05.05", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS", - "Storage", - "VM" + "Cost" ], - "severity": "High", - "subcategory": "Operations", - "text": "When ANF is used to extend storage for Azure VMware Solution, ensure it is used at the VM level only for now (ANF as NFS datastore is still in private preview)", - "waf": "Operations" + "subcategory": "Functions", + "text": "when using autoscale with different functions, there might be one driving all the autoscale for all the resources - consider moving it to a separate consumption plan (and consider higher plan for CPU)" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "aee3553a-fc83-4392-98b2-62d6cc5f5129", - "id": "D03.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "ad53cc7d-e2e8-4aaa-a357-1549ab9153d8", + "id": "E05.06", + "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", "services": [ - "AVS", - "Defender" + "Cost" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Ensure workloads running on Azure VMware Solution are onboarded to Microsoft Defender for Cloud", - "waf": "Security" + "subcategory": "Functions", + "text": "Function apps in a given plan are all scaled together, so any issues with scaling can affect all apps in the plan." }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "25398e6d-b9d3-47da-a43b-c6cd1d79a9b2", - "id": "E01.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "9f89dc7b-44be-43b1-a27f-8b9e91be1f38", + "id": "E05.07", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "services": [ - "AVS", - "Backup" + "Cost" ], - "severity": "Medium", - "subcategory": "Backup", - "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", - "waf": "Reliability" + "subcategory": "Functions", + "text": "Am I billed for 'await time' ?This question is typically asked in the context of a C# function that does an async operation and waits for the result, e.g. await Task.Delay(1000) or await client.GetAsync('http://google.com'). The answer is yes - the GB second calculation is based on the start and end time of the function and the memory usage over that period. What actually happens over that time in terms of CPU activity is not factored into the calculation.One exception to this rule is if you are using durable functions. You are not billed for time spent at awaits in orchestrator functions.apply demand shaping techinques where possible (dev environments?) https://github.com/Azure-Samples/functions-csharp-premium-scaler" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "5e6bfbb9-ed50-4354-9cc4-47e826028a71", - "id": "E02.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "df03a822-cd46-43cb-abc8-ac299ebc91a4", + "id": "E06.01", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "services": [ - "AVS", - "ASR" + "Cost" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", - "waf": "Reliability" + "subcategory": "Networking", + "text": "evaluate your network topology against networking costs and where applicable reduce the egress and peering data" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "f0f1cac6-d9ef-41d5-b832-d42e3611c818", - "id": "E02.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "3da1dae2-cc88-4147-8607-c1cca0e61465", + "id": "E06.02", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AVS", - "ASR" + "Cost", + "EventHubs", + "FrontDoor" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", - "waf": "Reliability" + "subcategory": "Networking", + "text": "Frontdoor - Turn off the default homepageIn the application settings of your App, set AzureWebJobsDisableHomepage to true. This will return a 204 (No Content) to the PoP so only header data is returned." }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "b0afbc51-0e43-4a18-a9cd-289bed6b17db", - "id": "E02.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "8dd458e9-2713-49b8-8110-2dbd6eaf11e6", + "id": "E06.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "services": [ - "AVS", - "ASR" + "Cost", + "FrontDoor", + "AppSvc" ], - "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Use Automated recovery plans with either of the Disaster solutions, avoid manual tasks as much as possible", - "waf": "Reliability" + "subcategory": "Networking", + "text": "Frontdoor -Route to something that returns nothingEither set up a Function, Function Proxy, or add a route in your WebApp that returns 200 (OK) and sends no or minimal content. The advantage of this is you will be able to log out when it is called." }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "8255461e-2aee-4345-9aec-8339248b262d", - "id": "E02.04", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "f843e52f-4722-4d92-ac1b-1cd521e54a29", + "id": "E07.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "services": [ - "AVS", - "ASR" + "Cost" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use the geopolitical region pair as the secondary disaster recovery environment", - "waf": "Reliability" + "subcategory": "PaaS", + "text": "consider using free tiers where applicable for all non-production environments" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "6cc5f512-9253-498e-9da9-d37dac43bc6c", - "id": "E02.05", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "b9de39ac-0e7c-428d-a936-657202bff456", + "id": "E08.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "services": [ - "AVS", - "ASR" + "Cost" ], - "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", - "waf": "Reliability" + "subcategory": "serverless", + "text": "using serverless patterns for spikes can help keeping costs down" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "d1d79a9b-2460-4448-aa8f-42d78e78cb6a", - "id": "E02.06", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "7e31c67d-68cf-46a6-8a11-94956d697dc3", + "id": "E09.01", + "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "services": [ - "AVS", - "ASR", - "NVA", - "ExpressRoute" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Will ExpressRoute Global Reach be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or is routing done through network virtual appliances?", - "waf": "Reliability" + "subcategory": "Storage", + "text": "consider archiving tiers for less used data" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "33bd2a09-17e7-4a8d-a0ae-0e27cee29711", - "id": "E03.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "a2ed27b2-d186-4f1a-8252-bddde68a487c", + "id": "E09.02", + "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "services": [ - "AVS", - "Backup" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Use MABS as your backup solution", - "waf": "Reliability" + "subcategory": "Storage", + "text": "check disk sizes where the size does not match the tier (i.e. A 513 GiB disk will pay a P30 (1TiB) and consider resizing" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "bd352caa-ab79-4b18-adab-81932c9fc9d1", - "id": "E03.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "dec4861b-c3bc-410a-b77e-26e4d5a3bec2", + "id": "E09.03", + "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "services": [ - "AVS", - "Backup" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", - "waf": "Reliability" + "subcategory": "Storage", + "text": "consider using standard SSD rather than Premium or Ultra where possible" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "bb77036f-5e6b-4fbb-aed5-03547cc447e8", - "id": "E03.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "c4e2436b-1336-4db5-9f17-960eee0bdf5c", + "id": "E09.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "services": [ - "AVS" + "Cost", + "Storage" ], - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", - "waf": "Reliability" + "subcategory": "Storage", + "text": "For storage accounts, make sure that the chosen tier is not adding up transaction charges (it might be cheaper to move to the next tier)" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "26028a71-f0f1-4cac-9d9e-f1d5e832d42e", - "id": "E03.04", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "c2efc5d7-61d4-41d2-900b-b47a393a040f", + "id": "E09.05", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "services": [ - "AVS" + "Cost", + "Storage", + "ASR" ], - "severity": "Low", - "subcategory": "Business Continuity", - "text": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", - "waf": "Reliability" + "subcategory": "Storage", + "text": "for ASR, consider using Standard SSD disks if the RPO/RTO and replication throughput allow it" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "4604489a-8f42-4d78-b78c-b7a33bd2a0a1", - "id": "F01.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "d3294798-b118-48b2-a5a4-6ceb544451e1", + "id": "E10.01", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "services": [ - "AVS" + "Cost", + "Storage" ], - "severity": "Low", - "subcategory": "Deployment strategy", - "text": "For manual deployments, all configuration and deployments must be documented", - "waf": "Operations" + "subcategory": "storage", + "text": "storage accounts: check hot tier and/or GRS necessary" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "7e7a8d90-ae0e-437c-be29-711bd352caaa", - "id": "F01.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "92d34429-3c76-4286-97a5-51c5b04e4f18", + "id": "E10.02", + "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "services": [ - "AVS" + "Cost", + "Storage" ], - "severity": "Low", - "subcategory": "Deployment strategy", - "text": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", - "waf": "Operations" + "subcategory": "storage", + "text": "Disks -validate use of Premium SSD disks everywhere: for example, non-prod could swap to Standard SSD or On demand Premium SSD " }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "b79b198d-ab81-4932-a9fc-9d1bb78036f5", - "id": "F02.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "54387e5c-ed12-46cd-832a-f5b2fc6998a5", + "id": "E11.01", + "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "services": [ - "AVS" + "Cost", + "EventHubs", + "Monitor" ], - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployments, deploy a minimal private cloud and scale as needed", - "waf": "Operations" + "subcategory": "Synapse", + "text": "Create budgets to manage costs and create alerts that automatically notify stakeholders of spending anomalies and overspending risks." }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "e6bfbb9e-d503-4547-ac44-7e826128a71f", - "id": "F02.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "35e33789-7e31-4c67-b68c-f6a62a119495", + "id": "E11.02", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "services": [ - "AVS" + "Cost", + "Storage" ], - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployments, request or reserve quota prior to starting the deployment", - "waf": "Operations" + "subcategory": "Synapse", + "text": "Export cost data to a storage account for additional data analysis." }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "0f1cac6d-9ef1-4d5e-a32e-42e3611c818b", - "id": "F02.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "6d697dc3-a2ed-427b-8d18-6f1a1252bddd", + "id": "E11.03", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "AVS", - "AzurePolicy" + "Cost", + "SQL" ], - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployment, ensure that relevant resource locks are created through the automation or through Azure Policy for proper governance", - "waf": "Operations" + "subcategory": "Synapse", + "text": "Control costs for a dedicated SQL pool by pausing the resource when it is not in use." }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "e2cc95d4-8c6b-4791-bca0-f6c56589e558", - "id": "F03.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "e68a487c-dec4-4861-ac3b-c10ae77e26e4", + "id": "E11.04", + "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "services": [ - "AVS", - "AKV" + "Cost" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", - "waf": "Operations" + "subcategory": "Synapse", + "text": "Enable the serverless Apache Spark automatic pause feature and set your timeout value accordingly." }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "255461e2-aee3-4553-afc8-339248b262d6", - "id": "F03.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "d5a3bec2-c4e2-4436-a133-6db55f17960e", + "id": "E11.05", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "services": [ - "AVS", - "AKV", - "ExpressRoute" + "Cost" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", - "waf": "Operations" + "subcategory": "Synapse", + "text": "Create multiple Apache Spark pool definitions of various sizes." }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "cc5f5129-2539-48e6-bb9d-37dac43bc6cd", - "id": "F03.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "ee0bdf5c-c2ef-4c5d-961d-41d2500bb47a", + "id": "E11.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "services": [ - "AVS" + "Cost" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Define resource dependencies for serializing actions in IaC when many resources need to be deployed in/on Azure VMware Solution as Azure VMware Solution only supports a limited number of parallel operations.", - "waf": "Operations" + "subcategory": "Synapse", + "text": "Purchase Azure Synapse commit units (SCU) for one year with a pre-purchase plan to save on your Azure Synapse Analytics costs.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "1d79a9b2-4604-4489-a8f4-2d78e78cb7a3", - "id": "F03.04", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "393a040f-d329-4479-ab11-88b2c5a46ceb", + "id": "E12.01", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "services": [ - "AVS" + "Cost", + "VM" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", - "waf": "Operations" + "subcategory": "VM", + "text": "Use SPOT VMs for interruptible jobs: These are VMs that can be bid on and purchased at a discounted price, providing a cost-effective solution for non-critical workloads.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "3bd2a0a1-7e7a-48d9-8ae0-e37cee29711b", - "id": "F04.01", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "544451e1-92d3-4442-a3c7-628637a551c5", + "id": "E12.02", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "Subscriptions", - "AVS" + "Cost", + "VM" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", - "waf": "Performance" + "subcategory": "VM", + "text": "right-sizing all VMs" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "d352caaa-b79b-4198-bab8-1932c9fc9d1b", - "id": "F04.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "b04e4f18-5438-47e5-aed1-26cd032af5b2", + "id": "E12.03", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "services": [ - "AVS", - "Storage", - "AzurePolicy" + "Cost", + "VM" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", - "waf": "Performance" + "subcategory": "VM", + "text": "swap VM sized with normalized and most recent sizes", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "b78036f5-e6bf-4bb9-bd50-3547cc447e82", - "id": "F04.03", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "fc6998a5-35e3-4378-a7e3-1c67d68cf6a6", + "id": "E12.04", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVS" + "Cost", + "VM", + "Monitor" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", - "waf": "Performance" + "subcategory": "VM", + "text": "right-sizing VMs - start with monitoring usage below 5% and then work up to 40%", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "bf15bce2-19e4-4a0e-a588-79424d226786", - "id": "F04.04", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "2a119495-6d69-47dc-9a2e-d27b2d186f1a", + "id": "E12.05", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVS" + "Cost", + "VM" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", - "waf": "Performance" + "subcategory": "VM", + "text": "containerizing an application can improve VM density and save money on scaling it", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "d20b56c5-7be5-4851-a0f8-3835c586cb29", - "id": "F04.05", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD control plane does not offer a financially backed service level agreement. We strive to attain at least 99.9% availability for the Azure Virtual Desktop service URLs. The availability of the session host virtual machines in your subscription is covered by the Virtual Machines SLA. Dependent resources/services and infrastructure availability must be also considered to properly satisfy global high-availability requirements.", + "guid": "56c57ba5-9119-4bf8-b8f5-c586c7d9cdc1", + "id": "A01.01", + "link": "https://azure.microsoft.com/support/legal/sla/virtual-desktop/v1_0/", "services": [ - "AVS" + "Subscriptions", + "VM", + "AVD", + "ASR" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Define and enforce scale in/out maximum limits for your environment in the automations", - "waf": "Performance" + "severity": "High", + "subcategory": "Compute", + "text": "Determine the expected High Availability SLA for applications/desktops published through AVD", + "waf": "Reliability" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "1dc15a1c-075e-4e9f-841a-cccd579376bc", - "id": "F04.06", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "'Active-Active' model can be achieved with multiple host pools in different regions. A single Host Pool with VMs from different regions is not recommended. If multiple pools for same users will be used, the problem of how to synchronize/replicate user profiles must be solved. FSLogix Cloud Cache could be used, but need to be carefully reviewed and planned, or customers can decide to do not synchronize/replicate at all. 'Active-Passive' can be achieved using Azure Site Recovery (ASR) or on-demand Pool deployment with automated mechanism. For a detailed discussion on multi-region BCDR, please read the companion article in the 'More Info' column and this FSLogix related page: https://learn.microsoft.com/fslogix/concepts-container-recovery-business-continuity.", + "guid": "6acc076e-f9b1-441a-a989-579e76b897e7", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/azure-virtual-desktop-multi-region-bcdr", "services": [ - "AVS", - "Monitor" + "Storage", + "VM", + "AVD", + "ASR" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", - "waf": "Operations" + "subcategory": "Compute", + "text": "Assess Geo Disaster Recovery requirements for AVD Host Pools", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "a95b86ad-8840-48e3-9273-4b875ba18f20", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Before approaching Azure Virtual Desktop BCDR planning and design, it is important to initially consider which applications consumed through AVD are critical. You may want to separate them from non-critical apps and use a separate Host Pool with a different disaster recovery approach and capabilities.", + "guid": "10a7da7b-e996-46e1-9d3c-4ada97cc3d13", + "id": "A01.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Monitor", - "Cost" + "AVD", + "ASR" ], - "subcategory": "Azure Monitor - enforce data collection rules", - "text": "Data collection rules in Azure Monitor -https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-rule-overview", - "training": "https://azure.microsoft.com/pricing/reservations/" + "severity": "Low", + "subcategory": "Compute", + "text": "Separate critical applications in different AVD Host Pools", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "45901365-d38e-443f-abcb-d868266abca2", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Each Host Pool can be deployed using Availability Zones (AZ) or Availability Set (AS). To maximize resiliency, usage of AZ is recommended: at Host Pool creation time you can decide to spread Host Pool Session Hosts across all available AZ. Usage of AS will not protect from single datacenter failure, then should be used only in regions where AZ are not available. More details on AZ and AVD in the companion article. For a comparison between AZ and AS you can read here: https://learn.microsoft.com/azure/virtual-machines/availability.", + "guid": "25ab225c-6f4e-4168-9fdd-dea8a4b7cdeb", + "id": "A01.04", + "link": "https://techcommunity.microsoft.com/t5/azure-virtual-desktop-blog/announcing-general-availability-of-support-for-azure/ba-p/3636262", "services": [ - "Backup", - "Cost" + "AVD", + "ACR", + "ASR" ], - "subcategory": "Backup", - "text": "check backup instances with the underlying datasource not found" + "severity": "High", + "subcategory": "Compute", + "text": "Plan the best resiliency option for AVD Host Pool deployment", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "64f9a19a-f29c-495d-94c6-c7919ca0f6c5", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Backup can be used to protect Host Pool VMs. For Pooled Pools, this is not necessary since should be stateless. Instead, this option can be considered for Personal Host Pools.", + "guid": "4c61fc3f-c14e-4ea6-b69e-8d9a3eec218e", + "id": "A01.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Cost" + "VM", + "AVD", + "Backup", + "ASR" ], - "subcategory": "delete/archive", - "text": "delete or archive unassociated services (disks, nics, ip addresses etc)" + "severity": "Medium", + "subcategory": "Compute", + "text": "Assess the requirement to backup AVD Session Host VMs", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "659d3958-fd77-4289-a835-556df2bfe456", - "id": "A03.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Even for Personal Pools, usage of Availability Zones, when available, is recommended. Three possible in-region DR strategies are possible, it is recommended to select the best one based on cost, RTO/RPO, and if it is really necessary to save the entire VM OS disk: (1) create each session host in a specific zone (AZ) and then use Azure Site Recovery (ASR) to replicate to a different zone. (2) Use Azure Backup to backup and restore the specific session host in a different AZ. (3) Create a new session host in a different AZ and rely on FSLogix and/or OneDrive to make data and settings available on the new machine. All options require administrator intervention for DR and direct user assignment at Host Pool level, then must be planned and configured in advance.", + "guid": "5da58639-ca3a-4961-890b-29663c5e10d", + "id": "A01.06", + "link": "https://learn.microsoft.com/azure/site-recovery/azure-to-azure-how-to-enable-zone-to-zone-disaster-recovery", "services": [ - "Cost" - ], - "subcategory": "delete/archive", - "text": "consider snooze and stop technique (snooze a service after x days, stop after 2x, delete/deallocate after 3x)" + "VM", + "ASR", + "Cost", + "AVD", + "Backup" + ], + "severity": "Medium", + "subcategory": "Compute", + "text": "Prepare a local DR strategy for Personal Host Pool Session Hosts", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "3b0d834a-3487-426d-b69c-6b5c2a26494b", - "id": "A03.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "If custom images are used to deploy AVD Host Pool VMs, it is important to ensure those artifacts are available in all regions where AVD is deployed. Azure Compute Gallery service can be used to replicate images across all regions where a Host Pool is deployed, with redundant storage and in multiple copies. Please be aware that the Azure Compute Gallery service isn't a global resource. For disaster recovery scenarios, the best practice is to have at least two galleries, in different regions.", + "guid": "dd2e0d5d-771d-441e-9610-cc57b4a4a141", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/azure-compute-gallery", "services": [ - "Backup", "Storage", - "Cost" + "VM", + "ACR", + "ASR", + "AVD" ], - "subcategory": "delete/archive", - "text": "delete or archive unused resources (old backups, logs, storage accounts, etc...)" + "severity": "Low", + "subcategory": "Dependencies", + "text": "Plan for Golden Image cross-region availability", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "69bad37a-ad53-4cc7-ae1d-76667357c449", - "id": "A03.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "If users of the AVD infrastructure need on-premises resource access, high availability of network infrastructure required to connect is also critical and should be considered. Resiliency of authentication infrastructure needs to be assessed and evaluated. BCDR aspects for dependent applications and other resources need to be considered to ensure availability in the secondary DR location.", + "guid": "fd339489-8c12-488b-9c6a-57cfb644451e", + "id": "A02.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Backup", - "Storage", - "Cost", + "AVD", "ASR" ], - "subcategory": "delete/archive", - "text": "consider a good balance between site recovery storage and backup for non mission critical applications" + "severity": "Medium", + "subcategory": "Dependencies", + "text": "Assess Infrastructure & Application dependencies ", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "674b5ed8-5a85-49c7-933b-e2a1a27b765a", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Not all data inside FSLogix user profiles may deserve protection from disaster. Additionally, if external storage is used, for example OneDrive or File Servers/Shares, what is remaining in the FSLogix profile is minimal and could be lost in some extreme circumstances. In other cases, data inside the profile can be rebuilt from other storages (for example Outlook Inbox in cached mode).", + "guid": "687ab077-adb5-49e5-a960-3334fdf8cc23", + "id": "A03.01", + "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt", "services": [ - "Monitor", - "Cost" + "Storage", + "AVD", + "ASR" ], - "subcategory": "Log Analytics retention for workspaces", - "text": "check spending and savings opportunities among the 40 different log analytics workspaces- use different retention and data collection for nonprod workspaces-create daily cap for awareness and tier sizing - If you do set a daily cap, in addition to creating an alert when the cap is reached,ensure that you also create an alert rule to be notified when some percentage has been reached (90% for example). - consider workspace transformation if possible - https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-transformations#workspace-transformation-dcr ", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/understand-work-scopes" + "severity": "Medium", + "subcategory": "Storage", + "text": "Assess which data need to be protected in the Profile and Office Containers", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "91be1f38-8ef3-494c-8bd4-63cbbac75819", - "id": "A05.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Preventing data loss for critical user data is important, first step is to assess which data need to be saved and protected. If using OneDrive or other external storage, saving user Profile and/or Office Containers data maybe not necessary. Appropriate mechanism must be considered to provide protection for critical user data. Azure Backup service can be used to protect Profile and Office Containers data when stored on Azure Files Standard and Premium tiers. Azure NetApp Files Snapshots and Policies can be used for Azure NetApp Files (all tiers).", + "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", + "id": "A03.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ "Storage", + "ASR", "AzurePolicy", - "Cost" + "AVD", + "Backup" ], - "subcategory": "Policy", - "text": "enforce a purging log policy and automation (if needed, logs can be moved to cold storage)", - "training": "https://www.youtube.com/watch?v=nHQYcYGKuyw" + "severity": "Medium", + "subcategory": "Storage", + "text": "Build a backup protection strategy for Profile and Office Containers", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "59bb91a3-ed90-4cae-8cc8-4c37b6b780cb", - "id": "A06.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "In AVD, multiple replication mechanisms and strategies can be used for user data residing in FSLogix containers: [Profile Pattern #1]: Native Azure storage replication mechanisms, for example Azure Files Standard GRS replication, Azure NetApp Files Cross Region Replication. Use Zone Replicated Storage (ZRS) or Geo replicated storage (GRS) for Azure Files is recommended. LRS with local-only resiliency can be used if no zone/region protection is required. NOTE: Azure Files Share Standard is LRS/ZRS/GRS, but with 100TB large support enabled only LRS/ZRS are supported. [Profile Pattern #2]: FSLogix Cloud Cache is built in automatic mechanism to replicate containers between different (up to 4) storage accounts. Cloud Cache should be used only when:(1) User Profile or Office containers data availability required high-availability SLA is critical and need to be resilient to region failure. (2) Selected storage option is not able to satisfy BCDR requirements. For example, with Azure File Share Premium tier, or Azure File Share Standard with Large File Support enabled, GRS is not available. (3) When replication between disparate storage is required. [Profile Pattern #3]: Only set up geo disaster recovery for application data and not for user data/profile containers: store important application data in separate storages, like OneDrive or other external storage with its own built-in DR mechanism.", + "guid": "9f7547c1-746d-4c56-868a-714435bd09dd", + "id": "A03.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Cost" + "Storage", + "AVD", + "ASR" ], - "subcategory": "run orphaned resources workbook - delete or snooze ghost items", - "text": "https://github.com/dolevshor/azure-orphan-resources", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets" + "severity": "Medium", + "subcategory": "Storage", + "text": "Assess Profile Container storage replication requirements and resiliency for BCDR purpose", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "9fe5c464-89d4-457a-a27c-3874d0102cac", - "id": "A07.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "For local disaster recovery, Azure Backup for Azure Files can be used. For cross-region geo disaster recovery: GRS for Azure Files is only available with standard SKU and no large share support, then not suitable in most customer scenarios. If geo-replication is required with Azure File Share Premium, replication with FSLogix Cloud Cache can be evaluated, or 'in-region' Availability Zone (AZ) only resiliency should be considered.", + "guid": "3d4f3537-c134-46dc-9602-7a71efe1bd05", + "id": "A03.04", + "link": "https://docs.microsoft.com/azure/backup/backup-afs", "services": [ - "Cost" + "Storage", + "AVD", + "Backup", + "ASR" ], - "subcategory": "shutdown/deallocate", - "text": "shutdown underutilized instances", - "training": "https://learn.microsoft.com/azure/cost-management-billing/understand/analyze-unexpected-charges" + "severity": "Medium", + "subcategory": "Storage", + "text": "Review Azure Files disaster recovery strategy", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "6aae01e6-a84d-4e5d-b36d-1d92881a1bd5", - "id": "A08.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Zone Redundant Storage will maximize in-region resiliency for the user profile data. ZRS is supported for premium file shares through the 'FileStorage' storage account kind. ZRS is supported in standard general-purpose v2 storage accounts. Usage of zone redundant storage must be paired with zone redundant deployment of Session Hosts in each Host Pool. ", + "guid": "10d4e875-d502-4142-a795-f2b6eff34f88", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/storage/files/files-redundancy#zone-redundant-storage", "services": [ - "Backup", "Storage", - "VM", - "Cost" + "AVD", + "ASR" ], - "subcategory": "stopped/deallocated VMs: check disks", - "text": "check that the disks are really needed, if not: delete. If they are needed, find lower storage tiers or use backup -", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/manage-automation" + "severity": "High", + "subcategory": "Storage", + "text": "Use Zone Redundant Storage (ZRS) for Azure Files to maximize resiliency", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "d1e44a19-659d-4395-afd7-7289b835556d", - "id": "A09.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "For local disaster recovery, Azure NetApp Files (ANF) native backup is available. ANF is essentially locally redundant, then for cross-region geo disaster recovery it is necessary to use an additional mechanism that is Cross-Region Replication (CRR) https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering. Currently, ANF does not provide replication nor redundancy across different Availability Zones (AZ), only the possibility to select in which single AZ to place the ANF volume: https://learn.microsoft.com/azure/azure-netapp-files/manage-availability-zone-volume-placement.", + "guid": "23429db7-2281-4376-85cc-57b4a4b18142", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering", "services": [ "Storage", - "AzurePolicy", - "Cost" + "ACR", + "ASR", + "AVD", + "Backup" ], - "subcategory": "storage accounts lifecycle policy", - "text": "consider moving unused storage to lower tier, with customized rule - https://learn.microsoft.com/azure/storage/blobs/lifecycle-management-policy-configure ", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance" + "severity": "Medium", + "subcategory": "Storage", + "text": "Review Azure NetApp Files disaster recovery strategy", + "waf": "Reliability" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "f2bfe456-3b0d-4834-a348-726de69c6b5c", - "id": "A10.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Applications can be preinstalled in the golden image/s, can be attached using MSIX & AppAttach feature or distributed to the session hosts after host pool deployment using traditional software distribution methods.", + "guid": "86ba2802-1459-4014-95d3-8e5309ccbd97", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", "services": [ - "Cost" + "AVD" ], - "subcategory": "Tagging", - "text": "use specific tags for temporary items with 'delete by DATE' format - and automate monthly cleanup" + "severity": "High", + "subcategory": "Golden Images", + "text": "Determine how applications will be deployed in AVD Host Pools", + "waf": "Operations" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "2a26494b-69ba-4d37-aad5-3cc78e1d7666", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Multiple golden images can be required to support different OS versions and/or settings, different groups of applications that must be separated and cannot be included in a single image.", + "guid": "9266bcca-274f-4aa1-abf3-9d95d44c7c89", + "id": "B01.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", "services": [ - "Cost" + "AVD" ], - "subcategory": "db optimization", - "text": "plan for db optimization with the intent of downsizing the related services (and improve performance)" + "severity": "Medium", + "subcategory": "Golden Images", + "text": "Estimate the number of golden images that will be required", + "waf": "Operations" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "7357c449-674b-45ed-a5a8-59c7733be2a1", - "id": "B02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Determine which Guest OS will be used to deploy each Host Pool: Windows 10 vs. Windows Server, Marketplace vs. Custom images", + "guid": "19ca1f6d-5315-4ae5-84ba-34d4585e2213", + "id": "B01.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#operating-systems-and-licenses", "services": [ - "Cost" + "AVD" ], - "subcategory": "app modernization", - "text": "modernizing the app towards a microservices architecture will have the effect of letting the app scale according to the single service and not the entire stack" + "severity": "Medium", + "subcategory": "Golden Images", + "text": "Determine which OS image/s you will use for Host Pool deployment", + "waf": "Reliability" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "a27b765a-91be-41f3-a8ef-394c2bd463cb", - "id": "B03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", - "services": [ + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure VM custom images can be created and stored in different ways: in an Azure Compute Gallery, as a managed image object or as a managed disk in the storage. The recommended way is to use Azure Compute Gallery.", + "guid": "5a2adb2c-3e23-426b-b225-ca44e1696fdd", + "id": "B01.04", + "link": "https://learn.microsoft.com/azure/virtual-machines/shared-image-galleries", + "services": [ "Storage", "VM", - "Cost" + "AVD" ], - "subcategory": "db optimization", - "text": "optimizing the DB queries will increase performance and allow better right-sizing of storage and VMs" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Select the proper store for custom images", + "waf": "Reliability" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "bac75819-59bb-491a-9ed9-0cae2cc84c37", - "id": "B04.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "If custom images will be used, plan for an automated build process. If no pre-existing software factory exists, consider using Custom Image Templates and/or Azure Image Builder to automate the build process.", + "guid": "9bd7bb01-2f7b-495e-86e1-54e2aa359282", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/create-custom-image-templates", "services": [ - "Cost" + "AVD" ], - "subcategory": "demand shaping", - "text": "using demand shaping on PaaS services will optimize costs and performances" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Design your build process for custom images", + "waf": "Operations" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "b6b780cb-9fe5-4c46-989d-457a927c3874", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "There are some known best practices and recommendations for the golden image customization, be sure to check the referenced article.", + "guid": "deace4cb-1dec-44c6-90c3-fc14eebb36a3", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", "services": [ - "Entra", - "Cost" + "AVD" ], - "subcategory": "Advisor", - "text": "Start from the Azure Advisor page suggestions." + "severity": "Medium", + "subcategory": "Golden Images", + "text": "If custom image will be used, check recommended best practices for AVD on how to build custom image", + "waf": "Operations" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "d0102cac-6aae-401e-9a84-de5de36d1d92", - "id": "C01.02", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "FSLogix stack installed in AVD session hosts does not provide auto-update capability. For this reason, it is recommended to download the latest version of FSLogix and include in the golden image update process.", + "guid": "ed5c9027-dd1a-4343-86ca-52b199223186", + "id": "B01.07", + "link": "https://learn.microsoft.com/fslogix/how-to-install-fslogix", "services": [ - "VM", - "Cost" + "AVD" ], - "subcategory": "Advisor", - "text": "make sure advisor is configured for VM right sizing " + "severity": "High", + "subcategory": "Golden Images", + "text": "Include the latest version of FSLogix in the golden image update process", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "881a1bd5-d1e4-44a1-a659-d3958fd77289", - "id": "C02.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "This tool-set has been created to automatically apply setting referenced in white paper 'Optimizing Windows 10, version 2004 for a Virtual Desktop Infrastructure (VDI) role': https://docs.microsoft.com/windows-server/remote/remote-desktop-services/rds-vdi-recommendations-2004. Usage of the tool and/or optimizations mentioned in the white-paper should be considered. ", + "guid": "829e3fec-2183-4687-a017-7a2b5945bda4", + "id": "B01.08", + "link": "https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool", "services": [ - "Cost" + "AVD", + "RBAC" ], - "subcategory": "Automation", - "text": "consider implementing IAC scripts or devops pipelines to match the cost governance process" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Evaluate the usage of Virtual-Desktop-Optimization-Tool", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "b835556d-f2bf-4e45-93b0-d834a348726d", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "If OneDrive is used and included in a golden image, be sure to follow the configuration procedure reported in the companion article in the 'More Info' section. Not in scope in this AVD checklist, but OneDrive optimizations like 'Known Folder Redirection' and 'Files On-Demand' should be evaluated used to reduce the space used in FSLogix profiles and provide a better user experience. OneDrive today is not supported for Remote Apps.", + "guid": "e3d3e084-4276-4d4b-bc01-5bcf219e4a1e", + "id": "B01.09", + "link": "https://learn.microsoft.com/azure/virtual-desktop/install-office-on-wvd-master-image#install-onedrive-in-per-machine-mode", "services": [ - "Monitor", - "Cost" + "Storage", + "AVD" ], - "subcategory": "Automation", - "text": "set up cost alerts for applications that have variable costs (ideally for all of them)" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Determine if Microsoft OneDrive will be part of AVD deployment", + "waf": "Operations" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "e69c6b5c-2a26-4494-a69b-ad37aad53cc7", - "id": "C02.03", - "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Be sure to review the requirements and configuration procedure contained in the companion article in the 'More Info' column. Since Teams automatic updates will be disabled, it is recommended to check and include Teams latest version in the golden image update process.", + "guid": "b5887953-5d22-4788-9d30-b66c67be5951", + "id": "B01.10", + "link": "https://learn.microsoft.com/azure/virtual-desktop/teams-on-AVD", "services": [ - "Cost" + "AVD" ], - "subcategory": "Automation", - "text": "Use Azure Automation: Automate repetitive tasks can help you save time and resources, reducing costs in the process. " + "severity": "Low", + "subcategory": "Golden Images", + "text": "Determine if Microsoft Teams will be part of AVD deployment", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "8e1d7666-7357-4c44-a674-b5ed85a859c7", - "id": "C02.04", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD can support users with different language and localization requirements in the same host pool. This can be done customizing golden images to ensure users can select whichever language they need. The procedure to configure additional language packs in Windows 11 is documented in the reference article.", + "guid": "7c336f3b-822a-498e-8cd1-667d1150df4a", + "id": "B01.11", + "link": "https://learn.microsoft.com/azure/virtual-desktop/windows-11-language-packs", "services": [ - "Cost" + "AVD" ], - "subcategory": "Automation", - "text": "run orphaned resources workbook" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Assess the requirement to support multiple languages", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "733be2a1-a27b-4765-a91b-e1f388ef394c", - "id": "C03.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "It is highly recommended to use separate storage accounts/shares to store MSIX packages. If necessary, storage can scale out independently and not being impacted by profile I/O activities. Azure offers multiple storage options that can be used for MISX app attach. We recommend using Azure Files or Azure NetApp Files as those options offer the best value between cost and management overhead. ", + "guid": "90083845-c587-4cb3-a1ec-16a1d076ef9f", + "id": "B02.01", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", "services": [ "Storage", + "AVD", "Cost" ], - "subcategory": "Baseline", - "text": "try and establish a baseline of monthly spending and an acceptable saving target against the baseline (new services will not be optimized at this stage)" + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Do not use the same storage account/share as FSLogix profiles", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "2bd463cb-bac7-4581-a59b-b91a3ed90cae", - "id": "C03.02", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "In the referenced article, we reported few but important performance considerations for MSIX usage in AVD context, be sure to carefully review.", + "guid": "241addce-5793-477b-adb3-751ab2ac1fad", + "id": "B02.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", "services": [ - "AzurePolicy", - "Cost" + "AVD" ], - "subcategory": "Baseline", - "text": "establish a cost optimization baseline by using a policy that tags every new resource as #NEW" + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Review performance considerations for MSIX", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "2cc84c37-b6b7-480c-a9fe-5c46489d457a", - "id": "C03.03", - "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "MSIX app attach requires read-only permissions to access the file share. If you're storing your MSIX applications in Azure Files, then for your session hosts, you'll need to assign all session host VMs both storage account role-based access control (RBAC) and file share New Technology File System (NTFS) permissions on the share.", + "guid": "66e15d4d-5a2a-4db2-a3e2-326bf225ca41", + "id": "B02.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", "services": [ - "Cost" + "Storage", + "VM", + "AVD", + "RBAC" ], - "subcategory": "Baseline", - "text": "Organize resources to maximize cost insights and accountability" + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Check proper session host permissions for MSIX share", + "waf": "Security" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "927c3874-d010-42ca-a6aa-e01e6a84de5d", - "id": "C04.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "3rd-party software vendor must provide a MSIX package, it is not recommended for customer to attempt the conversion procedure without proper support from the application owner.", + "guid": "bd362caa-ab79-4b19-adab-81932c9fc9d1", + "id": "B02.04", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", "services": [ - "Cost" + "AVD" ], - "subcategory": "Budgets", - "text": "Create budgets" + "severity": "Low", + "subcategory": "MSIX & AppAttach", + "text": "MSIX packages for 3rd-party applications", + "waf": "Cost" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "e36d1d92-881a-41bd-9d1e-44a19659d395", - "id": "C05.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "MSIX app attach doesn't support auto-update for MSIX applications, so they should be disabled.", + "guid": "bb88037f-5e6b-4fbb-aed5-03547cc447e8", + "id": "B02.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", "services": [ - "Cost" + "AVD" ], - "subcategory": "Cost Analysis", - "text": "in cost analysis - use daily granularity, grouped by service name to analyze the spending of the past 3 months and identify the top 3 spenders" + "severity": "Low", + "subcategory": "MSIX & AppAttach", + "text": "Disable auto-update for MSIX packages", + "waf": "Operations" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "8fd77289-b835-4556-bf2b-fe4563b0d834", - "id": "C05.02", - "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "In order to leverage MSIX & App Attach, guest OS image for AVD Host pool must be Windows 10/11 Enterprise or Windows 10/11 Enterprise Multi-session, version 2004 or later.", + "guid": "26128a71-f0f1-4cac-9d9e-f1d5e832e42e", + "id": "B02.06", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", "services": [ - "Cost" + "AVD" ], - "subcategory": "Cost Analysis", - "text": "check daily for cost spikes and anomalies (ideally with automatic billing exports)" + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Review operating systems support", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "a348726d-e69c-46b5-a2a2-6494b69bad37", - "id": "C05.03", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Once selected the VM SKU that will be used for Host Pool deployment, it is recommended to use Gen2 type of the SKU for higher security and improved capabilities.", + "guid": "e4633254-3185-40a1-b120-bd563a1c8e9d", + "id": "B03.01", + "link": "https://docs.microsoft.com/azure/virtual-machines/generation-2", "services": [ - "Cost" + "VM", + "AVD" ], - "subcategory": "Cost Analysis", - "text": "automate cost retrieval for deep analysis or integration" + "severity": "Medium", + "subcategory": "Session Host", + "text": "Evaluate the usage of Gen2 VM for Host Pool deployment", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "aad53cc7-8e1d-4766-9735-7c449674b5ed", - "id": "C06.01", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "MMR redirects the media content from Session Host to your local machine for faster processing and rendering. It only works when you play media content on Microsoft Edge or Google Chrome. See linked URL for more details.", + "guid": "adecb27f-dc40-40f5-aca2-0090f633b1c9", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/multimedia-redirection", "services": [ - "ACR", - "Cost" + "AVD" ], - "subcategory": "free services", - "text": "Take advantage of Azure free services: Azure offers a number of free services, such as DevOps, Azure Container Registry, and Azure Logic Apps, that can help you save costs on development and operations. " + "severity": "Low", + "subcategory": "Session Host", + "text": "Consider using MMR (MultiMedia Redirection) to get better video performance on browser", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "96c96ad8-844c-4f3b-8b38-c886ba2c0214", - "id": "C07.01", - "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "A host pool is a collection of Azure virtual machines that register to Azure Virtual Desktop as session hosts. A host pool can be one of two types: Personal and Pooled. Which type to use, and how many, is a key design decision that must be documented and validated. See companion article in 'More Info' column for more details.", + "guid": "8468c55a-775c-46ee-a5b8-6ad8844ce3b2", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology#host-pools", "services": [ - "Cost" + "VM", + "AVD" ], - "subcategory": "Tagging", - "text": "Tag shared resources" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Determine the Host Pool type to use", + "waf": "Cost" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "99014a5d-3ce5-474d-acbd-9792a6bcca2b", - "id": "C07.02", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Use your design criteria to determine the number of Host Pools to deploy. This will be based on factors such as different OS images, multi-region support, guest VM hardware differences (such as GPU support or no), different user expectations and uptime requirements (examples might be 'Executives', 'Office Workers', 'Developers', etc.), and Host Pool RDP settings (such as drive redirection support). These will determine the number of host pools as well as how many hosts will be in each pool.", + "guid": "4e98495f-d3c0-4af2-aa59-a793395a32a7", + "id": "C01.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#host-pools", "services": [ - "Cost" + "VM", + "AVD" ], - "subcategory": "Tagging", - "text": "consider using tags to all services for cost allocation" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Estimate the number of different Host Pools to deploy ", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "4fea1dbf-3dd9-45d4-ac7c-891dcb1f7d57", - "id": "D01.01", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Confirm that the difference between automatic and direct assignment is well understood and the selected option is appropriate for the scenario in question. Automatic is the default setting.", + "guid": "b38b875b-a1cf-4204-a901-3a5d3ce474db", + "id": "C01.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type", "services": [ - "Cost" + "AVD" ], - "subcategory": "automation", - "text": "consider Reservation automation to track and promptly react to changes" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "For Personal Host Pool type, select the proper assignment type", + "waf": "Operations" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "description": "check by searching the Meter Category Licenses in the Cost analysys", - "guid": "59ae568b-a38d-4498-9e22-13dbd7bb012f", - "id": "D02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Check which one to use and available options, autoscale ignores existing load-balancing algorithms.", + "guid": "cbd8682a-6abc-4a2a-9fda-1dbf3dc95d48", + "id": "C01.04", + "link": "https://docs.microsoft.com/azure/virtual-desktop/host-pool-load-balancing", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "For Pooled Host Pool type, select the best load balancing method", + "waf": "Performance" + }, + { + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "The number of cores increase, the system's synchronization overhead also increases. Especially for multiple user's sign-in simultaneously. Make sure not to use a VM that is too large for the session host", + "guid": "b3724959-4943-4577-a3a9-e10ff6345f24", + "id": "C01.05", + "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", "services": [ - "SQL", - "AzurePolicy", "VM", - "Cost" + "AVD" ], - "subcategory": "check AHUB is applied to all Windows VMs, RHEL and SQL", - "text": "run the script on all windows VMs https://learn.microsoft.com/azure/virtual-machines/windows/hybrid-use-benefit-licensing?ref=andrewmatveychuk.com#convert-an-existing-vm-using-azure-hybrid-benefit-for-windows-server- consider implementing a policy if windows VMs are created frequently" + "severity": "Medium", + "subcategory": "Capacity Planning", + "text": "For Pooled Host Pool type, VMs shouldn't have more than 32 cores", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "7b95e06e-158e-42ea-9992-c2de6e2065b3", - "id": "D03.01", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD does not support assigning both the RemoteApp and Desktop Application Group (DAG) in a single host pool to the same set of users. Doing so will cause a single user to have two user sessions in a single host pool. Users aren't supposed to have two active sessions at the same time in the same host pool using the same profile.", + "guid": "b384b7ed-1cdd-457e-a2cd-c8d4d55bc144", + "id": "C01.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#application-groups", "services": [ - "LoadBalancer", - "Cost" + "Storage", + "AVD" ], - "subcategory": "check Red Hat Licences if applicable", - "text": " this can be also put under AHUB if you already have licenses https://learn.microsoft.com/azure/virtual-machines/linux/azure-hybrid-benefit-linux?tabs=rhelpayg%2Crhelbyos%2CrhelEnablebyos%2Crhelcompliance" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Do not use the same Host Pool to offer both full desktops (DAG) and Remote Apps to the same set of users", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "a76af4a6-91e8-4839-ada4-6667e13c1056", - "id": "D04.01", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "There is a limit of 500 Application Groups that can be created in AVD for each Microsoft Entra ID (former Azure AD) tenant. The limit can be increased (see the companion link for details) but it is not recommended.", + "guid": "971cc4a4-b1f7-4c12-90e0-1ad96808f00c", + "id": "C01.07", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-virtual-desktop-service-limits", "services": [ - "Cost", - "AppSvc" + "Entra", + "AVD", + "ACR" ], - "subcategory": "Functions", - "text": "saving plans will provide 17% on select app service plans" + "severity": "Medium", + "subcategory": "Capacity Planning", + "text": "Estimate the number of Application Groups required across all Host Pools in the Microsoft Entra ID tenant", + "waf": "Reliability" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "75c1e945-b459-4837-bf7a-e7c6d3b475a5", - "id": "D05.01", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Applications are grouped under Application Groups as containers for publishing and assigning permissions: we recommend that you do not publish more than 50 applications per application group.", + "guid": "fa9f2895-473d-439b-ab8e-5a5cf92c7f32", + "id": "C01.08", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", "services": [ - "VM", - "Cost" + "AVD" ], - "subcategory": "planning", - "text": "consolidate reserved VM families with flexibility option (no more than 4-5 families)", - "training": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Estimate the number of Applications for each Application Group", + "waf": "Reliability" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "c7acbe49-bbe6-44dd-a9f2-e87778468d55", - "id": "D06.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "FSLogix is not required for Personal Host Pools since each VM is statically assigned to a single user, then no immediate needs for a roaming profile solution. In some usage scenarios FSLogix can help. For example, a VM can be re-assigned, or user moved to another desktop, or roaming profile can be used to save user profile in a different location for DR purposes.", + "guid": "38b19ab6-0693-4992-9394-5590883916ec", + "id": "C01.09", + "link": "https://learn.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type?tabs=azure#reassign-a-personal-desktop", "services": [ - "ARS", + "Storage", "VM", - "Cost" + "AVD" ], - "subcategory": "reservations/savings plans", - "text": "Utilize Azure Reserved Instances: This feature allows you to reserve VMs for a period of 1 or 3 years, providing significant cost savings compared to PAYG prices." + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Evaluate the usage of FSLogix for Personal Host Pools", + "waf": "Reliability" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "a785c6fe-96c9-46ad-a844-cf3b2b38c886", - "id": "D06.02", - "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Use the link provided to set a starting point for SKU decision, then validate using a performance test. Ensure a minimum of four cores for Production is selected per Session Host (multi-session)", + "guid": "e1112dbd-7ba0-412e-9b94-ef6e047d2ea2", + "id": "C01.10", + "link": "https://docs.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", "services": [ - "Cost" + "VM", + "AVD" ], - "subcategory": "reservations/savings plans", - "text": "plan for Azure Savings Plans for all the workloads that are dynamic and need maximum flexibility" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Run workload performance test to determine the best Azure VM SKU and size to use", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "ba2c0214-9901-44a5-b3ce-574dccbd9792", - "id": "D06.03", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "It is critical to check AVD capacity and limits reported in the referenced article. Additional limits and thresholds apply for network, compute, storage and service management. ", + "guid": "992b1cd6-d2f5-44b2-a769-e3a691e8838a", + "id": "C01.11", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", "services": [ - "Cost" + "Storage", + "AVD" ], - "subcategory": "reservations/savings plans", - "text": "plan for Azure Reservations for all the workloads that are less dynamic and won't change much" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Verify AVD scalability limits for the environment", + "waf": "Reliability" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "a6bcca2b-4fea-41db-b3dd-95d48c7c891d", - "id": "D07.01", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Host Pools with GPU require special configuration, please be sure to review the referenced article.", + "guid": "c936667e-13c0-4056-94b1-e945a459837e", + "id": "C01.12", + "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-vm-gpu", "services": [ - "Storage", - "Cost" + "AVD" ], - "subcategory": "reserve storage", - "text": "only larger disks can be reserved =>1TiB -" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Determine if Session Hosts will require GPU", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "cb1f7d57-59ae-4568-aa38-d4985e2213db", - "id": "D08.01", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Whenever is possible, it is recommended to leverage VM SKUs with Accelerated Networking feature. This feature does require specific VM SKU/size and OS versions, please see the list and requirement in the companion article.", + "guid": "b47a393a-0803-4272-a479-8b1578b219a4", + "id": "C01.13", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", "services": [ "VM", - "Cost" + "AVD" ], - "subcategory": "reserve VMs with normalized and rationalized sizes", - "text": "after the right-sizing optimization" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Use Azure VM SKUs able to leverage Accelerated Networking", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "d7bb012f-7b95-4e06-b158-e2ea3992c2de", - "id": "D09.01", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "For proper planning and deployment, it is important to assess the maximum number of concurrent and total users for each Host Pool. Additionally, users from different regions may require different Host Pools to ensure the best user experience.", + "guid": "bb91a33d-90ca-4e2c-a881-3706f7c0cb9f", + "id": "C02.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", "services": [ - "SQL", - "AzurePolicy", - "Cost" + "AVD" ], - "subcategory": "SQL Database AHUB", - "text": "check if applicable and enforce policy/change https://learn.microsoft.com/azure/azure-sql/azure-hybrid-benefit?view=azuresql&tabs=azure-portalhttps://learn.microsoft.com/azure/cost-management-billing/scope-level/create-sql-license-assignments?source=recommendations" + "severity": "Medium", + "subcategory": "Clients & Users", + "text": "Assess how many users will connect to AVD and from which regions", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "6e2065b3-a76a-4f4a-991e-8839ada46667", - "id": "D10.01", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "The dependencies on resources external to the AVD pool should be assessed and reviewed, for example Active Directory, external file shares or other storage, on-premises services and resources, network infrastructure components like VPN and or ExpressRoute, external services and 3rd-party components. For all these resources, latency from the AVD Host Pool needs to be evaluated and connectivity considered. Additionally, BCDR considerations need to be applied to these dependencies as well.", + "guid": "6abca2a4-fda1-4dbf-9dc9-5d48c7c791dc", + "id": "C02.02", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?toc=%2Fazure%2Fvirtual-desktop%2Ftoc.json&bc=%2Fazure%2Fvirtual-desktop%2Fbreadcrumb%2Ftoc.json", "services": [ - "SQL", - "VM", - "Cost" + "Storage", + "AVD", + "VPN", + "ExpressRoute" ], - "subcategory": "SQL Database Reservations", - "text": "the VM + licence part discount (ahub+3YRI) is around 70% discount" + "severity": "Medium", + "subcategory": "Clients & Users", + "text": "Assess external dependencies for each Host Pool", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "e13c1056-75c1-4e94-9b45-9837ff7ae7c6", - "id": "D11.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD offers a variety of client types (fat, thin, web) to connect over different platforms (Windows, MacOS, iOS, Android). Review limitations of each client and compare multiple options when possible.", + "guid": "a1f6d565-99e5-458b-a37d-4985e1112dbd", + "id": "C02.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/users/connect-windows", "services": [ - "Cost" + "AVD" ], - "subcategory": "tracking", - "text": "Make sure you Azure Reservations and Savings plans are close to 100% utilization or make the necessary changes to reach it." + "severity": "Low", + "subcategory": "Clients & Users", + "text": "Review user client OS used and AVD client type", + "waf": "Performance" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "d3b475a5-c7ac-4be4-abbe-64dd89f2e877", - "id": "D11.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Depending on the user locations, and AVD region deployment, users may have a non-optimal experience, hence is important to test as soon as possible in a small PoC environment. Run the 'Azure Virtual Desktop Experience Estimator' tool to select the best Azure region to deploy Host Pools. Beyond 150ms latency, user experience may be not optimal.", + "guid": "d2f54b29-769e-43a6-a1e8-838ac936667e", + "id": "C02.04", + "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", "services": [ - "AzurePolicy", - "Cost" + "AVD" ], - "subcategory": "tracking", - "text": "make sure that your reservations usage is close to 100%. If not, either enforce an allowed SKU policy or exchange the reservation" + "severity": "High", + "subcategory": "Clients & Users", + "text": "Run a PoC to validate end-to-end user experience and impact of network latency", + "waf": "Performance" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "78468d55-a785-4c6f-b96c-96ad8844cf3b", - "id": "E01.01", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "RDP settings can currently only be configured at the host pool level, not per user/group. If different settings are required for different set of users, it is recommended to create multiple Host Pools.", + "guid": "3b365a5c-7acb-4e48-abe5-4cd79f2e8776", + "id": "C02.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/customize-rdp-properties", "services": [ - "AzurePolicy", - "Cost" + "AVD" ], - "subcategory": "Automation", - "text": "plan and enforce a ON/OFF policy for production services, where possible" + "severity": "Low", + "subcategory": "Clients & Users", + "text": "Assess and document RDP settings for all user groups", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "2b38c886-ba2c-4021-9990-14a5d3ce574d", - "id": "E01.02", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD is a non-regional service, Host Pools can be created in any region, automatic redirection from closest front-end will happen automatically.", + "guid": "42e52f47-21d9-428c-8b1b-d521e44a29a9", + "id": "C03.01", + "link": "https://azure.microsoft.com/global-infrastructure/services/?products=virtual-desktop", "services": [ - "AzurePolicy", - "Cost" + "AVD" ], - "subcategory": "Automation", - "text": "plan and enforce a ON-DEMAND policy with auto-shutdown for non-production services, where possible" + "severity": "High", + "subcategory": "General", + "text": "Determine in which Azure regions AVD Host Pools will be deployed.", + "waf": "Performance" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "ccbd9792-a6bc-4ca2-a4fe-a1dbf3dd95d4", - "id": "E02.01", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD must store metadata to support the service; this is stored in the specified geography. However, this is independent of the regions where Host Pools are located.", + "guid": "bad37ead-53cc-47ce-8d7a-aab3571449ab", + "id": "C03.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/data-locations", "services": [ - "VM", - "Cost" + "AVD" ], - "subcategory": "Autoscale", - "text": "consider using a VMSS to match demand rather than flat sizing" + "severity": "Medium", + "subcategory": "General", + "text": "Determine metadata location for AVD service", + "waf": "Reliability" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "c1b1cd52-1e54-4a29-a9de-39ac0e7c28dc", - "id": "E02.02", - "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Check for specific VM SKUs, especially if you need GPU or high-specs SKUs, and eventually Azure NetApp Files if used.", + "guid": "8053d89e-89dc-47b3-9be2-a1a27f7a9e91", + "id": "C03.03", + "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "services": [ - "Cost", - "AKS" + "Storage", + "VM", + "AVD" ], - "subcategory": "Autoscale", - "text": "use AKS autoscaler to match your clusters usage (make sure the pods requirements match the scaler)" + "severity": "Low", + "subcategory": "General", + "text": "Check Azure quotas and availability for specific VM sizes and types in the selected regions", + "waf": "Reliability" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "93665720-2bff-4456-9b0d-934a359c363e", - "id": "E02.03", - "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "AD DCs in Azure are recommended (at least two in different AZ) to reduce latency for users logging into AVD session hosts, and eventually for Azure NetApp Files and AD integration. A DC need to be able to talk to DCs for ALL child domains. As alternative, on-premise connectivity must be used to reach AD DCs.", + "guid": "c14aea7e-65e8-4d9a-9aec-218e6436b073", + "id": "D01.01", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "services": [ - "Cost" + "Storage", + "VNet", + "AVD", + "Entra" ], - "subcategory": "Autoscale", - "text": "right-size PaaS service according to average use and accomodate spikes with auto or manual scaling" + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Create at least two Active Directory Domain Controllers (DCs) in Azure VNet environment close to AVD Host Pool", + "waf": "Reliability" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "7dd61623-a364-4a90-9eba-e38ead53cc7d", - "id": "E02.04", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", - "services": [ - "Cost" - ], - "subcategory": "Autoscale", - "text": "plan for demand shaping where applicable" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "e2e8aaab-3571-4549-ab91-53d89f89dc7b", - "id": "E02.05", - "services": [ - "Cost" - ], - "subcategory": "Autoscale", - "text": "consider implementing a service re-scaling logic within the application", - "training": "https://learn.microsoft.com/azure/cost-management-billing/savings-plan/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "44be3b1a-27f8-4b9e-a1be-1f38df03a822", - "id": "E03.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", - "services": [ - "Backup", - "Cost" - ], - "subcategory": "Backup", - "text": "Move recovery points to vault-archive where applicable (Validate)", - "training": "https://azure.microsoft.com/pricing/reservations/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "cd463cbb-bc8a-4c29-aebc-91a43da1dae2", - "id": "E04.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", - "services": [ - "LoadBalancer", - "VM", - "Cost" - ], - "subcategory": "databricks", - "text": "consider using Spot VMs with fallback where possibleconsider autotermination of clusters https://learn.microsoft.com/azure/databricks/clusters/cluster-config-best-practices#automatic-termination ", - "training": "https://andrewmatveychuk.com/how-to-audit-azure-hybrid-benefit-usage-with-azure-workbooks/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "cc881470-607c-41cc-a0e6-14658dd458e9", - "id": "E05.01", - "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", - "services": [ - "Cost" - ], - "subcategory": "Functions", - "text": "Functions - Reuse connections", - "training": "https://learn.microsoft.com/azure/cost-management-billing/reservations/reservation-apis?toc=%2Fazure%2Fcost-management-billing%2Ftoc.json" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "27139b82-1102-4dbd-9eaf-11e6f843e52f", - "id": "E05.02", - "link": "https://learn.microsoft.com/azure/automation/update-management/overview", - "services": [ - "Cost" - ], - "subcategory": "Functions", - "text": "functions -Cache data locally", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "4722d928-c1b1-4cd5-81e5-4a29b9de39ac", - "id": "E05.03", - "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Functions", - "text": "functions - Cold starts-Use the 'Run from package' functionality. This way, the code is downloaded as a single zip file. This can, for example, result in significant improvements with Javascript functions, which have a lot of node modules.Use language specific tools to reduce the package size, for example, tree shaking Javascript applications.", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "0e7c28dc-9366-4572-82bf-f4564b0d934a", - "id": "E05.04", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", - "services": [ - "Cost" - ], - "subcategory": "Functions", - "text": "Functions -Keep your functions warm", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "359c363e-7dd6-4162-9a36-4a907ebae38e", - "id": "E05.05", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [ - "Cost" - ], - "subcategory": "Functions", - "text": "when using autoscale with different functions, there might be one driving all the autoscale for all the resources - consider moving it to a separate consumption plan (and consider higher plan for CPU)" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "ad53cc7d-e2e8-4aaa-a357-1549ab9153d8", - "id": "E05.06", - "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", - "services": [ - "Cost" - ], - "subcategory": "Functions", - "text": "Function apps in a given plan are all scaled together, so any issues with scaling can affect all apps in the plan." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "9f89dc7b-44be-43b1-a27f-8b9e91be1f38", - "id": "E05.07", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", - "services": [ - "Cost" - ], - "subcategory": "Functions", - "text": "Am I billed for 'await time' ?This question is typically asked in the context of a C# function that does an async operation and waits for the result, e.g. await Task.Delay(1000) or await client.GetAsync('http://google.com'). The answer is yes - the GB second calculation is based on the start and end time of the function and the memory usage over that period. What actually happens over that time in terms of CPU activity is not factored into the calculation.One exception to this rule is if you are using durable functions. You are not billed for time spent at awaits in orchestrator functions.apply demand shaping techinques where possible (dev environments?) https://github.com/Azure-Samples/functions-csharp-premium-scaler" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "df03a822-cd46-43cb-abc8-ac299ebc91a4", - "id": "E06.01", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", - "services": [ - "Cost" - ], - "subcategory": "Networking", - "text": "evaluate your network topology against networking costs and where applicable reduce the egress and peering data" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "3da1dae2-cc88-4147-8607-c1cca0e61465", - "id": "E06.02", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", - "services": [ - "EventHubs", - "FrontDoor", - "Cost" - ], - "subcategory": "Networking", - "text": "Frontdoor - Turn off the default homepageIn the application settings of your App, set AzureWebJobsDisableHomepage to true. This will return a 204 (No Content) to the PoP so only header data is returned." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "8dd458e9-2713-49b8-8110-2dbd6eaf11e6", - "id": "E06.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", - "services": [ - "FrontDoor", - "Cost", - "AppSvc" - ], - "subcategory": "Networking", - "text": "Frontdoor -Route to something that returns nothingEither set up a Function, Function Proxy, or add a route in your WebApp that returns 200 (OK) and sends no or minimal content. The advantage of this is you will be able to log out when it is called." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "f843e52f-4722-4d92-ac1b-1cd521e54a29", - "id": "E07.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", - "services": [ - "Cost" - ], - "subcategory": "PaaS", - "text": "consider using free tiers where applicable for all non-production environments" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "b9de39ac-0e7c-428d-a936-657202bff456", - "id": "E08.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", - "services": [ - "Cost" - ], - "subcategory": "serverless", - "text": "using serverless patterns for spikes can help keeping costs down" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "7e31c67d-68cf-46a6-8a11-94956d697dc3", - "id": "E09.01", - "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Storage", - "text": "consider archiving tiers for less used data" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "a2ed27b2-d186-4f1a-8252-bddde68a487c", - "id": "E09.02", - "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Storage", - "text": "check disk sizes where the size does not match the tier (i.e. A 513 GiB disk will pay a P30 (1TiB) and consider resizing" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "dec4861b-c3bc-410a-b77e-26e4d5a3bec2", - "id": "E09.03", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Storage", - "text": "consider using standard SSD rather than Premium or Ultra where possible" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "c4e2436b-1336-4db5-9f17-960eee0bdf5c", - "id": "E09.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Storage", - "text": "For storage accounts, make sure that the chosen tier is not adding up transaction charges (it might be cheaper to move to the next tier)" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "c2efc5d7-61d4-41d2-900b-b47a393a040f", - "id": "E09.05", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", - "services": [ - "Storage", - "Cost", - "ASR" - ], - "subcategory": "Storage", - "text": "for ASR, consider using Standard SSD disks if the RPO/RTO and replication throughput allow it" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "d3294798-b118-48b2-a5a4-6ceb544451e1", - "id": "E10.01", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "storage", - "text": "storage accounts: check hot tier and/or GRS necessary" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "92d34429-3c76-4286-97a5-51c5b04e4f18", - "id": "E10.02", - "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "storage", - "text": "Disks -validate use of Premium SSD disks everywhere: for example, non-prod could swap to Standard SSD or On demand Premium SSD " - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "54387e5c-ed12-46cd-832a-f5b2fc6998a5", - "id": "E11.01", - "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", - "services": [ - "EventHubs", - "Monitor", - "Cost" - ], - "subcategory": "Synapse", - "text": "Create budgets to manage costs and create alerts that automatically notify stakeholders of spending anomalies and overspending risks." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "35e33789-7e31-4c67-b68c-f6a62a119495", - "id": "E11.02", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Synapse", - "text": "Export cost data to a storage account for additional data analysis." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "6d697dc3-a2ed-427b-8d18-6f1a1252bddd", - "id": "E11.03", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", - "services": [ - "SQL", - "Cost" - ], - "subcategory": "Synapse", - "text": "Control costs for a dedicated SQL pool by pausing the resource when it is not in use." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "e68a487c-dec4-4861-ac3b-c10ae77e26e4", - "id": "E11.04", - "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", - "services": [ - "Cost" - ], - "subcategory": "Synapse", - "text": "Enable the serverless Apache Spark automatic pause feature and set your timeout value accordingly." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "d5a3bec2-c4e2-4436-a133-6db55f17960e", - "id": "E11.05", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", - "services": [ - "Cost" - ], - "subcategory": "Synapse", - "text": "Create multiple Apache Spark pool definitions of various sizes." - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "ee0bdf5c-c2ef-4c5d-961d-41d2500bb47a", - "id": "E11.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", - "services": [ - "Cost" - ], - "subcategory": "Synapse", - "text": "Purchase Azure Synapse commit units (SCU) for one year with a pre-purchase plan to save on your Azure Synapse Analytics costs.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "393a040f-d329-4479-ab11-88b2c5a46ceb", - "id": "E12.01", - "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", - "services": [ - "VM", - "Cost" - ], - "subcategory": "VM", - "text": "Use SPOT VMs for interruptible jobs: These are VMs that can be bid on and purchased at a discounted price, providing a cost-effective solution for non-critical workloads.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "544451e1-92d3-4442-a3c7-628637a551c5", - "id": "E12.02", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", - "services": [ - "VM", - "Cost" - ], - "subcategory": "VM", - "text": "right-sizing all VMs" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "b04e4f18-5438-47e5-aed1-26cd032af5b2", - "id": "E12.03", - "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", - "services": [ - "VM", - "Cost" - ], - "subcategory": "VM", - "text": "swap VM sized with normalized and most recent sizes", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "fc6998a5-35e3-4378-a7e3-1c67d68cf6a6", - "id": "E12.04", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "services": [ - "VM", - "Monitor", - "Cost" - ], - "subcategory": "VM", - "text": "right-sizing VMs - start with monitoring usage below 5% and then work up to 40%", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "2a119495-6d69-47dc-9a2e-d27b2d186f1a", - "id": "E12.05", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "services": [ - "VM", - "Cost" - ], - "subcategory": "VM", - "text": "containerizing an application can improve VM density and save money on scaling it", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" - }, - { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD control plane does not offer a financially backed service level agreement. We strive to attain at least 99.9% availability for the Azure Virtual Desktop service URLs. The availability of the session host virtual machines in your subscription is covered by the Virtual Machines SLA. Dependent resources/services and infrastructure availability must be also considered to properly satisfy global high-availability requirements.", - "guid": "56c57ba5-9119-4bf8-b8f5-c586c7d9cdc1", - "id": "A01.01", - "link": "https://azure.microsoft.com/support/legal/sla/virtual-desktop/v1_0/", - "services": [ - "Subscriptions", - "AVD", - "VM", - "ASR" - ], - "severity": "High", - "subcategory": "Compute", - "text": "Determine the expected High Availability SLA for applications/desktops published through AVD", - "waf": "Reliability" - }, - { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "'Active-Active' model can be achieved with multiple host pools in different regions. A single Host Pool with VMs from different regions is not recommended. If multiple pools for same users will be used, the problem of how to synchronize/replicate user profiles must be solved. FSLogix Cloud Cache could be used, but need to be carefully reviewed and planned, or customers can decide to do not synchronize/replicate at all. 'Active-Passive' can be achieved using Azure Site Recovery (ASR) or on-demand Pool deployment with automated mechanism. For a detailed discussion on multi-region BCDR, please read the companion article in the 'More Info' column and this FSLogix related page: https://learn.microsoft.com/fslogix/concepts-container-recovery-business-continuity.", - "guid": "6acc076e-f9b1-441a-a989-579e76b897e7", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/azure-virtual-desktop-multi-region-bcdr", + "description": "Recommended to create a separate OU per Host Pool under a separate OU hierarchy. These OUs will contain machine accounts of AVD Session Hosts. ", + "guid": "6db55f57-9603-4334-adf9-cc23418db612", + "id": "D01.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", "services": [ - "AVD", - "Storage", - "VM", - "ASR" + "Entra", + "AVD" ], "severity": "Medium", - "subcategory": "Compute", - "text": "Assess Geo Disaster Recovery requirements for AVD Host Pools", - "waf": "Reliability" + "subcategory": "Active Directory", + "text": "Create a specific OU in Active Directory for each Host Pool", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Before approaching Azure Virtual Desktop BCDR planning and design, it is important to initially consider which applications consumed through AVD are critical. You may want to separate them from non-critical apps and use a separate Host Pool with a different disaster recovery approach and capabilities.", - "guid": "10a7da7b-e996-46e1-9d3c-4ada97cc3d13", - "id": "A01.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "description": "Carefully review, and potentially block/filter inheritance of GPOs to the OUs containing AVD Host Pools. ", + "guid": "7126504b-b47a-4393-a080-327294798b15", + "id": "D01.03", + "link": "https://docs.microsoft.com/previous-versions/windows/desktop/Policy/group-policy-hierarchy", "services": [ - "AVD", - "ASR" + "Entra", + "AVD" ], - "severity": "Low", - "subcategory": "Compute", - "text": "Separate critical applications in different AVD Host Pools", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Review Domain GPOs that will be applied to OU and impacting Host Pool Session Hosts functionalities", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Each Host Pool can be deployed using Availability Zones (AZ) or Availability Set (AS). To maximize resiliency, usage of AZ is recommended: at Host Pool creation time you can decide to spread Host Pool Session Hosts across all available AZ. Usage of AS will not protect from single datacenter failure, then should be used only in regions where AZ are not available. More details on AZ and AVD in the companion article. For a comparison between AZ and AS you can read here: https://learn.microsoft.com/azure/virtual-machines/availability.", - "guid": "25ab225c-6f4e-4168-9fdd-dea8a4b7cdeb", - "id": "A01.04", - "link": "https://techcommunity.microsoft.com/t5/azure-virtual-desktop-blog/announcing-general-availability-of-support-for-azure/ba-p/3636262", + "description": "If Active Directory Domain GPOs are used, it is recommended to configure FSLogix using the built-in provided GPO ADMX template referenced in the companion article in the 'More Info' column", + "guid": "2226a8e3-50a4-4ac3-8bd6-ee150553051f", + "id": "D01.04", + "link": "https://learn.microsoft.com/fslogix/how-to-use-group-policy-templates", "services": [ - "AVD", - "ACR", - "ASR" + "Entra", + "AVD" ], - "severity": "High", - "subcategory": "Compute", - "text": "Plan the best resiliency option for AVD Host Pool deployment", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Configure FSLogix settings using the built-in provided GPO ADMX template", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Azure Backup can be used to protect Host Pool VMs. For Pooled Pools, this is not necessary since should be stateless. Instead, this option can be considered for Personal Host Pools.", - "guid": "4c61fc3f-c14e-4ea6-b69e-8d9a3eec218e", - "id": "A01.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "description": "It is recommended to have a specific dedicated account with minimal permissions, and without the default 10 joins limitation. Review the companion article for more details.", + "guid": "347dc560-28a7-41ff-b1cd-15dd2f0d5e77", + "id": "D01.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#session-hosts", "services": [ - "AVD", "VM", - "ASR", - "Backup" + "AVD", + "Entra" ], "severity": "Medium", - "subcategory": "Compute", - "text": "Assess the requirement to backup AVD Session Host VMs", - "waf": "Reliability" + "subcategory": "Active Directory", + "text": "Create a dedicated user account with only permissions to join VM to the domain", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Even for Personal Pools, usage of Availability Zones, when available, is recommended. Three possible in-region DR strategies are possible, it is recommended to select the best one based on cost, RTO/RPO, and if it is really necessary to save the entire VM OS disk: (1) create each session host in a specific zone (AZ) and then use Azure Site Recovery (ASR) to replicate to a different zone. (2) Use Azure Backup to backup and restore the specific session host in a different AZ. (3) Create a new session host in a different AZ and rely on FSLogix and/or OneDrive to make data and settings available on the new machine. All options require administrator intervention for DR and direct user assignment at Host Pool level, then must be planned and configured in advance.", - "guid": "5da58639-ca3a-4961-890b-29663c5e10d", - "id": "A01.06", - "link": "https://learn.microsoft.com/azure/site-recovery/azure-to-azure-how-to-enable-zone-to-zone-disaster-recovery", + "description": "Avoid granting access per user, instead use AD groups and replicate them using Active Directory Connector (ADC) in Microsoft Entra ID (former Azure AD). ", + "guid": "2d41e361-1cc5-47b4-a4b1-410d43958a8c", + "id": "D01.06", + "link": "https://docs.microsoft.com/azure/virtual-desktop/manage-app-groups", "services": [ - "Cost", - "AVD", - "ASR", - "Backup", - "VM" + "Entra", + "AVD" ], "severity": "Medium", - "subcategory": "Compute", - "text": "Prepare a local DR strategy for Personal Host Pool Session Hosts", - "waf": "Reliability" + "subcategory": "Active Directory", + "text": "Create a domain user group for each set of users that will be granted access to each Host Pool Application Group (DAG or RAG)", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "If custom images are used to deploy AVD Host Pool VMs, it is important to ensure those artifacts are available in all regions where AVD is deployed. Azure Compute Gallery service can be used to replicate images across all regions where a Host Pool is deployed, with redundant storage and in multiple copies. Please be aware that the Azure Compute Gallery service isn't a global resource. For disaster recovery scenarios, the best practice is to have at least two galleries, in different regions.", - "guid": "dd2e0d5d-771d-441e-9610-cc57b4a4a141", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/virtual-machines/azure-compute-gallery", + "description": "If Azure Files Active Directory (AD) integration is used, as part of the configuration procedure, an AD account to represent the storage account (file share) will be created. You can choose to register as a computer account or service logon account, see FAQ for details. For computer accounts, there is a default password expiration age set in AD at 30 days. Similarly, the service logon account may have a default password expiration age set on the AD domain or Organizational Unit (OU). For both account types, we recommend you check the password expiration age configured in your AD environment and plan to update the password of your storage account identity of the AD account before the maximum password age. You can consider creating a new AD Organizational Unit (OU) in AD and disabling password expiration policy on computer accounts or service logon accounts accordingly.", + "guid": "2289b3d6-b57c-4fc6-9546-1e1a3e3453a3", + "id": "D01.07", + "link": "https://docs.microsoft.com/azure/storage/files/storage-files-identity-ad-ds-enable", "services": [ - "AVD", - "ACR", - "ASR", + "AzurePolicy", "Storage", - "VM" + "Entra", + "AVD" ], - "severity": "Low", - "subcategory": "Dependencies", - "text": "Plan for Golden Image cross-region availability", - "waf": "Reliability" + "severity": "High", + "subcategory": "Active Directory", + "text": "Review your organization password expiration policy for accounts used by Azure Files AD integration", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "If users of the AVD infrastructure need on-premises resource access, high availability of network infrastructure required to connect is also critical and should be considered. Resiliency of authentication infrastructure needs to be assessed and evaluated. BCDR aspects for dependent applications and other resources need to be considered to ensure availability in the secondary DR location.", - "guid": "fd339489-8c12-488b-9c6a-57cfb644451e", - "id": "A02.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "description": "You can configure this using Active Directory Connect (ADC) or Azure AD Domain Services (for hybrid or cloud organizations). Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", + "guid": "5119bf8e-8f58-4542-a7d9-cec166cd072a", + "id": "D01.08", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", "services": [ - "AVD", - "ASR" + "Entra", + "AVD" ], - "severity": "Medium", - "subcategory": "Dependencies", - "text": "Assess Infrastructure & Application dependencies ", + "severity": "High", + "subcategory": "Active Directory", + "text": "A Windows Server Active Directory forest/domain must be in sync with Microsoft Entra ID", "waf": "Reliability" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Not all data inside FSLogix user profiles may deserve protection from disaster. Additionally, if external storage is used, for example OneDrive or File Servers/Shares, what is remaining in the FSLogix profile is minimal and could be lost in some extreme circumstances. In other cases, data inside the profile can be rebuilt from other storages (for example Outlook Inbox in cached mode).", - "guid": "687ab077-adb5-49e5-a960-3334fdf8cc23", - "id": "A03.01", - "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt", + "description": "If Azure Files is used and pre-requisites can be satisfied, it is recommended to configure (Microsoft Entra ID) Kerberos authentication. This configuration will allow to store FSLogix profiles that can be accessed by hybrid user identities from Azure AD-joined session hosts without requiring network line-of-sight to domain controllers.", + "guid": "e777fd5e-c5f1-4d6e-8fa9-fc210b88e338", + "id": "D02.01", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-identity-auth-hybrid-identities-enable", "services": [ - "AVD", "Storage", - "ASR" + "Entra", + "AVD" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Assess which data need to be protected in the Profile and Office Containers", - "waf": "Reliability" + "subcategory": "Microsoft Entra ID", + "text": "Configure Azure Files share for Microsoft Entra ID (former Azure AD) Kerberos authentication on Microsoft Entra ID Joined scenario", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Preventing data loss for critical user data is important, first step is to assess which data need to be saved and protected. If using OneDrive or other external storage, saving user Profile and/or Office Containers data maybe not necessary. Appropriate mechanism must be considered to provide protection for critical user data. Azure Backup service can be used to protect Profile and Office Containers data when stored on Azure Files Standard and Premium tiers. Azure NetApp Files Snapshots and Policies can be used for Azure NetApp Files (all tiers).", - "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", - "id": "A03.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "description": "An Azure subscription must be parented to the same Microsoft Entra ID (former Azure AD) tenant, that contains a virtual network that either contains or is connected to the Windows Server Active Directory Domain Services or Microsoft Entra ID Domain Services instance.", + "guid": "6ceb5443-5125-4922-9442-93bb628537a5", + "id": "D03.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", "services": [ - "AzurePolicy", + "Entra", "AVD", - "ASR", - "Backup", - "Storage" + "VNet", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Build a backup protection strategy for Profile and Office Containers", + "severity": "High", + "subcategory": "Requirements", + "text": "A Microsoft Entra ID tenant must be available with at least one subscription linked", "waf": "Reliability" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "In AVD, multiple replication mechanisms and strategies can be used for user data residing in FSLogix containers: [Profile Pattern #1]: Native Azure storage replication mechanisms, for example Azure Files Standard GRS replication, Azure NetApp Files Cross Region Replication. Use Zone Replicated Storage (ZRS) or Geo replicated storage (GRS) for Azure Files is recommended. LRS with local-only resiliency can be used if no zone/region protection is required. NOTE: Azure Files Share Standard is LRS/ZRS/GRS, but with 100TB large support enabled only LRS/ZRS are supported. [Profile Pattern #2]: FSLogix Cloud Cache is built in automatic mechanism to replicate containers between different (up to 4) storage accounts. Cloud Cache should be used only when:(1) User Profile or Office containers data availability required high-availability SLA is critical and need to be resilient to region failure. (2) Selected storage option is not able to satisfy BCDR requirements. For example, with Azure File Share Premium tier, or Azure File Share Standard with Large File Support enabled, GRS is not available. (3) When replication between disparate storage is required. [Profile Pattern #3]: Only set up geo disaster recovery for application data and not for user data/profile containers: store important application data in separate storages, like OneDrive or other external storage with its own built-in DR mechanism.", - "guid": "9f7547c1-746d-4c56-868a-714435bd09dd", - "id": "A03.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "description": "Azure Virtual Desktop supports different types of identities depending on which configuration you choose. Please review the supported scenarios mentioned in the 'More Info' article and document the design decision accordingly in the 'Comment' column. Critically, external identities (B2B or B2C) are not supported. Be sure to review also the list of supported scenarios in https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios.", + "guid": "b4ce4781-7557-4a1f-8043-332ae199d44c", + "id": "D03.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication", "services": [ - "AVD", - "Storage", - "ASR" + "Entra", + "AVD" + ], + "severity": "High", + "subcategory": "Requirements", + "text": "Review and document your identity scenario", + "waf": "Security" + }, + { + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "Users need accounts that are in Microsoft Entra ID (former Azure AD). If you're also using AD DS or Azure AD Domain Services in your deployment of Azure Virtual Desktop, these accounts will need to be hybrid identities, which means the user accounts are synchronized. If you're using Microsoft Entra ID with AD DS, you'll need to configure Azure AD Connect to synchronize user identity data between AD DS and Microsoft Entra ID. If you're using Microsoft Entra ID with Azure AD Domain Services, user accounts are synchronized one way from Microsoft Entra ID to Azure AD Domain Services. This synchronization process is automatic. AVD also supports Microsoft Entra ID native accounts with some restrictions. External identities (B2B or B2C) are not supported.", + "guid": "f9b141a8-98a5-435e-9378-97e71ca7da7b", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "services": [ + "Entra", + "AVD" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Assess Profile Container storage replication requirements and resiliency for BCDR purpose", - "waf": "Reliability" + "subcategory": "Requirements", + "text": "Assess User Account types and requirements", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "For local disaster recovery, Azure Backup for Azure Files can be used. For cross-region geo disaster recovery: GRS for Azure Files is only available with standard SKU and no large share support, then not suitable in most customer scenarios. If geo-replication is required with Azure File Share Premium, replication with FSLogix Cloud Cache can be evaluated, or 'in-region' Availability Zone (AZ) only resiliency should be considered.", - "guid": "3d4f3537-c134-46dc-9602-7a71efe1bd05", - "id": "A03.04", - "link": "https://docs.microsoft.com/azure/backup/backup-afs", + "description": "AVD supports SSO using either Active Directory Federation Services (AD FS) or Microsoft Entra ID (former Azure AD) authentication. The latter is recommended, please check the requirements and limitation in the 'More Info' article. Using AD FS could be a viable choice if already present in the customer environment, it is not recommended to deploy a brand new ADFS infrastructure just for AVD SSO implementation.", + "guid": "5f9f680a-ba07-4429-bbf7-93d7071561f4", + "id": "D03.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication#single-sign-on-sso", "services": [ - "AVD", - "Storage", - "ASR", - "Backup" + "Entra", + "AVD" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Review Azure Files disaster recovery strategy", + "subcategory": "Requirements", + "text": "If Single-Sign On (SSO) is a requirement, review the supported scenarios and prerequisites", "waf": "Reliability" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "Zone Redundant Storage will maximize in-region resiliency for the user profile data. ZRS is supported for premium file shares through the 'FileStorage' storage account kind. ZRS is supported in standard general-purpose v2 storage accounts. Usage of zone redundant storage must be paired with zone redundant deployment of Session Hosts in each Host Pool. ", - "guid": "10d4e875-d502-4142-a795-f2b6eff34f88", - "id": "A03.05", - "link": "https://learn.microsoft.com/azure/storage/files/files-redundancy#zone-redundant-storage", + "description": "VMs can be Windows Active Directory (AD) domain-joined, Hybrid AD-joined, Microsoft Entra ID (former Azure AD) Joined or Azure AD Domain Services joined. Be sure to review supported scenarios, limitations and requirements from the referenced article.", + "guid": "ea962a15-9394-46da-a7cc-3923266b2258", + "id": "D03.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", "services": [ + "Entra", "AVD", - "Storage", - "ASR" + "VM" ], "severity": "High", - "subcategory": "Storage", - "text": "Use Zone Redundant Storage (ZRS) for Azure Files to maximize resiliency", - "waf": "Reliability" + "subcategory": "Requirements", + "text": "Select the proper AVD Session Host domain join type", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Identity", "checklist": "Azure Virtual Desktop Review", - "description": "For local disaster recovery, Azure NetApp Files (ANF) native backup is available. ANF is essentially locally redundant, then for cross-region geo disaster recovery it is necessary to use an additional mechanism that is Cross-Region Replication (CRR) https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering. Currently, ANF does not provide replication nor redundancy across different Availability Zones (AZ), only the possibility to select in which single AZ to place the ANF volume: https://learn.microsoft.com/azure/azure-netapp-files/manage-availability-zone-volume-placement.", - "guid": "23429db7-2281-4376-85cc-57b4a4b18142", - "id": "A03.06", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering", + "description": "Compare self-managed Windows Active Directory Domain Services, Microsoft Entra ID (former Azure AD), and managed Azure AD Domain Services (AAD-DS)", + "guid": "6f4a1651-bddd-4ea8-a487-cdeb4861bc3b", + "id": "D03.06", + "link": "https://docs.microsoft.com/azure/active-directory-domain-services/compare-identity-solutions", "services": [ - "ACR", - "AVD", - "ASR", - "Backup", - "Storage" + "Entra", + "AVD" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Review Azure NetApp Files disaster recovery strategy", + "severity": "Low", + "subcategory": "Requirements", + "text": "Before using Azure AD Domain Services (AAD-DS) for AVD, be sure to review the limitations.", "waf": "Reliability" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "Applications can be preinstalled in the golden image/s, can be attached using MSIX & AppAttach feature or distributed to the session hosts after host pool deployment using traditional software distribution methods.", - "guid": "86ba2802-1459-4014-95d3-8e5309ccbd97", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "description": "AVD provides administrative templates for Intune and Active Directory GPO. Using these templates it is possible to centrally control several AVD configuration settings: Graphics related data logging, Screen capture protection, RDP Shortpath for managed networks, Watermarking. See companion article in 'More Info' colum for details. NOTE: FSLogix has its own separate template.", + "guid": "5549524b-36c0-4f1a-892b-ab3ca78f5db2", + "id": "E01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/administrative-template", "services": [ - "AVD" + "Entra", + "AVD", + "Monitor" ], - "severity": "High", - "subcategory": "Golden Images", - "text": "Determine how applications will be deployed in AVD Host Pools", + "severity": "Low", + "subcategory": "Management", + "text": "Use built-in provided administrative templates for AVD settings configuration", "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "Multiple golden images can be required to support different OS versions and/or settings, different groups of applications that must be separated and cannot be included in a single image.", - "guid": "9266bcca-274f-4aa1-abf3-9d95d44c7c89", - "id": "B01.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "description": "Determine if a configuration management tool is already in place to manage Host Pool VM configuration after initial deployment, For example SCCM/SCOM, Intune/ConfigurationManager, 3rd-party solutions.", + "guid": "3334fdf9-1c23-4418-8b65-285269440b4b", + "id": "E01.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/management", "services": [ - "AVD" - ], - "severity": "Medium", - "subcategory": "Golden Images", - "text": "Estimate the number of golden images that will be required", + "VM", + "AVD", + "Monitor" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Plan AVD Session Hosts configuration management strategy", "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "Determine which Guest OS will be used to deploy each Host Pool: Windows 10 vs. Windows Server, Marketplace vs. Custom images", - "guid": "19ca1f6d-5315-4ae5-84ba-34d4585e2213", - "id": "B01.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#operating-systems-and-licenses", + "description": "We recommend using Microsoft Intune, if requirements can be satisfied, to manage your Azure Virtual Desktop environment. Review supported scenarios and requirements to enable Intune for AVD Session Host management in the referenced article in the “More Info” column. Document your choice in the 'Comment' column. In that article, review the different requirements and capabilities for single-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop and multi-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session AVD.", + "guid": "63a08be1-6004-4b4a-a79b-f3239faae113", + "id": "E01.03", + "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop", "services": [ - "AVD" + "AVD", + "Monitor" ], "severity": "Medium", - "subcategory": "Golden Images", - "text": "Determine which OS image/s you will use for Host Pool deployment", - "waf": "Reliability" + "subcategory": "Management", + "text": "Evaluate Intune for AVD Session Hosts management", + "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "Azure VM custom images can be created and stored in different ways: in an Azure Compute Gallery, as a managed image object or as a managed disk in the storage. The recommended way is to use Azure Compute Gallery.", - "guid": "5a2adb2c-3e23-426b-b225-ca44e1696fdd", - "id": "B01.04", - "link": "https://learn.microsoft.com/azure/virtual-machines/shared-image-galleries", + "description": "The scaling tool provides a low-cost automation option for customers who want to optimize their session host VM costs. You can use the scaling tool to schedule VMs to start and stop based on Peak and Off-Peak business hours, scale out VMs based on number of sessions per CPU core, scale in VMs during Off-Peak hours, leaving the minimum number of session host VMs running. Not available yet for Personal Host Pool type.", + "guid": "7138b820-102c-4e16-be30-1e6e872e52e3", + "id": "E01.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/autoscale-scenarios", "services": [ + "Cost", + "VM", "AVD", - "Storage", - "VM" + "Monitor" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Select the proper store for custom images", + "severity": "Medium", + "subcategory": "Management", + "text": "Assess the requirements for host pool auto-scaling capability", "waf": "Reliability" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "If custom images will be used, plan for an automated build process. If no pre-existing software factory exists, consider using Custom Image Templates and/or Azure Image Builder to automate the build process.", - "guid": "9bd7bb01-2f7b-495e-86e1-54e2aa359282", - "id": "B01.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-custom-image-templates", + "description": "Start VM On Connect lets you reduce costs by enabling end users to turn on their session host virtual machines (VMs) only when they need them. You can then turn off VMs when they're not needed. You can configure Start VM on Connect for personal or pooled host pools using the Azure portal or PowerShell. Start VM on Connect is a host pool wide setting.", + "guid": "55f612fe-f215-4f0d-a956-10e7dd96bcbc", + "id": "E01.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect", "services": [ - "AVD" + "Cost", + "VM", + "AVD", + "Monitor" ], "severity": "Low", - "subcategory": "Golden Images", - "text": "Design your build process for custom images", - "waf": "Operations" - }, - { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "There are some known best practices and recommendations for the golden image customization, be sure to check the referenced article.", - "guid": "deace4cb-1dec-44c6-90c3-fc14eebb36a3", - "id": "B01.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", - "services": [ - "AVD" - ], - "severity": "Medium", - "subcategory": "Golden Images", - "text": "If custom image will be used, check recommended best practices for AVD on how to build custom image", - "waf": "Operations" + "subcategory": "Management", + "text": "Consider the usage of Start VM on Connect for Personal Host Pools", + "waf": "Cost" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "FSLogix stack installed in AVD session hosts does not provide auto-update capability. For this reason, it is recommended to download the latest version of FSLogix and include in the golden image update process.", - "guid": "ed5c9027-dd1a-4343-86ca-52b199223186", - "id": "B01.07", - "link": "https://learn.microsoft.com/fslogix/how-to-install-fslogix", + "description": "'Start VM On Connect' provides a smart way to automatically start previously stopped Session Hosts but does not provide a mechanism to shut down when not in used. Administrators are encouraged to configure additional policies to sign users out of their sessions and run Azure automation scripts to de-allocate VMs. Users should be not allowed to shut down their Personal Hosts since will not be able to de-allocate Azure VMs, then billing will still be active with no cost reduction.", + "guid": "79a686ea-d971-4ea0-a9a8-1aea074c94cb", + "id": "E01.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect-faq#are-vms-automatically-deallocated-when-a-user-stops-using-them", "services": [ + "Monitor", + "VM", + "AzurePolicy", + "Cost", "AVD" ], - "severity": "High", - "subcategory": "Golden Images", - "text": "Include the latest version of FSLogix in the golden image update process", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Management", + "text": "Evaluate the implementation of an ad-hoc mechanism to shut down Personal AVD Session Hosts", + "waf": "Cost" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "This tool-set has been created to automatically apply setting referenced in white paper 'Optimizing Windows 10, version 2004 for a Virtual Desktop Infrastructure (VDI) role': https://docs.microsoft.com/windows-server/remote/remote-desktop-services/rds-vdi-recommendations-2004. Usage of the tool and/or optimizations mentioned in the white-paper should be considered. ", - "guid": "829e3fec-2183-4687-a017-7a2b5945bda4", - "id": "B01.08", - "link": "https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool", + "description": "Azure Virtual Desktop billing is mainly based on cost associated to compute, networking and storage resources consumed by Host Pools. In addition to this, costs can be generated by dependent resources, for example VPN or ExpressRoute or vWAN, Active Directory Domain Controllers, DNS, etc. There is no direct cost associated to AVD objects like workspaces, host pools or application groups. To make AVD associated costs more evident and grouped by Host Pool, it is recommended to use 'cm-resource-parent' tag. ", + "guid": "51bcafca-476a-48fa-9b91-9645a7679f20", + "id": "E01.07", + "link": "https://learn.microsoft.com/azure/virtual-desktop/tag-virtual-desktop-resources", "services": [ + "DNS", + "Storage", + "VWAN", + "Monitor", + "Cost", "AVD", - "RBAC" + "VPN", + "ExpressRoute" ], "severity": "Low", - "subcategory": "Golden Images", - "text": "Evaluate the usage of Virtual-Desktop-Optimization-Tool", - "waf": "Performance" + "subcategory": "Management", + "text": "Review and adopt suggested Azure Tags for Azure Virtual Desktop", + "waf": "Cost" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "If OneDrive is used and included in a golden image, be sure to follow the configuration procedure reported in the companion article in the 'More Info' section. Not in scope in this AVD checklist, but OneDrive optimizations like 'Known Folder Redirection' and 'Files On-Demand' should be evaluated used to reduce the space used in FSLogix profiles and provide a better user experience. OneDrive today is not supported for Remote Apps.", - "guid": "e3d3e084-4276-4d4b-bc01-5bcf219e4a1e", - "id": "B01.09", - "link": "https://learn.microsoft.com/azure/virtual-desktop/install-office-on-wvd-master-image#install-onedrive-in-per-machine-mode", + "description": "Azure Advisor analyzes your configurations and telemetry to offer personalized recommendations to solve common problems. With these recommendations, you can optimize your Azure resources for reliability, security, operational excellence, performance, and cost.", + "guid": "611dd68c-5a4b-4252-8e44-a59a9c2399c4", + "id": "E01.08", + "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-advisor-recommendations", "services": [ + "Cost", + "Entra", "AVD", - "Storage" + "Monitor" ], "severity": "Low", - "subcategory": "Golden Images", - "text": "Determine if Microsoft OneDrive will be part of AVD deployment", + "subcategory": "Management", + "text": "Periodically check Azure Advisor recommendations for AVD", "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "Be sure to review the requirements and configuration procedure contained in the companion article in the 'More Info' column. Since Teams automatic updates will be disabled, it is recommended to check and include Teams latest version in the golden image update process.", - "guid": "b5887953-5d22-4788-9d30-b66c67be5951", - "id": "B01.10", - "link": "https://learn.microsoft.com/azure/virtual-desktop/teams-on-AVD", + "description": "Customers have several options: Microsoft Configuration Manager, this article explains how to automatically apply updates to a Azure Virtual Desktop session hosts running Windows 10/11: https://learn.microsoft.com/azure/virtual-desktop/configure-automatic-updates, Microsoft Intune: https://docs.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session, Azure Update Management and WSUS for Windows Server OS only (client OS not supported: https://learn.microsoft.com/azure/automation/update-management/operating-system-requirements), 3rd Party tools. Outside an emergency security patching situation, it is recommended to move away from an 'in-place' update strategy patching strategy and adopt a re-imaging approach.", + "guid": "04722da2-9c2b-41cd-922f-54b29bade3aa", + "id": "E01.09", + "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop-multi-session", "services": [ - "AVD" + "AVD", + "Monitor" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Determine if Microsoft Teams will be part of AVD deployment", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Management", + "text": "Plan for a Session Host emergency patching and update strategy", + "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "AVD can support users with different language and localization requirements in the same host pool. This can be done customizing golden images to ensure users can select whichever language they need. The procedure to configure additional language packs in Windows 11 is documented in the reference article.", - "guid": "7c336f3b-822a-498e-8cd1-667d1150df4a", - "id": "B01.11", - "link": "https://learn.microsoft.com/azure/virtual-desktop/windows-11-language-packs", + "description": "The Scheduled Agent Updates feature lets you create up to two maintenance windows per Host Pool to update AVD components at a convenient time. It is recommended to specify maintenance windows then upgrading Session Hosts will not happen during peak business hours. Scheduled Agent Updates is disabled by default. This means that, unless you enable this setting, the agent can get updated at any time by the agent update flighting service.", + "guid": "c067939b-e5ca-4698-b9ce-3bd91843e73f", + "id": "E01.10", + "link": "https://learn.microsoft.com/azure/virtual-desktop/scheduled-agent-updates", "services": [ - "AVD" + "AVD", + "Monitor" ], "severity": "Low", - "subcategory": "Golden Images", - "text": "Assess the requirement to support multiple languages", + "subcategory": "Management", + "text": "Configure the Scheduled Agent Updates feature", "waf": "Reliability" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "It is highly recommended to use separate storage accounts/shares to store MSIX packages. If necessary, storage can scale out independently and not being impacted by profile I/O activities. Azure offers multiple storage options that can be used for MISX app attach. We recommend using Azure Files or Azure NetApp Files as those options offer the best value between cost and management overhead. ", - "guid": "90083845-c587-4cb3-a1ec-16a1d076ef9f", - "id": "B02.01", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "description": "Host pools are a collection of one or more identical virtual machines within Azure Virtual Desktop environment. We highly recommend you create a validation host pool where service updates are applied first. This allows you to monitor service updates before the service applies them to your standard or non-validation environment.", + "guid": "d1e8c38e-c936-4667-913c-005674b1e944", + "id": "E01.11", + "link": "https://docs.microsoft.com/azure/virtual-desktop/create-validation-host-pool", "services": [ + "VM", "AVD", - "Storage", - "Cost" + "Monitor" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Do not use the same storage account/share as FSLogix profiles", - "waf": "Performance" + "subcategory": "Management", + "text": "Create a validation (canary) Host Pool", + "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "In the referenced article, we reported few but important performance considerations for MSIX usage in AVD context, be sure to carefully review.", - "guid": "241addce-5793-477b-adb3-751ab2ac1fad", - "id": "B02.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "description": "An AVD Host Pool can be deployed in several ways: Azure Portal, ARM templates, Azure CLI tool, Powershell, manual VM creation with registration token, Terraform, 3rd-party tools. It is important to adopt proper method/s to support automatic deployment through automation and CI/CD tools.", + "guid": "a459c373-e7ed-4616-83b3-65a917ecbe48", + "id": "E01.12", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-platform-automation-and-devops", "services": [ - "AVD" + "VM", + "AVD", + "Monitor" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Review performance considerations for MSIX", - "waf": "Performance" + "subcategory": "Management", + "text": "Determine Host Pool deployment strategy", + "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "MSIX app attach requires read-only permissions to access the file share. If you're storing your MSIX applications in Azure Files, then for your session hosts, you'll need to assign all session host VMs both storage account role-based access control (RBAC) and file share New Technology File System (NTFS) permissions on the share.", - "guid": "66e15d4d-5a2a-4db2-a3e2-326bf225ca41", - "id": "B02.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "description": "After you register a VM to a host pool within the Azure Virtual Desktop service, the agent regularly refreshes the VM's token whenever the VM is active. The certificate for the registration token is valid for 90 days. Because of this 90-day limit, we recommend VMs to be online for 20 minutes every 90 days so that the machine can refresh its tokens and update the agent and side-by-side stack components.", + "guid": "ebe54cd7-df2e-48bb-ac35-81559bb9153e", + "id": "E01.13", + "link": "https://docs.microsoft.com/azure/virtual-desktop/faq", "services": [ - "AVD", - "RBAC", "VM", - "Storage" + "AVD", + "Monitor" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Check proper session host permissions for MSIX share", - "waf": "Security" + "subcategory": "Management", + "text": "Turn on Session Host VMs at least every 90 days for token refresh", + "waf": "Operations" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "3rd-party software vendor must provide a MSIX package, it is not recommended for customer to attempt the conversion procedure without proper support from the application owner.", - "guid": "bd362caa-ab79-4b19-adab-81932c9fc9d1", - "id": "B02.04", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "description": "Azure Virtual Desktop Insights is a dashboard built on Azure Monitor Workbooks that helps IT professionals understand their Azure Virtual Desktop environments. Read the referenced article to learn how to set up Azure Monitor for Azure Virtual Desktop to monitor your AVD environments.", + "guid": "63cfff1c-ac59-49ef-8d5a-83dd4de36c1c", + "id": "E02.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/insights", "services": [ - "AVD" + "AVD", + "Monitor" ], - "severity": "Low", - "subcategory": "MSIX & AppAttach", - "text": "MSIX packages for 3rd-party applications", - "waf": "Cost" + "severity": "High", + "subcategory": "Monitoring", + "text": "Enable monitoring for AVD", + "waf": "Reliability" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "MSIX app attach doesn't support auto-update for MSIX applications, so they should be disabled.", - "guid": "bb88037f-5e6b-4fbb-aed5-03547cc447e8", - "id": "B02.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "description": "Azure Virtual Desktop uses Azure Monitor and Log Analytics for monitoring and alerts like many other Azure services. This lets admins identify issues through a single interface. The service creates activity logs for both user and administrative actions. Each activity log falls under the following categories: Management, Feed, Connections, Host Registration, Errors, Checkpoints. ", + "guid": "81770afb-c4c0-4e43-a186-58d2857ed671", + "id": "E02.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics", "services": [ - "AVD" + "VM", + "AVD", + "Monitor" ], - "severity": "Low", - "subcategory": "MSIX & AppAttach", - "text": "Disable auto-update for MSIX packages", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Enable diagnostic settings for Workspaces, Host Pools, Application Groups and Host VMs to Log Analytics workspace", + "waf": "Reliability" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "In order to leverage MSIX & App Attach, guest OS image for AVD Host pool must be Windows 10/11 Enterprise or Windows 10/11 Enterprise Multi-session, version 2004 or later.", - "guid": "26128a71-f0f1-4cac-9d9e-f1d5e832e42e", - "id": "B02.06", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "description": "See the referenced article and this additional one to setup proper monitoring and alerting for storage: https://docs.microsoft.com/azure/storage/files/storage-troubleshooting-files-performance. ", + "guid": "2463cffe-179c-4599-be0d-5973dd4ce32c", + "id": "E02.03", + "link": "https://docs.microsoft.com/azure/storage/files/storage-files-monitoring?tabs=azure-portal", "services": [ - "AVD" + "Storage", + "AVD", + "Monitor" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Review operating systems support", + "subcategory": "Monitoring", + "text": "Create alerts on the profile storage to be alerted in case of high usage and throttling", "waf": "Reliability" }, { - "category": "Compute", + "category": "Monitoring and Management", "checklist": "Azure Virtual Desktop Review", - "description": "Once selected the VM SKU that will be used for Host Pool deployment, it is recommended to use Gen2 type of the SKU for higher security and improved capabilities.", - "guid": "e4633254-3185-40a1-b120-bd563a1c8e9d", - "id": "B03.01", - "link": "https://docs.microsoft.com/azure/virtual-machines/generation-2", + "description": "You can use Azure Service Health to monitor service issues and health advisories for Azure Virtual Desktop. Azure Service Health can notify you with different types of alerts (for example, email or SMS), help you understand the effect of an issue, and keep you updated as the issue resolves.", + "guid": "18813706-f7c4-4c0d-9e51-4548d2457ed6", + "id": "E02.04", + "link": "https://docs.microsoft.com/azure/virtual-desktop/set-up-service-alerts", "services": [ "AVD", - "VM" + "Monitor" ], "severity": "Medium", - "subcategory": "Session Host", - "text": "Evaluate the usage of Gen2 VM for Host Pool deployment", - "waf": "Performance" + "subcategory": "Monitoring", + "text": "Configure Azure Service Health for AVD alerts ", + "waf": "Reliability" }, { - "category": "Compute", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "MMR redirects the media content from Session Host to your local machine for faster processing and rendering. It only works when you play media content on Microsoft Edge or Google Chrome. See linked URL for more details.", - "guid": "adecb27f-dc40-40f5-aca2-0090f633b1c9", - "id": "B03.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/multimedia-redirection", + "description": "If required to connect to on-premises environment, assess the current connectivity option or plan for the required connectivity (ExpressRoute, Azure S2S or 3rd-party NVA VPN). ", + "guid": "dd399cfd-7b28-4dc8-9555-6202bfe4563b", + "id": "F01.01", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", "services": [ - "AVD" + "AVD", + "NVA", + "VPN", + "ExpressRoute" ], - "severity": "Low", - "subcategory": "Session Host", - "text": "Consider using MMR (MultiMedia Redirection) to get better video performance on browser", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Networking", + "text": "Determine if hybrid connectivity is required to connect to on-premises environment", + "waf": "Reliability" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "A host pool is a collection of Azure virtual machines that register to Azure Virtual Desktop as session hosts. A host pool can be one of two types: Personal and Pooled. Which type to use, and how many, is a key design decision that must be documented and validated. See companion article in 'More Info' column for more details.", - "guid": "8468c55a-775c-46ee-a5b8-6ad8844ce3b2", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology#host-pools", + "description": "AVD Host Pools can be deployed in either Azure Virtual WAN or traditional 'Hub & Spoke' network topologies. It is recommended to deploy each Host Pool in a separate 'spoke' VNet, using 'hub' is not recommended.", + "guid": "c8639648-a652-4d6c-85e5-02965388e5de", + "id": "F01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-network-topology-and-connectivity", "services": [ + "VNet", "AVD", - "VM" + "VWAN" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Determine the Host Pool type to use", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Networking", + "text": "Determine Azure Virtual Network (VNet) placement for each AVD Host Pool", + "waf": "Performance" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "Use your design criteria to determine the number of Host Pools to deploy. This will be based on factors such as different OS images, multi-region support, guest VM hardware differences (such as GPU support or no), different user expectations and uptime requirements (examples might be 'Executives', 'Office Workers', 'Developers', etc.), and Host Pool RDP settings (such as drive redirection support). These will determine the number of host pools as well as how many hosts will be in each pool.", - "guid": "4e98495f-d3c0-4af2-aa59-a793395a32a7", - "id": "C01.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#host-pools", + "description": "Evaluate the bandwidth requirements, ensure VPN/ER bandwidth will be enough, ensure proper routing and firewall rules are in place, test end-to-end latency. ", + "guid": "d227dd14-2b06-4c21-a799-9a646f4389a7", + "id": "F01.03", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", "services": [ "AVD", - "VM" + "VPN" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Estimate the number of different Host Pools to deploy ", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Networking", + "text": "Assess which on-premises resources are required from AVD Host Pools", + "waf": "Reliability" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "Confirm that the difference between automatic and direct assignment is well understood and the selected option is appropriate for the scenario in question. Automatic is the default setting.", - "guid": "b38b875b-a1cf-4204-a901-3a5d3ce474db", - "id": "C01.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type", + "description": "Several options are available. You can use Azure Firewall or equivalent 3rd-party NVA, Network Security Group (NSG) and/or Proxy servers. NSG is not able to enable/disable by URL, only ports and protocols. Proxy should be used only as explicit setting in user browser. Details on using Azure Firewall Premium with AVD are reported in the companion article in the 'More Info' column. Be sure to allow proper access to required AVD URLs. Forced Tunneling to on-premises is not recommended.", + "guid": "fc4972cd-3cd2-41bf-9703-6e5e6b4bed3d", + "id": "F01.04", + "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", "services": [ - "AVD" + "Firewall", + "AVD", + "NVA", + "VNet" ], - "severity": "Low", - "subcategory": "Capacity Planning", - "text": "For Personal Host Pool type, select the proper assignment type", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Networking", + "text": "Need to control/restrict Internet outbound traffic for AVD hosts?", + "waf": "Security" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "Check which one to use and available options, autoscale ignores existing load-balancing algorithms.", - "guid": "cbd8682a-6abc-4a2a-9fda-1dbf3dc95d48", - "id": "C01.04", - "link": "https://docs.microsoft.com/azure/virtual-desktop/host-pool-load-balancing", + "description": "Required URLs for AVD control plane access by session hosts are documented here: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list. A check tool is available to verify connectivity from the session hosts: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list#required-url-check-tool. Forced Tunneling to on-premises is not recommended.", + "guid": "65c7acbe-45bb-4e60-ad89-f2e87778424d", + "id": "F01.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/safe-url-list", "services": [ "AVD" ], - "severity": "Low", - "subcategory": "Capacity Planning", - "text": "For Pooled Host Pool type, select the best load balancing method", - "waf": "Performance" + "severity": "High", + "subcategory": "Networking", + "text": "Ensure AVD control plane endpoints are accessible", + "waf": "Reliability" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "The number of cores increase, the system's synchronization overhead also increases. Especially for multiple user's sign-in simultaneously. Make sure not to use a VM that is too large for the session host", - "guid": "b3724959-4943-4577-a3a9-e10ff6345f24", - "id": "C01.05", - "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "description": "Consider the usage of Azure Defender Endpoint or similar 3rd-party agents to control user web navigation, see the Security section for more details.", + "guid": "73676ae4-6691-4e88-95ad-a42223e13810", + "id": "F01.06", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/onboard-windows-multi-session-device?view=o365-worldwide", "services": [ - "AVD", - "VM" + "Defender", + "AVD" ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "For Pooled Host Pool type, VMs shouldn't have more than 32 cores", - "waf": "Performance" + "subcategory": "Networking", + "text": "Need to control/restrict Internet outbound traffic only for users on AVD hosts? ", + "waf": "Security" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "AVD does not support assigning both the RemoteApp and Desktop Application Group (DAG) in a single host pool to the same set of users. Doing so will cause a single user to have two user sessions in a single host pool. Users aren't supposed to have two active sessions at the same time in the same host pool using the same profile.", - "guid": "b384b7ed-1cdd-457e-a2cd-c8d4d55bc144", - "id": "C01.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#application-groups", + "description": "Custom UDR and NSG can be applied to AVD Host Pool subnets, for example to redirect to Azure Firewall or NVA, or to filter/block network traffic. In this case is recommended to carefully review to ensure optimal path for outbound traffic to AVD control plane is used. Service Tags can now be used with UDR and NSG, then AVD management plane traffic can be easily allowed: https://learn.microsoft.com/azure/virtual-desktop/safe-url-list.", + "guid": "523181a9-4174-4158-93ff-7ae7c6d37431", + "id": "F01.07", + "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", "services": [ + "VNet", "AVD", - "Storage" + "NVA", + "Firewall" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Do not use the same Host Pool to offer both full desktops (DAG) and Remote Apps to the same set of users", + "severity": "Low", + "subcategory": "Networking", + "text": "Review custom UDR and NSG for AVD Host Pool subnets", "waf": "Security" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "There is a limit of 500 Application Groups that can be created in AVD for each Microsoft Entra ID (former Azure AD) tenant. The limit can be increased (see the companion link for details) but it is not recommended.", - "guid": "971cc4a4-b1f7-4c12-90e0-1ad96808f00c", - "id": "C01.07", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-virtual-desktop-service-limits", + "description": "Network traffic from AVD Session Host VMs to AVD control plane should be as direct as possible. Redirecting this traffic through a Proxy or Firewall with deep packet inspection and/or SSL termination could cause serious issues and bad customer experience. It is recommended to bypass Proxy and Firewall just for the AVD control plane. User generated traffic surfing the web instead, should be filtered by Firewall and/or redirected to a Proxy. For details and guidelines, please see the companion article in the 'More Info' column.", + "guid": "cc6edca0-aeca-4566-9e92-cf246f1465af", + "id": "F01.08", + "link": "https://learn.microsoft.com/azure/virtual-desktop/proxy-server-support", "services": [ - "Entra", - "AVD", - "ACR" + "VM", + "AVD" ], - "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Estimate the number of Application Groups required across all Host Pools in the Microsoft Entra ID tenant", + "severity": "High", + "subcategory": "Networking", + "text": "Do not use Proxy servers, SSL termination and Deep Packet Inspection for AVD control plane traffic", "waf": "Reliability" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "Applications are grouped under Application Groups as containers for publishing and assigning permissions: we recommend that you do not publish more than 50 applications per application group.", - "guid": "fa9f2895-473d-439b-ab8e-5a5cf92c7f32", - "id": "C01.08", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", + "description": "It is recommended to assess and review networking bandwidth requirements for users, based on the specific workload type. The referenced article provide general estimations and recommendations, but specific measure are required for proper sizing. ", + "guid": "516785c6-fa96-4c96-ad88-408f372734c8", + "id": "F01.09", + "link": "https://learn.microsoft.com/azure/virtual-desktop/rdp-bandwidth", "services": [ + "VM", "AVD" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Estimate the number of Applications for each Application Group", - "waf": "Reliability" + "subcategory": "Networking", + "text": "Check the network bandwidth required for each user and in total for the VM SKU", + "waf": "Performance" }, - { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "FSLogix is not required for Personal Host Pools since each VM is statically assigned to a single user, then no immediate needs for a roaming profile solution. In some usage scenarios FSLogix can help. For example, a VM can be re-assigned, or user moved to another desktop, or roaming profile can be used to save user profile in a different location for DR purposes.", - "guid": "38b19ab6-0693-4992-9394-5590883916ec", - "id": "C01.09", - "link": "https://learn.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type?tabs=azure#reassign-a-personal-desktop", + { + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "If Azure Files SMB share will be used to store user profiles via FSLogix, the usage of Private Endpoint (PE) for private access to the storage is recommended. AVD Session Hosts will access the storage using a private IP in the same VNet, a separate subnet is recommended. This feature has an additional cost that must be evaluated. If PE will not be used, at least Service Endpoint is recommended (no cost associated).", + "guid": "ec27d589-9178-426d-8df2-ff60020f30a6", + "id": "F01.10", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-networking-endpoints", "services": [ - "AVD", "Storage", - "VM" + "PrivateLink", + "Cost", + "VNet", + "AVD" ], - "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Evaluate the usage of FSLogix for Personal Host Pools", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Networking", + "text": "Evaluate usage Private Endpoint for Azure Files share", + "waf": "Security" }, { - "category": "Foundation", + "category": "Networking", "checklist": "Azure Virtual Desktop Review", - "description": "Use the link provided to set a starting point for SKU decision, then validate using a performance test. Ensure a minimum of four cores for Production is selected per Session Host (multi-session)", - "guid": "e1112dbd-7ba0-412e-9b94-ef6e047d2ea2", - "id": "C01.10", - "link": "https://docs.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "description": "Connections to Azure Virtual Desktop can use TCP or UDP. RDP Shortpath is a feature of AVD that establishes a direct UDP-based transport between a supported Windows Remote Desktop client and session host. if clients have line of sight to AVD session hosts from internal network (VPN usage is not recommended), this feature can provide lower latency and best performances as explained in https://learn.microsoft.com/azure/virtual-desktop/rdp-shortpath?tabs=managed-networks#key-benefits.", + "guid": "b2074747-d01a-4f61-b1aa-92ad793d9ff4", + "id": "F01.11", + "link": "https://docs.microsoft.com/azure/virtual-desktop/shortpath", "services": [ "AVD", - "VM" + "VPN" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Run workload performance test to determine the best Azure VM SKU and size to use", + "severity": "Medium", + "subcategory": "Networking", + "text": "Evaluate usage of RDP ShortPath for clients connecting from managed internal networks", "waf": "Performance" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "It is critical to check AVD capacity and limits reported in the referenced article. Additional limits and thresholds apply for network, compute, storage and service management. ", - "guid": "992b1cd6-d2f5-44b2-a769-e3a691e8838a", - "id": "C01.11", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", + "description": "Security mechanisms provided by GPO should be used, if available. For example, it is possible to impose desktop screen lock and idle session disconnection time. Existing GPOs applied to on-premises environment should be reviewed and eventually applied also to secure also AVD Hosts when joined to the domain.", + "guid": "a135e337-897e-431c-97d6-8cb6a22ac19f", + "id": "G01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#establish-maximum-inactive-time-and-disconnection-policies", "services": [ - "AVD", - "Storage" + "AVD" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Verify AVD scalability limits for the environment", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Review Active Directory GPO to secure RDP sessions", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "Host Pools with GPU require special configuration, please be sure to review the referenced article.", - "guid": "c936667e-13c0-4056-94b1-e945a459837e", - "id": "C01.12", - "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-vm-gpu", + "description": "Microsoft Defender for Endpoint supports Azure Virtual Desktop for Windows 10/11 Enterprise multi-session. Check article for onboarding non-persistent virtual desktop infrastructure (VDI) devices: https://docs.microsoft.com/windows/security/threat-protection/microsoft-defender-atp/configure-endpoints-vdi", + "guid": "b1172576-9ef6-4691-a483-5ac932223ece", + "id": "G02.01", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/deployment-vdi-microsoft-defender-antivirus", "services": [ + "Defender", "AVD" ], - "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Determine if Session Hosts will require GPU", - "waf": "Performance" + "severity": "High", + "subcategory": "Host Configuration", + "text": "Ensure anti-virus and anti-malware solutions are used", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "Whenever is possible, it is recommended to leverage VM SKUs with Accelerated Networking feature. This feature does require specific VM SKU/size and OS versions, please see the list and requirement in the companion article.", - "guid": "b47a393a-0803-4272-a479-8b1578b219a4", - "id": "C01.13", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", + "description": "Disks in Azure are already encrypted at rest by default with Microsoft managed keys. Host VM OS disk encryption is possible and supported using Azure Disk Encryption (ADE - BitLocker) and Disk Encryption Set (DES - Server Side Encryption), the latter is recommended. Encryption of FSLogix storage using Azure Files can be done using SSE on Azure Storage. For OneDrive encryption, see this article: https://docs.microsoft.com/compliance/assurance/assurance-encryption-for-microsoft-365-services.", + "guid": "0fd32907-98bc-4178-adc5-a06ca7144351", + "id": "G02.02", + "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", "services": [ - "AVD", - "VM" + "AKV", + "Storage", + "VM", + "AVD" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Use Azure VM SKUs able to leverage Accelerated Networking", - "waf": "Performance" + "subcategory": "Host Configuration", + "text": "Assess disk encryption requirements for AVD Session Hosts", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "For proper planning and deployment, it is important to assess the maximum number of concurrent and total users for each Host Pool. Additionally, users from different regions may require different Host Pools to ensure the best user experience.", - "guid": "bb91a33d-90ca-4e2c-a881-3706f7c0cb9f", - "id": "C02.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", + "description": "Trusted launch are Gen2 Azure VMs with enhanced security features aimed to protect against “bottom of the stack” threats through attack vectors such as rootkits, boot kits, and kernel-level malware. Recommended to enable and leverage Secure Boot, Virtual TPM (vTPM) and Integrity Monitoring.", + "guid": "36a5a67f-bb9e-4d5b-9547-8c4479816b28", + "id": "G02.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#azure-virtual-desktop-support-for-trusted-launch", "services": [ - "AVD" + "VM", + "AVD", + "Monitor" ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Assess how many users will connect to AVD and from which regions", - "waf": "Performance" + "subcategory": "Host Configuration", + "text": "Enable Trusted launch in Azure Gen2 VM Session Hosts", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "The dependencies on resources external to the AVD pool should be assessed and reviewed, for example Active Directory, external file shares or other storage, on-premises services and resources, network infrastructure components like VPN and or ExpressRoute, external services and 3rd-party components. For all these resources, latency from the AVD Host Pool needs to be evaluated and connectivity considered. Additionally, BCDR considerations need to be applied to these dependencies as well.", - "guid": "6abca2a4-fda1-4dbf-9dc9-5d48c7c791dc", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?toc=%2Fazure%2Fvirtual-desktop%2Ftoc.json&bc=%2Fazure%2Fvirtual-desktop%2Fbreadcrumb%2Ftoc.json", + "description": "Trusted Launch and Gen2 VM are not only security and performance enhancing features but also system requirements for Windows 11. When building an AVD environment based on Windows 11, it is essential to enable these features.", + "guid": "135d3899-4b31-44d3-bc8f-028871a359d8", + "id": "G02.04", + "link": "https://learn.microsoft.com/windows/whats-new/windows-11-requirements", "services": [ - "VPN", - "AVD", - "Storage", - "ExpressRoute" + "VM", + "AVD" ], - "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Assess external dependencies for each Host Pool", - "waf": "Performance" + "severity": "High", + "subcategory": "Host Configuration", + "text": "Enable Trusted Launch and use Gen2 image are system requirements for Windows 11", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "AVD offers a variety of client types (fat, thin, web) to connect over different platforms (Windows, MacOS, iOS, Android). Review limitations of each client and compare multiple options when possible.", - "guid": "a1f6d565-99e5-458b-a37d-4985e1112dbd", - "id": "C02.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/users/connect-windows", + "description": "Displayed content will be automatically blocked or hidden in screenshots. Keep in mind screen sharing will also be blocked when using Teams or other collaboration software which use screen sharing.", + "guid": "a49dc137-7896-4343-b2bc-1a31bf1d30b6", + "id": "G02.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/screen-capture-protection", "services": [ "AVD" ], "severity": "Low", - "subcategory": "Clients & Users", - "text": "Review user client OS used and AVD client type", - "waf": "Performance" + "subcategory": "Host Configuration", + "text": "Consider enabling screen capture protection to prevent sensitive information from being captured", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "Depending on the user locations, and AVD region deployment, users may have a non-optimal experience, hence is important to test as soon as possible in a small PoC environment. Run the 'Azure Virtual Desktop Experience Estimator' tool to select the best Azure region to deploy Host Pools. Beyond 150ms latency, user experience may be not optimal.", - "guid": "d2f54b29-769e-43a6-a1e8-838ac936667e", - "id": "C02.04", - "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", + "description": "If not absolutely required, redirecting drives, printers, and USB devices to a user's local device in a remote desktop session should be disabled or highly restricted. Restrict Windows Explorer access by hiding local and remote drive mappings is also a secure measure to adopt preventing users from discovering unwanted information about system configuration and users.", + "guid": "7ce2cd20-85b4-4f82-828e-6558736ede6a", + "id": "G02.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#other-security-tips-for-session-hosts", "services": [ "AVD" ], - "severity": "High", - "subcategory": "Clients & Users", - "text": "Run a PoC to validate end-to-end user experience and impact of network latency", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Host Configuration", + "text": "Restrict device redirection and drive mapping", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "RDP settings can currently only be configured at the host pool level, not per user/group. If different settings are required for different set of users, it is recommended to create multiple Host Pools.", - "guid": "3b365a5c-7acb-4e48-abe5-4cd79f2e8776", - "id": "C02.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/customize-rdp-properties", + "description": "When choosing a deployment model, you can either provide remote users access to entire virtual desktops or only select applications. Remote applications, or RemoteApps, provide a seamless experience as the user works with apps on their virtual desktop. RemoteApps reduce risk by only letting the user work with a subset of the remote machine exposed by the application.", + "guid": "4e25d70e-3924-44f4-b66f-d6cdd4f4a973", + "id": "G03.01", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", "services": [ "AVD" ], - "severity": "Low", - "subcategory": "Clients & Users", - "text": "Assess and document RDP settings for all user groups", + "severity": "Medium", + "subcategory": "Management", + "text": "When possible, prefer Remote Apps over Full Desktops (DAG)", "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "AVD is a non-regional service, Host Pools can be created in any region, automatic redirection from closest front-end will happen automatically.", - "guid": "42e52f47-21d9-428c-8b1b-d521e44a29a9", - "id": "C03.01", - "link": "https://azure.microsoft.com/global-infrastructure/services/?products=virtual-desktop", + "description": "Web content filtering feature provided by Web Protection capability in Microsoft Defender for Endpoint, can be used to to control user web navigation. If this tool is used, configuration of web filtering for user Internet browsing is recommended. Access by the Guest OS system to required AVD control plane URLs must be guaranteed.", + "guid": "e19dd344-29eb-4722-a237-a151c5bb4e4f", + "id": "G03.02", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", "services": [ + "Defender", "AVD" ], - "severity": "High", - "subcategory": "General", - "text": "Determine in which Azure regions AVD Host Pools will be deployed.", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Management", + "text": "Need to control/restrict user Internet navigation from AVD session hosts?", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "AVD must store metadata to support the service; this is stored in the specified geography. However, this is independent of the regions where Host Pools are located.", - "guid": "bad37ead-53cc-47ce-8d7a-aab3571449ab", - "id": "C03.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/data-locations", + "description": "We recommend you don't grant your users admin access to virtual desktops. If you need software packages, we recommend you make them available through configuration management utilities.", + "guid": "a0cdb3b5-4eb2-4eb0-9dda-a3592718e2ed", + "id": "G03.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/security-guide", "services": [ "AVD" ], - "severity": "Medium", - "subcategory": "General", - "text": "Determine metadata location for AVD service", - "waf": "Reliability" + "severity": "High", + "subcategory": "Management", + "text": "Ensure AVD users will not have local administrator privileges on AVD Hosts", + "waf": "Security" }, { - "category": "Foundation", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "Check for specific VM SKUs, especially if you need GPU or high-specs SKUs, and eventually Azure NetApp Files if used.", - "guid": "8053d89e-89dc-47b3-9be2-a1a27f7a9e91", - "id": "C03.03", - "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "description": "We recommend you enable Defender for Cloud for the subscriptions, virtual machines, key vaults, and storage accounts used by AVD. With this tool is possible to assess and manage vulnerabilities, assess compliance with common frameworks like PCI, strengthen the overall security of your AVD environment and measure it over time using 'Secure Score': https://learn.microsoft.com/azure/virtual-desktop/security-guide#improve-your-secure-score.", + "guid": "1814387e-5ca9-4c26-a9b3-2ab5bdfc6998", + "id": "G03.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#enable-microsoft-defender-for-cloud", "services": [ - "AVD", "Storage", - "VM" + "VM", + "Subscriptions", + "AKV", + "Defender", + "AVD" ], - "severity": "Low", - "subcategory": "General", - "text": "Check Azure quotas and availability for specific VM sizes and types in the selected regions", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Management", + "text": "Enable Microsoft Defender for Cloud to manage AVD Session Hosts security posture", + "waf": "Security" }, { - "category": "Identity", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "AD DCs in Azure are recommended (at least two in different AZ) to reduce latency for users logging into AVD session hosts, and eventually for Azure NetApp Files and AD integration. A DC need to be able to talk to DCs for ALL child domains. As alternative, on-premise connectivity must be used to reach AD DCs.", - "guid": "c14aea7e-65e8-4d9a-9aec-218e6436b073", - "id": "D01.01", - "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "description": "Enabling audit log collection lets you view user and admin activity related to Azure Virtual Desktop and store in a central repository like Log Analytics workspace. ", + "guid": "a0916a76-4980-4ad0-b278-ee293c1bc352", + "id": "G03.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#collect-audit-logs", "services": [ "Entra", - "VNet", "AVD", - "Storage" + "Monitor" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create at least two Active Directory Domain Controllers (DCs) in Azure VNet environment close to AVD Host Pool", - "waf": "Reliability" + "subcategory": "Management", + "text": "Enable diagnostic and audit logging", + "waf": "Security" }, { - "category": "Identity", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "Recommended to create a separate OU per Host Pool under a separate OU hierarchy. These OUs will contain machine accounts of AVD Session Hosts. ", - "guid": "6db55f57-9603-4334-adf9-cc23418db612", - "id": "D01.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", + "description": "Assign the least privilege required by defining administrative, operations, and engineering roles to Azure RBAC roles. To limit access to high privilege roles within your Azure Virtual Desktop landing zone, consider integration with Azure Privileged Identity Management (PIM). Maintaining knowledge of which team is responsible for each particular administrative area helps you determine Azure role-based access control (RBAC) roles and configuration.", + "guid": "baaab757-1849-4ab8-893d-c9fc9d1bb73b", + "id": "G03.06", + "link": "https://docs.microsoft.com/azure/virtual-desktop/rbac", "services": [ "Entra", - "AVD" + "AVD", + "RBAC" ], - "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a specific OU in Active Directory for each Host Pool", - "waf": "Operations" + "severity": "Low", + "subcategory": "Management", + "text": "Assess the requirement to use custom RBAC roles for AVD management", + "waf": "Security" }, { - "category": "Identity", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "Carefully review, and potentially block/filter inheritance of GPOs to the OUs containing AVD Host Pools. ", - "guid": "7126504b-b47a-4393-a080-327294798b15", - "id": "D01.03", - "link": "https://docs.microsoft.com/previous-versions/windows/desktop/Policy/group-policy-hierarchy", + "description": "AVD users should not have permission to install application. If required, Windows Defender Application Control (WDAC) can be used to control which drivers and applications are allowed to run on their Windows clients. ", + "guid": "b9ea80c8-0628-49fc-ae63-125aa4c0a284", + "id": "G03.07", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#windows-defender-application-control", "services": [ - "Entra", + "Defender", "AVD" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Review Domain GPOs that will be applied to OU and impacting Host Pool Session Hosts functionalities", - "waf": "Operations" + "subcategory": "Management", + "text": "Restrict users from installing un-authorized applications", + "waf": "Security" }, { - "category": "Identity", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "If Active Directory Domain GPOs are used, it is recommended to configure FSLogix using the built-in provided GPO ADMX template referenced in the companion article in the 'More Info' column", - "guid": "2226a8e3-50a4-4ac3-8bd6-ee150553051f", - "id": "D01.04", - "link": "https://learn.microsoft.com/fslogix/how-to-use-group-policy-templates", + "description": "Enabling MFA and CA lets you manage risks before you grant users access to your AVD environment. When deciding which users to grant access to, we recommend you also consider who the user is, how they sign in, and which device they're using. Additional details and configuration procedures are provided in the companion article. Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", + "guid": "916d697d-8ead-4ed2-9bdd-186f1ac252b9", + "id": "G04.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-mfa", "services": [ "Entra", "AVD" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Configure FSLogix settings using the built-in provided GPO ADMX template", - "waf": "Operations" + "subcategory": "Microsoft Entra ID", + "text": "Evaluate the usage of Multi-Factor Authentication (MFA) and Conditional Access (CA) for AVD users", + "waf": "Security" }, { - "category": "Identity", + "category": "Security", "checklist": "Azure Virtual Desktop Review", - "description": "It is recommended to have a specific dedicated account with minimal permissions, and without the default 10 joins limitation. Review the companion article for more details.", - "guid": "347dc560-28a7-41ff-b1cd-15dd2f0d5e77", - "id": "D01.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#session-hosts", + "description": "If Zero Trust is a requirement, review the companion article in the 'More Info' column. It provides steps to apply the principles of Zero Trust to an Azure Virtual Desktop deployment.", + "guid": "221102d0-90af-49fc-b2b7-8d3fe397e43", + "id": "G05.01", + "link": "https://learn.microsoft.com/security/zero-trust/azure-infrastructure-avd", "services": [ - "Entra", - "AVD", - "VM" + "AVD" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a dedicated user account with only permissions to join VM to the domain", + "subcategory": "Zero Trust", + "text": "Review and Apply Zero Trust principles and guidance", "waf": "Security" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Avoid granting access per user, instead use AD groups and replicate them using Active Directory Connector (ADC) in Microsoft Entra ID (former Azure AD). ", - "guid": "2d41e361-1cc5-47b4-a4b1-410d43958a8c", - "id": "D01.06", - "link": "https://docs.microsoft.com/azure/virtual-desktop/manage-app-groups", + "description": "If used, make sure to check the list of best practices and recommendations described in the referenced article.", + "guid": "9164e990-9ae2-48c8-9c33-b6b7808bafe6", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files#best-practices-for-azure-virtual-desktop", "services": [ - "Entra", + "Storage", "AVD" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a domain user group for each set of users that will be granted access to each Host Pool Application Group (DAG or RAG)", - "waf": "Security" + "subcategory": "Azure Files", + "text": "Check best-practices for Azure Files", + "waf": "Performance" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "If Azure Files Active Directory (AD) integration is used, as part of the configuration procedure, an AD account to represent the storage account (file share) will be created. You can choose to register as a computer account or service logon account, see FAQ for details. For computer accounts, there is a default password expiration age set in AD at 30 days. Similarly, the service logon account may have a default password expiration age set on the AD domain or Organizational Unit (OU). For both account types, we recommend you check the password expiration age configured in your AD environment and plan to update the password of your storage account identity of the AD account before the maximum password age. You can consider creating a new AD Organizational Unit (OU) in AD and disabling password expiration policy on computer accounts or service logon accounts accordingly.", - "guid": "2289b3d6-b57c-4fc6-9546-1e1a3e3453a3", - "id": "D01.07", - "link": "https://docs.microsoft.com/azure/storage/files/storage-files-identity-ad-ds-enable", + "description": "SMB Multichannel enables clients to use multiple network connections that provide increased performance while lowering the cost of ownership. Increased performance is achieved through bandwidth aggregation over multiple NICs and utilizing Receive Side Scaling (RSS) support for NICs to distribute the IO load across multiple CPUs.", + "guid": "5784b6ca-5e9e-4bcf-8b54-c95459ea7369", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-smb-multichannel-performance", "services": [ - "Entra", - "AVD", "Storage", - "AzurePolicy" + "AVD", + "ACR", + "Cost" ], - "severity": "High", - "subcategory": "Active Directory", - "text": "Review your organization password expiration policy for accounts used by Azure Files AD integration", - "waf": "Security" + "severity": "Low", + "subcategory": "Azure Files", + "text": "Enable SMB multichannel when using a premium file share to host FSLogix profile containers.", + "waf": "Performance" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "You can configure this using Active Directory Connect (ADC) or Azure AD Domain Services (for hybrid or cloud organizations). Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", - "guid": "5119bf8e-8f58-4542-a7d9-cec166cd072a", - "id": "D01.08", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", + "description": "If a second region is required for DR purposes verify NetApp availability in there as well.", + "guid": "4a359836-ee79-4d6c-9d3a-364a5b7abae3", + "id": "H02.01", + "link": "https://azure.microsoft.com/global-infrastructure/services/", "services": [ - "Entra", + "Storage", "AVD" ], - "severity": "High", - "subcategory": "Active Directory", - "text": "A Windows Server Active Directory forest/domain must be in sync with Microsoft Entra ID", + "severity": "Medium", + "subcategory": "Azure NetApp Files", + "text": "If NetApp Files storage is required, check storage service availability in your specific region.", "waf": "Reliability" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "If Azure Files is used and pre-requisites can be satisfied, it is recommended to configure (Microsoft Entra ID) Kerberos authentication. This configuration will allow to store FSLogix profiles that can be accessed by hybrid user identities from Azure AD-joined session hosts without requiring network line-of-sight to domain controllers.", - "guid": "e777fd5e-c5f1-4d6e-8fa9-fc210b88e338", - "id": "D02.01", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-identity-auth-hybrid-identities-enable", + "description": "CA option is a recommended setting in the FSLogix scenario, as it enables a more resilient SMB session between the Session Host and NetApp Files.", + "guid": "a2661898-866a-4c8d-9d1f-8cfc86e88024", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/create-fslogix-profile-container", "services": [ - "Entra", - "AVD", - "Storage" + "Storage", + "AVD" ], "severity": "Medium", - "subcategory": "Microsoft Entra ID", - "text": "Configure Azure Files share for Microsoft Entra ID (former Azure AD) Kerberos authentication on Microsoft Entra ID Joined scenario", - "waf": "Security" - }, - { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "An Azure subscription must be parented to the same Microsoft Entra ID (former Azure AD) tenant, that contains a virtual network that either contains or is connected to the Windows Server Active Directory Domain Services or Microsoft Entra ID Domain Services instance.", - "guid": "6ceb5443-5125-4922-9442-93bb628537a5", - "id": "D03.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", - "services": [ - "Entra", - "VNet", - "AVD", - "Subscriptions" - ], - "severity": "High", - "subcategory": "Requirements", - "text": "A Microsoft Entra ID tenant must be available with at least one subscription linked", + "subcategory": "Azure NetApp Files", + "text": "If NetApp Files storage is used enable CA (Continuous Availability) option to increase resiliency", "waf": "Reliability" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop supports different types of identities depending on which configuration you choose. Please review the supported scenarios mentioned in the 'More Info' article and document the design decision accordingly in the 'Comment' column. Critically, external identities (B2B or B2C) are not supported. Be sure to review also the list of supported scenarios in https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios.", - "guid": "b4ce4781-7557-4a1f-8043-332ae199d44c", - "id": "D03.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication", + "description": "An Active Directory Site should be created for the Azure virtual network environment where Azure NetApp Files (ANF) subnet will be created, and that site name should be specified in the ANF connection property when executing the join procedure as explained in the reference article.", + "guid": "6647e977-db49-48a8-bc35-743f17499d42", + "id": "H02.03", + "link": "https://docs.microsoft.com/azure/azure-netapp-files/create-active-directory-connections", "services": [ - "Entra", + "Storage", + "VNet", "AVD" ], "severity": "High", - "subcategory": "Requirements", - "text": "Review and document your identity scenario", - "waf": "Security" + "subcategory": "Azure NetApp Files", + "text": "If Azure NetApp Files storage is used, check Active Directory Site name setting in the Active Directory Connection configuration", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Users need accounts that are in Microsoft Entra ID (former Azure AD). If you're also using AD DS or Azure AD Domain Services in your deployment of Azure Virtual Desktop, these accounts will need to be hybrid identities, which means the user accounts are synchronized. If you're using Microsoft Entra ID with AD DS, you'll need to configure Azure AD Connect to synchronize user identity data between AD DS and Microsoft Entra ID. If you're using Microsoft Entra ID with Azure AD Domain Services, user accounts are synchronized one way from Microsoft Entra ID to Azure AD Domain Services. This synchronization process is automatic. AVD also supports Microsoft Entra ID native accounts with some restrictions. External identities (B2B or B2C) are not supported.", - "guid": "f9b141a8-98a5-435e-9378-97e71ca7da7b", - "id": "D03.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "description": "Possible options: Standard HDD, Standard SSD, or Premium SSD. Ephemeral disks are not supported, Ultra-Disks not recommended. Recommended to evaluate Premium for OS disk if user density is not low, and if Cloud Cache will be used. ", + "guid": "3611c818-b0a0-4bc5-80e4-3a18a9cd289c", + "id": "H03.01", + "link": "https://docs.microsoft.com/azure/virtual-machines/disks-types", "services": [ - "Entra", + "Storage", "AVD" ], "severity": "Medium", - "subcategory": "Requirements", - "text": "Assess User Account types and requirements", - "waf": "Security" + "subcategory": "Capacity Planning", + "text": "Determine which type of managed disk will be used for the Session Hosts", + "waf": "Performance" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "AVD supports SSO using either Active Directory Federation Services (AD FS) or Microsoft Entra ID (former Azure AD) authentication. The latter is recommended, please check the requirements and limitation in the 'More Info' article. Using AD FS could be a viable choice if already present in the customer environment, it is not recommended to deploy a brand new ADFS infrastructure just for AVD SSO implementation.", - "guid": "5f9f680a-ba07-4429-bbf7-93d7071561f4", - "id": "D03.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication#single-sign-on-sso", + "description": "Possible options are: Azure NetApp Files, Azure Files, VM based File Server. File-server it is not recommended. Azure Files Premium typically a good starting point. NetApp usually required for large scale / high-performant environment. For a detailed comparison see the article in the 'More Info' column.", + "guid": "ed6b17db-8255-4462-b2ae-e4553afc8339", + "id": "H03.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/store-fslogix-profile", "services": [ - "Entra", + "Storage", + "VM", "AVD" ], - "severity": "Medium", - "subcategory": "Requirements", - "text": "If Single-Sign On (SSO) is a requirement, review the supported scenarios and prerequisites", - "waf": "Reliability" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Determine which storage backend solution will be used for FSLogix Profiles", + "waf": "Performance" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "VMs can be Windows Active Directory (AD) domain-joined, Hybrid AD-joined, Microsoft Entra ID (former Azure AD) Joined or Azure AD Domain Services joined. Be sure to review supported scenarios, limitations and requirements from the referenced article.", - "guid": "ea962a15-9394-46da-a7cc-3923266b2258", - "id": "D03.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "description": "Every Host Pool should use a separate set of storage accounts/volumes (at least one) and shares. Users should have a different profile for each Host Pool since settings and configurations are specific to each Host Pool. Additionally, accessing different Host Pools at the same time can cause errors on the shared user profile VHD/X. Usage of different storage accounts/volumes for multiple shares is also recommended to scale independently.", + "guid": "2fad62bd-5004-453c-ace4-64d862e7f5a4", + "id": "H03.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", "services": [ - "Entra", - "AVD", - "VM" + "Storage", + "AVD" ], "severity": "High", - "subcategory": "Requirements", - "text": "Select the proper AVD Session Host domain join type", - "waf": "Security" + "subcategory": "Capacity Planning", + "text": "Do not share storage and profiles between different Host Pools", + "waf": "Performance" }, { - "category": "Identity", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Compare self-managed Windows Active Directory Domain Services, Microsoft Entra ID (former Azure AD), and managed Azure AD Domain Services (AAD-DS)", - "guid": "6f4a1651-bddd-4ea8-a487-cdeb4861bc3b", - "id": "D03.06", - "link": "https://docs.microsoft.com/azure/active-directory-domain-services/compare-identity-solutions", + "description": "As a starting point for estimating profile container storage performance requirements we recommend to assume 10 IOPS per user in the steady state and 50 IOPS per user during sign-in/sign-out. Space requirements is simply obtained based on the maximum profiles size in FSLogix per the total number of users for each Host Pool. Multiple storage accounts can be used for the same Host Pool if required.", + "guid": "680e7828-9c93-4665-9d02-bff4564b0d93", + "id": "H03.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/faq#what-s-the-largest-profile-size-fslogix-can-handle-", "services": [ - "Entra", + "Storage", "AVD" ], - "severity": "Low", - "subcategory": "Requirements", - "text": "Before using Azure AD Domain Services (AAD-DS) for AVD, be sure to review the limitations.", + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Verify storage scalability limits and Host Pool requirements", "waf": "Reliability" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "AVD provides administrative templates for Intune and Active Directory GPO. Using these templates it is possible to centrally control several AVD configuration settings: Graphics related data logging, Screen capture protection, RDP Shortpath for managed networks, Watermarking. See companion article in 'More Info' colum for details. NOTE: FSLogix has its own separate template.", - "guid": "5549524b-36c0-4f1a-892b-ab3ca78f5db2", - "id": "E01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/administrative-template", + "description": "Avoid introducing additional latency and costs associated with cross-region network traffic where possible.", + "guid": "8aad53cc-79e2-4e86-9673-57c549675c5e", + "id": "H03.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files", "services": [ - "Entra", + "Storage", "AVD", - "Monitor" + "Cost" ], - "severity": "Low", - "subcategory": "Management", - "text": "Use built-in provided administrative templates for AVD settings configuration", - "waf": "Operations" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "For optimal performance, the storage solution and the FSLogix profile container should be in the same Azure region.", + "waf": "Performance" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Determine if a configuration management tool is already in place to manage Host Pool VM configuration after initial deployment, For example SCCM/SCOM, Intune/ConfigurationManager, 3rd-party solutions.", - "guid": "3334fdf9-1c23-4418-8b65-285269440b4b", - "id": "E01.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/management", + "description": "The recommendation in Azure Virtual Desktop is to use Profile Container without Office Container (ODFC) split unless you are planning for specific Business Continuity and Disaster Recovery (BCDR) scenarios as described in the Disaster Recovery section below. https://docs.microsoft.com/fslogix/profile-container-office-container-cncpt ", + "guid": "df47d2d9-2881-4b1c-b5d1-e54a29759e39", + "id": "H04.01", + "link": "https://learn.microsoft.com/fslogix/concepts-container-types#when-to-use-profile-and-odfc-containers", "services": [ - "VM", + "Storage", "AVD", - "Monitor" + "ASR" ], - "severity": "Low", - "subcategory": "Management", - "text": "Plan AVD Session Hosts configuration management strategy", - "waf": "Operations" + "severity": "High", + "subcategory": "FSLogix", + "text": "Do not use Office Containers (ODFC) if not strictly required and justified", + "waf": "Reliability" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "We recommend using Microsoft Intune, if requirements can be satisfied, to manage your Azure Virtual Desktop environment. Review supported scenarios and requirements to enable Intune for AVD Session Host management in the referenced article in the “More Info” column. Document your choice in the 'Comment' column. In that article, review the different requirements and capabilities for single-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop and multi-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session AVD.", - "guid": "63a08be1-6004-4b4a-a79b-f3239faae113", - "id": "E01.03", - "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop", + "description": "Make sure to configure the following antivirus exclusions for FSLogix Profile Container virtual hard drives, as documented in the referenced article in the 'More Info' column.", + "guid": "83f63047-22ee-479d-9b5c-3632054b69ba", + "id": "H04.02", + "link": "https://learn.microsoft.com/fslogix/overview-prerequisites#configure-antivirus-file-and-folder-exclusions", "services": [ - "AVD", - "Monitor" + "Storage", + "AVD" ], "severity": "Medium", - "subcategory": "Management", - "text": "Evaluate Intune for AVD Session Hosts management", - "waf": "Operations" + "subcategory": "FSLogix", + "text": "Configure the recommended antivirus exclusions for FSLogix (includes not scanning VHD(x) files on connect).", + "waf": "Security" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "The scaling tool provides a low-cost automation option for customers who want to optimize their session host VM costs. You can use the scaling tool to schedule VMs to start and stop based on Peak and Off-Peak business hours, scale out VMs based on number of sessions per CPU core, scale in VMs during Off-Peak hours, leaving the minimum number of session host VMs running. Not available yet for Personal Host Pool type.", - "guid": "7138b820-102c-4e16-be30-1e6e872e52e3", - "id": "E01.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/autoscale-scenarios", + "description": "Profile containers have a default max size of 30GB. If large Profile Containers are anticipated, and customers wants to try to keep them small, consider using OneDrive to host Office 365 files outside the FSLogix profile.", + "guid": "01e6a84d-e5df-443d-8992-481718d5d1e5", + "id": "H04.03", + "link": "https://docs.microsoft.com/fslogix/profile-container-configuration-reference", "services": [ - "VM", + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "FSLogix", + "text": "Review and confirm configured maximum profile size in FSLogix", + "waf": "Cost" + }, + { + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Defaults and recommended settings are reported in the companion article in the 'More Info' column. If not recommended keys and/or values must be used, be sure to review with a Microsoft AVD expert and clearly document your choices.", + "guid": "d34aad5e-8c78-4e1d-9666-7313c405674c", + "id": "H04.04", + "link": "https://learn.microsoft.com/fslogix/concepts-configuration-examples", + "services": [ + "AKV", + "Storage", "AVD", - "Monitor", - "Cost" + "ACR" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Assess the requirements for host pool auto-scaling capability", + "severity": "High", + "subcategory": "FSLogix", + "text": "Review FSLogix registry keys and determine which ones to apply", "waf": "Reliability" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Start VM On Connect lets you reduce costs by enabling end users to turn on their session host virtual machines (VMs) only when they need them. You can then turn off VMs when they're not needed. You can configure Start VM on Connect for personal or pooled host pools using the Azure portal or PowerShell. Start VM on Connect is a host pool wide setting.", - "guid": "55f612fe-f215-4f0d-a956-10e7dd96bcbc", - "id": "E01.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect", + "description": "Concurrent or multiple connections are not recommended in Azure Virtual Desktop. Concurrent connections are also not supported by Session Hosts running in an Azure Virtual Desktop Host Pool. OneDrive, if used, doesn't support concurrent or multiple connections using the same container, under any circumstance. For multiple connections, usage of the same profile disk is not recommended.", + "guid": "5e985b85-9c77-43e7-b261-623b775a917e", + "id": "H04.05", + "link": "https://learn.microsoft.com/fslogix/concepts-multi-concurrent-connections", "services": [ - "AVD", - "Cost", - "VM", - "Monitor" + "Storage", + "AVD" ], - "severity": "Low", - "subcategory": "Management", - "text": "Consider the usage of Start VM on Connect for Personal Host Pools", - "waf": "Cost" + "severity": "High", + "subcategory": "FSLogix", + "text": "Avoid usage of concurrent or multiple connections", + "waf": "Reliability" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "'Start VM On Connect' provides a smart way to automatically start previously stopped Session Hosts but does not provide a mechanism to shut down when not in used. Administrators are encouraged to configure additional policies to sign users out of their sessions and run Azure automation scripts to de-allocate VMs. Users should be not allowed to shut down their Personal Hosts since will not be able to de-allocate Azure VMs, then billing will still be active with no cost reduction.", - "guid": "79a686ea-d971-4ea0-a9a8-1aea074c94cb", - "id": "E01.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect-faq#are-vms-automatically-deallocated-when-a-user-stops-using-them", + "description": "Cloud Cache uses OS drive as local cache storage and may generate lot of pressure on the VM disk. Depending on the VM SKU and size used, the VM temporary drive can be a viable and performant solution where to relocate Cloud Cache cached content. Before adopting this solution, tests should be executed to confirm performance and stability. More details on Cloud Cache can be found here: https://learn.microsoft.com/fslogix/concepts-fslogix-cloud-cache. ", + "guid": "b2d1215a-e114-4ba3-9df5-85ecdcd9bd3b", + "id": "H04.06", + "link": "https://docs.microsoft.com/fslogix/cloud-cache-configuration-reference", "services": [ - "AzurePolicy", - "Monitor", - "Cost", - "AVD", - "VM" + "Storage", + "VM", + "AVD" ], "severity": "Low", - "subcategory": "Management", - "text": "Evaluate the implementation of an ad-hoc mechanism to shut down Personal AVD Session Hosts", - "waf": "Cost" + "subcategory": "FSLogix", + "text": "If FSLogix Cloud Cache is used, consider moving the cache directory to the VM temporary drive.", + "waf": "Performance" }, { - "category": "Monitoring and Management", + "category": "Storage", "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop billing is mainly based on cost associated to compute, networking and storage resources consumed by Host Pools. In addition to this, costs can be generated by dependent resources, for example VPN or ExpressRoute or vWAN, Active Directory Domain Controllers, DNS, etc. There is no direct cost associated to AVD objects like workspaces, host pools or application groups. To make AVD associated costs more evident and grouped by Host Pool, it is recommended to use 'cm-resource-parent' tag. ", - "guid": "51bcafca-476a-48fa-9b91-9645a7679f20", - "id": "E01.07", - "link": "https://learn.microsoft.com/azure/virtual-desktop/tag-virtual-desktop-resources", + "description": "REDIRECTION.XML file is used to control what folders are redirected out of the profile container to the 'C:' drive. Exclusions should be the exception and should never be used unless the specific exclusion is completely understood by the person configuring the exclusion. Exclusions should always be fully tested in the environment where they are intended to be implemented. Configuring exclusions may impact functionality, stability and performance.", + "guid": "0b50ca97-b1d2-473c-b4d9-6e98b0f912de", + "id": "H04.07", + "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt#redirectionsxml", "services": [ - "ExpressRoute", - "Monitor", - "Cost", - "AVD", - "DNS", - "VPN", "Storage", - "VWAN" + "AVD" ], - "severity": "Low", - "subcategory": "Management", - "text": "Review and adopt suggested Azure Tags for Azure Virtual Desktop", + "severity": "Medium", + "subcategory": "FSLogix", + "text": "Review the usage of FSLogix redirection.", "waf": "Cost" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Advisor analyzes your configurations and telemetry to offer personalized recommendations to solve common problems. With these recommendations, you can optimize your Azure resources for reliability, security, operational excellence, performance, and cost.", - "guid": "611dd68c-5a4b-4252-8e44-a59a9c2399c4", - "id": "E01.08", - "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-advisor-recommendations", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "services": [ - "Entra", - "AVD", - "Monitor", - "Cost" + "AKV", + "FrontDoor" ], - "severity": "Low", - "subcategory": "Management", - "text": "Periodically check Azure Advisor recommendations for AVD", + "severity": "Medium", + "subcategory": "App delivery - Front Door", + "text": "If you use customer-managed TLS certificates with Azure Front Door, use the 'Latest' certificate version. Reduce the risk of outages caused by manual certificate renewal.", "waf": "Operations" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Customers have several options: Microsoft Configuration Manager, this article explains how to automatically apply updates to a Azure Virtual Desktop session hosts running Windows 10/11: https://learn.microsoft.com/azure/virtual-desktop/configure-automatic-updates, Microsoft Intune: https://docs.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session, Azure Update Management and WSUS for Windows Server OS only (client OS not supported: https://learn.microsoft.com/azure/automation/update-management/operating-system-requirements), 3rd Party tools. Outside an emergency security patching situation, it is recommended to move away from an 'in-place' update strategy patching strategy and adopt a re-imaging approach.", - "guid": "04722da2-9c2b-41cd-922f-54b29bade3aa", - "id": "E01.09", - "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop-multi-session", - "services": [ - "AVD", - "Monitor" + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", + "services": [], + "severity": "Medium", + "subcategory": "App delivery", + "text": "Perform app delivery within landing zones for both internal-facing (corp) and external-facing apps (online).", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", + "guid": "553585a6-abe0-11ed-afa1-0242ac120002", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "services": [ + "AppGW" ], "severity": "Medium", - "subcategory": "Management", - "text": "Plan for a Session Host emergency patching and update strategy", - "waf": "Operations" + "subcategory": "App delivery - App Gateway", + "text": "Ensure you are using Application Gateway v2 SKU", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "The Scheduled Agent Updates feature lets you create up to two maintenance windows per Host Pool to update AVD components at a convenient time. It is recommended to specify maintenance windows then upgrading Session Hosts will not happen during peak business hours. Scheduled Agent Updates is disabled by default. This means that, unless you enable this setting, the agent can get updated at any time by the agent update flighting service.", - "guid": "c067939b-e5ca-4698-b9ce-3bd91843e73f", - "id": "E01.10", - "link": "https://learn.microsoft.com/azure/virtual-desktop/scheduled-agent-updates", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "A01.04", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "AVD", - "Monitor" + "LoadBalancer" ], - "severity": "Low", - "subcategory": "Management", - "text": "Configure the Scheduled Agent Updates feature", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "App delivery - Load Balancer", + "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Host pools are a collection of one or more identical virtual machines within Azure Virtual Desktop environment. We highly recommend you create a validation host pool where service updates are applied first. This allows you to monitor service updates before the service applies them to your standard or non-validation environment.", - "guid": "d1e8c38e-c936-4667-913c-005674b1e944", - "id": "E01.11", - "link": "https://docs.microsoft.com/azure/virtual-desktop/create-validation-host-pool", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", + "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "A01.05", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "services": [ - "VM", - "AVD", - "Monitor" + "VNet", + "AppGW" ], "severity": "Medium", - "subcategory": "Management", - "text": "Create a validation (canary) Host Pool", - "waf": "Operations" + "subcategory": "App delivery - App Gateway", + "text": "Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "An AVD Host Pool can be deployed in several ways: Azure Portal, ARM templates, Azure CLI tool, Powershell, manual VM creation with registration token, Terraform, 3rd-party tools. It is important to adopt proper method/s to support automatic deployment through automation and CI/CD tools.", - "guid": "a459c373-e7ed-4616-83b3-65a917ecbe48", - "id": "E01.12", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-platform-automation-and-devops", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "description": "Administration of reverse proxies in general and WAF in particular is closer to the application than to networking, so they belong in the same subscription as the app. Centralizing the Application Gateway and WAF in the connectivity subscription might be OK if it is managed by one single team.", + "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "A01.06", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "VM", - "AVD", - "Monitor" + "Entra", + "WAF", + "Subscriptions", + "VNet", + "NVA", + "AppGW" ], "severity": "Medium", - "subcategory": "Management", - "text": "Determine Host Pool deployment strategy", - "waf": "Operations" + "subcategory": "App delivery - App Gateway", + "text": "Deploy Azure Application Gateway v2 or partner NVAs used for proxying inbound HTTP(S) connections within the landing-zone virtual network and with the apps that they're securing.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "After you register a VM to a host pool within the Azure Virtual Desktop service, the agent regularly refreshes the VM's token whenever the VM is active. The certificate for the registration token is valid for 90 days. Because of this 90-day limit, we recommend VMs to be online for 20 minutes every 90 days so that the machine can refresh its tokens and update the agent and side-by-side stack components.", - "guid": "ebe54cd7-df2e-48bb-ac35-81559bb9153e", - "id": "E01.13", - "link": "https://docs.microsoft.com/azure/virtual-desktop/faq", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "A01.07", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVD", - "VM", - "Monitor" + "DDoS" ], "severity": "Medium", - "subcategory": "Management", - "text": "Turn on Session Host VMs at least every 90 days for token refresh", - "waf": "Operations" + "subcategory": "App delivery - App Gateway", + "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop Insights is a dashboard built on Azure Monitor Workbooks that helps IT professionals understand their Azure Virtual Desktop environments. Read the referenced article to learn how to set up Azure Monitor for Azure Virtual Desktop to monitor your AVD environments.", - "guid": "63cfff1c-ac59-49ef-8d5a-83dd4de36c1c", - "id": "E02.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/insights", - "services": [ - "AVD", - "Monitor" - ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Enable monitoring for AVD", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", + "id": "A01.08", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "services": [], + "severity": "Medium", + "subcategory": "App delivery - App Gateway", + "text": "Configure autoscaling with a minimum amount of instances of two.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Reliability" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop uses Azure Monitor and Log Analytics for monitoring and alerts like many other Azure services. This lets admins identify issues through a single interface. The service creates activity logs for both user and administrative actions. Each activity log falls under the following categories: Management, Feed, Connections, Host Registration, Errors, Checkpoints. ", - "guid": "81770afb-c4c0-4e43-a186-58d2857ed671", - "id": "E02.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", + "id": "A01.09", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", "services": [ - "VM", - "AVD", - "Monitor" + "ACR", + "AppGW" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable diagnostic settings for Workspaces, Host Pools, Application Groups and Host VMs to Log Analytics workspace", + "subcategory": "App delivery - App Gateway", + "text": "Deploy Application Gateway across Availability Zones", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Reliability" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "See the referenced article and this additional one to setup proper monitoring and alerting for storage: https://docs.microsoft.com/azure/storage/files/storage-troubleshooting-files-performance. ", - "guid": "2463cffe-179c-4599-be0d-5973dd4ce32c", - "id": "E02.03", - "link": "https://docs.microsoft.com/azure/storage/files/storage-files-monitoring?tabs=azure-portal", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVD", - "Storage", - "Monitor" + "AzurePolicy", + "FrontDoor", + "WAF" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Create alerts on the profile storage to be alerted in case of high usage and throttling", - "waf": "Reliability" + "subcategory": "App delivery - Front Door", + "text": "Use Azure Front Door with WAF policies to deliver and help protect global HTTP/S apps that span multiple Azure regions.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "You can use Azure Service Health to monitor service issues and health advisories for Azure Virtual Desktop. Azure Service Health can notify you with different types of alerts (for example, email or SMS), help you understand the effect of an issue, and keep you updated as the issue resolves.", - "guid": "18813706-f7c4-4c0d-9e51-4548d2457ed6", - "id": "E02.04", - "link": "https://docs.microsoft.com/azure/virtual-desktop/set-up-service-alerts", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "A01.11", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "services": [ - "AVD", - "Monitor" + "AzurePolicy", + "FrontDoor", + "WAF", + "AppGW" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Configure Azure Service Health for AVD alerts ", - "waf": "Reliability" + "subcategory": "App delivery", + "text": "When using Front Door and Application Gateway to help protect HTTP/S apps, use WAF policies in Front Door. Lock down Application Gateway to receive traffic only from Front Door.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "If required to connect to on-premises environment, assess the current connectivity option or plan for the required connectivity (ExpressRoute, Azure S2S or 3rd-party NVA VPN). ", - "guid": "dd399cfd-7b28-4dc8-9555-6202bfe4563b", - "id": "F01.01", - "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "A01.12", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "VPN", - "AVD", - "NVA", - "ExpressRoute" + "TrafficManager" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Determine if hybrid connectivity is required to connect to on-premises environment", + "severity": "High", + "subcategory": "App delivery - Traffic Manager", + "text": "Use Traffic Manager to deliver global apps that span protocols other than HTTP/S.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD Host Pools can be deployed in either Azure Virtual WAN or traditional 'Hub & Spoke' network topologies. It is recommended to deploy each Host Pool in a separate 'spoke' VNet, using 'hub' is not recommended.", - "guid": "c8639648-a652-4d6c-85e5-02965388e5de", - "id": "F01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-network-topology-and-connectivity", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "A01.13", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "services": [ - "VNet", - "AVD", - "VWAN" + "Entra", + "AVD" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Determine Azure Virtual Network (VNet) placement for each AVD Host Pool", - "waf": "Performance" - }, - { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Evaluate the bandwidth requirements, ensure VPN/ER bandwidth will be enough, ensure proper routing and firewall rules are in place, test end-to-end latency. ", - "guid": "d227dd14-2b06-4c21-a799-9a646f4389a7", - "id": "F01.03", - "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "severity": "Low", + "subcategory": "App delivery", + "text": "If users only need access to internal applications, has Microsoft Entra ID Application Proxy been considered as an alternative to Azure Virtual Desktop (AVD)?", + "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "A01.14", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "services": [ - "VPN", - "AVD" + "Entra" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Assess which on-premises resources are required from AVD Host Pools", - "waf": "Reliability" + "subcategory": "App delivery", + "text": "To reduce the number of firewall ports open for incoming connections in your network, consider using Microsoft Entra ID Application Proxy to give remote users secure and authenticated access to internal applications.", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Several options are available. You can use Azure Firewall or equivalent 3rd-party NVA, Network Security Group (NSG) and/or Proxy servers. NSG is not able to enable/disable by URL, only ports and protocols. Proxy should be used only as explicit setting in user browser. Details on using Azure Firewall Premium with AVD are reported in the companion article in the 'More Info' column. Be sure to allow proper access to required AVD URLs. Forced Tunneling to on-premises is not recommended.", - "guid": "fc4972cd-3cd2-41bf-9703-6e5e6b4bed3d", - "id": "F01.04", - "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", + "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "A01.15", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "services": [ - "Firewall", - "AVD", - "VNet", - "NVA" + "Storage", + "FrontDoor", + "WAF" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Need to control/restrict Internet outbound traffic for AVD hosts?", + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Required URLs for AVD control plane access by session hosts are documented here: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list. A check tool is available to verify connectivity from the session hosts: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list#required-url-check-tool. Forced Tunneling to on-premises is not recommended.", - "guid": "65c7acbe-45bb-4e60-ad89-f2e87778424d", - "id": "F01.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/safe-url-list", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "A01.16", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "services": [ - "AVD" + "TrafficManager", + "FrontDoor" ], "severity": "High", - "subcategory": "Networking", - "text": "Ensure AVD control plane endpoints are accessible", - "waf": "Reliability" + "subcategory": "App delivery - Front Door", + "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Consider the usage of Azure Defender Endpoint or similar 3rd-party agents to control user web navigation, see the Security section for more details.", - "guid": "73676ae4-6691-4e88-95ad-a42223e13810", - "id": "F01.06", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/onboard-windows-multi-session-device?view=o365-worldwide", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "A01.17", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "services": [ - "AVD", - "Defender" + "FrontDoor" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Need to control/restrict Internet outbound traffic only for users on AVD hosts? ", + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Use the same domain name on Azure Front Door and your origin. Mismatched host names can cause subtle bugs.", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Custom UDR and NSG can be applied to AVD Host Pool subnets, for example to redirect to Azure Firewall or NVA, or to filter/block network traffic. In this case is recommended to carefully review to ensure optimal path for outbound traffic to AVD control plane is used. Service Tags can now be used with UDR and NSG, then AVD management plane traffic can be easily allowed: https://learn.microsoft.com/azure/virtual-desktop/safe-url-list.", - "guid": "523181a9-4174-4158-93ff-7ae7c6d37431", - "id": "F01.07", - "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "A01.18", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "services": [ - "VNet", - "AVD", - "NVA", - "Firewall" + "FrontDoor" ], "severity": "Low", - "subcategory": "Networking", - "text": "Review custom UDR and NSG for AVD Host Pool subnets", - "waf": "Security" + "subcategory": "App delivery - Front Door", + "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", + "waf": "Performance" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Network traffic from AVD Session Host VMs to AVD control plane should be as direct as possible. Redirecting this traffic through a Proxy or Firewall with deep packet inspection and/or SSL termination could cause serious issues and bad customer experience. It is recommended to bypass Proxy and Firewall just for the AVD control plane. User generated traffic surfing the web instead, should be filtered by Firewall and/or redirected to a Proxy. For details and guidelines, please see the companion article in the 'More Info' column.", - "guid": "cc6edca0-aeca-4566-9e92-cf246f1465af", - "id": "F01.08", - "link": "https://learn.microsoft.com/azure/virtual-desktop/proxy-server-support", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "A01.19", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "services": [ - "AVD", - "VM" + "FrontDoor" ], - "severity": "High", - "subcategory": "Networking", - "text": "Do not use Proxy servers, SSL termination and Deep Packet Inspection for AVD control plane traffic", + "severity": "Medium", + "subcategory": "App delivery - Front Door", + "text": "Select good health probe endpoints for Azure Front Door. Consider building health endpoints that check all of your application's dependencies.", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "It is recommended to assess and review networking bandwidth requirements for users, based on the specific workload type. The referenced article provide general estimations and recommendations, but specific measure are required for proper sizing. ", - "guid": "516785c6-fa96-4c96-ad88-408f372734c8", - "id": "F01.09", - "link": "https://learn.microsoft.com/azure/virtual-desktop/rdp-bandwidth", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "A01.20", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "services": [ - "AVD", - "VM" + "FrontDoor" ], "severity": "Low", - "subcategory": "Networking", - "text": "Check the network bandwidth required for each user and in total for the VM SKU", + "subcategory": "App delivery - Front Door", + "text": "Use HEAD health probes with Azure Front Door, to reduce the traffic that Front Door sends to your application.", "waf": "Performance" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "If Azure Files SMB share will be used to store user profiles via FSLogix, the usage of Private Endpoint (PE) for private access to the storage is recommended. AVD Session Hosts will access the storage using a private IP in the same VNet, a separate subnet is recommended. This feature has an additional cost that must be evaluated. If PE will not be used, at least Service Endpoint is recommended (no cost associated).", - "guid": "ec27d589-9178-426d-8df2-ff60020f30a6", - "id": "F01.10", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-networking-endpoints", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", + "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "A01.21", + "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "services": [ - "PrivateLink", + "LoadBalancer" + ], + "severity": "High", + "subcategory": "App delivery - Load Balancer", + "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", + "waf": "Reliability" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "A01.22", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", + "services": [ + "AKV", "Cost", - "VNet", - "AVD", - "Storage" + "FrontDoor" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Evaluate usage Private Endpoint for Azure Files share", - "waf": "Security" + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Use managed TLS certificates with Azure Front Door. Reduce operational cost and risk of outages due to certificate renewals.", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Connections to Azure Virtual Desktop can use TCP or UDP. RDP Shortpath is a feature of AVD that establishes a direct UDP-based transport between a supported Windows Remote Desktop client and session host. if clients have line of sight to AVD session hosts from internal network (VPN usage is not recommended), this feature can provide lower latency and best performances as explained in https://learn.microsoft.com/azure/virtual-desktop/rdp-shortpath?tabs=managed-networks#key-benefits.", - "guid": "b2074747-d01a-4f61-b1aa-92ad793d9ff4", - "id": "F01.11", - "link": "https://docs.microsoft.com/azure/virtual-desktop/shortpath", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "A01.23", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "services": [ - "VPN", - "AVD" + "FrontDoor", + "WAF" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Evaluate usage of RDP ShortPath for clients connecting from managed internal networks", - "waf": "Performance" + "subcategory": "App delivery - Front Door", + "text": "Define your Azure Front Door WAF configuration as code. By using code, you can more easily adopt new ruleset versions and gain additional protection.", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Security mechanisms provided by GPO should be used, if available. For example, it is possible to impose desktop screen lock and idle session disconnection time. Existing GPOs applied to on-premises environment should be reviewed and eventually applied also to secure also AVD Hosts when joined to the domain.", - "guid": "a135e337-897e-431c-97d6-8cb6a22ac19f", - "id": "G01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#establish-maximum-inactive-time-and-disconnection-policies", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "A01.24", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "services": [ - "AVD" + "FrontDoor" + ], + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Use end-to-end TLS with Azure Front Door. Use TLS for connections from your clients to Front Door, and from Front Door to your origin.", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "A01.25", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", + "services": [ + "FrontDoor" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Review Active Directory GPO to secure RDP sessions", + "subcategory": "App delivery - Front Door", + "text": "Use HTTP to HTTPS redirection with Azure Front Door. Support older clients by redirecting them to an HTTPS request automatically.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Microsoft Defender for Endpoint supports Azure Virtual Desktop for Windows 10/11 Enterprise multi-session. Check article for onboarding non-persistent virtual desktop infrastructure (VDI) devices: https://docs.microsoft.com/windows/security/threat-protection/microsoft-defender-atp/configure-endpoints-vdi", - "guid": "b1172576-9ef6-4691-a483-5ac932223ece", - "id": "G02.01", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/deployment-vdi-microsoft-defender-antivirus", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "A01.26", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "services": [ - "AVD", - "Defender" + "FrontDoor", + "WAF" ], "severity": "High", - "subcategory": "Host Configuration", - "text": "Ensure anti-virus and anti-malware solutions are used", + "subcategory": "App delivery - Front Door", + "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Disks in Azure are already encrypted at rest by default with Microsoft managed keys. Host VM OS disk encryption is possible and supported using Azure Disk Encryption (ADE - BitLocker) and Disk Encryption Set (DES - Server Side Encryption), the latter is recommended. Encryption of FSLogix storage using Azure Files can be done using SSE on Azure Storage. For OneDrive encryption, see this article: https://docs.microsoft.com/compliance/assurance/assurance-encryption-for-microsoft-365-services.", - "guid": "0fd32907-98bc-4178-adc5-a06ca7144351", - "id": "G02.02", - "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "A01.27", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "services": [ - "AVD", - "Storage", - "VM", - "AKV" + "FrontDoor", + "WAF" ], - "severity": "Low", - "subcategory": "Host Configuration", - "text": "Assess disk encryption requirements for AVD Session Hosts", + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Trusted launch are Gen2 Azure VMs with enhanced security features aimed to protect against “bottom of the stack” threats through attack vectors such as rootkits, boot kits, and kernel-level malware. Recommended to enable and leverage Secure Boot, Virtual TPM (vTPM) and Integrity Monitoring.", - "guid": "36a5a67f-bb9e-4d5b-9547-8c4479816b28", - "id": "G02.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#azure-virtual-desktop-support-for-trusted-launch", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "A01.28", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "services": [ - "AVD", - "VM", - "Monitor" + "FrontDoor", + "WAF" ], - "severity": "Medium", - "subcategory": "Host Configuration", - "text": "Enable Trusted launch in Azure Gen2 VM Session Hosts", + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Trusted Launch and Gen2 VM are not only security and performance enhancing features but also system requirements for Windows 11. When building an AVD environment based on Windows 11, it is essential to enable these features.", - "guid": "135d3899-4b31-44d3-bc8f-028871a359d8", - "id": "G02.04", - "link": "https://learn.microsoft.com/windows/whats-new/windows-11-requirements", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "A01.29", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "services": [ - "AVD", - "VM" + "FrontDoor", + "WAF" ], "severity": "High", - "subcategory": "Host Configuration", - "text": "Enable Trusted Launch and use Gen2 image are system requirements for Windows 11", + "subcategory": "App delivery - Front Door", + "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Displayed content will be automatically blocked or hidden in screenshots. Keep in mind screen sharing will also be blocked when using Teams or other collaboration software which use screen sharing.", - "guid": "a49dc137-7896-4343-b2bc-1a31bf1d30b6", - "id": "G02.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/screen-capture-protection", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "A01.30", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "services": [ - "AVD" + "FrontDoor", + "WAF" ], - "severity": "Low", - "subcategory": "Host Configuration", - "text": "Consider enabling screen capture protection to prevent sensitive information from being captured", + "severity": "High", + "subcategory": "App delivery - Front Door", + "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "If not absolutely required, redirecting drives, printers, and USB devices to a user's local device in a remote desktop session should be disabled or highly restricted. Restrict Windows Explorer access by hiding local and remote drive mappings is also a secure measure to adopt preventing users from discovering unwanted information about system configuration and users.", - "guid": "7ce2cd20-85b4-4f82-828e-6558736ede6a", - "id": "G02.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#other-security-tips-for-session-hosts", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "A01.31", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "services": [ - "AVD" + "FrontDoor", + "WAF" ], "severity": "Medium", - "subcategory": "Host Configuration", - "text": "Restrict device redirection and drive mapping", + "subcategory": "App delivery - Front Door", + "text": "Use the latest Azure Front Door WAF ruleset versions. Ruleset updates are regularly updated to take account of the current threat landscape.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "When choosing a deployment model, you can either provide remote users access to entire virtual desktops or only select applications. Remote applications, or RemoteApps, provide a seamless experience as the user works with apps on their virtual desktop. RemoteApps reduce risk by only letting the user work with a subset of the remote machine exposed by the application.", - "guid": "4e25d70e-3924-44f4-b66f-d6cdd4f4a973", - "id": "G03.01", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "A01.32", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "services": [ - "AVD" + "FrontDoor", + "WAF" ], "severity": "Medium", - "subcategory": "Management", - "text": "When possible, prefer Remote Apps over Full Desktops (DAG)", + "subcategory": "App delivery - Front Door", + "text": "Add rate limiting to the Azure Front Door WAF. Rate limiting blocks clients accidentally or intentionally sending large amounts of traffic in a short period of time.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Web content filtering feature provided by Web Protection capability in Microsoft Defender for Endpoint, can be used to to control user web navigation. If this tool is used, configuration of web filtering for user Internet browsing is recommended. Access by the Guest OS system to required AVD control plane URLs must be guaranteed.", - "guid": "e19dd344-29eb-4722-a237-a151c5bb4e4f", - "id": "G03.02", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "A01.33", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "services": [ - "AVD", - "Defender" + "FrontDoor", + "WAF" ], "severity": "Medium", - "subcategory": "Management", - "text": "Need to control/restrict user Internet navigation from AVD session hosts?", - "waf": "Security" - }, - { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "We recommend you don't grant your users admin access to virtual desktops. If you need software packages, we recommend you make them available through configuration management utilities.", - "guid": "a0cdb3b5-4eb2-4eb0-9dda-a3592718e2ed", - "id": "G03.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/security-guide", - "services": [ - "AVD" - ], - "severity": "High", - "subcategory": "Management", - "text": "Ensure AVD users will not have local administrator privileges on AVD Hosts", + "subcategory": "App delivery - Front Door", + "text": "Use a high threshold for Azure Front Door WAF rate limits. High rate limit thresholds avoid blocking legitimate traffic, while still providing protection against extremely high numbers of requests that might overwhelm your infrastructure. ", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "We recommend you enable Defender for Cloud for the subscriptions, virtual machines, key vaults, and storage accounts used by AVD. With this tool is possible to assess and manage vulnerabilities, assess compliance with common frameworks like PCI, strengthen the overall security of your AVD environment and measure it over time using 'Secure Score': https://learn.microsoft.com/azure/virtual-desktop/security-guide#improve-your-secure-score.", - "guid": "1814387e-5ca9-4c26-a9b3-2ab5bdfc6998", - "id": "G03.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#enable-microsoft-defender-for-cloud", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "A01.34", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "services": [ - "AVD", - "AKV", - "Defender", - "Subscriptions", - "Storage", - "VM" + "FrontDoor", + "WAF" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Enable Microsoft Defender for Cloud to manage AVD Session Hosts security posture", + "severity": "Low", + "subcategory": "App delivery - Front Door", + "text": "Geo-filter traffic by using the Azure Front Door WAF. Allow traffic only from expected regions, and block traffic from other regions.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Enabling audit log collection lets you view user and admin activity related to Azure Virtual Desktop and store in a central repository like Log Analytics workspace. ", - "guid": "a0916a76-4980-4ad0-b278-ee293c1bc352", - "id": "G03.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#collect-audit-logs", + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "A01.35", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "services": [ - "Entra", - "AVD", - "Monitor" + "FrontDoor", + "WAF" ], "severity": "Medium", - "subcategory": "Management", - "text": "Enable diagnostic and audit logging", + "subcategory": "App delivery - Front Door", + "text": "Specify the unknown (ZZ) location when geo-filtering traffic with the Azure Front Door WAF. Avoid accidentally blocking legitimate requests when IP addresses can't be geo-matched.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Assign the least privilege required by defining administrative, operations, and engineering roles to Azure RBAC roles. To limit access to high privilege roles within your Azure Virtual Desktop landing zone, consider integration with Azure Privileged Identity Management (PIM). Maintaining knowledge of which team is responsible for each particular administrative area helps you determine Azure role-based access control (RBAC) roles and configuration.", - "guid": "baaab757-1849-4ab8-893d-c9fc9d1bb73b", - "id": "G03.06", - "link": "https://docs.microsoft.com/azure/virtual-desktop/rbac", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hub provides encryption of data at rest. If you use your own key, the data is still encrypted using the Microsoft-managed key, but in addition the Microsoft-managed key will be encrypted using the customer-managed key. ", + "guid": "7aaf12e7-b94e-4f6e-847d-2d92981b1cd6", + "link": "https://learn.microsoft.com/azure/event-hubs/configure-customer-managed-key", "services": [ - "Entra", - "AVD", - "RBAC" + "EventHubs" ], "severity": "Low", - "subcategory": "Management", - "text": "Assess the requirement to use custom RBAC roles for AVD management", - "waf": "Security" + "subcategory": "Data Protection", + "text": "Use customer-managed key option in data at rest encryption when required", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" }, { "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD users should not have permission to install application. If required, Windows Defender Application Control (WDAC) can be used to control which drivers and applications are allowed to run on their Windows clients. ", - "guid": "b9ea80c8-0628-49fc-ae63-125aa4c0a284", - "id": "G03.07", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#windows-defender-application-control", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hubs namespaces permit clients to send and receive data with TLS 1.0 and above. To enforce stricter security measures, you can configure your Event Hubs namespace to require that clients send and receive data with a newer version of TLS. If an Event Hubs namespace requires a minimum version of TLS, then any requests made with an older version will fail. ", + "guid": "d2f54b29-769e-43a6-a0e7-828ac936657e", + "link": "https://learn.microsoft.com/azure/event-hubs/transport-layer-security-configure-minimum-version", "services": [ - "AVD", - "Defender" + "EventHubs" ], "severity": "Medium", - "subcategory": "Management", - "text": "Restrict users from installing un-authorized applications", - "waf": "Security" + "subcategory": "Data Protection", + "text": "Enforce a minimum required version of Transport Layer Security (TLS) for requests ", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" }, { "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Enabling MFA and CA lets you manage risks before you grant users access to your AVD environment. When deciding which users to grant access to, we recommend you also consider who the user is, how they sign in, and which device they're using. Additional details and configuration procedures are provided in the companion article. Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", - "guid": "916d697d-8ead-4ed2-9bdd-186f1ac252b9", - "id": "G04.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-mfa", + "checklist": "Azure Event Hub Review", + "description": "When you create an Event Hubs namespace, a policy rule named RootManageSharedAccessKey is automatically created for the namespace. This policy has manage permissions for the entire namespace. It’s recommended that you treat this rule like an administrative root account and don’t use it in your application. Using AAD as an authentication provider with RBAC is recommended. ", + "guid": "13b0f566-4b1e-4944-a459-837ee79d6c6d", + "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature#shared-access-authorization-policies", "services": [ + "TrafficManager", + "EventHubs", + "AzurePolicy", "Entra", - "AVD" + "RBAC" ], "severity": "Medium", - "subcategory": "Microsoft Entra ID", - "text": "Evaluate the usage of Multi-Factor Authentication (MFA) and Conditional Access (CA) for AVD users", - "waf": "Security" + "subcategory": "Identity and Access Management", + "text": "Avoid using root account when it is not necessary", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" }, { "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "If Zero Trust is a requirement, review the companion article in the 'More Info' column. It provides steps to apply the principles of Zero Trust to an Azure Virtual Desktop deployment.", - "guid": "221102d0-90af-49fc-b2b7-8d3fe397e43", - "id": "G05.01", - "link": "https://learn.microsoft.com/security/zero-trust/azure-infrastructure-avd", + "checklist": "Azure Event Hub Review", + "description": "Managed identities for Azure resources can authorize access to Event Hubs resources using Azure AD credentials from applications running in Azure Virtual Machines (VMs), Function apps, Virtual Machine Scale Sets, and other services. By using managed identities for Azure resources together with Azure AD authentication, you can avoid storing credentials with your applications that run in the cloud. ", + "guid": "3a365a5c-7acb-4e48-abd5-4cd79f2e8776", + "link": "https://learn.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest", "services": [ - "AVD" + "Storage", + "VM", + "EventHubs", + "AKV", + "Entra" ], "severity": "Medium", - "subcategory": "Zero Trust", - "text": "Review and Apply Zero Trust principles and guidance", - "waf": "Security" + "subcategory": "Identity and Access Management", + "text": "When possible, your application should be using a managed identity to authenticate to Azure Event Hub. If not, consider having the storage credential (SAS, service principal credential) in Azure Key Vault or an equivalent service", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "If used, make sure to check the list of best practices and recommendations described in the referenced article.", - "guid": "9164e990-9ae2-48c8-9c33-b6b7808bafe6", - "id": "H01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files#best-practices-for-azure-virtual-desktop", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "When creating permissions, provide fine-grained control over a client's access to Azure Event Hub. Permissions in Azure Event Hub can and should be scoped to the individual resource level e.g. consumer group, event hub entity, event hub namespaces, etc.", + "guid": "8357c559-675c-45ee-a5b8-6ad8844ce3b2", + "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory#azure-built-in-roles-for-azure-event-hubs", "services": [ - "AVD", - "Storage" + "Entra", + "EventHubs", + "RBAC" ], - "severity": "Medium", - "subcategory": "Azure Files", - "text": "Check best-practices for Azure Files", - "waf": "Performance" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "Use least privilege data plane RBAC", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "SMB Multichannel enables clients to use multiple network connections that provide increased performance while lowering the cost of ownership. Increased performance is achieved through bandwidth aggregation over multiple NICs and utilizing Receive Side Scaling (RSS) support for NICs to distribute the IO load across multiple CPUs.", - "guid": "5784b6ca-5e9e-4bcf-8b54-c95459ea7369", - "id": "H01.02", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-smb-multichannel-performance", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hub resource logs include operational logs, virtual network and Kafka logs. Runtime audit logs capture aggregated diagnostic information for all data plane access operations (such as send or receive events) in Event Hubs.", + "guid": "b38b875b-a1cf-4104-a900-3a4d3ce474db", + "link": "https://learn.microsoft.com/azure/event-hubs/monitor-event-hubs-reference", "services": [ - "AVD", - "Storage", - "Cost", - "ACR" + "VNet", + "EventHubs", + "Monitor" ], - "severity": "Low", - "subcategory": "Azure Files", - "text": "Enable SMB multichannel when using a premium file share to host FSLogix profile containers.", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Enable logging for security investigation. Use Azure Monitor to captured metrics and logs such as resource logs, runtime audit logs and Kafka logs", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "If a second region is required for DR purposes verify NetApp availability in there as well.", - "guid": "4a359836-ee79-4d6c-9d3a-364a5b7abae3", - "id": "H02.01", - "link": "https://azure.microsoft.com/global-infrastructure/services/", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hub by default has a public IP address and is Internet-reachable. Private endpoints allow traffic between your virtual network and Azure Event Hub traverses over the Microsoft backbone network. In addition to that, you should disable public endpoints if those are not used. ", + "guid": "5abca2a4-eda1-4dae-8cc9-5d48c6b791dc", + "link": "https://learn.microsoft.com/azure/event-hubs/private-link-service", "services": [ - "AVD", - "Storage" + "VNet", + "EventHubs", + "PrivateLink" ], "severity": "Medium", - "subcategory": "Azure NetApp Files", - "text": "If NetApp Files storage is required, check storage service availability in your specific region.", - "waf": "Reliability" + "subcategory": "Networking", + "text": "Consider using private endpoints to access Azure Event Hub and disable public network access when applicable.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "CA option is a recommended setting in the FSLogix scenario, as it enables a more resilient SMB session between the Session Host and NetApp Files.", - "guid": "a2661898-866a-4c8d-9d1f-8cfc86e88024", - "id": "H02.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-fslogix-profile-container", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "With IP firewall, you can restrict public endpoint further to only a set of IPv4 addresses or IPv4 address ranges in CIDR (Classless Inter-Domain Routing) notation. ", + "guid": "a0e6c465-89e5-458b-a37d-3974d1112dbd", + "link": "https://learn.microsoft.com/azure/event-hubs/event-hubs-ip-filtering", "services": [ - "AVD", - "Storage" + "EventHubs" ], "severity": "Medium", - "subcategory": "Azure NetApp Files", - "text": "If NetApp Files storage is used enable CA (Continuous Availability) option to increase resiliency", - "waf": "Reliability" + "subcategory": "Networking", + "text": "Consider only allowing access to Azure Event Hub namespace from specific IP addresses or ranges", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "An Active Directory Site should be created for the Azure virtual network environment where Azure NetApp Files (ANF) subnet will be created, and that site name should be specified in the ANF connection property when executing the join procedure as explained in the reference article.", - "guid": "6647e977-db49-48a8-bc35-743f17499d42", - "id": "H02.03", - "link": "https://docs.microsoft.com/azure/azure-netapp-files/create-active-directory-connections", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable image export to prevent data exfiltration. Note that this will prevent image import of images into another ACR instance.", + "guid": "ab91932c-9fc9-4d1b-a880-37f5e6bfcb9e", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/container-registry/data-loss-prevention", "services": [ - "VNet", - "AVD", - "Storage" + "ACR" ], "severity": "High", - "subcategory": "Azure NetApp Files", - "text": "If Azure NetApp Files storage is used, check Active Directory Site name setting in the Active Directory Connection configuration", - "waf": "Reliability" + "subcategory": "Data Protection", + "text": "Disable Azure Container Registry image export", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Possible options: Standard HDD, Standard SSD, or Premium SSD. Ephemeral disks are not supported, Ultra-Disks not recommended. Recommended to evaluate Premium for OS disk if user density is not low, and if Cloud Cache will be used. ", - "guid": "3611c818-b0a0-4bc5-80e4-3a18a9cd289c", - "id": "H03.01", - "link": "https://docs.microsoft.com/azure/virtual-machines/disks-types", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Enable audit compliance visibility by enabling Azure Policy for Azure Container Registry", + "guid": "d503547c-d447-4e82-9128-a7100f1cac6d", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-azure-policy", "services": [ - "AVD", - "Storage" + "AzurePolicy", + "ACR" ], - "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Determine which type of managed disk will be used for the Session Hosts", - "waf": "Performance" + "severity": "High", + "subcategory": "Data Protection", + "text": "Enable Azure Policies for Azure Container Registry", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Possible options are: Azure NetApp Files, Azure Files, VM based File Server. File-server it is not recommended. Azure Files Premium typically a good starting point. NetApp usually required for large scale / high-performant environment. For a detailed comparison see the article in the 'More Info' column.", - "guid": "ed6b17db-8255-4462-b2ae-e4553afc8339", - "id": "H03.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "The Azure Key Vault (AKV) is used to store a signing key that can be utilized by?notation?with the notation AKV plugin (azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach these signatures using the?az?or?oras?CLI commands.", + "guid": "d345293c-7639-4637-a551-c5c04e401955", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-tutorial-sign-build-push", "services": [ - "AVD", - "Storage", - "VM" + "AKV", + "ACR" ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "Determine which storage backend solution will be used for FSLogix Profiles", - "waf": "Performance" + "subcategory": "Data Protection", + "text": "Sign and Verify containers with notation (Notary v2)", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Every Host Pool should use a separate set of storage accounts/volumes (at least one) and shares. Users should have a different profile for each Host Pool since settings and configurations are specific to each Host Pool. Additionally, accessing different Host Pools at the same time can cause errors on the shared user profile VHD/X. Usage of different storage accounts/volumes for multiple shares is also recommended to scale independently.", - "guid": "2fad62bd-5004-453c-ace4-64d862e7f5a4", - "id": "H03.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Azure Container Registry automatically encrypts images and other artifacts that you store. By default, Azure automatically encrypts the registry content at rest by using service-managed keys. By using a customer-managed key, you can supplement default encryption with an additional encryption layer.", + "guid": "0bd05dc2-efd5-4d76-8d41-d2500cc47b49", + "id": "A01.04", + "link": "https://learn.microsoft.com/azure/container-registry/tutorial-customer-managed-keys", "services": [ - "AVD", - "Storage" + "AKV", + "ACR" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Do not share storage and profiles between different Host Pools", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Data Protection", + "text": "Encrypt registry with a customer managed key", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "As a starting point for estimating profile container storage performance requirements we recommend to assume 10 IOPS per user in the steady state and 50 IOPS per user during sign-in/sign-out. Space requirements is simply obtained based on the maximum profiles size in FSLogix per the total number of users for each Host Pool. Multiple storage accounts can be used for the same Host Pool if required.", - "guid": "680e7828-9c93-4665-9d02-bff4564b0d93", - "id": "H03.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/faq#what-s-the-largest-profile-size-fslogix-can-handle-", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Use managed identities to secure ACRPull/Push RBAC access from client applications", + "guid": "8f42d78e-79dc-47b3-9bd2-a1a27e7a8e90", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", "services": [ - "AVD", - "Storage" + "Entra", + "RBAC", + "ACR" ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "Verify storage scalability limits and Host Pool requirements", - "waf": "Reliability" + "subcategory": "Identity and Access Control", + "text": "Use Managed Identities to connect instead of Service Principals", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Avoid introducing additional latency and costs associated with cross-region network traffic where possible.", - "guid": "8aad53cc-79e2-4e86-9673-57c549675c5e", - "id": "H03.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "The local Administrator account is disabled by default and should not be enabled. Use either Token or RBAC-based access methods instead", + "guid": "be0e38ce-e297-411b-b363-caaab79b198d", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", "services": [ - "AVD", - "Storage", - "Cost" + "Entra", + "RBAC", + "ACR" ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "For optimal performance, the storage solution and the FSLogix profile container should be in the same Azure region.", - "waf": "Performance" + "subcategory": "Identity and Access Control", + "text": "Disable local authentication for management plane access", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "The recommendation in Azure Virtual Desktop is to use Profile Container without Office Container (ODFC) split unless you are planning for specific Business Continuity and Disaster Recovery (BCDR) scenarios as described in the Disaster Recovery section below. https://docs.microsoft.com/fslogix/profile-container-office-container-cncpt ", - "guid": "df47d2d9-2881-4b1c-b5d1-e54a29759e39", - "id": "H04.01", - "link": "https://learn.microsoft.com/fslogix/concepts-container-types#when-to-use-profile-and-odfc-containers", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable Administrator account and assign RBAC roles to principals for ACR Pull/Push operations", + "guid": "387e5ced-126c-4d13-8af5-b20c6998a646", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-roles?tabs=azure-cli", "services": [ - "AVD", - "Storage", - "ASR" + "Entra", + "RBAC", + "ACR" ], "severity": "High", - "subcategory": "FSLogix", - "text": "Do not use Office Containers (ODFC) if not strictly required and justified", - "waf": "Reliability" + "subcategory": "Identity and Access Control", + "text": "Assign AcrPull & AcrPush RBAC roles rather than granting Administrative access to identity principals", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Make sure to configure the following antivirus exclusions for FSLogix Profile Container virtual hard drives, as documented in the referenced article in the 'More Info' column.", - "guid": "83f63047-22ee-479d-9b5c-3632054b69ba", - "id": "H04.02", - "link": "https://learn.microsoft.com/fslogix/overview-prerequisites#configure-antivirus-file-and-folder-exclusions", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable anonymous pull/push access", + "guid": "e338997e-41c7-47d7-acf6-a62a1194956d", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/container-registry/anonymous-pull-access#configure-anonymous-pull-access", "services": [ - "AVD", - "Storage" + "Entra", + "ACR" ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "Configure the recommended antivirus exclusions for FSLogix (includes not scanning VHD(x) files on connect).", + "subcategory": "Identity and Access Control", + "text": "Disable Anonymous pull access", "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Profile containers have a default max size of 30GB. If large Profile Containers are anticipated, and customers wants to try to keep them small, consider using OneDrive to host Office 365 files outside the FSLogix profile.", - "guid": "01e6a84d-e5df-443d-8992-481718d5d1e5", - "id": "H04.03", - "link": "https://docs.microsoft.com/fslogix/profile-container-configuration-reference", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Token authentication doesn't support assignment to an AAD principal. Any tokens provided are able to be used by anyone who can access the token", + "guid": "698dc3a2-fd27-4b2e-8870-1a1252beedf6", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication?tabs=azure-cli", "services": [ - "AVD", - "Storage" + "Entra", + "ACR" ], "severity": "High", - "subcategory": "FSLogix", - "text": "Review and confirm configured maximum profile size in FSLogix", - "waf": "Cost" + "subcategory": "Identity and Access Control", + "text": "Disable repository-scoped access tokens", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Defaults and recommended settings are reported in the companion article in the 'More Info' column. If not recommended keys and/or values must be used, be sure to review with a Microsoft AVD expert and clearly document your choices.", - "guid": "d34aad5e-8c78-4e1d-9666-7313c405674c", - "id": "H04.04", - "link": "https://learn.microsoft.com/fslogix/concepts-configuration-examples", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Deploy container images to an ACR behind a Private endpoint within a trusted network", + "guid": "b3bec3d4-f343-47c1-936d-b55f27a71eee", + "id": "A02.06", "services": [ - "AVD", - "ACR", - "AKV", - "Storage" + "Entra", + "PrivateLink", + "EventHubs", + "ACR" ], "severity": "High", - "subcategory": "FSLogix", - "text": "Review FSLogix registry keys and determine which ones to apply", - "waf": "Reliability" + "subcategory": "Identity and Access Control", + "text": "Deploy images from a trusted environment", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Concurrent or multiple connections are not recommended in Azure Virtual Desktop. Concurrent connections are also not supported by Session Hosts running in an Azure Virtual Desktop Host Pool. OneDrive, if used, doesn't support concurrent or multiple connections using the same container, under any circumstance. For multiple connections, usage of the same profile disk is not recommended.", - "guid": "5e985b85-9c77-43e7-b261-623b775a917e", - "id": "H04.05", - "link": "https://learn.microsoft.com/fslogix/concepts-multi-concurrent-connections", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Only tokens with an ACR audience can be used for authentication. Used when enabling Conditional access policies for ACR", + "guid": "3a041fd3-2947-498b-8288-b3c6a56ceb54", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-enable-conditional-access-policy", "services": [ - "AVD", - "Storage" + "AzurePolicy", + "Entra", + "ACR" ], - "severity": "High", - "subcategory": "FSLogix", - "text": "Avoid usage of concurrent or multiple connections", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Identity and Access Control", + "text": "Disable Azure ARM audience tokens for authentication", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Cloud Cache uses OS drive as local cache storage and may generate lot of pressure on the VM disk. Depending on the VM SKU and size used, the VM temporary drive can be a viable and performant solution where to relocate Cloud Cache cached content. Before adopting this solution, tests should be executed to confirm performance and stability. More details on Cloud Cache can be found here: https://learn.microsoft.com/fslogix/concepts-fslogix-cloud-cache. ", - "guid": "b2d1215a-e114-4ba3-9df5-85ecdcd9bd3b", - "id": "H04.06", - "link": "https://docs.microsoft.com/fslogix/cloud-cache-configuration-reference", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Set up a diagnostic setting to send 'repositoryEvents' & 'LoginEvents' to Log Analytics as the central destination for logging and monitoring. This allows you to monitor control plane activity on the ACR resource itself.", + "guid": "8a488cde-c486-42bc-9bd2-1be77f26e5e6", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/container-registry/monitor-service", "services": [ - "AVD", - "Storage", - "VM" + "Entra", + "ACR", + "Monitor" ], - "severity": "Low", - "subcategory": "FSLogix", - "text": "If FSLogix Cloud Cache is used, consider moving the cache directory to the VM temporary drive.", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Logging and Monitoring", + "text": "Enable diagnostics logging", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "REDIRECTION.XML file is used to control what folders are redirected out of the profile container to the 'C:' drive. Exclusions should be the exception and should never be used unless the specific exclusion is completely understood by the person configuring the exclusion. Exclusions should always be fully tested in the environment where they are intended to be implemented. Configuring exclusions may impact functionality, stability and performance.", - "guid": "0b50ca97-b1d2-473c-b4d9-6e98b0f912de", - "id": "H04.07", - "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt#redirectionsxml", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Service supports disabling public network access either through using service-level IP ACL filtering rule (not NSG or Azure Firewall) or using a 'Disable Public Network Access' toggle switch", + "guid": "21d41d25-00b7-407a-b9ea-b40fd3290798", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", "services": [ - "AVD", - "Storage" + "Firewall", + "PrivateLink", + "ACR", + "VNet" ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "Review the usage of FSLogix redirection.", - "waf": "Cost" + "subcategory": "Network Security", + "text": "Control inbound network access with Private Link", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable public network access if inbound network access is secured using Private Link", + "guid": "cd289ced-6b17-4db8-8554-62f2aee4553a", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-access-selected-networks#disable-public-network-access", "services": [ - "FrontDoor", - "AKV" + "PrivateLink", + "ACR" ], "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "If you use customer-managed TLS certificates with Azure Front Door, use the 'Latest' certificate version. Reduce the risk of outages caused by manual certificate renewal.", - "waf": "Operations" + "subcategory": "Network Security", + "text": "Disable Public Network access", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", - "services": [], + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Only the ACR Premium SKU supports Private Link access", + "guid": "fc833934-8b26-42d6-ac5f-512925498f6d", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-skus", + "services": [ + "PrivateLink", + "ACR" + ], "severity": "Medium", - "subcategory": "App delivery", - "text": "Perform app delivery within landing zones for both internal-facing (corp) and external-facing apps (online).", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "subcategory": "Network Security", + "text": "Use an Azure Container Registry SKU that supports Private Link (Premium SKU)", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", - "guid": "553585a6-abe0-11ed-afa1-0242ac120002", - "id": "A01.03", - "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Azure Defender for containers or equivalent service should be used to scan container images for vulnerabilities", + "guid": "bad37dac-43bc-46ce-8d7a-a9b24604489a", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", "services": [ - "AppGW" + "Defender", + "ACR" + ], + "severity": "Low", + "subcategory": "Network Security", + "text": "Enable Defender for Containers to scan Azure Container Registry for vulnerabilities", + "waf": "Security" + }, + { + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", + "guid": "4451e1a2-d345-4293-a763-9637a551c5c0", + "id": "A05.01", + "services": [ + "ACR" ], "severity": "Medium", - "subcategory": "App delivery - App Gateway", - "text": "Ensure you are using Application Gateway v2 SKU", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "subcategory": "Vulnerability Management", + "text": "Deploy validated container images", + "waf": "Security" + }, + { + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", + "guid": "4e401955-387e-45ce-b126-cd132af5b20c", + "id": "A05.02", + "services": [ + "ACR" + ], + "severity": "High", + "subcategory": "Vulnerability Management", + "text": "Use up-to-date platforms, languages, protocols and frameworks", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", - "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", - "id": "A01.04", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "Define a resource group structure for placement of Azure Arc-enabled servers resources", + "guid": "585e1112-9bd7-4ba0-82f7-b94ef6e043d2", "services": [ - "LoadBalancer" + "Arc" ], - "severity": "Medium", - "subcategory": "App delivery - Load Balancer", - "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", - "waf": "Security" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "One or more resource groups is required for onboarding servers into Azure", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", - "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", - "id": "A01.05", - "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", + "category": "Foundation", + "checklist": "Azure Arc Review", + "guid": "aa359271-8e6e-4205-8725-769e46691e88", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", "services": [ - "VNet", - "AppGW" + "Arc", + "Entra" ], "severity": "Medium", - "subcategory": "App delivery - App Gateway", - "text": "Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Security" + "subcategory": "Capacity Planning", + "text": "Take Azure Active Directory object limitations into account", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "description": "Administration of reverse proxies in general and WAF in particular is closer to the application than to networking, so they belong in the same subscription as the app. Centralizing the Application Gateway and WAF in the connectivity subscription might be OK if it is managed by one single team.", - "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", - "id": "A01.06", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "The following resource providers needs to be registered: Microsoft.HybridCompute, Microsoft.GuestConfiguration, Microsoft.HybridConnectivity", + "guid": "deace4bb-1deb-44c6-9fc3-fc14eeaa3692", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-resource-providers", "services": [ - "Entra", - "AppGW", - "VNet", - "WAF", - "NVA", + "Arc", "Subscriptions" ], - "severity": "Medium", - "subcategory": "App delivery - App Gateway", - "text": "Deploy Azure Application Gateway v2 or partner NVAs used for proxying inbound HTTP(S) connections within the landing-zone virtual network and with the apps that they're securing.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Security" + "severity": "High", + "subcategory": "General", + "text": "Has the Resource providers required been registered in all subscriptions", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", - "id": "A01.07", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "Aligning with an existing or creating an Azure tagging strategy is recommended. Resource tags allow you to quickly locate it, automate operational tasks amd more. ", + "guid": "c6d37331-65c7-4acb-b44b-be609d79f2e8", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/", "services": [ - "DDoS" + "Arc" ], - "severity": "Medium", - "subcategory": "App delivery - App Gateway", - "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "severity": "Low", + "subcategory": "General", + "text": "Has a tagging strategy for Azure Arc-enabled servers been defined", + "waf": "Cost" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", - "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", - "id": "A01.08", - "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", - "services": [], - "severity": "Medium", - "subcategory": "App delivery - App Gateway", - "text": "Configure autoscaling with a minimum amount of instances of two.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Reliability" + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "Installation of the connected machine agent is supported on most newer Windows and Linux operative systems, review the link to se the latest list", + "guid": "7778424c-5167-475c-9fa9-5b96ad88408e", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#supported-operating-systems", + "services": [ + "Arc" + ], + "severity": "High", + "subcategory": "General", + "text": "What operating systems need to be Azure Arc-enabled", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", - "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", - "id": "A01.09", - "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "There are software requirements to the agent installation. Some might require a system reboot after installation, review to link", + "guid": "372734b8-76ba-428f-8145-901365d38e53", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#software-requirements", "services": [ - "ACR", - "AppGW" + "Arc" ], - "severity": "Medium", - "subcategory": "App delivery - App Gateway", - "text": "Deploy Application Gateway across Availability Zones", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "severity": "High", + "subcategory": "General", + "text": "Are required software installed on Windows and Linux servers to support the installation", + "waf": "Operations" + }, + { + "category": "Foundation", + "checklist": "Azure Arc Review", + "guid": "d44c7c89-19ca-41f6-b521-5ae514ba34d4", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=azure-arc®ions=all", + "services": [ + "Arc" + ], + "severity": "High", + "subcategory": "General", + "text": "Make sure to use a supported Azure region", "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", - "id": "A01.10", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "The scope include organization into management groups, subscriptions, and resource groups.", + "guid": "f9ccbd86-8266-4abc-a264-f9a19bf39d95", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/organize-inventory-servers#organize-resources-with-built-in-azure-hierarchies", "services": [ - "WAF", - "FrontDoor", - "AzurePolicy" + "Arc", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Use Azure Front Door with WAF policies to deliver and help protect global HTTP/S apps that span multiple Azure regions.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "severity": "Low", + "subcategory": "Organization", + "text": "Define the structure for Azure management of resources", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "3f29812b-2363-4cef-b179-b599de0d5973", - "id": "A01.11", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Define RBAC rules to the servers / resource groups as required for servers management, the 'Azure Connected Machine Resource Administrator' or 'Hybrid Server Resource Administrator' role would be sufficient for management of the Azure Arc-enabled servers resources in Azure", + "guid": "9bf39d95-d44c-47c8-a19c-a1f6d5215ae5", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#identity-and-access-control", "services": [ - "WAF", - "FrontDoor", - "AppGW", - "AzurePolicy" + "Arc", + "Entra", + "RBAC" ], "severity": "Medium", - "subcategory": "App delivery", - "text": "When using Front Door and Application Gateway to help protect HTTP/S apps, use WAF policies in Front Door. Lock down Application Gateway to receive traffic only from Front Door.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "subcategory": "Access", + "text": "Assign RBAC rights to Azure AD user/group access for managing Azure Arc-enabled servers", "waf": "Security" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "A01.12", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Identity", + "checklist": "Azure Arc Review", + "guid": "14ba34d4-585e-4111-89bd-7ba012f7b94e", + "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-nonaad", "services": [ - "TrafficManager" + "AKV", + "Arc", + "Entra" ], - "severity": "High", - "subcategory": "App delivery - Traffic Manager", - "text": "Use Traffic Manager to deliver global apps that span protocols other than HTTP/S.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Access", + "text": "Consider using managed identities for applications to access Azure resources like Key Vault example in link", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "A01.13", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "An Azure subscription must be parented to the same Azure AD tenant", + "guid": "35ac9322-23e1-4380-8523-081a94174158", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", "services": [ + "Arc", "Entra", - "AVD" + "Subscriptions" ], - "severity": "Low", - "subcategory": "App delivery", - "text": "If users only need access to internal applications, has Microsoft Entra ID Application Proxy been considered as an alternative to Azure Virtual Desktop (AVD)?", - "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", - "waf": "Security" + "severity": "High", + "subcategory": "Requirements", + "text": "An Azure Active Directory tenant must be available with at least one subscription", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "A01.14", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Users (or SPs) need the 'Azure Connected Machine Onboarding' or 'Contributor' role to onboarding of servers", + "guid": "33ee7ad6-c6d3-4733-865c-7acbe44bbe60", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", "services": [ - "Entra" + "Arc", + "Entra", + "RBAC" ], "severity": "Medium", - "subcategory": "App delivery", - "text": "To reduce the number of firewall ports open for incoming connections in your network, consider using Microsoft Entra ID Application Proxy to give remote users secure and authenticated access to internal applications.", - "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "subcategory": "Requirements", + "text": "Define which users (AAD user/groups) has access to onboard Azure Arc-enabled servers", "waf": "Security" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", - "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "A01.15", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Ensure to only add the rights to users or groups that is required to perform their role", + "guid": "9d79f2e8-7778-4424-a516-775c6fa95b96", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", "services": [ - "WAF", - "Storage", - "FrontDoor" + "Arc", + "Entra", + "RBAC" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", + "severity": "Medium", + "subcategory": "Security", + "text": "Use the principle of least privileged", "waf": "Security" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "A01.16", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "A service principle with the 'Azure Connected Machine Onboarding' role is required for at-scale onboarding of servers, consider more SP's if onboarding is done by different teams/decentralized management", + "guid": "ad88408e-3727-434b-a76b-a28f21459013", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", "services": [ - "TrafficManager", - "FrontDoor" + "Arc", + "Entra", + "RBAC" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", + "severity": "Medium", + "subcategory": "Security", + "text": "How many Service Principals are needed for onboarding Arc-enabled servers into Azure", "waf": "Security" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "A01.17", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Consider assigning the rights for the 'Azure Connected Machine Onboarding' role at the resource group level, to control the resource creation", + "guid": "65d38e53-f9cc-4bd8-9826-6abca264f9a1", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", "services": [ - "FrontDoor" + "Arc", + "Entra", + "RBAC" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Use the same domain name on Azure Front Door and your origin. Mismatched host names can cause subtle bugs.", + "severity": "Medium", + "subcategory": "Security", + "text": "Limit the rights to onboard Azure Arc-enabled servers to the desired resource groups", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "A01.18", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", - "services": [ - "FrontDoor" - ], - "severity": "Low", - "subcategory": "App delivery - Front Door", - "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", - "waf": "Performance" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "A01.19", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Plan for agent deployments at scale", + "guid": "6ee79d6b-5c2a-4364-a4b6-9bad38aad53c", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment", "services": [ - "FrontDoor" + "Arc", + "Monitor" ], "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Select good health probe endpoints for Azure Front Door. Consider building health endpoints that check all of your application's dependencies.", - "waf": "Reliability" + "subcategory": "Management", + "text": "Define a strategy for agent provisioning", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "A01.20", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Use Microsoft Update to ensure that the connected machine agent is always up-to-date", + "guid": "c78e1d76-6673-457c-9496-74c5ed85b859", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#upgrade-the-agent", "services": [ - "FrontDoor" + "Arc", + "Monitor" ], - "severity": "Low", - "subcategory": "App delivery - Front Door", - "text": "Use HEAD health probes with Azure Front Door, to reduce the traffic that Front Door sends to your application.", - "waf": "Performance" + "severity": "High", + "subcategory": "Management", + "text": "Define a strategy for agent updates", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", - "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "A01.21", - "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Recommendation is to use Azure Policy, or another automation tool like Azure DevOps - important is to avoid configuration drift.", + "guid": "c7733be2-a1a2-47b7-95a9-1be1f388ff39", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-vm-extensions", "services": [ - "LoadBalancer" + "AzurePolicy", + "Arc", + "Monitor" ], - "severity": "High", - "subcategory": "App delivery - Load Balancer", - "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Management", + "text": "Define a strategy for extension installation", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "A01.22", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Use automatic upgrades where available and define an update strategy for all extensions not supporting automatic upgrades.", + "guid": "4c2bd463-cbbb-4c86-a195-abb91a4ed90d", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-automatic-vm-extension-upgrade?tabs=azure-portal", "services": [ - "AKV", - "FrontDoor", - "Cost" + "Arc", + "Monitor" ], "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Use managed TLS certificates with Azure Front Door. Reduce operational cost and risk of outages due to certificate renewals.", + "subcategory": "Management", + "text": "Define a strategy for extension updates", "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "A01.23", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Azure Automanage help implement Microsoft best-practices for servers management in Azure", + "guid": "7a927c39-74d1-4102-aac6-aae01e6a84de", + "link": "https://learn.microsoft.com/azure/automanage/automanage-arc", "services": [ - "WAF", - "FrontDoor" + "Arc", + "Monitor" ], "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Define your Azure Front Door WAF configuration as code. By using code, you can more easily adopt new ruleset versions and gain additional protection.", + "subcategory": "Management", + "text": "Consider using Azure Automanage to control settings and avoid configuration drift on servers", "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "A01.24", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "37b6b780-cbaf-4e6c-9658-9d457a927c39", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", "services": [ - "FrontDoor" + "Arc", + "Monitor" ], "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Use end-to-end TLS with Azure Front Door. Use TLS for connections from your clients to Front Door, and from Front Door to your origin.", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Monitor for unresponsive agents", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "A01.25", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "74d1102c-ac6a-4ae0-8e6a-84de5df47d2d", + "link": "https://learn.microsoft.com/azure/azure-monitor/agents/log-analytics-agent#data-collected", "services": [ - "FrontDoor" + "Arc", + "Monitor" ], "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Use HTTP to HTTPS redirection with Azure Front Door. Support older clients by redirecting them to an HTTPS request automatically.", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Design a monitoring strategy to send metrics and logs to an Log Analytics workspace", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "A01.26", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "92881b1c-d5d1-4e54-a296-59e3958fd782", + "link": "https://learn.microsoft.com/azure/service-health/resource-health-alert-monitor-guide", "services": [ - "WAF", - "FrontDoor" + "Arc", + "Monitor" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", - "waf": "Security" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use notification in Activity logs to receive notification on unexpected changes to the resources", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "A01.27", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "89c93555-6d02-4bfe-9564-b0d834a34872", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/learn/tutorial-enable-vm-insights", "services": [ - "WAF", - "FrontDoor" + "Arc", + "Monitor" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", - "waf": "Security" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Monitor for compliance and operational monitoring", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "A01.28", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "5df47d2d-9288-41b1-ad5d-1e54a29659e3", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", "services": [ - "WAF", - "FrontDoor" + "Arc", + "Monitor" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", - "waf": "Security" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Create an alert to identify Azure Arc-enabled servers that aren't using the latest version of the Azure connected machine agent", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "A01.29", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Use Update Management in Azure Automation or the new Update Management Center (preview) functionality to ensure update management of servers", + "guid": "ae2cc84c-37b6-4b78-8cba-fe6c46589d45", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/hybrid/server/best-practices/arc-update-management", "services": [ - "WAF", - "FrontDoor" + "Arc", + "Monitor" ], - "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", - "waf": "Security" + "severity": "Low", + "subcategory": "Security", + "text": "Use Azure Arc-enabled servers to control software updates deployments to servers", + "waf": "Operations" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "A01.30", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "The Connected Machine Agent will by default communicate with Azure services over public Internet connectivity using HTTPS (TCP port 443)", + "guid": "f6e043d2-aa35-4927-88e6-e2050725769e", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#details", "services": [ - "WAF", - "FrontDoor" + "Arc" ], "severity": "High", - "subcategory": "App delivery - Front Door", - "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", - "waf": "Security" + "subcategory": "Networking", + "text": "Define a connectivity method from the server to Azure", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "A01.31", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "The Connected Machine Agent can be configured to use a proxy server, it is recommended to define the proxy server address using 'azcmagent config set proxy.url' command on the local system.", + "guid": "46691e88-35ac-4932-823e-13800523081a", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#update-or-remove-proxy-settings", "services": [ - "WAF", - "FrontDoor" + "Arc" ], "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Use the latest Azure Front Door WAF ruleset versions. Ruleset updates are regularly updated to take account of the current threat landscape.", - "waf": "Security" + "subcategory": "Networking", + "text": "Is a proxy server a required for communication over the Public Internet", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "A01.32", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "The Connected Machine Agent can use a Private Link for communication with Azure Services over an existing ExpressRoute or VPN connection", + "guid": "94174158-33ee-47ad-9c6d-3733165c7acb", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/private-link-security", "services": [ - "WAF", - "FrontDoor" + "ExpressRoute", + "Arc", + "PrivateLink", + "VPN" ], "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Add rate limiting to the Azure Front Door WAF. Rate limiting blocks clients accidentally or intentionally sending large amounts of traffic in a short period of time.", - "waf": "Security" + "subcategory": "Networking", + "text": "Is a private (not public Internet) connection required?", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "A01.33", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "Firewall configuration might be required for the agent to communicate with Azure, use the link to see ServiceTags and/or URL's required", + "guid": "e44bbe60-9d79-4f2e-a777-8424c516775c", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#service-tags", "services": [ - "WAF", - "FrontDoor" + "Arc" ], - "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Use a high threshold for Azure Front Door WAF rate limits. High rate limit thresholds avoid blocking legitimate traffic, while still providing protection against extremely high numbers of requests that might overwhelm your infrastructure. ", + "severity": "High", + "subcategory": "Networking", + "text": "Will Firewall configurations be needed in order to ensure communication with Azure Services?", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "A01.34", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "Use available automation tool for the system in question to regularly update the Azure endpoints", + "guid": "6fa95b96-ad88-4408-b372-734b876ba28f", + "link": "https://www.microsoft.com/download/details.aspx?id=56519", "services": [ - "WAF", - "FrontDoor" + "Arc" ], "severity": "Low", - "subcategory": "App delivery - Front Door", - "text": "Geo-filter traffic by using the Azure Front Door WAF. Allow traffic only from expected regions, and block traffic from other regions.", + "subcategory": "Networking", + "text": "Can the Firewall or Proxy rules be automated updated if Service Tags or IP addresses change", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Application Delivery Networking", - "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "A01.35", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "Configure Servers to use Transport Layer Security (TLS) version 1.2", + "guid": "21459013-65d3-48e5-9f9c-cbd868266abc", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#transport-layer-security-12-protocol", "services": [ - "WAF", - "FrontDoor" + "Arc" ], - "severity": "Medium", - "subcategory": "App delivery - Front Door", - "text": "Specify the unknown (ZZ) location when geo-filtering traffic with the Azure Front Door WAF. Avoid accidentally blocking legitimate requests when IP addresses can't be geo-matched.", + "severity": "High", + "subcategory": "Networking", + "text": "Always use secure communication for Azure where possible", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hub provides encryption of data at rest. If you use your own key, the data is still encrypted using the Microsoft-managed key, but in addition the Microsoft-managed key will be encrypted using the customer-managed key. ", - "guid": "7aaf12e7-b94e-4f6e-847d-2d92981b1cd6", - "link": "https://learn.microsoft.com/azure/event-hubs/configure-customer-managed-key", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "All extensions (like log analytics etc.) have separate network requirements, be sure to include all in the network design.", + "guid": "a264f9a1-9bf3-49d9-9d44-c7c8919ca1f6", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/hybrid/arc-enabled-servers/eslz-arc-servers-connectivity#define-extensions-connectivity-method", "services": [ - "EventHubs" + "Arc", + "PrivateLink", + "Monitor" ], "severity": "Low", - "subcategory": "Data Protection", - "text": "Use customer-managed key option in data at rest encryption when required", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" - }, - { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hubs namespaces permit clients to send and receive data with TLS 1.0 and above. To enforce stricter security measures, you can configure your Event Hubs namespace to require that clients send and receive data with a newer version of TLS. If an Event Hubs namespace requires a minimum version of TLS, then any requests made with an older version will fail. ", - "guid": "d2f54b29-769e-43a6-a0e7-828ac936657e", - "link": "https://learn.microsoft.com/azure/event-hubs/transport-layer-security-configure-minimum-version", - "services": [ - "EventHubs" - ], - "severity": "Medium", - "subcategory": "Data Protection", - "text": "Enforce a minimum required version of Transport Layer Security (TLS) for requests ", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" + "subcategory": "Networking", + "text": "Include communication for Azure Arc-enabled Servers extensions in the design (firewall/proxy/private link)", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "When you create an Event Hubs namespace, a policy rule named RootManageSharedAccessKey is automatically created for the namespace. This policy has manage permissions for the entire namespace. It’s recommended that you treat this rule like an administrative root account and don’t use it in your application. Using AAD as an authentication provider with RBAC is recommended. ", - "guid": "13b0f566-4b1e-4944-a459-837ee79d6c6d", - "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature#shared-access-authorization-policies", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "ac6aae01-e6a8-44de-9df4-7d2d92881b1c", + "link": "https://learn.microsoft.com/azure/governance/policy/", "services": [ - "Entra", "AzurePolicy", - "TrafficManager", - "EventHubs", - "RBAC" - ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Avoid using root account when it is not necessary", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" - }, - { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Managed identities for Azure resources can authorize access to Event Hubs resources using Azure AD credentials from applications running in Azure Virtual Machines (VMs), Function apps, Virtual Machine Scale Sets, and other services. By using managed identities for Azure resources together with Azure AD authentication, you can avoid storing credentials with your applications that run in the cloud. ", - "guid": "3a365a5c-7acb-4e48-abd5-4cd79f2e8776", - "link": "https://learn.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest", - "services": [ - "Entra", - "AKV", - "EventHubs", - "Storage", - "VM" - ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "When possible, your application should be using a managed identity to authenticate to Azure Event Hub. If not, consider having the storage credential (SAS, service principal credential) in Azure Key Vault or an equivalent service", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" - }, - { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "When creating permissions, provide fine-grained control over a client's access to Azure Event Hub. Permissions in Azure Event Hub can and should be scoped to the individual resource level e.g. consumer group, event hub entity, event hub namespaces, etc.", - "guid": "8357c559-675c-45ee-a5b8-6ad8844ce3b2", - "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory#azure-built-in-roles-for-azure-event-hubs", - "services": [ - "EventHubs", - "RBAC", - "Entra" + "Arc" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Use least privilege data plane RBAC", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" + "severity": "Medium", + "subcategory": "Management", + "text": "Use Azure Policy to implement a governance model for hybrid connected servers", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hub resource logs include operational logs, virtual network and Kafka logs. Runtime audit logs capture aggregated diagnostic information for all data plane access operations (such as send or receive events) in Event Hubs.", - "guid": "b38b875b-a1cf-4104-a900-3a4d3ce474db", - "link": "https://learn.microsoft.com/azure/event-hubs/monitor-event-hubs-reference", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "5c2a3649-4b69-4bad-98aa-d53cc78e1d76", + "link": "https://learn.microsoft.com/azure/governance/machine-configuration/overview", "services": [ - "EventHubs", - "VNet", - "Monitor" + "Arc" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable logging for security investigation. Use Azure Monitor to captured metrics and logs such as resource logs, runtime audit logs and Kafka logs", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" + "subcategory": "Management", + "text": "Consider using Machine configurations for in guest OS configurations", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hub by default has a public IP address and is Internet-reachable. Private endpoints allow traffic between your virtual network and Azure Event Hub traverses over the Microsoft backbone network. In addition to that, you should disable public endpoints if those are not used. ", - "guid": "5abca2a4-eda1-4dae-8cc9-5d48c6b791dc", - "link": "https://learn.microsoft.com/azure/event-hubs/private-link-service", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "667357c4-4967-44c5-bd85-b859c7733be2", + "link": "https://learn.microsoft.com/azure/governance/machine-configuration/machine-configuration-create", "services": [ - "EventHubs", - "PrivateLink", - "VNet" + "AzurePolicy", + "Arc" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Consider using private endpoints to access Azure Event Hub and disable public network access when applicable.", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "subcategory": "Management", + "text": "Evaluate the need for custom Guest Configuration policies", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "With IP firewall, you can restrict public endpoint further to only a set of IPv4 addresses or IPv4 address ranges in CIDR (Classless Inter-Domain Routing) notation. ", - "guid": "a0e6c465-89e5-458b-a37d-3974d1112dbd", - "link": "https://learn.microsoft.com/azure/event-hubs/event-hubs-ip-filtering", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "49674c5e-d85b-4859-a773-3be2a1a27b77", + "link": "https://learn.microsoft.com/azure/automation/change-tracking/overview", "services": [ - "EventHubs" + "Arc", + "Monitor" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Consider only allowing access to Azure Event Hub namespace from specific IP addresses or ranges", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "subcategory": "Monitoring", + "text": "Consider using change tracking for tracking changes made on the servers", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable image export to prevent data exfiltration. Note that this will prevent image import of images into another ACR instance.", - "guid": "ab91932c-9fc9-4d1b-a880-37f5e6bfcb9e", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/container-registry/data-loss-prevention", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "d5d1e54a-2965-49e3-a58f-d78289c93555", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/data-residency", "services": [ - "ACR" + "Arc" ], - "severity": "High", - "subcategory": "Data Protection", - "text": "Disable Azure Container Registry image export", + "severity": "Medium", + "subcategory": "Requirements", + "text": "Make sure to use an Azure region for storing the metadata approved by the organization", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Enable audit compliance visibility by enabling Azure Policy for Azure Container Registry", - "guid": "d503547c-d447-4e82-9128-a7100f1cac6d", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-azure-policy", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "195abb91-a4ed-490d-ae2c-c84c37b6b780", + "link": "https://learn.microsoft.com/azure/key-vault/general/basic-concepts", "services": [ - "ACR", - "AzurePolicy" + "AKV", + "Arc" ], - "severity": "High", - "subcategory": "Data Protection", - "text": "Enable Azure Policies for Azure Container Registry", + "severity": "Medium", + "subcategory": "Secrets", + "text": "Use Azure Key Vault for certificate management on servers", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "The Azure Key Vault (AKV) is used to store a signing key that can be utilized by?notation?with the notation AKV plugin (azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach these signatures using the?az?or?oras?CLI commands.", - "guid": "d345293c-7639-4637-a551-c5c04e401955", - "id": "A01.03", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-tutorial-sign-build-push", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Consider using a short-lived Azure AD service principal client secrets.", + "guid": "6d02bfe4-564b-40d8-94a3-48726ee79d6b", + "link": "https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret", "services": [ - "ACR", - "AKV" + "AKV", + "Arc", + "Storage", + "Entra" ], "severity": "High", - "subcategory": "Data Protection", - "text": "Sign and Verify containers with notation (Notary v2)", + "subcategory": "Secrets", + "text": "What is the acceptable life time of the secret used by SP's", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Azure Container Registry automatically encrypts images and other artifacts that you store. By default, Azure automatically encrypts the registry content at rest by using service-managed keys. By using a customer-managed key, you can supplement default encryption with an additional encryption layer.", - "guid": "0bd05dc2-efd5-4d76-8d41-d2500cc47b49", - "id": "A01.04", - "link": "https://learn.microsoft.com/azure/container-registry/tutorial-customer-managed-keys", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "A private key is saved to the disk, ensure this is protected using disk encryption", + "guid": "a1a27b77-5a91-4be1-b388-ff394c2bd463", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#using-disk-encryption", "services": [ - "ACR", - "AKV" + "AKV", + "Arc" ], "severity": "Medium", - "subcategory": "Data Protection", - "text": "Encrypt registry with a customer managed key", - "waf": "Security" - }, - { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Use managed identities to secure ACRPull/Push RBAC access from client applications", - "guid": "8f42d78e-79dc-47b3-9bd2-a1a27e7a8e90", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", - "services": [ - "Entra", - "ACR", - "RBAC" - ], - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Use Managed Identities to connect instead of Service Principals", + "subcategory": "Secrets", + "text": "Secure the public key for Azure Arc-enabled Servers", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "The local Administrator account is disabled by default and should not be enabled. Use either Token or RBAC-based access methods instead", - "guid": "be0e38ce-e297-411b-b363-caaab79b198d", - "id": "A02.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Local administrator is required to install the Connected Machine Agent on Windows and Linux systems", + "guid": "29659e39-58fd-4782-a9c9-35556d02bfe4", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-portal#install-manually", "services": [ - "Entra", - "ACR", - "RBAC" + "Arc" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable local authentication for management plane access", + "subcategory": "Security", + "text": "Ensure there is local administrator access for executing the agent installation", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable Administrator account and assign RBAC roles to principals for ACR Pull/Push operations", - "guid": "387e5ced-126c-4d13-8af5-b20c6998a646", - "id": "A02.03", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-roles?tabs=azure-cli", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Members of the local administrator group on Windows and users with root privileges on Linux, have permissions to manage the agent via command line.", + "guid": "564b0d83-4a34-4872-9ee7-9d6b5c2a3649", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#agent-security-and-permissions", "services": [ - "Entra", - "ACR", - "RBAC" + "Arc" ], - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Assign AcrPull & AcrPush RBAC roles rather than granting Administrative access to identity principals", + "severity": "Medium", + "subcategory": "Security", + "text": "Limit the amount of users with local administrator rights to the servers", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable anonymous pull/push access", - "guid": "e338997e-41c7-47d7-acf6-a62a1194956d", - "id": "A02.04", - "link": "https://learn.microsoft.com/azure/container-registry/anonymous-pull-access#configure-anonymous-pull-access", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "4b69bad3-8aad-453c-a78e-1d76667357c4", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication", "services": [ - "Entra", - "ACR" + "Arc", + "Entra" ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Disable Anonymous pull access", + "subcategory": "Security", + "text": "Consider using and restricting access to managed identities for applications.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Token authentication doesn't support assignment to an AAD principal. Any tokens provided are able to be used by anyone who can access the token", - "guid": "698dc3a2-fd27-4b2e-8870-1a1252beedf6", - "id": "A02.05", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication?tabs=azure-cli", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Use Defender for Endpoint or another AV and EDR solution to protect endpoints", + "guid": "5a91be1f-388f-4f39-9c2b-d463cbbbc868", + "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", "services": [ - "Entra", - "ACR" + "Arc", + "Defender" ], - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable repository-scoped access tokens", + "severity": "Medium", + "subcategory": "Security", + "text": "Enable Defender for Servers for all servers to secure hybrid workloads from threats", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Deploy container images to an ACR behind a Private endpoint within a trusted network", - "guid": "b3bec3d4-f343-47c1-936d-b55f27a71eee", - "id": "A02.06", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "cbafe6c4-6589-4d45-9a92-7c3974d1102c", "services": [ - "Entra", - "PrivateLink", - "ACR", - "EventHubs" + "Arc" ], - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Deploy images from a trusted environment", + "severity": "Medium", + "subcategory": "Security", + "text": "Define controls to detect security misconfigurations and track compliance", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Only tokens with an ACR audience can be used for authentication. Used when enabling Conditional access policies for ACR", - "guid": "3a041fd3-2947-498b-8288-b3c6a56ceb54", - "id": "A02.07", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-enable-conditional-access-policy", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "cbbbc868-195a-4bb9-8a4e-d90dae2cc84c", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#extension-allowlists-and-blocklists", "services": [ - "Entra", - "ACR", - "AzurePolicy" + "Arc" ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Disable Azure ARM audience tokens for authentication", + "subcategory": "Security", + "text": "Use allow- or block-lists to control what extensions can be installed on the Azure Arc-enabled servers", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Set up a diagnostic setting to send 'repositoryEvents' & 'LoginEvents' to Log Analytics as the central destination for logging and monitoring. This allows you to monitor control plane activity on the ACR resource itself.", - "guid": "8a488cde-c486-42bc-9bd2-1be77f26e5e6", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/container-registry/monitor-service", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", + "guid": "976f32a7-30d1-6caa-c2a0-207fdc26571b", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", "services": [ - "Entra", - "ACR", - "Monitor" + "Storage", + "Backup", + "AVS" ], "severity": "Medium", - "subcategory": "Logging and Monitoring", - "text": "Enable diagnostics logging", - "waf": "Security" + "subcategory": "Backup", + "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Service supports disabling public network access either through using service-level IP ACL filtering rule (not NSG or Azure Firewall) or using a 'Disable Public Network Access' toggle switch", - "guid": "21d41d25-00b7-407a-b9ea-b40fd3290798", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Microsoft backup service", + "guid": "fc8af7a1-c724-e255-c18d-4ca22a6f27f0", + "id": "A02.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", "services": [ - "PrivateLink", - "ACR", - "VNet", - "Firewall" + "Backup", + "AVS" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Control inbound network access with Private Link", - "waf": "Security" + "subcategory": "Business Continuity", + "text": "Use MABS as your backup solution", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable public network access if inbound network access is secured using Private Link", - "guid": "cd289ced-6b17-4db8-8554-62f2aee4553a", - "id": "A04.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-access-selected-networks#disable-public-network-access", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Best practice - this is Backup, not disaster recovery", + "guid": "be28860f-3d29-a79a-1a0e-36f1b23b36ae", + "id": "A02.02", + "link": "Best practice to deploy backup in the same region as your AVS deployment", "services": [ - "PrivateLink", - "ACR" + "Backup", + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Disable Public Network access", - "waf": "Security" + "subcategory": "Business Continuity", + "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Only the ACR Premium SKU supports Private Link access", - "guid": "fc833934-8b26-42d6-ac5f-512925498f6d", - "id": "A04.03", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-skus", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Best practice - in case AVS is unavailable", + "guid": "4d2f79a5-4ccf-0dfc-557c-49619b99a540", + "id": "A02.03", + "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", "services": [ - "PrivateLink", - "ACR" + "AVS" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Use an Azure Container Registry SKU that supports Private Link (Premium SKU)", - "waf": "Security" + "subcategory": "Business Continuity", + "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Azure Defender for containers or equivalent service should be used to scan container images for vulnerabilities", - "guid": "bad37dac-43bc-46ce-8d7a-a9b24604489a", - "id": "A04.04", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", + "guid": "ff431c40-962c-5182-d536-0c2f0c4ce9e0", + "id": "A02.04", + "link": "Will Disaster Recovery Site Recovery, HCX Disaster Recovery, SRM or back tools be used?", "services": [ - "ACR", - "Defender" + "AVS" ], - "severity": "Low", - "subcategory": "Network Security", - "text": "Enable Defender for Containers to scan Azure Container Registry for vulnerabilities", - "waf": "Security" + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Escalation process with Microsoft in the event of a regional DR", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", - "guid": "4451e1a2-d345-4293-a763-9637a551c5c0", - "id": "A05.01", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Compare SRM with HCX", + "guid": "f379436d-3051-daa0-01fb-dc4e0e04d677", + "id": "A03.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/disaster-recovery-using-vmware-site-recovery-manager", "services": [ - "ACR" + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "Vulnerability Management", - "text": "Deploy validated container images", - "waf": "Security" + "subcategory": "Disaster Recovery", + "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", - "guid": "4e401955-387e-45ce-b126-cd132af5b20c", - "id": "A05.02", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Recovery into Azure instead of Vmware solution", + "guid": "367f71d8-3cf6-51a0-91a5-3db3d570cc19", + "id": "A03.02", + "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", "services": [ - "ACR" + "AVS", + "ASR" ], - "severity": "High", - "subcategory": "Vulnerability Management", - "text": "Use up-to-date platforms, languages, protocols and frameworks", - "waf": "Security" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "Define a resource group structure for placement of Azure Arc-enabled servers resources", - "guid": "585e1112-9bd7-4ba0-82f7-b94ef6e043d2", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Avoid manual tasks as much as possible", + "guid": "ee02ada0-1887-bb3a-b84c-423f45a09ef9", + "id": "A03.03", + "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", "services": [ - "Arc" + "AVS", + "ASR" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "One or more resource groups is required for onboarding servers into Azure", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use Automated recovery plans with either of the Disaster solutions,", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "guid": "aa359271-8e6e-4205-8725-769e46691e88", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Any other datacenter in the same region", + "guid": "0c2b74e5-9c28-780d-1df3-12d3de4aaa76", + "id": "A03.04", + "link": "https://docs.microsoft.com/azure/azure-vmware/connect-multiple-private-clouds-same-region", "services": [ - "Entra", - "Arc" + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Take Azure Active Directory object limitations into account", - "waf": "Performance" + "subcategory": "Disaster Recovery", + "text": "Configure a secondary disaster recovery environment", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "The following resource providers needs to be registered: Microsoft.HybridCompute, Microsoft.GuestConfiguration, Microsoft.HybridConnectivity", - "guid": "deace4bb-1deb-44c6-9fc3-fc14eeaa3692", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-resource-providers", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", + "guid": "c2a34ec4-2933-4e6c-dc36-e20e67abbe3f", + "id": "A03.05", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "Subscriptions", - "Arc" + "AVS", + "ASR" ], - "severity": "High", - "subcategory": "General", - "text": "Has the Resource providers required been registered in all subscriptions", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Assign IP ranges unique to each region", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "Aligning with an existing or creating an Azure tagging strategy is recommended. Resource tags allow you to quickly locate it, automate operational tasks amd more. ", - "guid": "c6d37331-65c7-4acb-b44b-be609d79f2e8", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "ExpressRoute Global Reach can be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or routing must be done through network virtual appliances?", + "guid": "b44fb6ec-bfc1-3a8e-dba2-ca97f0991d2c", + "id": "A03.06", + "link": "This depends if you have multiple AVS Private Clouds. If so and they are in the same region then use AVS Interconnect. If they are in separate regions then use ExpressRoute Global Reach.", "services": [ - "Arc" + "ExpressRoute", + "NVA", + "AVS", + "ASR" ], - "severity": "Low", - "subcategory": "General", - "text": "Has a tagging strategy for Azure Arc-enabled servers been defined", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use Global Reach between DR regions", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "Installation of the connected machine agent is supported on most newer Windows and Linux operative systems, review the link to se the latest list", - "guid": "7778424c-5167-475c-9fa9-5b96ad88408e", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#supported-operating-systems", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "An ExR Global Reach connection will be established to the ExR circuit, no other connections", + "guid": "a2c12df2-07fa-3edd-2cec-fda0b55fb952", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", "services": [ - "Arc" + "VWAN", + "AVS" ], - "severity": "High", - "subcategory": "General", - "text": "What operating systems need to be Azure Arc-enabled", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Direct (no vWAN, no H&S)", + "text": "Global Reach to ExR circuit - no Azure resources", + "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "There are software requirements to the agent installation. Some might require a system reboot after installation, review to link", - "guid": "372734b8-76ba-428f-8145-901365d38e53", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#software-requirements", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use ExR to connect on-premises (other) location to Azure", + "guid": "f62ce162-ba5a-429d-674e-fafa1af5f706", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", "services": [ - "Arc" + "ExpressRoute", + "AVS" ], - "severity": "High", - "subcategory": "General", - "text": "Are required software installed on Windows and Linux servers to support the installation", - "waf": "Operations" + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Connect to Azure using ExR", + "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "guid": "d44c7c89-19ca-41f6-b521-5ae514ba34d4", - "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=azure-arc®ions=all", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use the migration assesment tool and timeline to determine bandwidth required", + "guid": "cf01c73b-1247-0a7a-740c-e1ea29bda340", + "id": "B02.02", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-introduction", "services": [ - "Arc" + "ExpressRoute", + "AVS" ], - "severity": "High", - "subcategory": "General", - "text": "Make sure to use a supported Azure region", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Bandwidth sizing", + "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "The scope include organization into management groups, subscriptions, and resource groups.", - "guid": "f9ccbd86-8266-4abc-a264-f9a19bf39d95", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/organize-inventory-servers#organize-resources-with-built-in-azure-hierarchies", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "What traffic is routed through a firewall, what goes directly into Azure", + "guid": "aab216ee-8941-315e-eada-c7e1f2243bd1", + "id": "B02.03", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", "services": [ - "Subscriptions", - "Arc" + "ExpressRoute", + "AVS" ], - "severity": "Low", - "subcategory": "Organization", - "text": "Define the structure for Azure management of resources", + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Traffic routing ", "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Define RBAC rules to the servers / resource groups as required for servers management, the 'Azure Connected Machine Resource Administrator' or 'Hybrid Server Resource Administrator' role would be sufficient for management of the Azure Arc-enabled servers resources in Azure", - "guid": "9bf39d95-d44c-47c8-a19c-a1f6d5215ae5", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#identity-and-access-control", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "AVS to ExR circuit, no traffic inspection", + "guid": "1f956e45-f62d-5c95-3a95-3bab718907f8", + "id": "B02.04", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", "services": [ - "Entra", - "RBAC", - "Arc" + "ExpressRoute", + "AVS" ], "severity": "Medium", - "subcategory": "Access", - "text": "Assign RBAC rights to Azure AD user/group access for managing Azure Arc-enabled servers", - "waf": "Security" + "subcategory": "ExpressRoute", + "text": "Global Reach ", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "guid": "14ba34d4-585e-4111-89bd-7ba012f7b94e", - "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-nonaad", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Name of the vNet and a unique address space /24 minimum", + "guid": "91f7a87b-21ac-d712-959c-8df2ba034253", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/virtual-network/quick-create-portal", "services": [ - "Entra", - "AKV", - "Arc" + "VNet", + "AVS" ], - "severity": "Low", - "subcategory": "Access", - "text": "Consider using managed identities for applications to access Azure resources like Key Vault example in link", - "waf": "Security" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "VNet name & address space", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "An Azure subscription must be parented to the same Azure AD tenant", - "guid": "35ac9322-23e1-4380-8523-081a94174158", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Subnet must be called GatewaySubnet", + "guid": "58a027e2-f37f-b540-45d5-e44843aba26b", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", "services": [ - "Entra", - "Subscriptions", - "Arc" + "ExpressRoute", + "VNet", + "VPN", + "AVS" ], - "severity": "High", - "subcategory": "Requirements", - "text": "An Azure Active Directory tenant must be available with at least one subscription", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "Gateway subnet", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Users (or SPs) need the 'Azure Connected Machine Onboarding' or 'Contributor' role to onboarding of servers", - "guid": "33ee7ad6-c6d3-4733-865c-7acbe44bbe60", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create a VPN gateway on the hub Gateway subnet", + "guid": "d4806549-0913-3e79-b580-ac2d3706e65a", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", "services": [ - "Entra", - "RBAC", - "Arc" + "ExpressRoute", + "VNet", + "VPN", + "AVS" ], "severity": "Medium", - "subcategory": "Requirements", - "text": "Define which users (AAD user/groups) has access to onboard Azure Arc-enabled servers", - "waf": "Security" + "subcategory": "Hub & Spoke", + "text": "VPN Gateway", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Ensure to only add the rights to users or groups that is required to perform their role", - "guid": "9d79f2e8-7778-4424-a516-775c6fa95b96", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create an ExR Gateway in the hub Gateway subnet.", + "guid": "864d7a8b-7016-c769-a717-61af6bfb73d2", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", "services": [ - "Entra", - "RBAC", - "Arc" + "ExpressRoute", + "VNet", + "VPN", + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "Use the principle of least privileged", - "waf": "Security" + "subcategory": "Hub & Spoke", + "text": "ExR Gateway", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "A service principle with the 'Azure Connected Machine Onboarding' role is required for at-scale onboarding of servers, consider more SP's if onboarding is done by different teams/decentralized management", - "guid": "ad88408e-3727-434b-a76b-a28f21459013", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "How will Internet traffic be routes, Az Firewall, NVA, Secure Hub, On-Premises firewall?", + "guid": "cc2e11b9-7911-7da1-458c-d7fcef794aad", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/enable-public-internet-access", "services": [ - "Entra", - "RBAC", - "Arc" + "NVA", + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "How many Service Principals are needed for onboarding Arc-enabled servers into Azure", - "waf": "Security" + "subcategory": "Internet", + "text": "Egress point", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Consider assigning the rights for the 'Azure Connected Machine Onboarding' role at the resource group level, to control the resource creation", - "guid": "65d38e53-f9cc-4bd8-9826-6abca264f9a1", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Allow remote connectivity to AVS via the portal, specifically to vCenter, NSX-T and HCX", + "guid": "71e68ce3-982e-5e56-0191-01100ad0e66f", + "id": "B05.01", + "link": "https://learn.microsoft.com/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", "services": [ - "Entra", - "RBAC", - "Arc" + "Bastion", + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "Limit the rights to onboard Azure Arc-enabled servers to the desired resource groups", - "waf": "Security" + "subcategory": "Jumpbox & Bastion", + "text": "Remote connectivity to AVS", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Plan for agent deployments at scale", - "guid": "6ee79d6b-5c2a-4364-a4b6-9bad38aad53c", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Name the jumpbox and identify the subnet where it will be hosted", + "guid": "6f8e93a2-44b1-bb1d-28a1-4d5b3c2ea857", + "id": "B05.02", + "link": "https://learn.microsoft.com/azure/bastion/tutorial-create-host-portal", "services": [ - "Monitor", - "Arc" + "VNet", + "Bastion", + "AVS" ], "severity": "Medium", - "subcategory": "Management", - "text": "Define a strategy for agent provisioning", - "waf": "Operations" + "subcategory": "Jumpbox & Bastion", + "text": "Configure a jumbox and Azure Bastion", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Use Microsoft Update to ensure that the connected machine agent is always up-to-date", - "guid": "c78e1d76-6673-457c-9496-74c5ed85b859", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#upgrade-the-agent", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Provides secure / seamless RDP/SSH connectivity to your vm's directly through the portal.", + "guid": "ba430d58-4541-085c-3641-068c00be9bc5", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", "services": [ - "Monitor", - "Arc" + "VM", + "Bastion", + "AVS" ], - "severity": "High", - "subcategory": "Management", - "text": "Define a strategy for agent updates", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Jumpbox & Bastion", + "text": "Security measure allowing RDP access via the portal", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Recommendation is to use Azure Policy, or another automation tool like Azure DevOps - important is to avoid configuration drift.", - "guid": "c7733be2-a1a2-47b7-95a9-1be1f388ff39", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-vm-extensions", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Using a VPN to connect to Azure to enable VMware communications (HCX) (not recommended)", + "guid": "9988598f-2a9f-6b12-9b46-488415ceb325", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-site-to-site-vpn-gateway", "services": [ - "AzurePolicy", - "Monitor", - "Arc" + "VPN", + "AVS" ], "severity": "Medium", - "subcategory": "Management", - "text": "Define a strategy for extension installation", - "waf": "Operations" + "subcategory": "VPN", + "text": "Connect to Azure using a VPN", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Use automatic upgrades where available and define an update strategy for all extensions not supporting automatic upgrades.", - "guid": "4c2bd463-cbbb-4c86-a195-abb91a4ed90d", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-automatic-vm-extension-upgrade?tabs=azure-portal", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use the migration assesment tool and timeline to determine bandwidth required (eg 3rd party tool in link)", + "guid": "956ce5e9-a862-fe2b-a50d-a22923569357", + "id": "B06.02", + "link": "https://www.omnicalculator.com/other/data-transfer#:~:text=To%20calculate%20the%20data%20transfer%20speed%3A%201%20Download,measured%20time%20to%20find%20the%20data%20transfer%20speed.", "services": [ - "Monitor", - "Arc" + "VPN", + "AVS" ], - "severity": "High", - "subcategory": "Management", - "text": "Define a strategy for extension updates", - "waf": "Operations" + "severity": "Medium", + "subcategory": "VPN", + "text": "Bandwidth sizing", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Azure Automanage help implement Microsoft best-practices for servers management in Azure", - "guid": "7a927c39-74d1-4102-aac6-aae01e6a84de", - "link": "https://learn.microsoft.com/azure/automanage/automanage-arc", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "What traffic is routed through a firewall, what goes directly into Azure", + "guid": "e095116f-0bdc-4b51-4d71-b9e469d56f59", + "id": "B06.03", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", "services": [ - "Monitor", - "Arc" + "VPN", + "AVS" ], "severity": "Medium", - "subcategory": "Management", - "text": "Consider using Azure Automanage to control settings and avoid configuration drift on servers", - "waf": "Operations" + "subcategory": "VPN", + "text": "Traffic routing ", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "37b6b780-cbaf-4e6c-9658-9d457a927c39", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Name and unique address space for the vWAN, name for the vWAN hub", + "guid": "4dc480ac-cecd-39c4-fdc6-680b300716ab", + "id": "B07.01", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-site-to-site-portal#openvwan", "services": [ - "Monitor", - "Arc" + "VWAN", + "AVS" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Monitor for unresponsive agents", - "waf": "Operations" + "severity": "Medium", + "subcategory": "vWAN hub", + "text": "vWAN name, hub name and address space", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "74d1102c-ac6a-4ae0-8e6a-84de5df47d2d", - "link": "https://learn.microsoft.com/azure/azure-monitor/agents/log-analytics-agent#data-collected", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Select either boh or the appropriate connection type.", + "guid": "51d6affd-8e02-6aea-d3d4-0baf618b3076", + "id": "B07.02", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-point-to-site-portal", "services": [ - "Monitor", - "Arc" + "VWAN", + "VPN", + "AVS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Design a monitoring strategy to send metrics and logs to an Log Analytics workspace", - "waf": "Operations" + "subcategory": "vWAN hub", + "text": "ExR and/or VPN gateway provisioned", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "92881b1c-d5d1-4e54-a296-59e3958fd782", - "link": "https://learn.microsoft.com/azure/service-health/resource-health-alert-monitor-guide", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Add Azure firewall to vWAN (recommended)", + "guid": "e32a4c67-3dc0-c134-1c12-52d46dcbab5b", + "id": "B07.03", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-expressroute-portal", "services": [ - "Monitor", - "Arc" + "Firewall", + "VWAN", + "AVS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use notification in Activity logs to receive notification on unexpected changes to the resources", - "waf": "Operations" + "subcategory": "vWAN hub", + "text": "Secure vWAN", + "waf": "Security" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "89c93555-6d02-4bfe-9564-b0d834a34872", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/learn/tutorial-enable-vm-insights", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Active directory or other identity provider servers", + "guid": "fbc47fbf-bc96-fa93-ed5d-8c9be63cd5c3", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", "services": [ - "Monitor", - "Arc" + "Entra", + "AVS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor for compliance and operational monitoring", - "waf": "Operations" + "subcategory": "Access", + "text": "External Identity (user accounts)", + "waf": "Security" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "5df47d2d-9288-41b1-ad5d-1e54a29659e3", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Not required for LDAPS, required for Kerberos", + "guid": "b5db7975-f6bb-8ba3-ee5f-e3e805887997", + "id": "C01.02", + "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", "services": [ - "Monitor", - "Arc" + "Entra", + "AVS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Create an alert to identify Azure Arc-enabled servers that aren't using the latest version of the Azure connected machine agent", - "waf": "Operations" + "subcategory": "Access", + "text": "If using AD domain, ensure Sites & Services has been configured", + "waf": "Security" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Use Update Management in Azure Automation or the new Update Management Center (preview) functionality to ensure update management of servers", - "guid": "ae2cc84c-37b6-4b78-8cba-fe6c46589d45", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/hybrid/server/best-practices/arc-update-management", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Authentication for users, must be secure.", + "guid": "c30749c4-e2af-558c-2eb9-0b6ae84881d1", + "id": "C01.03", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", "services": [ - "Monitor", - "Arc" + "Entra", + "AVS" ], - "severity": "Low", - "subcategory": "Security", - "text": "Use Azure Arc-enabled servers to control software updates deployments to servers", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Access", + "text": "Use LDAPS not ldap ( vCenter)", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "The Connected Machine Agent will by default communicate with Azure services over public Internet connectivity using HTTPS (TCP port 443)", - "guid": "f6e043d2-aa35-4927-88e6-e2050725769e", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#details", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Authentication for users, must be secure.", + "guid": "64cb9b5c-9edd-787e-1dd8-2b2338e51635", + "id": "C01.04", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-external-identity-source-nsx-t", "services": [ - "Arc" - ], - "severity": "High", - "subcategory": "Networking", - "text": "Define a connectivity method from the server to Azure", - "waf": "Operations" + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Access", + "text": "Use LDAPS not ldap (NSX-T)", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "The Connected Machine Agent can be configured to use a proxy server, it is recommended to define the proxy server address using 'azcmagent config set proxy.url' command on the local system.", - "guid": "46691e88-35ac-4932-823e-13800523081a", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#update-or-remove-proxy-settings", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "CN or SAN names, no wildcards, contains private key - CER or PFX", + "guid": "bec285ab-037e-d629-81d1-f61dac23cd4c", + "id": "C02.01", + "link": "https://youtu.be/4jvfbsrhnEs", "services": [ - "Arc" + "Entra", + "AVS" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Is a proxy server a required for communication over the Public Internet", - "waf": "Operations" + "subcategory": "Security", + "text": "Security certificate installed on LDAPS servers ", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "The Connected Machine Agent can use a Private Link for communication with Azure Services over an existing ExpressRoute or VPN connection", - "guid": "94174158-33ee-47ad-9c6d-3733165c7acb", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/private-link-security", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Standard Azure Roles Based Access Controls", + "guid": "4ba394a2-3c33-104c-8e34-2dadaba9cc73", + "id": "C02.02", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity", "services": [ - "VPN", - "PrivateLink", - "Arc", - "ExpressRoute" + "Entra", + "RBAC", + "AVS" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Is a private (not public Internet) connection required?", - "waf": "Operations" + "subcategory": "Security", + "text": "RBAC applied to Azure roles", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "Firewall configuration might be required for the agent to communicate with Azure, use the link to see ServiceTags and/or URL's required", - "guid": "e44bbe60-9d79-4f2e-a777-8424c516775c", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#service-tags", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create roles in vCenter required to meet minimum viable access guidelines", + "guid": "b04ca129-83a9-3494-7512-347dd2d766db", + "id": "C02.03", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity#view-the-vcenter-server-privileges", "services": [ - "Arc" + "Entra", + "RBAC", + "AVS" ], - "severity": "High", - "subcategory": "Networking", - "text": "Will Firewall configurations be needed in order to ensure communication with Azure Services?", + "severity": "Medium", + "subcategory": "Security", + "text": "RBAC model in vCenter", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "Use available automation tool for the system in question to regularly update the Azure endpoints", - "guid": "6fa95b96-ad88-4408-b372-734b876ba28f", - "link": "https://www.microsoft.com/download/details.aspx?id=56519", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", + "guid": "8e477d2f-8004-3dd0-93d6-0aece9e1b2fb", + "id": "C02.04", + "link": "Best practice", "services": [ - "Arc" + "Entra", + "RBAC", + "AVS" ], - "severity": "Low", - "subcategory": "Networking", - "text": "Can the Firewall or Proxy rules be automated updated if Service Tags or IP addresses change", + "severity": "Medium", + "subcategory": "Security", + "text": "CloudAdmin role usage", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "Configure Servers to use Transport Layer Security (TLS) version 1.2", - "guid": "21459013-65d3-48e5-9f9c-cbd868266abc", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#transport-layer-security-12-protocol", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", + "guid": "00e0b729-f9be-f600-8c32-5ec0e8f2ed63", + "id": "C03.01", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "Arc" + "Entra", + "RBAC", + "AVS" ], - "severity": "High", - "subcategory": "Networking", - "text": "Always use secure communication for Azure where possible", + "severity": "Medium", + "subcategory": "Security ", + "text": "Is Privileged Identity Management implemented", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "All extensions (like log analytics etc.) have separate network requirements, be sure to include all in the network design.", - "guid": "a264f9a1-9bf3-49d9-9d44-c7c8919ca1f6", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/hybrid/arc-enabled-servers/eslz-arc-servers-connectivity#define-extensions-connectivity-method", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For the Azure VMware Solution PIM roles", + "guid": "0842d45f-41a8-8274-1155-2f6ed554d315", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "PrivateLink", - "Monitor", - "Arc" + "Entra", + "RBAC", + "AVS" ], - "severity": "Low", - "subcategory": "Networking", - "text": "Include communication for Azure Arc-enabled Servers extensions in the design (firewall/proxy/private link)", + "severity": "Medium", + "subcategory": "Security ", + "text": "Is Privileged Identity Management audit reporting implemented", "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "ac6aae01-e6a8-44de-9df4-7d2d92881b1c", - "link": "https://learn.microsoft.com/azure/governance/policy/", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Best practice, also see Monitoring/Alerts", + "guid": "915cbcd7-0640-eb7c-4162-9f33775de559", + "id": "C03.03", + "link": "Best practice", "services": [ - "AzurePolicy", - "Arc" + "Entra", + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Management", - "text": "Use Azure Policy to implement a governance model for hybrid connected servers", + "subcategory": "Security ", + "text": "Limit use of CloudAdmin account to emergency access only", "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "5c2a3649-4b69-4bad-98aa-d53cc78e1d76", - "link": "https://learn.microsoft.com/azure/governance/machine-configuration/overview", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Operational procedure", + "guid": "7effa0c0-9172-e8e4-726a-67dbea8be40a", + "id": "C03.04", + "link": "https://learn.microsoft.com/azure/azure-vmware/rotate-cloudadmin-credentials?tabs=azure-portal", "services": [ - "Arc" + "Entra", + "AVS" ], "severity": "Medium", - "subcategory": "Management", - "text": "Consider using Machine configurations for in guest OS configurations", - "waf": "Operations" + "subcategory": "Security ", + "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", + "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "667357c4-4967-44c5-bd85-b859c7733be2", - "link": "https://learn.microsoft.com/azure/governance/machine-configuration/machine-configuration-create", + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", + "guid": "8f426fd0-d73b-d398-1f6f-df0cbe262a82", + "id": "D01.01", + "link": "https://learn.microsoft.com/azure/azure-arc/vmware-vsphere/overview", "services": [ - "AzurePolicy", - "Arc" + "Arc", + "VM", + "AVS" ], "severity": "Medium", - "subcategory": "Management", - "text": "Evaluate the need for custom Guest Configuration policies", + "subcategory": "Operations", + "text": "AVS VM Management (Azure Arc)", "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "49674c5e-d85b-4859-a773-3be2a1a27b77", - "link": "https://learn.microsoft.com/azure/automation/change-tracking/overview", + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", + "guid": "11dbe773-e380-9191-1418-e886fa7a6fd0", + "id": "D01.02", + "link": "https://docs.microsoft.com/azure/governance/policy/overview", "services": [ - "Monitor", - "Arc" + "AzurePolicy", + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Consider using change tracking for tracking changes made on the servers", + "subcategory": "Operations", + "text": "Azure policy", "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "d5d1e54a-2965-49e3-a58f-d78289c93555", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/data-residency", + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", + "guid": "1e59c639-9b7e-a60b-5e93-3798c1aff5db", + "id": "D01.03", + "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json#configure-locks", "services": [ - "Arc" + "AVS" ], "severity": "Medium", - "subcategory": "Requirements", - "text": "Make sure to use an Azure region for storing the metadata approved by the organization", - "waf": "Security" + "subcategory": "Operations", + "text": "Resource locks", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "195abb91-a4ed-490d-ae2c-c84c37b6b780", - "link": "https://learn.microsoft.com/azure/key-vault/general/basic-concepts", + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For manual deployments, all configuration and deployments must be documented", + "guid": "8f2c46aa-ca1b-cad3-3ac9-213dfc0a265e", + "id": "D01.04", + "link": "Make sure to create your own runbook on the deployment of AVS.", "services": [ - "AKV", - "Arc" + "AVS" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Use Azure Key Vault for certificate management on servers", - "waf": "Security" + "subcategory": "Operations", + "text": "Run books", + "waf": "Operations" }, - { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Consider using a short-lived Azure AD service principal client secrets.", - "guid": "6d02bfe4-564b-40d8-94a3-48726ee79d6b", - "link": "https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret", + { + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", + "guid": "86b314f9-1f1e-317a-4dfb-cf510ad4a030", + "id": "D01.05", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations", "services": [ - "Entra", - "Storage", "AKV", - "Arc" + "AVS" ], - "severity": "High", - "subcategory": "Secrets", - "text": "What is the acceptable life time of the secret used by SP's", - "waf": "Security" + "severity": "Medium", + "subcategory": "Operations", + "text": "Naming conventions for auth keys", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "A private key is saved to the disk, ensure this is protected using disk encryption", - "guid": "a1a27b77-5a91-4be1-b388-ff394c2bd463", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#using-disk-encryption", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "guid": "e22a2d99-eb71-7d7c-07af-6d4cdb1d4443", + "id": "E01.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", "services": [ - "AKV", - "Arc" + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Secure the public key for Azure Arc-enabled Servers", - "waf": "Security" + "subcategory": "Alerts", + "text": "Create warning alerts for critical thresholds ", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Local administrator is required to install the Connected Machine Agent on Windows and Linux systems", - "guid": "29659e39-58fd-4782-a9c9-35556d02bfe4", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-portal#install-manually", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "guid": "6d02f159-627d-79bf-a931-fab6d947eda2", + "id": "E01.02", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", "services": [ - "Arc" + "AVS", + "Monitor" ], - "severity": "High", - "subcategory": "Security", - "text": "Ensure there is local administrator access for executing the agent installation", - "waf": "Security" + "severity": "Medium", + "subcategory": "Alerts", + "text": "Create critical alert vSAN consumption", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Members of the local administrator group on Windows and users with root privileges on Linux, have permissions to manage the agent via command line.", - "guid": "564b0d83-4a34-4872-9ee7-9d6b5c2a3649", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#agent-security-and-permissions", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Provides platform alerts (generated by Microsoft)", + "guid": "1cc97b39-2c7e-246f-6d73-789cfebfe951", + "id": "E01.03", + "link": "https://www.virtualworkloads.com/2021/04/azure-vmware-solution-azure-service-health/", "services": [ - "Arc" + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Security", - "text": "Limit the amount of users with local administrator rights to the servers", - "waf": "Security" + "subcategory": "Alerts", + "text": "Configured for Azure Service Health alerts and notifications", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "4b69bad3-8aad-453c-a78e-1d76667357c4", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", + "guid": "0962606c-e3b4-62a9-5661-e4ffd62a4509", + "id": "E02.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", "services": [ - "Entra", - "Arc" + "Monitor", + "VM", + "AVS", + "AzurePolicy", + "Backup" ], "severity": "Medium", - "subcategory": "Security", - "text": "Consider using and restricting access to managed identities for applications.", - "waf": "Security" + "subcategory": "Backup", + "text": "Backup policy", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Use Defender for Endpoint or another AV and EDR solution to protect endpoints", - "guid": "5a91be1f-388f-4f39-9c2b-d463cbbbc868", - "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Keep in mind the lead time for requesting new nodes", + "guid": "4ec7ccfb-795e-897e-4a84-fd31c04eadc6", + "id": "E03.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", "services": [ - "Arc", - "Defender" + "AzurePolicy", + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Security", - "text": "Enable Defender for Servers for all servers to secure hybrid workloads from threats", - "waf": "Security" + "subcategory": "Capacity", + "text": "Policy around ESXi host density and efficiency", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "cbafe6c4-6589-4d45-9a92-7c3974d1102c", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Azure Cost Management can be used - one option, put AVS in it's own Subscription. ", + "guid": "7f8f175d-13f4-5298-9e61-0bc7e9fcc279", + "id": "E04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/govern", "services": [ - "Arc" + "Subscriptions", + "Cost", + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Security", - "text": "Define controls to detect security misconfigurations and track compliance", - "waf": "Security" + "subcategory": "Costs", + "text": "Ensure a good cost management process is in place for Azure VMware Solution - ", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "cbbbc868-195a-4bb9-8a4e-d90dae2cc84c", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#extension-allowlists-and-blocklists", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create dashboards to enable core Azure VMware Solution monitoring insights", + "guid": "01e689e0-7c6c-b58f-37bd-4d6b9b1b9c74", + "id": "E05.01", + "link": "https://docs.microsoft.com/azure/azure-portal/azure-portal-dashboards", "services": [ - "Arc" + "Monitor", + "AVS", + "NetworkWatcher" ], "severity": "Medium", - "subcategory": "Security", - "text": "Use allow- or block-lists to control what extensions can be installed on the Azure Arc-enabled servers", - "waf": "Security" + "subcategory": "Dashboard", + "text": "Connection monitor dashboard", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", - "guid": "976f32a7-30d1-6caa-c2a0-207fdc26571b", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "description": "Send to an Azure Storage account or Azure EventHub for processing (direct to Log Analytics is pending)", + "guid": "f9afdcc9-649d-d840-9fb5-a3c0edcc697d", + "id": "E06.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", "services": [ - "AVS", "Storage", - "Backup" + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Backup", - "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", - "waf": "Reliability" + "subcategory": "Logs & Metrics", + "text": "Configure Azure VMware Solution logging ", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Microsoft backup service", - "guid": "fc8af7a1-c724-e255-c18d-4ca22a6f27f0", - "id": "A02.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "description": "Must be on-premises, implement if available", + "guid": "7cbac8c3-4eda-d5d9-9bda-c6b5abba9fb6", + "id": "E06.02", + "link": "Is vROPS or vRealize Network Insight going to be used? ", "services": [ "AVS", - "Backup" + "Monitor" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Use MABS as your backup solution", - "waf": "Reliability" + "subcategory": "Logs & Metrics", + "text": "vRealize Operations", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Best practice - this is Backup, not disaster recovery", - "guid": "be28860f-3d29-a79a-1a0e-36f1b23b36ae", - "id": "A02.02", - "link": "Best practice to deploy backup in the same region as your AVS deployment", + "description": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", + "guid": "b243521a-644d-f865-7fb6-21f9019c0dd2", + "id": "E06.03", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", "services": [ + "VM", "AVS", - "ASR", - "Backup" + "Monitor" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", - "waf": "Reliability" + "subcategory": "Logs & Metrics", + "text": "AVS VM logging", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Best practice - in case AVS is unavailable", - "guid": "4d2f79a5-4ccf-0dfc-557c-49619b99a540", - "id": "A02.03", - "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "description": "Between on-premises to Azure are monitored using 'connection monitor'", + "guid": "2ca97d91-dd36-7229-b668-01036ccc3cd3", + "id": "E07.01", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", "services": [ - "AVS" + "Monitor", + "NetworkWatcher", + "AVS", + "VPN", + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", - "waf": "Reliability" + "subcategory": "Network", + "text": "Monitor ExpressRoute and/or VPN connections ", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", - "guid": "ff431c40-962c-5182-d536-0c2f0c4ce9e0", - "id": "A02.04", - "link": "Will Disaster Recovery Site Recovery, HCX Disaster Recovery, SRM or back tools be used?", + "description": "To monitor the Azure VMware Solution back-end ExpressRoute connection (Azure native to AVS)", + "guid": "99209143-60fe-19f0-5633-8b5671277ba5", + "id": "E07.02", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", "services": [ - "AVS" + "ExpressRoute", + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Escalation process with Microsoft in the event of a regional DR", - "waf": "Reliability" + "subcategory": "Network", + "text": "Monitor from an Azure native resource to an Azure VMware Solution VM", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Compare SRM with HCX", - "guid": "f379436d-3051-daa0-01fb-dc4e0e04d677", - "id": "A03.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/disaster-recovery-using-vmware-site-recovery-manager", + "description": "To monitor end-to-end, on-premises to AVS workloads", + "guid": "b9e5867c-57d3-036f-fb1b-3f0a71664efe", + "id": "E07.03", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", "services": [ "AVS", - "ASR" + "Monitor" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", - "waf": "Reliability" + "subcategory": "Network", + "text": "Monitor from an on-premises resource to an Azure VMware Solution VM", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Recovery into Azure instead of Vmware solution", - "guid": "367f71d8-3cf6-51a0-91a5-3db3d570cc19", - "id": "A03.02", - "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", + "description": "Track requests to Azure VMware Solution and Azure VMware Solution based workloads", + "guid": "4af7c5f7-e5e9-bedf-a8cf-314b81735962", + "id": "E08.01", + "link": "Firewall logging and alerting rules are configured (Azure Firewall or 3rd party)", "services": [ "AVS", - "ASR" + "Monitor" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", - "waf": "Reliability" + "subcategory": "Security", + "text": "Auditing and logging is implemented for inbound internet ", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Avoid manual tasks as much as possible", - "guid": "ee02ada0-1887-bb3a-b84c-423f45a09ef9", - "id": "A03.03", - "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", + "description": "Implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", + "guid": "74be60a3-cfac-f057-eda6-3ee087e805d5", + "id": "E08.02", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", "services": [ "AVS", - "ASR" + "Monitor" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Automated recovery plans with either of the Disaster solutions,", - "waf": "Reliability" + "subcategory": "Security", + "text": "Session monitoring ", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Any other datacenter in the same region", - "guid": "0c2b74e5-9c28-780d-1df3-12d3de4aaa76", - "id": "A03.04", - "link": "https://docs.microsoft.com/azure/azure-vmware/connect-multiple-private-clouds-same-region", + "description": "Enable Diagnostic and metric logging on Azure VMware Solution", + "guid": "a434b3b5-f258-0845-cd76-d7df6ef5890e", + "id": "E09.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", "services": [ "AVS", - "ASR" + "Monitor" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Configure a secondary disaster recovery environment", - "waf": "Reliability" + "subcategory": "VMWare", + "text": "Logging and diagnostics", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Monitoring", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", - "guid": "c2a34ec4-2933-4e6c-dc36-e20e67abbe3f", - "id": "A03.05", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "description": "Monitor AVS workloads (each VM in AVS)", + "guid": "fb00b69a-83ec-ce72-446e-6c23a0cab09a", + "id": "E10.01", + "link": "https://docs.microsoft.com/azure/azure-monitor/agents/agent-windows?tabs=setup-wizard", "services": [ + "VM", "AVS", - "ASR" + "Monitor" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Assign IP ranges unique to each region", - "waf": "Reliability" + "subcategory": "VMware", + "text": "Log Analytics Agents deployed on Azure VMware Solution guest VM workloads", + "waf": "Operations" }, { - "category": "BCDR", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "ExpressRoute Global Reach can be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or routing must be done through network virtual appliances?", - "guid": "b44fb6ec-bfc1-3a8e-dba2-ca97f0991d2c", - "id": "A03.06", - "link": "This depends if you have multiple AVS Private Clouds. If so and they are in the same region then use AVS Interconnect. If they are in separate regions then use ExpressRoute Global Reach.", + "description": "Decision on traffic flow", + "guid": "a1354b87-e18e-bf5c-c50b-8ddf0540e971", + "id": "F01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", "services": [ - "AVS", - "NVA", - "ASR", - "ExpressRoute" + "AVS" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Global Reach between DR regions", - "waf": "Reliability" + "subcategory": "Hub & Spoke", + "text": "North/South routing through Az Firewall or 3rd party ", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "An ExR Global Reach connection will be established to the ExR circuit, no other connections", - "guid": "a2c12df2-07fa-3edd-2cec-fda0b55fb952", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", + "guid": "29a8a499-ec31-f336-3266-0895f035e379", + "id": "F01.02", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", "services": [ - "AVS", - "VWAN" + "AVS" ], "severity": "Medium", - "subcategory": "Direct (no vWAN, no H&S)", - "text": "Global Reach to ExR circuit - no Azure resources", - "waf": "Performance" + "subcategory": "Hub & Spoke", + "text": "East West (Internal to Azure)", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use ExR to connect on-premises (other) location to Azure", - "guid": "f62ce162-ba5a-429d-674e-fafa1af5f706", - "id": "B02.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "description": "Requires a 3rd party NVA with Azure Route server - Scenario 2 (see link)", + "guid": "ebd3cc3c-ac3d-4293-950d-cecd8445a523", + "id": "F01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", "services": [ + "NVA", "AVS", - "ExpressRoute" + "ARS" ], "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Connect to Azure using ExR", - "waf": "Performance" + "subcategory": "Hub & Spoke", + "text": "ExR without Global Reach", + "waf": "Operations" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use the migration assesment tool and timeline to determine bandwidth required", - "guid": "cf01c73b-1247-0a7a-740c-e1ea29bda340", - "id": "B02.02", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-introduction", + "description": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", + "guid": "ffb5c5ca-bd89-ff1b-8b73-8a54d503d506", + "id": "F01.04", + "link": "https://learn.microsoft.com/azure/route-server/route-server-faq", "services": [ "AVS", - "ExpressRoute" + "ARS" ], "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Bandwidth sizing", - "waf": "Performance" + "subcategory": "Hub & Spoke", + "text": "Route server ", + "waf": "Operations" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "What traffic is routed through a firewall, what goes directly into Azure", - "guid": "aab216ee-8941-315e-eada-c7e1f2243bd1", - "id": "B02.03", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "description": "Via on-premises, Az Firewall, 3rd Party, NSX-T pubic IP", + "guid": "a4070dad-3def-818d-e9f7-be440d10e7de", + "id": "F02.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-design-public-internet-access", "services": [ - "AVS", - "ExpressRoute" + "AVS" ], "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Traffic routing ", - "waf": "Performance" + "subcategory": "Internet", + "text": "Egress point(s)", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "AVS to ExR circuit, no traffic inspection", - "guid": "1f956e45-f62d-5c95-3a95-3bab718907f8", - "id": "B02.04", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "description": "Az Firewall, 3rd party NVA, Application Gateway, Azure Frontdoor ", + "guid": "e942c03d-beaa-3d9f-0526-9b26cd5e9937", + "id": "F02.02", + "link": "Research and choose optimal solution for each application", "services": [ + "NVA", + "FrontDoor", "AVS", - "ExpressRoute" + "AppGW" ], "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Global Reach ", - "waf": "Performance" + "subcategory": "Internet", + "text": "Internet facing applications", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Name of the vNet and a unique address space /24 minimum", - "guid": "91f7a87b-21ac-d712-959c-8df2ba034253", - "id": "B03.01", - "link": "https://learn.microsoft.com/azure/virtual-network/quick-create-portal", + "description": "Ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", + "guid": "e778a2ec-b4d7-1d27-574c-14476b167d37", + "id": "F03.01", + "link": "https://docs.microsoft.com/azure/route-server/route-server-faq#route-server-limits", "services": [ - "VNet", - "AVS" + "AVS", + "ARS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "VNet name & address space", - "waf": "Performance" + "subcategory": "Routing", + "text": "When route server Route limit understood? ", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Subnet must be called GatewaySubnet", - "guid": "58a027e2-f37f-b540-45d5-e44843aba26b", - "id": "B03.02", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "description": "(VPN Gateway, AppGW, FrontDoor, Load balancer, VMs (etc) (Remove: enabled on ExR/VPN Gateway subnet in Azure)", + "guid": "66c97b30-81b9-139a-cc76-dd1d94aef42a", + "id": "F04.01", + "link": "https://docs.microsoft.com/azure/ddos-protection/manage-ddos-protection", "services": [ - "VPN", + "FrontDoor", + "VM", + "LoadBalancer", + "DDoS", "AVS", "VNet", - "ExpressRoute" + "VPN", + "ExpressRoute", + "AppGW" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "Gateway subnet", - "waf": "Performance" + "subcategory": "Security", + "text": "Is DDoS standard protection of public facing IP addresses? ", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create a VPN gateway on the hub Gateway subnet", - "guid": "d4806549-0913-3e79-b580-ac2d3706e65a", - "id": "B03.03", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "description": "To manage Azure VMware Solution, vCenter, NSX manager and HCX manager", + "guid": "d43da920-4ecc-a4e9-dd45-a2986ce81d32", + "id": "F04.02", + "link": "Best practice: Bastion or 3rd party tool", "services": [ - "VPN", - "AVS", - "VNet", - "ExpressRoute" + "AVS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "VPN Gateway", - "waf": "Performance" + "subcategory": "Security", + "text": "Use a dedicated privileged access workstation (PAW)", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create an ExR Gateway in the hub Gateway subnet.", - "guid": "864d7a8b-7016-c769-a717-61af6bfb73d2", - "id": "B03.04", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "description": "Use NSX-T for inter-vmware-traffic inspection", + "guid": "a2dac74f-5380-6e39-25e6-f13b99ece51f", + "id": "F05.01", + "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-F6685367-7AA1-4771-927E-ED77727CFDA3.html", "services": [ - "VPN", - "AVS", - "VNet", - "ExpressRoute" + "AVS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "ExR Gateway", - "waf": "Performance" + "subcategory": "Traffic Inspection", + "text": "East West (Internal to AVS)", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "How will Internet traffic be routes, Az Firewall, NVA, Secure Hub, On-Premises firewall?", - "guid": "cc2e11b9-7911-7da1-458c-d7fcef794aad", - "id": "B04.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/enable-public-internet-access", + "description": "Decision on whether or not to use Secure hub for E/W and Internet traffic - requires Global Reach", + "guid": "3f621543-dfac-c471-54a6-7b2849b6909a", + "id": "F06.01", + "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", "services": [ - "AVS", - "NVA" + "Firewall", + "VWAN", + "AVS" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Egress point", - "waf": "Performance" + "subcategory": "Virtual WAN", + "text": "Use Secure Hub (Azure Firewall or 3rd party)", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Networking", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Allow remote connectivity to AVS via the portal, specifically to vCenter, NSX-T and HCX", - "guid": "71e68ce3-982e-5e56-0191-01100ad0e66f", - "id": "B05.01", - "link": "https://learn.microsoft.com/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", + "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", + "guid": "d7af5670-1b39-d95d-6da2-8d660dfbe16b", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/firewall-manager/secure-cloud-network", "services": [ - "AVS", - "Bastion" + "VWAN", + "AVS" ], "severity": "Medium", - "subcategory": "Jumpbox & Bastion", - "text": "Remote connectivity to AVS", - "waf": "Performance" + "subcategory": "Virtual WAN", + "text": "East West (Internal to Azure)", + "waf": "Security" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Name the jumpbox and identify the subnet where it will be hosted", - "guid": "6f8e93a2-44b1-bb1d-28a1-4d5b3c2ea857", - "id": "B05.02", - "link": "https://learn.microsoft.com/azure/bastion/tutorial-create-host-portal", + "description": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", + "guid": "7d049005-eb35-4a93-50a5-3b31a9f61161", + "id": "G01.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-nsx-network-components-azure-portal", "services": [ - "VNet", "AVS", - "Bastion" + "Subscriptions" ], "severity": "Medium", - "subcategory": "Jumpbox & Bastion", - "text": "Configure a jumbox and Azure Bastion", + "subcategory": "Automated Scale", + "text": "Scale out operations planning", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Provides secure / seamless RDP/SSH connectivity to your vm's directly through the portal.", - "guid": "ba430d58-4541-085c-3641-068c00be9bc5", - "id": "B05.03", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "description": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", + "guid": "7242c1de-da37-27f3-1ddd-565ccccb8ece", + "id": "G01.02", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", "services": [ - "VM", - "AVS", - "Bastion" + "AzurePolicy", + "Storage", + "AVS" ], "severity": "Medium", - "subcategory": "Jumpbox & Bastion", - "text": "Security measure allowing RDP access via the portal", + "subcategory": "Automated Scale", + "text": "Scale in operations planning", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Using a VPN to connect to Azure to enable VMware communications (HCX) (not recommended)", - "guid": "9988598f-2a9f-6b12-9b46-488415ceb325", - "id": "B06.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-site-to-site-vpn-gateway", + "description": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", + "guid": "3233e49e-62ce-97f3-8737-8230e771b694", + "id": "G01.03", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", "services": [ - "VPN", "AVS" ], "severity": "Medium", - "subcategory": "VPN", - "text": "Connect to Azure using a VPN", + "subcategory": "Automated Scale", + "text": "Scale serialized operations planning", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use the migration assesment tool and timeline to determine bandwidth required (eg 3rd party tool in link)", - "guid": "956ce5e9-a862-fe2b-a50d-a22923569357", - "id": "B06.02", - "link": "https://www.omnicalculator.com/other/data-transfer#:~:text=To%20calculate%20the%20data%20transfer%20speed%3A%201%20Download,measured%20time%20to%20find%20the%20data%20transfer%20speed.", + "description": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", + "guid": "68161d66-5707-319b-e77d-9217da892593", + "id": "G01.04", + "link": "Best practice (testing)", "services": [ - "VPN", "AVS" ], "severity": "Medium", - "subcategory": "VPN", - "text": "Bandwidth sizing", + "subcategory": "Automated Scale", + "text": "Scale rd operations planning", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "What traffic is routed through a firewall, what goes directly into Azure", - "guid": "e095116f-0bdc-4b51-4d71-b9e469d56f59", - "id": "B06.03", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "description": "Define and enforce scale in/out maximum limits for your environment in the automations", + "guid": "c32cb953-e860-f204-957a-c79d61202669", + "id": "G01.05", + "link": "Operational planning - understand workload requirements", "services": [ - "VPN", "AVS" ], "severity": "Medium", - "subcategory": "VPN", - "text": "Traffic routing ", + "subcategory": "Automated Scale", + "text": "Scale maximum operations planning", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Name and unique address space for the vWAN, name for the vWAN hub", - "guid": "4dc480ac-cecd-39c4-fdc6-680b300716ab", - "id": "B07.01", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-site-to-site-portal#openvwan", + "description": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", + "guid": "7bd65a5e-7b5d-652d-dbea-fc6f73a42857", + "id": "G01.06", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-management-and-monitoring", "services": [ "AVS", - "VWAN" + "Monitor" ], "severity": "Medium", - "subcategory": "vWAN hub", - "text": "vWAN name, hub name and address space", + "subcategory": "Automated Scale", + "text": "Monitor scaling operations ", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Select either boh or the appropriate connection type.", - "guid": "51d6affd-8e02-6aea-d3d4-0baf618b3076", - "id": "B07.02", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-point-to-site-portal", + "description": "Consider the use of Azure Private-Link when using other Azure Native Services", + "guid": "95e374af-8a2a-2672-7ab7-b4a1be43ada7", + "id": "G02.01", + "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", "services": [ - "VPN", - "AVS", - "VWAN" + "PrivateLink", + "AVS" ], "severity": "Medium", - "subcategory": "vWAN hub", - "text": "ExR and/or VPN gateway provisioned", + "subcategory": "Networking", + "text": "Private link", "waf": "Performance" }, { - "category": "Connectivity", + "category": "Other Services/Operations", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Add Azure firewall to vWAN (recommended)", - "guid": "e32a4c67-3dc0-c134-1c12-52d46dcbab5b", - "id": "B07.03", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-expressroute-portal", + "description": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", + "guid": "71eff90d-5ad7-ac60-6244-2a6f7d3c51f2", + "id": "G02.02", + "link": "Best practice", "services": [ - "Firewall", - "AVS", - "VWAN" + "AVS" ], "severity": "Medium", - "subcategory": "vWAN hub", - "text": "Secure vWAN", - "waf": "Security" + "subcategory": "Networking", + "text": "Provisioning Vmware VLANs", + "waf": "Performance" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Active directory or other identity provider servers", - "guid": "fbc47fbf-bc96-fa93-ed5d-8c9be63cd5c3", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", + "description": "In which region will AVS be deployed", + "guid": "04e3a2f9-83b7-968a-1044-2811811a924b", + "id": "H01.01", + "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", "services": [ - "Entra", "AVS" ], "severity": "Medium", - "subcategory": "Access", - "text": "External Identity (user accounts)", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Region selected", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Not required for LDAPS, required for Kerberos", - "guid": "b5db7975-f6bb-8ba3-ee5f-e3e805887997", - "id": "C01.02", - "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", + "description": "Are there regulatory or compliance policies in play", + "guid": "e52d1615-9cc6-565c-deb6-743ed7e90f4b", + "id": "H01.02", + "link": "Internal policy or regulatory compliance", "services": [ - "Entra", + "AzurePolicy", "AVS" ], "severity": "Medium", - "subcategory": "Access", - "text": "If using AD domain, ensure Sites & Services has been configured", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Data residency compliant with selected regions", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Authentication for users, must be secure.", - "guid": "c30749c4-e2af-558c-2eb9-0b6ae84881d1", - "id": "C01.03", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", + "description": "Request through the support blade", + "guid": "92bd5ad6-441f-a983-7aa9-05dd669d760b", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/migrate/concepts-azure-vmware-solution-assessment-calculation", "services": [ - "Entra", "AVS" ], "severity": "Medium", - "subcategory": "Access", - "text": "Use LDAPS not ldap ( vCenter)", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Request for number of AVS hosts submitted ", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Authentication for users, must be secure.", - "guid": "64cb9b5c-9edd-787e-1dd8-2b2338e51635", - "id": "C01.04", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-external-identity-source-nsx-t", + "description": "PG approval for deployment", + "guid": "28370f63-1cb8-2e35-907f-c5516b6954fa", + "id": "H01.04", + "link": "Support request through portal or get help from Account Team", "services": [ - "Entra", "AVS" ], "severity": "Medium", - "subcategory": "Access", - "text": "Use LDAPS not ldap (NSX-T)", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Region and number of AVS nodes approved", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "CN or SAN names, no wildcards, contains private key - CER or PFX", - "guid": "bec285ab-037e-d629-81d1-f61dac23cd4c", - "id": "C02.01", - "link": "https://youtu.be/4jvfbsrhnEs", + "description": "Portal/subscription/resource providers/ Microsoft.AVS", + "guid": "96c76997-30a6-bb92-024d-f4f93f5f57fa", + "id": "H01.05", + "link": "Done through the subscription/resource providers/ AVS register in the portal", "services": [ - "Entra", - "AVS" + "AVS", + "Subscriptions" ], "severity": "Medium", - "subcategory": "Security", - "text": "Security certificate installed on LDAPS servers ", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Resource provider for AVS registered", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Standard Azure Roles Based Access Controls", - "guid": "4ba394a2-3c33-104c-8e34-2dadaba9cc73", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity", + "description": "Connectivity, subscription & governanace model", + "guid": "5898e3ff-5e6b-bee1-6f85-22fee261ce63", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/enterprise-scale-landing-zone", "services": [ - "Entra", "AVS", - "RBAC" + "Subscriptions" ], "severity": "Medium", - "subcategory": "Security", - "text": "RBAC applied to Azure roles", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Landing zone architecture", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create roles in vCenter required to meet minimum viable access guidelines", - "guid": "b04ca129-83a9-3494-7512-347dd2d766db", - "id": "C02.03", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity#view-the-vcenter-server-privileges", + "description": "The name of the RG where AVS will exist", + "guid": "d0181fb8-9cb8-bf4b-f5e5-b5f9bf7ae4ea", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal", "services": [ - "Entra", - "AVS", - "RBAC" + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "RBAC model in vCenter", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Resource group name selected", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", - "guid": "8e477d2f-8004-3dd0-93d6-0aece9e1b2fb", - "id": "C02.04", - "link": "Best practice", + "description": "Each resource created as part of the deployment will also utilize this prefix in the name", + "guid": "0f0d20c2-5a19-726c-de20-0984e070d9d6", + "id": "H01.08", + "link": "Best practice - naming standards", "services": [ - "Entra", - "AVS", - "RBAC" + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "CloudAdmin role usage", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Deployment prefix selected", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", - "guid": "00e0b729-f9be-f600-8c32-5ec0e8f2ed63", - "id": "C03.01", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "description": "/22 unique non-overlapping IPv4 address space", + "guid": "7fbf2ab7-a36c-5957-c27a-67038557af2a", + "id": "H01.09", + "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-network-checklist#routing-and-subnet-considerations", "services": [ - "Entra", - "AVS", - "RBAC" + "AVS" ], "severity": "Medium", - "subcategory": "Security ", - "text": "Is Privileged Identity Management implemented", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Network space for AVS management layer", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For the Azure VMware Solution PIM roles", - "guid": "0842d45f-41a8-8274-1155-2f6ed554d315", - "id": "C03.02", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "description": "vNets used by workloads running in AVS (non-stretched)", + "guid": "0c87f999-e517-21ef-f355-f210ad4134d2", + "id": "H01.10", + "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/installation/GUID-4B3860B8-1883-48CA-B2F3-7C2205D91D6D.html", "services": [ - "Entra", - "AVS", - "RBAC" + "VNet", + "AVS" ], "severity": "Medium", - "subcategory": "Security ", - "text": "Is Privileged Identity Management audit reporting implemented", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Network space for AVS NSX-T segments", + "waf": "Reliability" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Best practice, also see Monitoring/Alerts", - "guid": "915cbcd7-0640-eb7c-4162-9f33775de559", - "id": "C03.03", - "link": "Best practice", + "description": "Choose AV36, AV36P, AV52, AV36T (AV36T = Trial)", + "guid": "946c8966-f902-6f53-4f37-00847e8895c2", + "id": "H01.11", + "link": "https://azure.microsoft.com/pricing/details/azure-vmware/", "services": [ - "Entra", - "AVS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Security ", - "text": "Limit use of CloudAdmin account to emergency access only", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "AVS SKU (region dependent)", + "waf": "Performance" }, { - "category": "Identity", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Operational procedure", - "guid": "7effa0c0-9172-e8e4-726a-67dbea8be40a", - "id": "C03.04", - "link": "https://learn.microsoft.com/azure/azure-vmware/rotate-cloudadmin-credentials?tabs=azure-portal", + "description": "Use the Azure migration assessment tool to determine the minimum number of nodes required (consider BCDR as well)", + "guid": "31833808-26ba-9c31-416f-d54a89a17f5d", + "id": "H01.12", + "link": "https://learn.microsoft.com/azure/migrate/how-to-assess", "services": [ - "Entra", "AVS" ], "severity": "Medium", - "subcategory": "Security ", - "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", - "waf": "Security" + "subcategory": "Pre-deployment", + "text": "Number of hosts to be deployed", + "waf": "Performance" }, { - "category": "Management", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", - "guid": "8f426fd0-d73b-d398-1f6f-df0cbe262a82", - "id": "D01.01", - "link": "https://learn.microsoft.com/azure/azure-arc/vmware-vsphere/overview", + "description": "Understand how and if you should be using reserved instances (cost control)", + "guid": "f2b73c4f-3d46-32c9-5df1-5b8dfcd3947f", + "id": "H01.13", + "link": "https://azure.microsoft.com/en-ca/pricing/details/azure-vmware/#:~:text=Azure%20VMware%20Solution%20%20%20%20Instance%20size,TB%20%28all%20NVMe%29%20%20%20N%2FA%20%2Fhour%20", "services": [ - "AVS", - "VM", - "Arc" + "Cost", + "AVS" ], "severity": "Medium", - "subcategory": "Operations", - "text": "AVS VM Management (Azure Arc)", - "waf": "Operations" + "subcategory": "Pre-deployment", + "text": "Reserverd Instances", + "waf": "Cost" }, { - "category": "Management", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", - "guid": "11dbe773-e380-9191-1418-e886fa7a6fd0", - "id": "D01.02", - "link": "https://docs.microsoft.com/azure/governance/policy/overview", + "description": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", + "guid": "94ac48ab-ade5-3fa7-f800-263feeb97070", + "id": "H01.14", + "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", "services": [ "AVS", - "AzurePolicy", - "Monitor" + "ASR" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Azure policy", - "waf": "Operations" + "subcategory": "Pre-deployment", + "text": "Capacity ", + "waf": "Performance" }, { - "category": "Management", + "category": "Planning", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", - "guid": "1e59c639-9b7e-a60b-5e93-3798c1aff5db", - "id": "D01.03", - "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json#configure-locks", + "description": "Identify which of the networking scenarios make ", + "guid": "1f9d4bd5-14b8-928c-b4cb-eb211f9b8de5", + "id": "H01.15", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Networking & Connectivity See docs describing scenrario 1 through 5", + "waf": "Reliability" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", + "guid": "070db19b-8a2a-fd6a-c39b-4488d8780da9", + "id": "H01.16", + "link": "Please Check Partner Ecosystem", "services": [ "AVS" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Resource locks", - "waf": "Operations" + "subcategory": "Pre-deployment", + "text": "3rd party application compatibility ", + "waf": "Reliability" }, { - "category": "Management", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For manual deployments, all configuration and deployments must be documented", - "guid": "8f2c46aa-ca1b-cad3-3ac9-213dfc0a265e", - "id": "D01.04", - "link": "Make sure to create your own runbook on the deployment of AVS.", + "description": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", + "guid": "70cfbddc-d3d4-9188-77c8-1cabaefef646", + "id": "I01.01", + "link": "General recommendation for storing encryption keys.", "services": [ + "AKV", "AVS" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Run books", - "waf": "Operations" + "subcategory": "Encryption", + "text": "Use Azure Key Vault with in-guest encryption ", + "waf": "Security" }, { - "category": "Management", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", - "guid": "86b314f9-1f1e-317a-4dfb-cf510ad4a030", - "id": "D01.05", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations", + "description": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", + "guid": "c1a81638-18df-0ce9-a73a-4b9a8a8dd392", + "id": "I01.02", + "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#data-at-rest-encryption", "services": [ - "AVS", - "AKV" + "SQL", + "AVS" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Naming conventions for auth keys", - "waf": "Operations" + "subcategory": "Encryption", + "text": "Use in-guest encryption", + "waf": "Security" }, { - "category": "Monitoring", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", - "guid": "e22a2d99-eb71-7d7c-07af-6d4cdb1d4443", - "id": "E01.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "description": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", + "guid": "8d0a8f51-8d35-19cd-c2fe-4e3512fb467e", + "id": "I01.03", + "link": "https://docs.microsoft.com/azure/key-vault/general/authentication", "services": [ + "AKV", "AVS", - "Monitor" + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Alerts", - "text": "Create warning alerts for critical thresholds ", - "waf": "Operations" + "subcategory": "Encryption", + "text": "Keyvault use for secrets", + "waf": "Security" }, { - "category": "Monitoring", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", - "guid": "6d02f159-627d-79bf-a931-fab6d947eda2", - "id": "E01.02", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "description": "Older OS security patching configured for workloads running on Azure VMware Solution are eligible for ESU", + "guid": "4f8b20e9-a2a1-f80f-af9b-8aa3b26dca08", + "id": "I02.01", + "link": "https://docs.microsoft.com/windows-server/get-started/extended-security-updates-deploy", "services": [ - "AVS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Alerts", - "text": "Create critical alert vSAN consumption", - "waf": "Operations" + "subcategory": "Extended support", + "text": "Ensure extended security update support ", + "waf": "Security" }, { - "category": "Monitoring", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Provides platform alerts (generated by Microsoft)", - "guid": "1cc97b39-2c7e-246f-6d73-789cfebfe951", - "id": "E01.03", - "link": "https://www.virtualworkloads.com/2021/04/azure-vmware-solution-azure-service-health/", + "description": "Use a SIEM/SOAR", + "guid": "9bb22fec-4d00-3b95-7136-e225d0f5c63a", + "id": "I03.01", + "link": "https://learn.microsoft.com/azure/sentinel/overview", "services": [ - "AVS", - "Monitor" + "Sentinel", + "AVS" ], "severity": "Medium", - "subcategory": "Alerts", - "text": "Configured for Azure Service Health alerts and notifications", - "waf": "Operations" + "subcategory": "Investigation", + "text": "Enable Azure Sentinel or 3rd party SIEM ", + "waf": "Security" }, { - "category": "Monitoring", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", - "guid": "0962606c-e3b4-62a9-5661-e4ffd62a4509", - "id": "E02.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "description": "MS Defender For Cloud, for workloads running on Azure VMware Solution", + "guid": "f42b0b09-c591-238a-1580-2de3c485ebd2", + "id": "I04.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/azure-security-integration#prerequisites", "services": [ - "AzurePolicy", - "Monitor", - "AVS", - "Backup", - "VM" + "Defender", + "AVS" ], "severity": "Medium", - "subcategory": "Backup", - "text": "Backup policy", - "waf": "Operations" + "subcategory": "Security", + "text": "Enable Advanced Threat Detection ", + "waf": "Security" }, { - "category": "Monitoring", + "category": "Security", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Keep in mind the lead time for requesting new nodes", - "guid": "4ec7ccfb-795e-897e-4a84-fd31c04eadc6", - "id": "E03.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "description": "Are the applicable policies enabled (compliance baselines added to MDfC)", + "guid": "bcdd2348-3d0e-c6bb-1092-aa4cd1a66d6b", + "id": "I04.02", + "link": "https://docs.microsoft.com/azure/azure-vmware/azure-security-integration", "services": [ - "AVS", "AzurePolicy", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Capacity", - "text": "Policy around ESXi host density and efficiency", - "waf": "Operations" + "subcategory": "Security", + "text": "Policy & Regulatory Compliance", + "waf": "Security" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Azure Cost Management can be used - one option, put AVS in it's own Subscription. ", - "guid": "7f8f175d-13f4-5298-9e61-0bc7e9fcc279", - "id": "E04.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/govern", + "description": "Azure to Azure (E/W), Azure to On-premises), AVS to Internet, AVS to Azure", + "guid": "607c1ca9-da92-ae19-5a4c-eb1e876acbe7", + "id": "J01.01", + "link": "https://techcommunity.microsoft.com/t5/azure-migration-and/firewall-integration-in-azure-vmware-solution/ba-p/2254961#:~:text=Azure%20VMware%20Solution%20customers%20have%20multiple%20security%20options,the%20box%20to%20provide%20East-West%20and%20North-South%20firewalling.", "services": [ - "Subscriptions", - "AVS", - "Monitor", - "Cost" + "AVS" ], "severity": "Medium", - "subcategory": "Costs", - "text": "Ensure a good cost management process is in place for Azure VMware Solution - ", - "waf": "Operations" + "subcategory": "Firewalls", + "text": "Azure / 3rd party firewall", + "waf": "Security" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create dashboards to enable core Azure VMware Solution monitoring insights", - "guid": "01e689e0-7c6c-b58f-37bd-4d6b9b1b9c74", - "id": "E05.01", - "link": "https://docs.microsoft.com/azure/azure-portal/azure-portal-dashboards", + "description": "To allow HCX appliance to connect/sync", + "guid": "1d87925c-c02b-7fde-a425-7e95ad846a27", + "id": "J01.02", + "link": "https://docs.vmware.com/en/VMware-Cloud-on-AWS/services/com.vmware.vmc-aws-networking-security/GUID-2CFE1654-9CC9-4EDB-A625-21317299E559.html", "services": [ - "AVS", - "NetworkWatcher", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Dashboard", - "text": "Connection monitor dashboard", - "waf": "Operations" + "subcategory": "Firewalls", + "text": "Firewalls allow for East/West traffic inside AVS", + "waf": "Security" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Send to an Azure Storage account or Azure EventHub for processing (direct to Log Analytics is pending)", - "guid": "f9afdcc9-649d-d840-9fb5-a3c0edcc697d", - "id": "E06.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", + "description": "Decision on which tool to use (SRM requires additional license - enables automation & other features)", + "guid": "468b3495-2f6e-b65a-38ef-3ba631bcaa46", + "id": "J02.01", + "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-B842696B-89EF-4183-9C73-B77157F56055.html", "services": [ - "AVS", - "Storage", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Logs & Metrics", - "text": "Configure Azure VMware Solution logging ", - "waf": "Operations" + "subcategory": "Networking", + "text": "HCX and/or SRM", + "waf": "Reliability" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Must be on-premises, implement if available", - "guid": "7cbac8c3-4eda-d5d9-9bda-c6b5abba9fb6", - "id": "E06.02", - "link": "Is vROPS or vRealize Network Insight going to be used? ", + "description": "Read up on requirements for Service Mesh requirements and how HCX ", + "guid": "be2ced52-da08-d366-cf7c-044c19e29509", + "id": "J02.02", + "link": "https://docs.vmware.com/en/VMware-HCX/4.6/hcx-user-guide/GUID-76BCD059-A31A-4041-9105-ACFB56213E7C.html", "services": [ - "AVS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Logs & Metrics", - "text": "vRealize Operations", - "waf": "Operations" + "subcategory": "Networking", + "text": "Configuring and Managing the HCX Interconnect", + "waf": "Reliability" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", - "guid": "b243521a-644d-f865-7fb6-21f9019c0dd2", - "id": "E06.03", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", + "description": "If you are planning on using stretch networks ensure that your on-premises environment requirements", + "guid": "7dcac579-fc5c-5c9c-f1f7-9b1149ff2c37", + "id": "J02.03", + "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-DBDB4D1B-60B6-4D16-936B-4AC632606909.html", "services": [ - "AVS", - "VM", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Logs & Metrics", - "text": "AVS VM logging", - "waf": "Operations" + "subcategory": "Networking", + "text": "Restrictions and limitations for network extensions", + "waf": "Performance" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Between on-premises to Azure are monitored using 'connection monitor'", - "guid": "2ca97d91-dd36-7229-b668-01036ccc3cd3", - "id": "E07.01", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", + "description": "Do workloads require MoN?", + "guid": "cf45c0b9-6c4b-3bfb-86c5-62fe54061c73", + "id": "J02.04", + "link": "https://learn.microsoft.com/azure/azure-vmware/vmware-hcx-mon-guidance", "services": [ - "ExpressRoute", - "Monitor", - "AVS", - "VPN", - "NetworkWatcher" + "AVS" ], "severity": "Medium", - "subcategory": "Network", - "text": "Monitor ExpressRoute and/or VPN connections ", - "waf": "Operations" + "subcategory": "Networking", + "text": "Mobility optimized networking", + "waf": "Performance" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To monitor the Azure VMware Solution back-end ExpressRoute connection (Azure native to AVS)", - "guid": "99209143-60fe-19f0-5633-8b5671277ba5", - "id": "E07.02", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", + "description": "Operating system level of Vmware environment", + "guid": "b7cf11f3-b12e-5189-991a-06df5250d2ca", + "id": "J03.01", + "link": "https://learn.microsoft.com/azure/site-recovery/vmware-physical-azure-support-matrix", "services": [ - "AVS", - "Monitor", - "ExpressRoute" + "AVS" ], "severity": "Medium", - "subcategory": "Network", - "text": "Monitor from an Azure native resource to an Azure VMware Solution VM", + "subcategory": "On-premises pre-requisites", + "text": "Support matrix (OS versions etc).", "waf": "Operations" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To monitor end-to-end, on-premises to AVS workloads", - "guid": "b9e5867c-57d3-036f-fb1b-3f0a71664efe", - "id": "E07.03", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", + "description": "Required that all switches are dynamic", + "guid": "45fe9252-aa1b-4e30-45c6-bc02f3b76acf", + "id": "J03.02", + "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/vsan-network-design-guide/GUID-91E1CD6F-33A6-4AC6-BC22-3E4807296F86.html#:~:text=Migrate%20Management%20Network%201%20Add%20hosts%20to%20the,each%20host.%20...%204%20Finish%20the%20configuration.%20", "services": [ - "AVS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Network", - "text": "Monitor from an on-premises resource to an Azure VMware Solution VM", + "subcategory": "On-premises pre-requisites", + "text": "Standard switches converted to dynamic switches", "waf": "Operations" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Track requests to Azure VMware Solution and Azure VMware Solution based workloads", - "guid": "4af7c5f7-e5e9-bedf-a8cf-314b81735962", - "id": "E08.01", - "link": "Firewall logging and alerting rules are configured (Azure Firewall or 3rd party)", + "description": "See sections on sizing and capacity in the link.", + "guid": "e9f6d736-ee44-e2ac-e7f9-e361f8c857f3", + "id": "J03.03", + "link": "https://learn.microsoft.com/azure/azure-vmware/plan-private-cloud-deployment", "services": [ - "AVS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "Auditing and logging is implemented for inbound internet ", - "waf": "Operations" + "subcategory": "On-premises pre-requisites", + "text": "Capacity for HCX appliance", + "waf": "Performance" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", - "guid": "74be60a3-cfac-f057-eda6-3ee087e805d5", - "id": "E08.02", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "description": "Check hardware restrictions to ensure compatibility with AVS/OS ", + "guid": "1be2cdd6-15a7-9a33-aea7-113859035ce9", + "id": "J03.04", + "link": "https://kb.vmware.com/s/article/2007240#:~:text=ESXi%2FESX%20hosts%20and%20compatible%20virtual%20machine%20hardware%20versions,%20Not%20Supported%20%204%20more%20rows", "services": [ - "AVS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "Session monitoring ", + "subcategory": "On-premises pre-requisites", + "text": "Hardware compatibility", "waf": "Operations" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Enable Diagnostic and metric logging on Azure VMware Solution", - "guid": "a434b3b5-f258-0845-cd76-d7df6ef5890e", - "id": "E09.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", + "description": "Need to be converted", + "guid": "16ab821a-27c6-b6d3-6042-10dc4d6dfcb7", + "id": "J04.01", + "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.storage.doc/GUID-01D3CF47-A84A-4988-8103-A0487D6441AA.html", "services": [ - "AVS", - "Monitor" + "Storage", + "AVS" ], "severity": "Medium", - "subcategory": "VMWare", - "text": "Logging and diagnostics", + "subcategory": "Storage", + "text": "VSAN RDM disks are converted - not supported.", "waf": "Operations" }, { - "category": "Monitoring", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Monitor AVS workloads (each VM in AVS)", - "guid": "fb00b69a-83ec-ce72-446e-6c23a0cab09a", - "id": "E10.01", - "link": "https://docs.microsoft.com/azure/azure-monitor/agents/agent-windows?tabs=setup-wizard", + "description": "Need to be converted", + "guid": "eb2f9313-afb2-ab35-aa24-6d97a3cb0611", + "id": "J04.02", + "link": "3rd-Party tools", "services": [ - "AVS", + "Storage", "VM", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "VMware", - "text": "Log Analytics Agents deployed on Azure VMware Solution guest VM workloads", + "subcategory": "Storage", + "text": "VM with SCSI shared bus are not supported", "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision on traffic flow", - "guid": "a1354b87-e18e-bf5c-c50b-8ddf0540e971", - "id": "F01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", + "description": "Remove Direct IO before migration", + "guid": "3f2a5cff-c8a6-634a-1f1b-53ef9d321381", + "id": "J04.03", + "link": "Contact VMware", "services": [ + "Storage", + "VM", "AVS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "North/South routing through Az Firewall or 3rd party ", - "waf": "Security" + "subcategory": "Storage", + "text": "VM with Direct IO require removing DirectPath device", + "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", - "guid": "29a8a499-ec31-f336-3266-0895f035e379", - "id": "F01.02", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", + "description": "Cannot migrate clusters ", + "guid": "efc8a311-74f8-0252-c6a0-4bac7610e266", + "id": "J04.04", + "link": "Contact VMware", "services": [ + "Storage", "AVS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "East West (Internal to Azure)", - "waf": "Security" + "subcategory": "Storage", + "text": "Shared VMDK files are not supported", + "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Requires a 3rd party NVA with Azure Route server - Scenario 2 (see link)", - "guid": "ebd3cc3c-ac3d-4293-950d-cecd8445a523", - "id": "F01.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "description": "Convert to a different format", + "guid": "ab6c89cd-a26f-b894-fe59-61863975458e", + "id": "J04.05", + "link": "Contact VMware", "services": [ - "AVS", - "NVA", - "ARS" + "Storage", + "AVS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "ExR without Global Reach", + "subcategory": "Storage", + "text": "RDM with 'physical compatibility mode' are not supported.", "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", - "guid": "ffb5c5ca-bd89-ff1b-8b73-8a54d503d506", - "id": "F01.04", - "link": "https://learn.microsoft.com/azure/route-server/route-server-faq", + "description": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning 'RAID-1 FTT-1' is default with Thin Provisioning", + "guid": "7628d446-6b10-9678-9cec-f407d990de43", + "id": "J04.06", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", "services": [ - "AVS", - "ARS" + "AzurePolicy", + "Storage", + "VM", + "AVS" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "Route server ", + "subcategory": "Storage", + "text": "Default storage policy", "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Via on-premises, Az Firewall, 3rd Party, NSX-T pubic IP", - "guid": "a4070dad-3def-818d-e9f7-be440d10e7de", - "id": "F02.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-design-public-internet-access", + "description": "The default storage policy is set to RAID-1 (Mirroring) FTT-1, with Object Space Reservation set to Thin provisioning.", + "guid": "37fef358-7ab9-43a9-542c-22673955200e", + "id": "J04.07", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-storage-policy", "services": [ + "AzurePolicy", + "Storage", + "VM", "AVS" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Egress point(s)", - "waf": "Security" + "subcategory": "Storage", + "text": "Ensure that the appropriate VM template storage policy is used", + "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Az Firewall, 3rd party NVA, Application Gateway, Azure Frontdoor ", - "guid": "e942c03d-beaa-3d9f-0526-9b26cd5e9937", - "id": "F02.02", - "link": "Research and choose optimal solution for each application", + "description": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", + "guid": "ebebd109-9f9d-d85e-1b2f-d302012843b7", + "id": "J04.08", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", "services": [ - "AVS", - "FrontDoor", - "AppGW", - "NVA" + "AzurePolicy", + "Storage", + "AVS" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Internet facing applications", - "waf": "Security" + "subcategory": "Storage", + "text": "Failure to tolerate policy", + "waf": "Operations" }, { - "category": "Networking", + "category": "VMware", "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", - "guid": "e778a2ec-b4d7-1d27-574c-14476b167d37", - "id": "F03.01", - "link": "https://docs.microsoft.com/azure/route-server/route-server-faq#route-server-limits", + "description": "ANF can be used to extend storage for Azure VMware Solution,", + "guid": "1be821bd-4f37-216a-3e3d-2a5ac6996863", + "id": "J04.09", + "link": "https://learn.microsoft.com/azure/azure-vmware/netapp-files-with-azure-vmware-solution", "services": [ - "AVS", - "ARS" + "Storage", + "AVS" ], - "severity": "Medium", - "subcategory": "Routing", - "text": "When route server Route limit understood? ", - "waf": "Security" + "severity": "Medium", + "subcategory": "Storage", + "text": "Use ANF for external storage", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "(VPN Gateway, AppGW, FrontDoor, Load balancer, VMs (etc) (Remove: enabled on ExR/VPN Gateway subnet in Azure)", - "guid": "66c97b30-81b9-139a-cc76-dd1d94aef42a", - "id": "F04.01", - "link": "https://docs.microsoft.com/azure/ddos-protection/manage-ddos-protection", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "aff6691b-4935-4ada-9222-3ece81b12318", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "services": [ - "LoadBalancer", - "AppGW", - "ExpressRoute", - "DDoS", - "VNet", - "AVS", - "FrontDoor", - "VPN", - "VM" + "ASR" ], "severity": "Medium", - "subcategory": "Security", - "text": "Is DDoS standard protection of public facing IP addresses? ", - "waf": "Security" + "subcategory": " ", + "text": "Do not combine ASCS and Database cluster on to single/same VM" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To manage Azure VMware Solution, vCenter, NSX manager and HCX manager", - "guid": "d43da920-4ecc-a4e9-dd45-a2986ce81d32", - "id": "F04.02", - "link": "Best practice: Bastion or 3rd party tool", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "1a541741-5833-4fb4-ae3c-2df743165c3a", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "services": [ - "AVS" + "LoadBalancer", + "ASR" ], "severity": "Medium", - "subcategory": "Security", - "text": "Use a dedicated privileged access workstation (PAW)", - "waf": "Security" + "subcategory": " ", + "text": "Make sure the Floating IP is enabled on the Load balancer" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use NSX-T for inter-vmware-traffic inspection", - "guid": "a2dac74f-5380-6e39-25e6-f13b99ece51f", - "id": "F05.01", - "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-F6685367-7AA1-4771-927E-ED77727CFDA3.html", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "cbe05bbe-209d-4490-ba47-778424d11678", + "link": "https://learn.microsoft.com/azure/security-center/", "services": [ - "AVS" + "ASR", + "VM", + "RBAC", + "Entra" ], "severity": "Medium", - "subcategory": "Traffic Inspection", - "text": "East West (Internal to AVS)", - "waf": "Security" + "subcategory": " ", + "text": "Do not mix servers of different roles in the same availability set. Keep central services VMs, database VMs, application VMs in their own availability sets" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision on whether or not to use Secure hub for E/W and Internet traffic - requires Global Reach", - "guid": "3f621543-dfac-c471-54a6-7b2849b6909a", - "id": "F06.01", - "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "5d2fa56c-56ad-4484-88fe-72734c486ba2", + "link": "https://learn.microsoft.com/azure/security-center/", "services": [ - "Firewall", - "AVS", - "VWAN" + "ASR", + "ACR", + "SAP" ], "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Use Secure Hub (Azure Firewall or 3rd party)", - "waf": "Security" + "subcategory": " ", + "text": "Use one proximity placement group per SAP SID. Groups don't span across Availability Zones or Azure regions" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", - "guid": "d7af5670-1b39-d95d-6da2-8d660dfbe16b", - "id": "F06.02", - "link": "https://learn.microsoft.com/azure/firewall-manager/secure-cloud-network", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "80dc0591-cf65-4de8-b130-9cccd579266b", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AVS", - "VWAN" + "VM", + "Entra", + "ASR" ], "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "East West (Internal to Azure)", - "waf": "Security" + "subcategory": " ", + "text": "Azure doesn't currently support combining ASCS and db HA in the same Linux Pacemaker cluster; separate them into individual clusters. However, you can combine up to five multiple central-services clusters into a pair of VMs." }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", - "guid": "7d049005-eb35-4a93-50a5-3b31a9f61161", - "id": "G01.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-nsx-network-components-azure-portal", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "cca275fa-a1ab-4fe9-b55d-04c3c4919cb1", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "services": [ - "Subscriptions", - "AVS" + "LoadBalancer", + "ASR" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale out operations planning", - "waf": "Performance" + "subcategory": " ", + "text": "Use a Standard Load Balancer SKU in front of ASCS and DB clusters" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", - "guid": "7242c1de-da37-27f3-1ddd-565ccccb8ece", - "id": "G01.02", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "b3d1325a-e124-4ba3-9df6-85eddce9bd3b", + "link": "https://www.microsoft.com/itshowcase/implementing-a-zero-trust-security-model-at-microsoft", "services": [ - "AVS", "Storage", - "AzurePolicy" + "VM", + "ASR" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale in operations planning", - "waf": "Performance" + "subcategory": " ", + "text": "Both VMs in the HA pair should be deployed in an availability set, or Availability Zones should be the same size and have the same storage configuration" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", - "guid": "3233e49e-62ce-97f3-8737-8230e771b694", - "id": "G01.03", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "b0cdb3b5-5eb2-4ec1-9eea-a3592829e2ed", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "services": [ - "AVS" + "ASR" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale serialized operations planning", - "waf": "Performance" + "subcategory": " ", + "text": "Native database replication technology should be used to synchronize the database in a HA pair." }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", - "guid": "68161d66-5707-319b-e77d-9217da892593", - "id": "G01.04", - "link": "Best practice (testing)", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "b2173676-aff6-4691-a493-5ada42223ece", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "services": [ - "AVS" + "ASR", + "SAP" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale rd operations planning", - "waf": "Performance" + "subcategory": " ", + "text": "Perform a point-in-time recovery for your production databases at any point and in a time frame that meets your RTO; point-in-time recovery typically includes operator errors deleting data either on the DBMS layer or through SAP, incidentally" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Define and enforce scale in/out maximum limits for your environment in the automations", - "guid": "c32cb953-e860-f204-957a-c79d61202669", - "id": "G01.05", - "link": "Operational planning - understand workload requirements", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "81b12318-1a54-4174-8583-3fb4ae3c2df7", "services": [ - "AVS" + "VNet", + "ASR" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale maximum operations planning", - "waf": "Performance" + "subcategory": " ", + "text": "The CIDR for the primary virtual network (VNet) shouldn't conflict or overlap with the CIDR of the DR site's Vnet" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", - "guid": "7bd65a5e-7b5d-652d-dbea-fc6f73a42857", - "id": "G01.06", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-management-and-monitoring", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "43165c3a-cbe0-45bb-b209-d490da477784", "services": [ - "AVS", - "Monitor" + "VM", + "Entra", + "ASR" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Monitor scaling operations ", - "waf": "Performance" + "subcategory": " ", + "text": "Use Site Recovery to replicate an application server to a DR site. Site Recovery can also help with replicating central-services cluster VMs to the DR site. When you invoke DR, you'll need to reconfigure the Linux Pacemaker cluster on the DR site (for example, replace the VIP or SBD, run corosync.conf, and more)." }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Consider the use of Azure Private-Link when using other Azure Native Services", - "guid": "95e374af-8a2a-2672-7ab7-b4a1be43ada7", - "id": "G02.01", - "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "24d11678-5d2f-4a56-a56a-d48408fe7273", "services": [ - "PrivateLink", - "AVS" + "ASR" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Private link", - "waf": "Performance" + "subcategory": " ", + "text": "Native database replication should be used to synchronize data to the DR site, rather than Azure Site Recovery" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", - "guid": "71eff90d-5ad7-ac60-6244-2a6f7d3c51f2", - "id": "G02.02", - "link": "Best practice", + "category": "Compute", + "checklist": "Azure Landing Zone Review", + "guid": "2829e2ed-b217-4367-9aff-6691b4935ada", "services": [ - "AVS" + "VM" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Provisioning Vmware VLANs", - "waf": "Performance" + "subcategory": " ", + "text": "Make quota requests for correct VM SKU and Zones" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "In which region will AVS be deployed", - "guid": "04e3a2f9-83b7-968a-1044-2811811a924b", - "id": "H01.01", - "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", + "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", "services": [ - "AVS" + "Entra", + "RBAC", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Region selected", - "waf": "Reliability" + "severity": "High", + "subcategory": "Identity", + "text": "Enforce a RBAC model for management groups, subscriptions, resource groups and resources", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Are there regulatory or compliance policies in play", - "guid": "e52d1615-9cc6-565c-deb6-743ed7e90f4b", - "id": "H01.02", - "link": "Internal policy or regulatory compliance", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "45911475-e39e-4530-accc-d979366bcda2", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "services": [ - "AVS", - "AzurePolicy" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Data residency compliant with selected regions", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Enforce Principle propagation for forwarding the identity from SAP cloud application to SAP on-premises (Including IaaS) through cloud connector", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Request through the support blade", - "guid": "92bd5ad6-441f-a983-7aa9-05dd669d760b", - "id": "H01.03", - "link": "https://learn.microsoft.com/azure/migrate/concepts-azure-vmware-solution-assessment-calculation", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "services": [ - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Request for number of AVS hosts submitted ", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Implement SSO to SAP SaaS applications like SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics and SAP C4C with Azure AD using SAML." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "PG approval for deployment", - "guid": "28370f63-1cb8-2e35-907f-c5516b6954fa", - "id": "H01.04", - "link": "Support request through portal or get help from Account Team", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "services": [ - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Region and number of AVS nodes approved", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Portal/subscription/resource providers/ Microsoft.AVS", - "guid": "96c76997-30a6-bb92-024d-f4f93f5f57fa", - "id": "H01.05", - "link": "Done through the subscription/resource providers/ AVS register in the portal", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "9eb54dad-7861-4e1c-973a-f3bb003fc9c1", "services": [ - "Subscriptions", - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Resource provider for AVS registered", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Connectivity, subscription & governanace model", - "guid": "5898e3ff-5e6b-bee1-6f85-22fee261ce63", - "id": "H01.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/enterprise-scale-landing-zone", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "services": [ - "Subscriptions", - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Landing zone architecture", - "waf": "Reliability" + "subcategory": "Identity", + "text": "You can implement SSO to SAP GUI by using SAP NetWeaver SSO or a partner solution.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "The name of the RG where AVS will exist", - "guid": "d0181fb8-9cb8-bf4b-f5e5-b5f9bf7ae4ea", - "id": "H01.07", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "23181aa4-1742-4694-9ff8-ae7d7d474317", "services": [ - "AVS" + "AKV", + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Resource group name selected", - "waf": "Reliability" + "subcategory": "Identity", + "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Each resource created as part of the deployment will also utilize this prefix in the name", - "guid": "0f0d20c2-5a19-726c-de20-0984e070d9d6", - "id": "H01.08", - "link": "Best practice - naming standards", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "6c8bcbf4-5bbe-4609-b8a0-3e97778424d6", + "link": "https://blogs.sap.com/2017/07/12/sap-single-sign-on-protect-your-sap-landscape-with-x.509-certificates/", "services": [ - "AVS" + "AKV", + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Deployment prefix selected", - "waf": "Reliability" + "subcategory": "Identity", + "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "/22 unique non-overlapping IPv4 address space", - "guid": "7fbf2ab7-a36c-5957-c27a-67038557af2a", - "id": "H01.09", - "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-network-checklist#routing-and-subnet-considerations", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "16785d6f-a96c-496a-b885-18f482734c88", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", "services": [ - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Network space for AVS management layer", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Implement SSO by using OAuth for SAP NetWeaver to allow third-party or custom applications to access SAP NetWeaver OData services." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "vNets used by workloads running in AVS (non-stretched)", - "guid": "0c87f999-e517-21ef-f355-f210ad4134d2", - "id": "H01.10", - "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/installation/GUID-4B3860B8-1883-48CA-B2F3-7C2205D91D6D.html", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "a747c350-8d4c-449c-93af-393dbca77c48", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", "services": [ - "VNet", - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Network space for AVS NSX-T segments", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Implement SSO to SAP HANA" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Choose AV36, AV36P, AV52, AV36T (AV36T = Trial)", - "guid": "946c8966-f902-6f53-4f37-00847e8895c2", - "id": "H01.11", - "link": "https://azure.microsoft.com/pricing/details/azure-vmware/", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", "services": [ - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "AVS SKU (region dependent)", - "waf": "Performance" + "subcategory": "Identity", + "text": "Consider Azure AD an identity provider for SAP systems hosted on RISE. For more information, see Integrating the Service with Azure AD." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use the Azure migration assessment tool to determine the minimum number of nodes required (consider BCDR as well)", - "guid": "31833808-26ba-9c31-416f-d54a89a17f5d", - "id": "H01.12", - "link": "https://learn.microsoft.com/azure/migrate/how-to-assess", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "e4e48226-ce54-44b6-bb6b-bfa15bd8f753", + "link": "https://github.com/azuredevcollege/SAP/blob/master/sap-oauth-saml-flow/README.md", "services": [ - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Number of hosts to be deployed", - "waf": "Performance" + "subcategory": "Identity", + "text": "For applications that access SAP, you might want to use principal propagation to establish SSO." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Understand how and if you should be using reserved instances (cost control)", - "guid": "f2b73c4f-3d46-32c9-5df1-5b8dfcd3947f", - "id": "H01.13", - "link": "https://azure.microsoft.com/en-ca/pricing/details/azure-vmware/#:~:text=Azure%20VMware%20Solution%20%20%20%20Instance%20size,TB%20%28all%20NVMe%29%20%20%20N%2FA%20%2Fhour%20", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", "services": [ - "AVS", - "Cost" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Reserverd Instances", - "waf": "Cost" + "subcategory": "Identity", + "text": "If you're using SAP BTP services or SaaS solutions that require SAP Identity Authentication Service (IAS), consider implementing SSO between SAP Cloud Identity Authentication Services and Azure AD to access those SAP services. This integration lets SAP IAS act as a proxy identity provider and forwards authentication requests to Azure AD as the central user store and identity provider." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", - "guid": "94ac48ab-ade5-3fa7-f800-263feeb97070", - "id": "H01.14", - "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", "services": [ - "AVS", - "ASR" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Capacity ", - "waf": "Performance" + "subcategory": "Identity", + "text": "Implement SSO to SAP BTP" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Identify which of the networking scenarios make ", - "guid": "1f9d4bd5-14b8-928c-b4cb-eb211f9b8de5", - "id": "H01.15", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "01f11b7f-38df-4251-9c76-4dec19abd3e8", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-successfactors-inbound-provisioning-cloud-only-tutorial", "services": [ - "AVS" + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Networking & Connectivity See docs describing scenrario 1 through 5", - "waf": "Reliability" + "subcategory": "Identity", + "text": "If you're using SAP SuccessFactors, consider using the Azure AD automated user provisioning. With this integration, as you add new employees to SAP SuccessFactors, you can automatically create their user accounts in Azure AD. Optionally, you can create user accounts in Microsoft 365 or other SaaS applications that are supported by Azure AD. Use write-back of the email address to SAP SuccessFactors." }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", - "guid": "070db19b-8a2a-fd6a-c39b-4488d8780da9", - "id": "H01.16", - "link": "Please Check Partner Ecosystem", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "6ba28021-4591-4147-9e39-e5309cccd979", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "services": [ - "AVS" + "AzurePolicy", + "SAP", + "Subscriptions" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "3rd party application compatibility ", - "waf": "Reliability" + "subcategory": "Subscriptions", + "text": "enforce existing Management Group policies to SAP Subscriptions", + "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", - "guid": "70cfbddc-d3d4-9188-77c8-1cabaefef646", - "id": "I01.01", - "link": "General recommendation for storing encryption keys.", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", "services": [ - "AVS", - "AKV" + "SAP", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Encryption", - "text": "Use Azure Key Vault with in-guest encryption ", - "waf": "Security" + "severity": "High", + "subcategory": "Subscriptions", + "text": "Integrate tightly coupled applications into the same SAP subscription to avoid additional routing and management complexity", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", - "guid": "c1a81638-18df-0ce9-a73a-4b9a8a8dd392", - "id": "I01.02", - "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#data-at-rest-encryption", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", "services": [ - "SQL", - "AVS" + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Encryption", - "text": "Use in-guest encryption", - "waf": "Security" + "severity": "High", + "subcategory": "Subscriptions", + "text": "Leverage Subscription as scale unit and scaling our resources, consider deploying subscription per environment eg. Sandbox, non-prod, prod ", + "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", - "guid": "8d0a8f51-8d35-19cd-c2fe-4e3512fb467e", - "id": "I01.03", - "link": "https://docs.microsoft.com/azure/key-vault/general/authentication", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", + "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", "services": [ - "AVS", - "AKV", - "ExpressRoute" + "VM", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Encryption", - "text": "Keyvault use for secrets", - "waf": "Security" + "severity": "High", + "subcategory": "Subscriptions", + "text": "Ensure quota increase as a part of subscription provisioning (e.g. total available VM cores within a subscription)", + "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Older OS security patching configured for workloads running on Azure VMware Solution are eligible for ESU", - "guid": "4f8b20e9-a2a1-f80f-af9b-8aa3b26dca08", - "id": "I02.01", - "link": "https://docs.microsoft.com/windows-server/get-started/extended-security-updates-deploy", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", + "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", "services": [ - "AVS" + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Extended support", - "text": "Ensure extended security update support ", - "waf": "Security" + "severity": "Low", + "subcategory": "Subscriptions", + "text": "The Quota API is a REST API that you can use to view and manage quotas for Azure services. Consider using it if necessary." }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use a SIEM/SOAR", - "guid": "9bb22fec-4d00-3b95-7136-e225d0f5c63a", - "id": "I03.01", - "link": "https://learn.microsoft.com/azure/sentinel/overview", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", + "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", "services": [ - "AVS", - "Sentinel" + "VM", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Investigation", - "text": "Enable Azure Sentinel or 3rd party SIEM ", - "waf": "Security" + "severity": "High", + "subcategory": "Subscriptions", + "text": "If deploying to an availability zone, ensure that the VM's zone deployment is available once the quota has been approved. Submit a support request with the subscription, VM series, number of CPUs and availability zone required." }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "MS Defender For Cloud, for workloads running on Azure VMware Solution", - "guid": "f42b0b09-c591-238a-1580-2de3c485ebd2", - "id": "I04.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/azure-security-integration#prerequisites", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "e6e20617-3686-4af4-9791-f8935ada4332", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", "services": [ - "AVS", - "Defender" + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Enable Advanced Threat Detection ", - "waf": "Security" + "severity": "High", + "subcategory": "Subscriptions", + "text": "Ensure required services and features are available within the chosen deployment regions eg. ANF , Zone etc.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Are the applicable policies enabled (compliance baselines added to MDfC)", - "guid": "bcdd2348-3d0e-c6bb-1092-aa4cd1a66d6b", - "id": "I04.02", - "link": "https://docs.microsoft.com/azure/azure-vmware/azure-security-integration", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", "services": [ - "AVS", - "AzurePolicy" + "Cost", + "TrafficManager", + "Subscriptions" ], "severity": "Medium", - "subcategory": "Security", - "text": "Policy & Regulatory Compliance", - "waf": "Security" + "subcategory": "Subscriptions", + "text": "Leverage Azure resource tag for cost categorization and resource grouping (: BillTo, Department (or Business Unit), Environment (Production, Stage, Development), Tier (Web Tier, Application Tier), Application Owner, ProjectName)", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Azure to Azure (E/W), Azure to On-premises), AVS to Internet, AVS to Azure", - "guid": "607c1ca9-da92-ae19-5a4c-eb1e876acbe7", - "id": "J01.01", - "link": "https://techcommunity.microsoft.com/t5/azure-migration-and/firewall-integration-in-azure-vmware-solution/ba-p/2254961#:~:text=Azure%20VMware%20Solution%20customers%20have%20multiple%20security%20options,the%20box%20to%20provide%20East-West%20and%20North-South%20firewalling.", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "2f7c95f0-6e15-44e3-aa35-92829e6e2061", + "link": "https://learn.microsoft.com/azure/backup/sap-hana-database-about", "services": [ - "AVS" + "Backup", + "Monitor" ], - "severity": "Medium", - "subcategory": "Firewalls", - "text": "Azure / 3rd party firewall", - "waf": "Security" + "severity": "High", + "subcategory": "BCDR", + "text": "Help protect your HANA database by using the Azure Backup service.", + "training": "https://learn.microsoft.com/training/modules/implement-azure-backup-sap-workloads-azure-virtual-machines/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To allow HCX appliance to connect/sync", - "guid": "1d87925c-c02b-7fde-a425-7e95ad846a27", - "id": "J01.02", - "link": "https://docs.vmware.com/en/VMware-Cloud-on-AWS/services/com.vmware.vmc-aws-networking-security/GUID-2CFE1654-9CC9-4EDB-A625-21317299E559.html", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "302a2fbf-3745-4a5f-a365-c9d1a16ca22c", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/azacsnap-introduction", "services": [ - "AVS" + "Storage", + "VM", + "Entra", + "Monitor" ], "severity": "Medium", - "subcategory": "Firewalls", - "text": "Firewalls allow for East/West traffic inside AVS", - "waf": "Security" + "subcategory": "BCDR", + "text": "If you deploy Azure NetApp Files for your HANA, Oracle, or DB2 database, use the Azure Application Consistent Snapshot tool (AzAcSnap) to take application-consistent snapshots. AzAcSnap also supports Oracle databases. Consider using AzAcSnap on a central VM rather than on individual VMs." }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision on which tool to use (SRM requires additional license - enables automation & other features)", - "guid": "468b3495-2f6e-b65a-38ef-3ba631bcaa46", - "id": "J02.01", - "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-B842696B-89EF-4183-9C73-B77157F56055.html", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "42d37218-a3a7-45df-bff6-1173e7f249ea", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", "services": [ - "AVS" + "Monitor", + "SAP" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "HCX and/or SRM", - "waf": "Reliability" - }, - { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Read up on requirements for Service Mesh requirements and how HCX ", - "guid": "be2ced52-da08-d366-cf7c-044c19e29509", - "id": "J02.02", - "link": "https://docs.vmware.com/en/VMware-HCX/4.6/hcx-user-guide/GUID-76BCD059-A31A-4041-9105-ACFB56213E7C.html", + "severity": "High", + "subcategory": "Management", + "text": "Ensure time-zone matches between the operating system and the SAP system." + }, + { + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "c3c7abc0-716c-4486-893c-40e181d65539", + "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel-multi-sid", "services": [ - "AVS" + "Entra", + "Monitor" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Configuring and Managing the HCX Interconnect", - "waf": "Reliability" + "subcategory": "Management", + "text": "Don't group different application services in the same cluster. For example, don't combine DRBD and central services clusters on the same cluster. However, you can use the same Pacemaker cluster to manage approximately five different central services (multi-SID cluster).", + "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "If you are planning on using stretch networks ensure that your on-premises environment requirements", - "guid": "7dcac579-fc5c-5c9c-f1f7-9b1149ff2c37", - "id": "J02.03", - "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-DBDB4D1B-60B6-4D16-936B-4AC632606909.html", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "a491dfc4-9353-4213-9217-eef0949f9467", + "link": "https://azure.microsoft.com/pricing/offers/dev-test/", "services": [ - "AVS" + "Cost", + "Monitor" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Restrictions and limitations for network extensions", - "waf": "Performance" + "severity": "Low", + "subcategory": "Management", + "text": "Consider running dev/test systems in a snooze model to save and optimize Azure run costs." }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Do workloads require MoN?", - "guid": "cf45c0b9-6c4b-3bfb-86c5-62fe54061c73", - "id": "J02.04", - "link": "https://learn.microsoft.com/azure/azure-vmware/vmware-hcx-mon-guidance", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "b7056168-6199-4732-a514-cdbb2d5c9c54", + "link": "https://learn.microsoft.com/azure/lighthouse/overview", "services": [ - "AVS" + "Monitor", + "Entra", + "SAP" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Mobility optimized networking", - "waf": "Performance" + "subcategory": "Management", + "text": "If you partner with customers by managing their SAP estates, consider Azure Lighthouse. Azure Lighthouse allows managed service providers to use Azure native identity services to authenticate to the customers' environment. It puts the control in the hands of customers, because they can revoke access at any time and audit service providers' actions." }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Operating system level of Vmware environment", - "guid": "b7cf11f3-b12e-5189-991a-06df5250d2ca", - "id": "J03.01", - "link": "https://learn.microsoft.com/azure/site-recovery/vmware-physical-azure-support-matrix", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "4d116785-d2fa-456c-96ad-48408fe72734", + "link": "https://learn.microsoft.com/azure/update-manager/scheduled-patching?tabs=schedule-updates-single-machine%2Cschedule-updates-scale-overview", "services": [ - "AVS" + "VM", + "Monitor" ], "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Support matrix (OS versions etc).", - "waf": "Operations" + "subcategory": "Management", + "text": "Use Azure Update Manager to check the status of available updates for a single VM or multiple VMs and consider scheduling regular patching.", + "training": "https://learn.microsoft.com/training/modules/keep-your-virtual-machines-updated/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Required that all switches are dynamic", - "guid": "45fe9252-aa1b-4e30-45c6-bc02f3b76acf", - "id": "J03.02", - "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/vsan-network-design-guide/GUID-91E1CD6F-33A6-4AC6-BC22-3E4807296F86.html#:~:text=Migrate%20Management%20Network%201%20Add%20hosts%20to%20the,each%20host.%20...%204%20Finish%20the%20configuration.%20", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "76c8bcbf-45bb-4e60-ad8a-03e97778424d", + "link": "https://learn.microsoft.com/azure/sap/workloads/lama-installation", "services": [ - "AVS" + "Monitor", + "SAP" ], - "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Standard switches converted to dynamic switches", - "waf": "Operations" + "severity": "Low", + "subcategory": "Management", + "text": "Optimize and manage SAP Basis operations by using SAP Landscape Management (LaMa). Use the SAP LaMa connector for Azure to relocate, copy, clone, and refresh SAP systems.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-remote-management/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "See sections on sizing and capacity in the link.", - "guid": "e9f6d736-ee44-e2ac-e7f9-e361f8c857f3", - "id": "J03.03", - "link": "https://learn.microsoft.com/azure/azure-vmware/plan-private-cloud-deployment", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "14591147-5e39-4e53-89cc-cd979366bcda", + "link": "https://learn.microsoft.com/azure/sap/monitor/about-azure-monitor-sap-solutions", "services": [ - "AVS" + "SQL", + "SAP", + "Monitor" ], "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Capacity for HCX appliance", - "waf": "Performance" + "subcategory": "Monitoring", + "text": "Use Azure Monitor for SAP solutions to monitor your SAP workloads(SAP HANA, high-availability SUSE clusters, and SQL systems) on Azure. Consider supplementing Azure Monitor for SAP solutions with SAP Solution Manager.", + "training": "https://learn.microsoft.com/training/modules/implement-azure-monitoring-sap-workloads-azure-virtual-machines/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Check hardware restrictions to ensure compatibility with AVS/OS ", - "guid": "1be2cdd6-15a7-9a33-aea7-113859035ce9", - "id": "J03.04", - "link": "https://kb.vmware.com/s/article/2007240#:~:text=ESXi%2FESX%20hosts%20and%20compatible%20virtual%20machine%20hardware%20versions,%20Not%20Supported%20%204%20more%20rows", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "2750ab1a-b039-4d95-b54c-7c8929cb107d", + "link": "https://learn.microsoft.com/azure/sap/workloads/vm-extension-for-sap", "services": [ - "AVS" + "VM", + "SAP", + "Entra", + "Monitor" ], - "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Hardware compatibility", - "waf": "Operations" + "severity": "High", + "subcategory": "Monitoring", + "text": "Run a VM Extension for SAP check. VM Extension for SAP uses the assigned managed identity of a virtual machine (VM) to access VM monitoring and configuration data. The check ensures that all performance metrics in your SAP application come from the underlying Azure Extension for SAP.", + "training": "https://learn.microsoft.com/training/modules/configure-azure-enhanced-monitoring-extension-for-sap/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Need to be converted", - "guid": "16ab821a-27c6-b6d3-6042-10dc4d6dfcb7", - "id": "J04.01", - "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.storage.doc/GUID-01D3CF47-A84A-4988-8103-A0487D6441AA.html", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "5325ae52-5ba3-44d4-985e-2213ace7bb12", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AVS", - "Storage" + "AzurePolicy", + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "VSAN RDM disks are converted - not supported.", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Use Azure Policy for access control and compliance reporting. Azure Policy provides the ability to enforce organization-wide settings to ensure consistent policy adherence and fast violation detection. ", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Need to be converted", - "guid": "eb2f9313-afb2-ab35-aa24-6d97a3cb0611", - "id": "J04.02", - "link": "3rd-Party tools", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "523181aa-4174-4269-93ff-8ae7d7d47431", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-overview", "services": [ - "AVS", - "Storage", - "VM" + "SAP", + "NetworkWatcher", + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "VM with SCSI shared bus are not supported", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Use Connection Monitor in Azure Network Watcher to monitor latency metrics for SAP databases and application servers. Or collect and display network latency measurements by using Azure Monitor.", + "training": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/collecting-and-displaying-niping-network-latency-measurements/ba-p/1833979" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Remove Direct IO before migration", - "guid": "3f2a5cff-c8a6-634a-1f1b-53ef9d321381", - "id": "J04.03", - "link": "Contact VMware", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "d89fd98d-23e4-4b40-a92e-32db9365522c", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-monitor-and-troubleshoot", "services": [ - "AVS", - "Storage", - "VM" + "SAP", + "ASR", + "Monitor" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "VM with Direct IO require removing DirectPath device", - "waf": "Operations" + "severity": "High", + "subcategory": "Monitoring", + "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", + "training": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Cannot migrate clusters ", - "guid": "efc8a311-74f8-0252-c6a0-4bac7610e266", - "id": "J04.04", - "link": "Contact VMware", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "73686af4-6791-4f89-95ad-a43324e13811", + "link": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/QualityCheck", "services": [ - "AVS", - "Storage" + "Monitor", + "VM", + "SAP" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Shared VMDK files are not supported", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Perform a quality check for SAP HANA on the provisioned Azure infrastructure to verify that provisioned VMs comply with SAP HANA on Azure best practices." }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Convert to a different format", - "guid": "ab6c89cd-a26f-b894-fe59-61863975458e", - "id": "J04.05", - "link": "Contact VMware", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "616785d6-fa96-4c96-ad88-518f482734c8", + "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-zones", "services": [ - "AVS", - "Storage" + "Monitor", + "SAP", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "RDM with 'physical compatibility mode' are not supported.", - "waf": "Operations" + "severity": "High", + "subcategory": "Monitoring", + "text": "For each Azure subscription, run a latency test on Azure availability zones before zonal deployment to choose low-latency zones for deployment of SAP on Azure.", + "training": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/AvZone-Latency-Test" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning 'RAID-1 FTT-1' is default with Thin Provisioning", - "guid": "7628d446-6b10-9678-9cec-f407d990de43", - "id": "J04.06", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "410adcba-db46-424f-a6c4-05ecde75c52e", + "link": "https://learn.microsoft.com/azure/advisor/advisor-how-to-improve-reliability", "services": [ - "VM", - "AVS", "Storage", - "AzurePolicy" + "Monitor", + "ASR" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Default storage policy", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Run the Resiliency Report to ensure that the configuration of the entire provisioned Azure infrastructure (Compute, Database, Networking, Storage, Site Recovery) complies with the configuration defined by Cloud Adaption Framework for Azure.", + "training": "https://learn.microsoft.com/training/paths/azure-well-architected-framework/" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "The default storage policy is set to RAID-1 (Mirroring) FTT-1, with Object Space Reservation set to Thin provisioning.", - "guid": "37fef358-7ab9-43a9-542c-22673955200e", - "id": "J04.07", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-storage-policy", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "86ba2802-1459-4114-95e3-9e5309cccd97", + "link": "https://learn.microsoft.com/azure/sentinel/sap/deployment-overview", "services": [ - "AVS", - "Storage", - "VM", - "AzurePolicy" + "Sentinel", + "SAP", + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Ensure that the appropriate VM template storage policy is used", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Implement threat protection by using the Microsoft Sentinel solution for SAP. Use this solution to monitor your SAP systems and detect sophisticated threats throughout the business logic and application layers.", + "training": "https://learn.microsoft.com/training/modules/plan-microsoft-sentinel-deployment-sap/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", - "guid": "ebebd109-9f9d-d85e-1b2f-d302012843b7", - "id": "J04.08", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "579266bc-ca27-45fa-a1ab-fe9d55d04c3c", + "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance", "services": [ - "AVS", - "Storage", - "AzurePolicy" + "Cost", + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Failure to tolerate policy", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Azure tagging can be leveraged to logically group and track resources, automate their deployments, and most importantly, provide visibility on the incurred costs.", + "training": "https://learn.microsoft.com/training/modules/analyze-costs-create-budgets-azure-cost-management/?source=recommendations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "ANF can be used to extend storage for Azure VMware Solution,", - "guid": "1be821bd-4f37-216a-3e3d-2a5ac6996863", - "id": "J04.09", - "link": "https://learn.microsoft.com/azure/azure-vmware/netapp-files-with-azure-vmware-solution", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "04b8e5e5-13cb-4b22-af62-5a8ecfcf0337", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-test-latency?tabs=windows", "services": [ - "AVS", - "Storage" + "VM", + "Monitor" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Use ANF for external storage", - "waf": "Operations" + "severity": "Low", + "subcategory": "Performance", + "text": "Use inter-VM latency monitoring for latency-sensitive applications." }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Management and Monitoring", "checklist": "Azure Landing Zone Review", - "guid": "aff6691b-4935-4ada-9222-3ece81b12318", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", + "guid": "07e5ed53-3d96-43d8-87ea-631b77da5aba", + "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide-storage", "services": [ - "ASR" + "SAP", + "ASR", + "Monitor" ], "severity": "Medium", - "subcategory": " ", - "text": "Do not combine ASCS and Database cluster on to single/same VM" + "subcategory": "Performance", + "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-storage/?source=recommendations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Management and Monitoring", "checklist": "Azure Landing Zone Review", - "guid": "1a541741-5833-4fb4-ae3c-2df743165c3a", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", + "guid": "abb6af9c-982c-4cf1-83fb-329fafd1ee56", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", "services": [ - "LoadBalancer", - "ASR" + "Storage", + "Monitor", + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Make sure the Floating IP is enabled on the Load balancer" + "subcategory": "Performance", + "text": "Exclude all the database file systems and executable programs from antivirus scans. Including them could lead to performance problems. Check with the database vendors for prescriptive details on the exclusion list. For example, Oracle recommends excluding /oracle//sapdata from antivirus scans." }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Management and Monitoring", "checklist": "Azure Landing Zone Review", - "guid": "cbe05bbe-209d-4490-ba47-778424d11678", - "link": "https://learn.microsoft.com/azure/security-center/", + "guid": "c027f893-f404-41a9-b33d-39d625a14964", + "link": "https://sapit-forme-prod.authentication.eu11.hana.ondemand.com/login", "services": [ - "Entra", - "RBAC", - "VM", - "ASR" + "Monitor", + "SAP" ], - "severity": "Medium", - "subcategory": " ", - "text": "Do not mix servers of different roles in the same availability set. Keep central services VMs, database VMs, application VMs in their own availability sets" + "severity": "Low", + "subcategory": "Performance", + "text": "Consider collecting full database statistics for non-HANA databases after migration. For example, implement SAP note 1020260 - Delivery of Oracle statistics." }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Management and Monitoring", "checklist": "Azure Landing Zone Review", - "guid": "5d2fa56c-56ad-4484-88fe-72734c486ba2", - "link": "https://learn.microsoft.com/azure/security-center/", + "guid": "fdafb1f5-3eee-4354-a8c9-deb8127ebc2e", + "link": "https://learn.microsoft.com/azure/virtual-machines/workloads/oracle/configure-oracle-asm", "services": [ - "ACR", - "ASR", + "Storage", + "Monitor", "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Use one proximity placement group per SAP SID. Groups don't span across Availability Zones or Azure regions" + "subcategory": "Performance", + "text": "Consider using Oracle Automatic Storage Management (ASM) for all Oracle deployments that use SAP on Azure.", + "training": "https://learn.microsoft.com/training/paths/administer-infrastructure-resources-in-azure/?source=recommendations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Management and Monitoring", "checklist": "Azure Landing Zone Review", - "guid": "80dc0591-cf65-4de8-b130-9cccd579266b", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "guid": "33c5d5bf-daf3-4f0d-bd50-6010fdcec22e", + "link": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/announcement-sap-on-azure-oracle-performance-efficiency-scripts/ba-p/3725178", "services": [ - "Entra", - "VM", - "ASR" + "SQL", + "Monitor", + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Azure doesn't currently support combining ASCS and db HA in the same Linux Pacemaker cluster; separate them into individual clusters. However, you can combine up to five multiple central-services clusters into a pair of VMs." + "subcategory": "Performance", + "text": "For SAP on Azure running Oracle, a collection of SQL scripts can help you diagnose performance problems. Automatic Workload Repository (AWR) reports contain valuable information for diagnosing problems in the Oracle system. We recommend that you run an AWR report during several sessions and choose peak times for it, to ensure broad coverage for the analysis.", + "training": "https://learn.microsoft.com/ja-jp/azure/well-architected/oracle-iaas/performance-efficiency" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "cca275fa-a1ab-4fe9-b55d-04c3c4919cb1", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "guid": "5ba34d46-85e2-4213-ace7-bb122f7c95f0", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "services": [ - "LoadBalancer", - "ASR" + "AzurePolicy", + "WAF", + "AppGW" ], "severity": "Medium", - "subcategory": " ", - "text": "Use a Standard Load Balancer SKU in front of ASCS and DB clusters" + "subcategory": "App delivery", + "text": "For secure delivery of HTTP/S apps, use Application Gateway v2 and ensure that WAF protection and policies are enabled.", + "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "b3d1325a-e124-4ba3-9df6-85eddce9bd3b", - "link": "https://www.microsoft.com/itshowcase/implementing-a-zero-trust-security-model-at-microsoft", + "guid": "fa9d30bc-1b82-4e4b-bfdf-6b017938b9e6", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", "services": [ - "Storage", + "DNS", "VM", - "ASR" + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Both VMs in the HA pair should be deployed in an availability set, or Availability Zones should be the same size and have the same storage configuration" + "subcategory": "DNS", + "text": "If the virtual machine's DNS or virtual name is not changed during migration to Azure, Background DNS and virtual names connect many system interfaces in the SAP landscape, and customers are only sometimes aware of the interfaces that developers define over time. Connection challenges arise between various systems when virtual or DNS names change after migrations, and it's recommended to retain DNS aliases to prevent these types of difficulties.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "b0cdb3b5-5eb2-4ec1-9eea-a3592829e2ed", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "guid": "a2858f78-105b-4f52-b7a9-5b0f4439743b", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", "services": [ - "ASR" + "DNS", + "VNet", + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Native database replication technology should be used to synchronize the database in a HA pair." + "subcategory": "DNS", + "text": "Use different DNS zones to distinguish each environment (sandbox, development, preproduction, and production) from each other. The exception is for SAP deployments with their own VNet; here, private DNS zones might not be necessary.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "b2173676-aff6-4691-a493-5ada42223ece", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "guid": "a3592829-e6e2-4061-9368-6af46791f893", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", "services": [ - "ASR", + "VNet", + "ACR", "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Perform a point-in-time recovery for your production databases at any point and in a time frame that meets your RTO; point-in-time recovery typically includes operator errors deleting data either on the DBMS layer or through SAP, incidentally" + "subcategory": "Hybrid", + "text": "Local and global VNet peering provide connectivity and are the preferred approaches to ensure connectivity between landing zones for SAP deployments across multiple Azure regions", + "training": "https://learn.microsoft.com/training/modules/configure-vnet-peering/?source=recommendations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "81b12318-1a54-4174-8583-3fb4ae3c2df7", + "guid": "41742694-3ff8-4ae7-b7d4-743176c8bcbf", + "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide", "services": [ - "VNet", - "ASR" + "NVA", + "SAP" ], - "severity": "Medium", - "subcategory": " ", - "text": "The CIDR for the primary virtual network (VNet) shouldn't conflict or overlap with the CIDR of the DR site's Vnet" + "severity": "High", + "subcategory": "Hybrid", + "text": "It is not supported to deploy any NVA between SAP application and SAP Database server", + "training": "https://me.sap.com/notes/2731110" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "43165c3a-cbe0-45bb-b209-d490da477784", + "guid": "7d4bc7d2-c34a-452e-8f1d-6ae3c8eafcc3", + "link": "https://learn.microsoft.com/training/modules/introduction-azure-virtual-wan/?source=recommendations", "services": [ - "Entra", - "VM", - "ASR" + "ACR", + "VWAN", + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Use Site Recovery to replicate an application server to a DR site. Site Recovery can also help with replicating central-services cluster VMs to the DR site. When you invoke DR, you'll need to reconfigure the Linux Pacemaker cluster on the DR site (for example, replace the VIP or SBD, run corosync.conf, and more)." + "subcategory": "Hybrid", + "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", + "training": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "24d11678-5d2f-4a56-a56a-d48408fe7273", + "guid": "0cedb1f6-ae6c-492b-8b17-8061f50b16d3", + "link": "https://learn.microsoft.com/azure/well-architected/services/networking/network-virtual-appliances/reliability", "services": [ - "ASR" + "VNet", + "NVA" ], "severity": "Medium", - "subcategory": " ", - "text": "Native database replication should be used to synchronize data to the DR site, rather than Azure Site Recovery" + "subcategory": "Hybrid", + "text": "Consider deploying network virtual appliances (NVAs) between regions only if partner NVAs are used. NVAs between regions or VNets aren't required if native NVAs are present. When you're deploying partner networking technologies and NVAs, follow the vendor's guidance to verify conflicting configurations with Azure networking.", + "training": "https://learn.microsoft.com/training/modules/control-network-traffic-flow-with-routes/?source=recommendations" }, { - "category": "Compute", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "2829e2ed-b217-4367-9aff-6691b4935ada", + "guid": "facc08c6-ea95-4641-91cd-fa09e573adbd", + "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", "services": [ - "VM" + "VNet", + "NVA", + "VWAN", + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Make quota requests for correct VM SKU and Zones" + "subcategory": "Hybrid", + "text": "Virtual WAN manages connectivity between spoke VNets for virtual-WAN-based topologies (no need to set up user-defined routing [UDR] or NVAs), and maximum network throughput for VNet-to-VNet traffic in the same virtual hub is 50 gigabits per second. If necessary, SAP landing zones can use VNet peering to connect to other landing zones and overcome this bandwidth limitation.", + "training": "https://learn.microsoft.com/training/modules/hub-and-spoke-network-architecture/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", - "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", + "guid": "82734c88-6ba2-4802-8459-11475e39e530", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "Subscriptions", - "RBAC", - "Entra" + "VM", + "VNet", + "SAP" ], "severity": "High", - "subcategory": "Identity", - "text": "Enforce a RBAC model for management groups, subscriptions, resource groups and resources", - "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" + "subcategory": "IP plan", + "text": "Public I.P assignment to VM running SAP Workload is not recommended.", + "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "45911475-e39e-4530-accc-d979366bcda2", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "guid": "9cccd979-366b-4cda-8750-ab1ab039d95d", + "link": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations", "services": [ - "Entra", - "SAP" + "VNet", + "ASR" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Enforce Principle propagation for forwarding the identity from SAP cloud application to SAP on-premises (Including IaaS) through cloud connector", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" + "severity": "High", + "subcategory": "IP plan", + "text": "Consider reserving I.P address on DR side when configuring ASR", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "guid": "54c7c892-9cb1-407d-9325-ae525ba34d46", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "Entra", - "SAP" + "VNet" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP SaaS applications like SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics and SAP C4C with Azure AD using SAML." + "severity": "High", + "subcategory": "IP plan", + "text": "Avoid using overlapping IP address ranges for production and DR sites.", + "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "guid": "6e154e3a-a359-4282-ae6e-206173686af4", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-delegate-subnet", "services": [ - "Entra", - "SAP" + "Storage", + "VNet" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "subcategory": "IP plan", + "text": "While Azure does help you to create multiple delegated subnets in a VNet, only one delegated subnet can exist in a VNet for Azure NetApp Files. Attempts to create a new volume will fail if you use more than one delegated subnet for Azure NetApp Files.", + "training": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-network-topologies?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "9eb54dad-7861-4e1c-973a-f3bb003fc9c1", + "guid": "d8a03e97-7784-424d-9167-85d6fa96c96a", + "link": "https://learn.microsoft.com/azure/well-architected/services/networking/azure-firewall?toc=%2Fazure%2Ffirewall%2Ftoc.json&bc=%2Fazure%2Ffirewall%2Fbreadcrumb%2Ftoc.json", "services": [ - "Entra", - "SAP" + "Firewall" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" + "subcategory": "Internet", + "text": "Use Azure Firewall to govern Azure outbound traffic to the internet, non-HTTP/S inbound connections, and East/West traffic filtering (if the organization requires it)", + "training": "https://learn.microsoft.com/training/paths/secure-networking-infrastructure/" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "guid": "91a65e40-be90-45b3-9f73-f3edbf8dc324", + "link": "https://learn.microsoft.com/azure/sap/workloads/expose-sap-process-orchestration-on-azure", "services": [ - "Entra", + "AppGW", + "WAF", "SAP" ], "severity": "Medium", - "subcategory": "Identity", - "text": "You can implement SSO to SAP GUI by using SAP NetWeaver SSO or a partner solution.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "subcategory": "Internet", + "text": "Application Gateway and Web Application Firewall have limitations when Application Gateway serves as a reverse proxy for SAP web apps, as shown in the comparison between Application Gateway, SAP Web Dispatcher, and other third-party services.", + "training": "https://help.sap.com/docs/SUPPORT_CONTENT/si/3362959506.html" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "23181aa4-1742-4694-9ff8-ae7d7d474317", + "guid": "5e39e530-9ccc-4d97-a366-bcda2750ab1a", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "Entra", - "AKV", - "SAP" + "AzurePolicy", + "FrontDoor", + "ACR", + "WAF" ], "severity": "Medium", - "subcategory": "Identity", - "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" + "subcategory": "Internet", + "text": "Use Azure Front Door and WAF policies to provide global protection across Azure regions for inbound HTTP/S connections to a landing zone.", + "training": "https://learn.microsoft.com/training/paths/secure-application-delivery/" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "6c8bcbf4-5bbe-4609-b8a0-3e97778424d6", - "link": "https://blogs.sap.com/2017/07/12/sap-single-sign-on-protect-your-sap-landscape-with-x.509-certificates/", + "guid": "b039d95d-54c7-4c89-89cb-107d5325ae52", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "services": [ - "Entra", - "AKV", - "SAP" + "AzurePolicy", + "FrontDoor", + "WAF", + "AppGW" ], "severity": "Medium", - "subcategory": "Identity", - "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution." + "subcategory": "Internet", + "text": "Take advantage of Web Application Firewall policies in Azure Front Door when you're using Azure Front Door and Application Gateway to protect HTTP/S applications. Lock down Application Gateway to receive traffic only from Azure Front Door.", + "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", + "guid": "5ada4332-4e13-4811-9231-81aa41742694", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "Entra", - "SAP" + "LoadBalancer", + "WAF", + "AppGW" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO by using OAuth for SAP NetWeaver to allow third-party or custom applications to access SAP NetWeaver OData services." + "subcategory": "Internet", + "text": "Use a web application firewall to scan your traffic when it's exposed to the internet. Another option is to use it with your load balancer or with resources that have built-in firewall capabilities like Application Gateway or third-party solutions.", + "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "a747c350-8d4c-449c-93af-393dbca77c48", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", + "guid": "e73de7d5-6f36-4217-a526-e1a621ecddde", + "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", "services": [ - "Entra", + "ACR", + "VWAN", "SAP" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP HANA" + "subcategory": "Internet", + "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/10-explore-azure-front-door" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", - "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", + "guid": "3c536a3e-1b6b-4e87-95ca-15edb47251c0", + "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "services": [ - "Entra", - "SAP" + "Storage", + "PrivateLink", + "ACR", + "VNet", + "Backup" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Consider Azure AD an identity provider for SAP systems hosted on RISE. For more information, see Integrating the Service with Azure AD." + "subcategory": "Internet", + "text": "To prevent data leakage, use Azure Private Link to securely access platform as a service resources like Azure Blob Storage, Azure Files, Azure Data Lake Storage Gen2, Azure Data Factory, and more. Azure Private Endpoint can also help to secure traffic between VNets and services like Azure Storage, Azure Backup, and more. Traffic between your VNet and the Private Endpoint enabled service travels across the Microsoft global network, which prevents its exposure to the public internet.", + "training": "https://learn.microsoft.com/training/modules/design-implement-private-access-to-azure-services/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "e4e48226-ce54-44b6-bb6b-bfa15bd8f753", - "link": "https://github.com/azuredevcollege/SAP/blob/master/sap-oauth-saml-flow/README.md", + "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", "services": [ - "Entra", + "VM", "SAP" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "For applications that access SAP, you might want to use principal propagation to establish SSO." + "severity": "High", + "subcategory": "Segmentation", + "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", + "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", + "guid": "3ff8ae7d-7d47-4431-96c8-bcbf45bbe609", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-multivip-overview", "services": [ - "Entra", - "SAP" + "LoadBalancer" ], "severity": "Medium", - "subcategory": "Identity", - "text": "If you're using SAP BTP services or SaaS solutions that require SAP Identity Authentication Service (IAS), consider implementing SSO between SAP Cloud Identity Authentication Services and Azure AD to access those SAP services. This integration lets SAP IAS act as a proxy identity provider and forwards authentication requests to Azure AD as the central user store and identity provider." + "subcategory": "Segmentation", + "text": "Make sure that internal deployments for Azure Load Balancer are set up to use Direct Server Return (DSR). This setting will reduce latency when internal load balancer configurations are used for high-availability configurations on the DBMS layer.", + "training": "https://learn.microsoft.com/ja-jp/training/modules/load-balancing-non-https-traffic-azure/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", + "guid": "6791f893-5ada-4433-84e1-3811523181aa", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "services": [ - "Entra", + "VM", + "VNet", "SAP" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP BTP" + "subcategory": "Segmentation", + "text": "You can use application security group (ASG) and NSG rules to define network security access-control lists between the SAP application and DBMS layers. ASGs group virtual machines to help manage their security.", + "training": "https://learn.microsoft.com/training/modules/configure-network-security-groups/?source=recommendations" }, { - "category": "Identity and Access", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "01f11b7f-38df-4251-9c76-4dec19abd3e8", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-successfactors-inbound-provisioning-cloud-only-tutorial", + "guid": "45bbe609-d8a0-43e9-9778-424d616785d6", + "link": "https://me.sap.com/notes/2015553", "services": [ - "Entra", + "VNet", "SAP" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "If you're using SAP SuccessFactors, consider using the Azure AD automated user provisioning. With this integration, as you add new employees to SAP SuccessFactors, you can automatically create their user accounts in Azure AD. Optionally, you can create user accounts in Microsoft 365 or other SaaS applications that are supported by Azure AD. Use write-back of the email address to SAP SuccessFactors." + "severity": "High", + "subcategory": "Segmentation", + "text": "Placing of the SAP application layer and SAP DBMS in different Azure VNets that aren't peered isn't supported.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" }, { - "category": "Management Group and Subscriptions", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", + "guid": "fa96c96a-d885-418f-9827-34c886ba2802", + "link": "https://learn.microsoft.com/azure/sap/workloads/proximity-placement-scenarios", "services": [ - "Subscriptions", - "AzurePolicy", "SAP" ], "severity": "Medium", - "subcategory": "Subscriptions", - "text": "enforce existing Management Group policies to SAP Subscriptions", - "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" + "subcategory": "Segmentation", + "text": "For optimal network latency with SAP applications, consider using Azure proximity placement groups.", + "training": "https://learn.microsoft.com/azure/virtual-machines/co-location#planned-maintenance-and-proximity-placement-groups" }, { - "category": "Management Group and Subscriptions", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "guid": "18c8b61c-855a-4405-b6ed-266455e4f4ce", + "link": "https://me.sap.com/notes/2015553", "services": [ - "Subscriptions", "SAP" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Integrate tightly coupled applications into the same SAP subscription to avoid additional routing and management complexity", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" + "subcategory": "Segmentation", + "text": "It is NOT supported at all to run an SAP Application Server layer and DBMS layer split between on-premise and Azure. Both layers need to completely reside either on-premise or in Azure.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" }, { - "category": "Management Group and Subscriptions", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "guid": "b65c878b-4b14-4f4e-92d8-d873936493f2", + "link": "https://me.sap.com/notes/2015553", "services": [ - "Subscriptions" + "Cost", + "VNet", + "SAP" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Leverage Subscription as scale unit and scaling our resources, consider deploying subscription per environment eg. Sandbox, non-prod, prod ", - "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" + "subcategory": "Segmentation", + "text": "It isn't recommended to host the database management system (DBMS) and application layers of SAP systems in different VNets and connect them with VNet peering because of the substantial costs that excessive network traffic between the layers can produce. Recommend using subnets within the Azure virtual network to separate the SAP application layer and DBMS layer.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" }, { - "category": "Management Group and Subscriptions", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", + "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", "services": [ - "Subscriptions", - "VM" + "VM", + "SAP" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Ensure quota increase as a part of subscription provisioning (e.g. total available VM cores within a subscription)", - "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" + "subcategory": "Segmentation", + "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", + "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" }, { - "category": "Management Group and Subscriptions", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", - "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", + "guid": "402a9846-d515-4061-aff8-cd30088693fa", + "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel", "services": [ - "Subscriptions" + "LoadBalancer" ], - "severity": "Low", - "subcategory": "Subscriptions", - "text": "The Quota API is a REST API that you can use to view and manage quotas for Azure services. Consider using it if necessary." + "severity": "High", + "subcategory": "Segmentation", + "text": "If using Load Balancer with Linux guest operating systems, check that the Linux network parameter net.ipv4.tcp_timestamps is set to 0.", + "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" }, { - "category": "Management Group and Subscriptions", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", - "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", + "guid": "87585797-5551-4d53-bb7d-a94ee415734d", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration", "services": [ - "Subscriptions", - "VM" + "VNet", + "SAP" ], - "severity": "High", - "subcategory": "Subscriptions", - "text": "If deploying to an availability zone, ensure that the VM's zone deployment is available once the quota has been approved. Submit a support request with the subscription, VM series, number of CPUs and availability zone required." + "severity": "Medium", + "subcategory": "Segmentation", + "text": "For SAP RISE/ECS deployments, virtual peering is the preferred way to establish connectivity with customer’s existing Azure environment. Both the SAP vnet and customer vnet(s) are protected with network security groups (NSG), enabling communication on SAP and database ports through the vnet peering" }, { - "category": "Management Group and Subscriptions", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", + "guid": "209d490d-a477-4784-84d1-16785d2fa56c", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ + "SAP", + "RBAC", "Subscriptions" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Ensure required services and features are available within the chosen deployment regions eg. ANF , Zone etc.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" + "subcategory": "Governance", + "text": "Customize role-based access control (RBAC) roles for SAP on Azure spoke subscriptions to avoid accidental network-related changes" }, { - "category": "Management Group and Subscriptions", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", + "guid": "56ad4840-8fe7-4273-9c48-6ba280dc0591", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "TrafficManager", - "Subscriptions", - "Cost" + "NVA", + "PrivateLink", + "SAP" ], "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Leverage Azure resource tag for cost categorization and resource grouping (: BillTo, Department (or Business Unit), Environment (Production, Stage, Development), Tier (Web Tier, Application Tier), Application Owner, ProjectName)", - "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" + "subcategory": "Governance", + "text": "Isolate DMZs and NVAs from the rest of the SAP estate, configure Azure Private Link, and securely manage and control the SAP on Azure resources" }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "2f7c95f0-6e15-44e3-aa35-92829e6e2061", - "link": "https://learn.microsoft.com/azure/backup/sap-hana-database-about", + "guid": "cf65de8e-1309-4ccc-b579-266bcca275fa", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ + "SQL", + "Storage", "Backup", - "Monitor" + "SAP" ], - "severity": "High", - "subcategory": "BCDR", - "text": "Help protect your HANA database by using the Azure Backup service.", - "training": "https://learn.microsoft.com/training/modules/implement-azure-backup-sap-workloads-azure-virtual-machines/?source=recommendations" + "severity": "Medium", + "subcategory": "Governance", + "text": "For SAP database server encryption, use the SAP HANA native encryption technology. If you're using Azure SQL Database, use Transparent Data Encryption (TDE) offered by the DBMS provider to secure your data and log files, and ensure the backups are also encrypted." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "302a2fbf-3745-4a5f-a365-c9d1a16ca22c", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/azacsnap-introduction", + "guid": "a1abfe9d-55d0-44c3-a491-9cb1b3d1325a", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Entra", - "Monitor", - "Storage", - "VM" + "Storage" ], "severity": "Medium", - "subcategory": "BCDR", - "text": "If you deploy Azure NetApp Files for your HANA, Oracle, or DB2 database, use the Azure Application Consistent Snapshot tool (AzAcSnap) to take application-consistent snapshots. AzAcSnap also supports Oracle databases. Consider using AzAcSnap on a central VM rather than on individual VMs." + "subcategory": "Governance", + "text": "Azure Storage encryption is enabled by default" }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "42d37218-a3a7-45df-bff6-1173e7f249ea", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", + "guid": "e124ba34-df68-45ed-bce9-bd3bb0cdb3b5", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [], + "severity": "Medium", + "subcategory": "Governance", + "text": " " + }, + { + "category": "Security, Governance and Compliance", + "checklist": "Azure Landing Zone Review", + "guid": "5eb2ec14-eeaa-4359-8829-e2edb2173676", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [], + "severity": "Medium", + "subcategory": "Governance", + "text": " " + }, + { + "category": "Security, Governance and Compliance", + "checklist": "Azure Landing Zone Review", + "guid": "ce9bd3bb-0cdb-43b5-9eb2-ec14eeaa3592", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "services": [ - "Monitor", - "SAP" + "AKV" ], "severity": "High", - "subcategory": "Management", - "text": "Ensure time-zone matches between the operating system and the SAP system." + "subcategory": "Secrets", + "text": "Use Azure Key Vault to store your secrets and credentials" }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "c3c7abc0-716c-4486-893c-40e181d65539", - "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel-multi-sid", + "guid": "829e2edb-2173-4676-aff6-691b4935ada4", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "services": [ - "Entra", - "Monitor" + "AKV" ], "severity": "Medium", - "subcategory": "Management", - "text": "Don't group different application services in the same cluster. For example, don't combine DRBD and central services clusters on the same cluster. However, you can use the same Pacemaker cluster to manage approximately five different central services (multi-SID cluster).", - "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" + "subcategory": "Secrets", + "text": "It is recommended to LOCK the Azure Resources post successful deployment to safeguard against unauthorized changes" }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "a491dfc4-9353-4213-9217-eef0949f9467", - "link": "https://azure.microsoft.com/pricing/offers/dev-test/", + "guid": "2223ece8-1b12-4318-8a54-17415833fb4a", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Monitor", - "Cost" + "AKV", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Management", - "text": "Consider running dev/test systems in a snooze model to save and optimize Azure run costs." + "severity": "Medium", + "subcategory": "Secrets", + "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "b7056168-6199-4732-a514-cdbb2d5c9c54", - "link": "https://learn.microsoft.com/azure/lighthouse/overview", + "guid": "e3c2df74-3165-4c3a-abe0-5bbe209d490d", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "Monitor", + "AzurePolicy", + "AKV", + "RBAC" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": "Based on existing requirements, regulatory and compliance controls (internal/external) - Determine what Azure Policies and Azure RBAC role are needed" + }, + { + "category": "Security, Governance and Compliance", + "checklist": "Azure Landing Zone Review", + "guid": "a4777842-4d11-4678-9d2f-a56c56ad4840", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AzurePolicy", + "Defender", + "AKV", "SAP" ], "severity": "Medium", - "subcategory": "Management", - "text": "If you partner with customers by managing their SAP estates, consider Azure Lighthouse. Azure Lighthouse allows managed service providers to use Azure native identity services to authenticate to the customers' environment. It puts the control in the hands of customers, because they can revoke access at any time and audit service providers' actions." + "subcategory": "Secrets", + "text": "When you enable Microsoft Defender for Cloud Standard for SAP, make sure to exclude the SAP database servers from any policy that installs endpoint protection." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "4d116785-d2fa-456c-96ad-48408fe72734", - "link": "https://learn.microsoft.com/azure/update-manager/scheduled-patching?tabs=schedule-updates-single-machine%2Cschedule-updates-scale-overview", + "guid": "8fe72734-c486-4ba2-a0dc-0591cf65de8e", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Monitor", - "VM" + "AKV", + "RBAC", + "SAP" ], "severity": "Medium", - "subcategory": "Management", - "text": "Use Azure Update Manager to check the status of available updates for a single VM or multiple VMs and consider scheduling regular patching.", - "training": "https://learn.microsoft.com/training/modules/keep-your-virtual-machines-updated/?source=recommendations" + "subcategory": "Secrets", + "text": "Delegate an SAP admin custom role with just-in-time access." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "76c8bcbf-45bb-4e60-ad8a-03e97778424d", - "link": "https://learn.microsoft.com/azure/sap/workloads/lama-installation", + "guid": "1309cccd-5792-466b-aca2-75faa1abfe9d", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Monitor", + "AKV", "SAP" ], - "severity": "Low", - "subcategory": "Management", - "text": "Optimize and manage SAP Basis operations by using SAP Landscape Management (LaMa). Use the SAP LaMa connector for Azure to relocate, copy, clone, and refresh SAP systems.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-remote-management/?source=recommendations" + "severity": "Medium", + "subcategory": "Secrets", + "text": "encrypt data in transit by integrating the third-party security product with secure network communications (SNC) for DIAG (SAP GUI), RFC, and SPNEGO for HTTPS" }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "14591147-5e39-4e53-89cc-cd979366bcda", - "link": "https://learn.microsoft.com/azure/sap/monitor/about-azure-monitor-sap-solutions", + "guid": "55d04c3c-4919-4cb1-a3d1-325ae124ba34", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "SQL", - "Monitor", + "AKV", + "Entra", "SAP" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor for SAP solutions to monitor your SAP workloads(SAP HANA, high-availability SUSE clusters, and SQL systems) on Azure. Consider supplementing Azure Monitor for SAP solutions with SAP Solution Manager.", - "training": "https://learn.microsoft.com/training/modules/implement-azure-monitoring-sap-workloads-azure-virtual-machines/?source=recommendations" + "subcategory": "Secrets", + "text": "Azure Active Directory (Azure AD) with SAML 2.0 can also provide SSO to a range of SAP applications and platforms like SAP NetWeaver, SAP HANA, and the SAP Cloud Platform" }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "2750ab1a-b039-4d95-b54c-7c8929cb107d", - "link": "https://learn.microsoft.com/azure/sap/workloads/vm-extension-for-sap", + "guid": "df685edd-ce9b-4d3b-a0cd-b3b55eb2ec14", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "VM", - "Monitor", + "AKV", "SAP" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Run a VM Extension for SAP check. VM Extension for SAP uses the assigned managed identity of a virtual machine (VM) to access VM monitoring and configuration data. The check ensures that all performance metrics in your SAP application come from the underlying Azure Extension for SAP.", - "training": "https://learn.microsoft.com/training/modules/configure-azure-enhanced-monitoring-extension-for-sap/?source=recommendations" + "severity": "Medium", + "subcategory": "Secrets", + "text": "Make sure you harden the operating system to eradicate vulnerabilities that could lead to attacks on the SAP database." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "5325ae52-5ba3-44d4-985e-2213ace7bb12", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "guid": "eeaa3592-829e-42ed-a217-3676aff6691b", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Monitor", - "AzurePolicy" + "AKV" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Policy for access control and compliance reporting. Azure Policy provides the ability to enforce organization-wide settings to ensure consistent policy adherence and fast violation detection. ", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" + "subcategory": "Secrets", + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "523181aa-4174-4269-93ff-8ae7d7d47431", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-overview", + "guid": "4935ada4-2223-4ece-a1b1-23181a541741", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "NetworkWatcher", - "Monitor", - "SAP" + "AKV" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Connection Monitor in Azure Network Watcher to monitor latency metrics for SAP databases and application servers. Or collect and display network latency measurements by using Azure Monitor.", - "training": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/collecting-and-displaying-niping-network-latency-measurements/ba-p/1833979" + "subcategory": "Secrets", + "text": "Use an Azure Key Vault per application per environment per region." }, { - "category": "Management and Monitoring", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "d89fd98d-23e4-4b40-a92e-32db9365522c", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-monitor-and-troubleshoot", + "guid": "5833fb4a-e3c2-4df7-9316-5c3acbe05bbe", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Monitor", - "ASR", - "SAP" + "AKV" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", - "training": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations" + "severity": "Medium", + "subcategory": "Secrets", + "text": " " }, { - "category": "Management and Monitoring", + "category": "Storage", "checklist": "Azure Landing Zone Review", - "guid": "73686af4-6791-4f89-95ad-a43324e13811", - "link": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/QualityCheck", + "guid": "d579266b-cca2-475f-aa1a-bfe9d55d04c3", "services": [ - "Monitor", - "VM", - "SAP" + "SQL", + "Storage" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Perform a quality check for SAP HANA on the provisioned Azure infrastructure to verify that provisioned VMs comply with SAP HANA on Azure best practices." + "subcategory": " ", + "text": "Disk config for Oracle, SQL, HANA" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "616785d6-fa96-4c96-ad88-518f482734c8", - "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-zones", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "When you are creating a SQL Server on Azure VM, carefully consider the type of workload necessary. If you are migrating an existing environment, collect a performance baseline to determine your SQL Server on Azure VM requirements. If this is a new VM, then create your new SQL Server VM based on your vendor requirements.", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16", "services": [ - "Subscriptions", - "Monitor", - "SAP" + "SQL", + "VM" ], "severity": "High", - "subcategory": "Monitoring", - "text": "For each Azure subscription, run a latency test on Azure availability zones before zonal deployment to choose low-latency zones for deployment of SAP on Azure.", - "training": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/AvZone-Latency-Test" + "subcategory": "VM Size", + "text": "Collect the target workload's performance characteristics and use them to determine the appropriate VM size for your business.", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "410adcba-db46-424f-a6c4-05ecde75c52e", - "link": "https://learn.microsoft.com/azure/advisor/advisor-how-to-improve-reliability", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "The memory optimized virtual machine sizes are a primary target for SQL Server VMs and the recommended choice by Microsoft. The memory optimized virtual machines offer stronger memory-to-CPU ratios and medium-to-large cache options.Consider Ebdsv5-series series first for most SQL Server workloads.", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized", "services": [ - "Storage", - "Monitor", - "ASR" + "SQL", + "VM" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Run the Resiliency Report to ensure that the configuration of the entire provisioned Azure infrastructure (Compute, Database, Networking, Storage, Site Recovery) complies with the configuration defined by Cloud Adaption Framework for Azure.", - "training": "https://learn.microsoft.com/training/paths/azure-well-architected-framework/" + "subcategory": "VM Size", + "text": "Use memory optimized virtual machine sizes for the best performance of SQL Server workloads.", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "86ba2802-1459-4114-95e3-9e5309cccd97", - "link": "https://learn.microsoft.com/azure/sentinel/sap/deployment-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "To find the most effective configuration for SQL Server workloads on an Azure VM, start by measuring the storage performance of your business application. Once storage requirements are known, select a virtual machine that supports the necessary IOPS and throughput with the appropriate memory-to-vCore ratio.", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements", "services": [ - "Monitor", - "Sentinel", - "SAP" + "SQL", + "Storage", + "VM" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Implement threat protection by using the Microsoft Sentinel solution for SAP. Use this solution to monitor your SAP systems and detect sophisticated threats throughout the business logic and application layers.", - "training": "https://learn.microsoft.com/training/modules/plan-microsoft-sentinel-deployment-sap/?source=recommendations" + "subcategory": "Storage", + "text": "Determine storage bandwidth and latency requirements for SQL Server data, log, and tempdb files before choosing the disk type.", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "579266bc-ca27-45fa-a1ab-fe9d55d04c3c", - "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "This provides more dedicated disk IOPS and throughput on the disk level and also allows you to configure the Azure disk host caching setting for each disk to the optimal setting for that data type.", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ - "Monitor", - "Cost" + "SQL", + "Storage" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Azure tagging can be leveraged to logically group and track resources, automate their deployments, and most importantly, provide visibility on the incurred costs.", - "training": "https://learn.microsoft.com/training/modules/analyze-costs-create-budgets-azure-cost-management/?source=recommendations" + "severity": "High", + "subcategory": "Storage", + "text": "Place data, log, and tempdb files on separate drives", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "04b8e5e5-13cb-4b22-af62-5a8ecfcf0337", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-test-latency?tabs=windows", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Premium SSD is always recommend as a minimum for SQL Server in order to obtain better performance and lower latency. P30 and P40 are recommended because disk caching is not supported for disks 4 TiB and larger ( P50 and above) and they provide the optimal price to performance ratio", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ - "VM", - "Monitor" + "SQL", + "Storage" ], - "severity": "Low", - "subcategory": "Performance", - "text": "Use inter-VM latency monitoring for latency-sensitive applications." + "severity": "High", + "subcategory": "Storage", + "text": "For the data drive, use premium P30 and P40 or smaller disks to ensure the availability of cache support", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "07e5ed53-3d96-43d8-87ea-631b77da5aba", - "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide-storage", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Log files have primarily write-heavy operations. Therefore, they do not benefit from the ReadOnly cache. Hence evaluate your price vs performance vs capacity and chose the right storage disk.", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ - "Monitor", - "ASR", - "SAP" + "SQL", + "Storage", + "Cost" ], - "severity": "Medium", - "subcategory": "Performance", - "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-storage/?source=recommendations" + "severity": "High", + "subcategory": "Storage", + "text": "For the log drive plan for capacity and test performance versus cost while evaluating the premium P30 - P80 disks", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "abb6af9c-982c-4cf1-83fb-329fafd1ee56", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Placing TempDB on the D drive can help performance. Consider the size required and always test performance.", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ "Storage", - "Monitor", - "SAP" + "SQL", + "VM" ], "severity": "Medium", - "subcategory": "Performance", - "text": "Exclude all the database file systems and executable programs from antivirus scans. Including them could lead to performance problems. Check with the database vendors for prescriptive details on the exclusion list. For example, Oracle recommends excluding /oracle//sapdata from antivirus scans." + "subcategory": "Storage", + "text": "Place tempdb on the local ephemeral SSD (default D:\\) drive for most SQL Server workloads that are not part of Failover Cluster Instance (FCI) after choosing the optimal VM size.", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "c027f893-f404-41a9-b33d-39d625a14964", - "link": "https://sapit-forme-prod.authentication.eu11.hana.ondemand.com/login", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Striping Data and Log disk can increase bandwidth. Ensure that VM size also matches expected output", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ - "Monitor", - "SAP" + "SQL", + "Storage", + "VM" ], - "severity": "Low", - "subcategory": "Performance", - "text": "Consider collecting full database statistics for non-HANA databases after migration. For example, implement SAP note 1020260 - Delivery of Oracle statistics." + "severity": "High", + "subcategory": "Storage", + "text": "Stripe multiple Azure data disks using Storage Spaces to increase I/O bandwidth", + "waf": "Performance" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "fdafb1f5-3eee-4354-a8c9-deb8127ebc2e", - "link": "https://learn.microsoft.com/azure/virtual-machines/workloads/oracle/configure-oracle-asm", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Your storage caching policy varies depending on the type of SQL Server data files that are hosted on the drive.Enable Read-only caching for the disks hosting SQL Server data files.Reads from cache will be faster than the uncached reads from the data disk.Set the caching policy to None for disks hosting the transaction log. There is no performance benefit to enabling caching for the Transaction log disk.", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ - "Storage", - "Monitor", - "SAP" + "AzurePolicy", + "SQL", + "Storage" ], - "severity": "Medium", - "subcategory": "Performance", - "text": "Consider using Oracle Automatic Storage Management (ASM) for all Oracle deployments that use SAP on Azure.", - "training": "https://learn.microsoft.com/training/paths/administer-infrastructure-resources-in-azure/?source=recommendations" - }, - { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "33c5d5bf-daf3-4f0d-bd50-6010fdcec22e", - "link": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/announcement-sap-on-azure-oracle-performance-efficiency-scripts/ba-p/3725178", + "severity": "High", + "subcategory": "Storage", + "text": "Set host caching to read-only for data file disks and none for log file disks.", + "waf": "Performance" + }, + { + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Check that you storage is in the same region as your VM. For exaplme if your VM is in EAST US 2 ensure your storage is in East US 2.", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ "SQL", - "Monitor", - "SAP" + "Storage", + "VM" ], - "severity": "Medium", - "subcategory": "Performance", - "text": "For SAP on Azure running Oracle, a collection of SQL scripts can help you diagnose performance problems. Automatic Workload Repository (AWR) reports contain valuable information for diagnosing problems in the Oracle system. We recommend that you run an AWR report during several sessions and choose peak times for it, to ensure broad coverage for the analysis.", - "training": "https://learn.microsoft.com/ja-jp/azure/well-architected/oracle-iaas/performance-efficiency" + "severity": "High", + "subcategory": "Storage", + "text": "Provision the storage account in the same region as the SQL Server VM", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5ba34d46-85e2-4213-ace7-bb122f7c95f0", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "SQL Server uses extents to store data. These are 64KB in size. Therefore, on a SQL Server machine, the NTFS allocation unit size for hosting SQL database files should be 64 KB.", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", "services": [ - "WAF", - "AppGW", - "AzurePolicy" + "SQL", + "Storage" ], - "severity": "Medium", - "subcategory": "App delivery", - "text": "For secure delivery of HTTP/S apps, use Application Gateway v2 and ensure that WAF protection and policies are enabled.", - "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/" + "severity": "High", + "subcategory": "Storage", + "text": "Format your data disk to use 64 KB block size (allocation unit size) for all data files placed on a drive other than the temporary D:\\ drive", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "fa9d30bc-1b82-4e4b-bfdf-6b017938b9e6", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "It is recommended that you determine BCDR needs and requirements ensuring that you are able to meet you SLAs of the environment.", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions", "services": [ - "VM", - "DNS", - "SAP" + "SQL", + "VM" ], "severity": "Medium", - "subcategory": "DNS", - "text": "If the virtual machine's DNS or virtual name is not changed during migration to Azure, Background DNS and virtual names connect many system interfaces in the SAP landscape, and customers are only sometimes aware of the interfaces that developers define over time. Connection challenges arise between various systems when virtual or DNS names change after migrations, and it's recommended to retain DNS aliases to prevent these types of difficulties.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" + "subcategory": "HADR", + "text": "Determine HA/DR requirements for each VM to be migrated.", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a2858f78-105b-4f52-b7a9-5b0f4439743b", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "When depoying High Availability you need to use availability sets or availability zones to avoid unexpected outages.", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set", "services": [ - "VNet", - "DNS", - "SAP" + "SQL", + "VM" ], - "severity": "Medium", - "subcategory": "DNS", - "text": "Use different DNS zones to distinguish each environment (sandbox, development, preproduction, and production) from each other. The exception is for SAP deployments with their own VNet; here, private DNS zones might not be necessary.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" + "severity": "High", + "subcategory": "HADR", + "text": "Place your VMs in an availability set or different availability zones.", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a3592829-e6e2-4061-9368-6af46791f893", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Prefered option when deploying an Availability Group. The recommended solution is to use multi-subnets when deploying Always on Availability Groups.", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli", "services": [ + "SQL", + "VM", "VNet", - "ACR", - "SAP" + "LoadBalancer" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "Local and global VNet peering provide connectivity and are the preferred approaches to ensure connectivity between landing zones for SAP deployments across multiple Azure regions", - "training": "https://learn.microsoft.com/training/modules/configure-vnet-peering/?source=recommendations" + "subcategory": "HADR", + "text": "Deploy your SQL Server VMs to multiple subnets whenever possible to avoid the dependency on an Azure Load Balancer or a distributed network name (DNN) to route traffic to your HADR solution. ( If one is implementing FCI or AG)", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "41742694-3ff8-4ae7-b7d4-743176c8bcbf", - "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "High availability and disaster recovery (HADR) features, such as the Always On availability group and the failover cluster instance rely on underlying Windows Server Failover Cluster technology. Review the best practices for modifying your HADR settings to better support the cloud environment.", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration", "services": [ - "NVA", - "SAP" + "SQL", + "ASR" ], "severity": "High", - "subcategory": "Hybrid", - "text": "It is not supported to deploy any NVA between SAP application and SAP Database server", - "training": "https://me.sap.com/notes/2731110" + "subcategory": "HADR", + "text": "Change the cluster to less aggressive parameters to avoid unexpected outages from transient network failures or Azure platform maintenance. ( If one is implementing FCI or AG)", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "7d4bc7d2-c34a-452e-8f1d-6ae3c8eafcc3", - "link": "https://learn.microsoft.com/training/modules/introduction-azure-virtual-wan/?source=recommendations", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Ensure that quorum is set correct for the number of instances deployed.", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting", "services": [ - "ACR", - "VWAN", - "SAP" + "SQL" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", - "training": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" + "severity": "High", + "subcategory": "HADR", + "text": "Configure cluster quorum voting to use 3 or more odd number of votes. Don't assign votes to DR regions. ( If one is implementing FCI or AG)", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "0cedb1f6-ae6c-492b-8b17-8061f50b16d3", - "link": "https://learn.microsoft.com/azure/well-architected/services/networking/network-virtual-appliances/reliability", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "On Azure virtual machines, clusters use a load balancer to hold an IP address that needs to be on one cluster node at a time. In this solution, the load balancer holds the IP address for the virtual network name (VNN) listener for the Always On availability group when the SQL Server VMs are in a single subnet.", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb", "services": [ + "SQL", "VNet", - "NVA" + "VM", + "LoadBalancer" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Consider deploying network virtual appliances (NVAs) between regions only if partner NVAs are used. NVAs between regions or VNets aren't required if native NVAs are present. When you're deploying partner networking technologies and NVAs, follow the vendor's guidance to verify conflicting configurations with Azure networking.", - "training": "https://learn.microsoft.com/training/modules/control-network-traffic-flow-with-routes/?source=recommendations" + "severity": "High", + "subcategory": "HADR", + "text": "When using the virtual network name (VNN) and Azure Load Balancer to connect to your HADR solution, specify MultiSubnetFailover = true in the connection string, even if your cluster only spans one subnet. ( If one is implementing FCI or AG)", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "facc08c6-ea95-4641-91cd-fa09e573adbd", - "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "SQL Server, Azure SQL Database, and Azure SQL Managed Instance support row and page compression for rowstore tables and indexes, and support columnstore and columnstore archival compression for columnstore tables and indexes.", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16", "services": [ - "VNet", - "NVA", - "VWAN", - "SAP" + "SQL", + "Storage" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Virtual WAN manages connectivity between spoke VNets for virtual-WAN-based topologies (no need to set up user-defined routing [UDR] or NVAs), and maximum network throughput for VNet-to-VNet traffic in the same virtual hub is 50 gigabits per second. If necessary, SAP landing zones can use VNet peering to connect to other landing zones and overcome this bandwidth limitation.", - "training": "https://learn.microsoft.com/training/modules/hub-and-spoke-network-architecture/?source=recommendations" + "severity": "Low", + "subcategory": "SQL Server", + "text": "Enable database page compression where appropriate.", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "82734c88-6ba2-4802-8459-11475e39e530", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "By default, data and log files are initialized to overwrite any existing data left on the disk from previously deleted files. Data and log files are first initialized by zeroing the files (filling with zeros).In SQL Server, for data files only, instant file initialization (IFI) allows for faster execution of the previously mentioned file operations, since it reclaims used disk space without filling that space with zeros. Instead, disk content is overwritten as new data is written to the files.", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16", "services": [ - "VNet", - "VM", - "SAP" + "SQL", + "Storage" ], "severity": "High", - "subcategory": "IP plan", - "text": "Public I.P assignment to VM running SAP Workload is not recommended.", - "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" + "subcategory": "SQL Server", + "text": "Enable instant file initialization for data files.", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "9cccd979-366b-4cda-8750-ab1ab039d95d", - "link": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Recommended for best performance and availability migrate all databases to data and log disks", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16", "services": [ - "VNet", - "ASR" + "SQL" ], - "severity": "High", - "subcategory": "IP plan", - "text": "Consider reserving I.P address on DR side when configuring ASR", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "severity": "Medium", + "subcategory": "SQL Server", + "text": "Move all databases to data disks, including system databases.", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "54c7c892-9cb1-407d-9325-ae525ba34d46", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features", "services": [ - "VNet" + "SQL", + "Storage", + "VM" + ], + "severity": "Low", + "subcategory": "SQL Server", + "text": "Move SQL Server error log and trace file directories to data disks.", + "waf": "Operations" + }, + { + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-", + "services": [ + "SQL", + "VM" ], "severity": "High", - "subcategory": "IP plan", - "text": "Avoid using overlapping IP address ranges for production and DR sites.", - "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" + "subcategory": "SQL Server", + "text": "Set max SQL Server memory limit to leave enough memory for the Operating System.", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6e154e3a-a359-4282-ae6e-206173686af4", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-delegate-subnet", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows", "services": [ - "VNet", - "Storage" + "SQL", + "VM" ], - "severity": "Medium", - "subcategory": "IP plan", - "text": "While Azure does help you to create multiple delegated subnets in a VNet, only one delegated subnet can exist in a VNet for Azure NetApp Files. Attempts to create a new volume will fail if you use more than one delegated subnet for Azure NetApp Files.", - "training": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-network-topologies?source=recommendations" + "severity": "High", + "subcategory": "SQL Server", + "text": "Enable lock pages in memory.", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d8a03e97-7784-424d-9167-85d6fa96c96a", - "link": "https://learn.microsoft.com/azure/well-architected/services/networking/azure-firewall?toc=%2Fazure%2Ffirewall%2Ftoc.json&bc=%2Fazure%2Ffirewall%2Fbreadcrumb%2Ftoc.json", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store", "services": [ - "Firewall" + "SQL", + "VM" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Firewall to govern Azure outbound traffic to the internet, non-HTTP/S inbound connections, and East/West traffic filtering (if the organization requires it)", - "training": "https://learn.microsoft.com/training/paths/secure-networking-infrastructure/" + "severity": "Low", + "subcategory": "SQL Server", + "text": "Enable Query Store on all production SQL Server databases following best practices.", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "91a65e40-be90-45b3-9f73-f3edbf8dc324", - "link": "https://learn.microsoft.com/azure/sap/workloads/expose-sap-process-orchestration-on-azure", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server", "services": [ - "WAF", - "AppGW", - "SAP" + "SQL", + "VM" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Application Gateway and Web Application Firewall have limitations when Application Gateway serves as a reverse proxy for SAP web apps, as shown in the comparison between Application Gateway, SAP Web Dispatcher, and other third-party services.", - "training": "https://help.sap.com/docs/SUPPORT_CONTENT/si/3362959506.html" + "severity": "High", + "subcategory": "SQL Server", + "text": "Ensure that all tempdb best practices are followed.", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5e39e530-9ccc-4d97-a366-bcda2750ab1a", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "services": [ - "ACR", - "AzurePolicy", - "FrontDoor", - "WAF" + "SQL", + "VM" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Front Door and WAF policies to provide global protection across Azure regions for inbound HTTP/S connections to a landing zone.", - "training": "https://learn.microsoft.com/training/paths/secure-application-delivery/" + "severity": "High", + "subcategory": "SQL Server", + "text": "Schedule SQL Server Agent jobs to run DBCC CHECKDB, index reorganize, index rebuild, and update statistics jobs.", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b039d95d-54c7-4c89-89cb-107d5325ae52", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "services": [ - "WAF", - "FrontDoor", - "AppGW", - "AzurePolicy" + "SQL", + "VM" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Take advantage of Web Application Firewall policies in Azure Front Door when you're using Azure Front Door and Application Gateway to protect HTTP/S applications. Lock down Application Gateway to receive traffic only from Azure Front Door.", - "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" + "subcategory": "SQL Server", + "text": "Limit autogrowth of the database and Disable autoshrink", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5ada4332-4e13-4811-9231-81aa41742694", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Constrained vCPU virtual machines (VMs) are a type of VM where the vCPU count can be constrained to a half or a quarter of the original VM size. This allows customers to reduce the cost of software licensing while maintaining the same memory, storage, and I/O bandwidth", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu", "services": [ - "LoadBalancer", - "WAF", - "AppGW" + "Storage", + "SQL", + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use a web application firewall to scan your traffic when it's exposed to the internet. Another option is to use it with your load balancer or with resources that have built-in firewall capabilities like Application Gateway or third-party solutions.", - "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" + "severity": "Low", + "subcategory": "Cost Optimization", + "text": "Optimize SQL Server License cost with Constrained vCPU VM's", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "Cost" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e73de7d5-6f36-4217-a526-e1a621ecddde", - "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Azure Hybrid Benefit allows you to exchange your existing licenses for discounted rates on Azure SQL Database and Azure SQL Managed Instance. Y", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/", "services": [ - "ACR", - "VWAN", - "SAP" + "SQL", + "Cost" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/10-explore-azure-front-door" + "severity": "Low", + "subcategory": "Cost Optimization", + "text": "Leverage Azure Hybrid benefit to maximize the value of your on premises licenses in the cloud", + "waf": "Cost" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "3c536a3e-1b6b-4e87-95ca-15edb47251c0", - "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "The SQL Server IaaS Agent extension (SqlIaasExtension) runs on SQL Server on Azure Windows Virtual Machines (VMs) to automate management and administration tasks.", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli", "services": [ - "PrivateLink", - "VNet", - "ACR", - "Backup", - "Storage" + "SQL", + "VM" ], "severity": "Medium", - "subcategory": "Internet", - "text": "To prevent data leakage, use Azure Private Link to securely access platform as a service resources like Azure Blob Storage, Azure Files, Azure Data Lake Storage Gen2, Azure Data Factory, and more. Azure Private Endpoint can also help to secure traffic between VNets and services like Azure Storage, Azure Backup, and more. Traffic between your VNet and the Private Endpoint enabled service travels across the Microsoft global network, which prevents its exposure to the public internet.", - "training": "https://learn.microsoft.com/training/modules/design-implement-private-access-to-azure-services/?source=recommendations" + "subcategory": "Azure", + "text": "Register with the SQL IaaS Agent Extension to unlock a number of feature benefits.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Accelerated Networking provides consistent ultra-low network latency via Azure's in-house programmable hardware and technologies", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", "services": [ - "VM", - "SAP" + "SQL", + "VM" ], "severity": "High", - "subcategory": "Segmentation", - "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", - "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" + "subcategory": "Azure", + "text": "Ensure Accelerated Networking is enabled on the virtual machine.", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "3ff8ae7d-7d47-4431-96c8-bcbf45bbe609", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-multivip-overview", + "category": "SQL Server on Azure VM", + "checklist": "SQL Migration Review", + "description": "Microsoft Defender detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases on the SQL server.", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", "services": [ - "LoadBalancer" + "SQL", + "VM", + "Defender" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "Make sure that internal deployments for Azure Load Balancer are set up to use Direct Server Return (DSR). This setting will reduce latency when internal load balancer configurations are used for high-availability configurations on the DBMS layer.", - "training": "https://learn.microsoft.com/ja-jp/training/modules/load-balancing-non-https-traffic-azure/?source=recommendations" + "severity": "High", + "subcategory": "Azure", + "text": "Leverage Microsoft Defender for Cloud to improve the overall security posture of your virtual machine deployment.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6791f893-5ada-4433-84e1-3811523181aa", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "There are some PaaS limitations that are introduced in SQL Managed Instance and some behavior changes compared to SQL Server. It is important to review and understand these differences.", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql", "services": [ - "VNet", - "VM", - "SAP" + "SQL", + "EventHubs" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "You can use application security group (ASG) and NSG rules to define network security access-control lists between the SAP application and DBMS layers. ASGs group virtual machines to help manage their security.", - "training": "https://learn.microsoft.com/training/modules/configure-network-security-groups/?source=recommendations" + "severity": "High", + "subcategory": "Pre Migration", + "text": "Review the major differences between SQL Server and Managed Instance", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "45bbe609-d8a0-43e9-9778-424d616785d6", - "link": "https://me.sap.com/notes/2015553", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "SQL Managed Instance has characteristics and resource limits that depend on the underlying infrastructure and architecture. It is important to review these limits.", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits", "services": [ - "VNet", - "SAP" + "SQL" ], "severity": "High", - "subcategory": "Segmentation", - "text": "Placing of the SAP application layer and SAP DBMS in different Azure VNets that aren't peered isn't supported.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" + "subcategory": "Pre Migration", + "text": "Review capacity limits for SQL MI", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "fa96c96a-d885-418f-9827-34c886ba2802", - "link": "https://learn.microsoft.com/azure/sap/workloads/proximity-placement-scenarios", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "The instance settings between managed instance and your source SQL Server can be different . It is important to review those differences that can impact performance.", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08", "services": [ - "SAP" + "SQL" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "For optimal network latency with SAP applications, consider using Azure proximity placement groups.", - "training": "https://learn.microsoft.com/azure/virtual-machines/co-location#planned-maintenance-and-proximity-placement-groups" + "severity": "High", + "subcategory": "Pre Migration", + "text": "Compare instance settings on SQL Server and Azure SQL MI that may impact performance", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "18c8b61c-855a-4405-b6ed-266455e4f4ce", - "link": "https://me.sap.com/notes/2015553", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Assess on-premises SQL Server instance(s) migrating to Azure SQL Managed Instance. The assessment workflow helps you to detect issues that block the migration itself and also partially supported and unsupported features", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend", "services": [ - "SAP" + "SQL" ], "severity": "High", - "subcategory": "Segmentation", - "text": "It is NOT supported at all to run an SAP Application Server layer and DBMS layer split between on-premise and Azure. Both layers need to completely reside either on-premise or in Azure.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" + "subcategory": "Pre Migration", + "text": "Run Data Migration assistant or Azure Data Studio Migration Extension to detect compatibility issues that can impact database functionality on Managed Instance", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b65c878b-4b14-4f4e-92d8-d873936493f2", - "link": "https://me.sap.com/notes/2015553", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "The SKU recommendation feature can evaluate the source SQL Server performance and utilization characteristics to recommend a right-sized Azure SQL Managed Instance to assist with your migration journey.", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", "services": [ - "VNet", - "Cost", - "SAP" + "SQL" ], "severity": "High", - "subcategory": "Segmentation", - "text": "It isn't recommended to host the database management system (DBMS) and application layers of SAP systems in different VNets and connect them with VNet peering because of the substantial costs that excessive network traffic between the layers can produce. Recommend using subnets within the Azure virtual network to separate the SAP application layer and DBMS layer.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" + "subcategory": "Pre Migration", + "text": "Select the right compute resources for your workload by leveraging the SKU recommendation tools.", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Review Unsupported Features, Migration Blockers and Breaking Changes for each database from the Assessment", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", "services": [ - "VM", - "SAP" + "SQL" ], "severity": "High", - "subcategory": "Segmentation", - "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", - "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" + "subcategory": "Pre Migration", + "text": "Review and address the issues highlighted in DMA/Azure Data Studio", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "402a9846-d515-4061-aff8-cd30088693fa", - "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "The SQL Managed Instance default DNS zone .database.windows.net can be changed with your own. However, the managed instance hostname part of its FQDN should remain the same.", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance", "services": [ - "LoadBalancer" + "DNS", + "SQL" ], "severity": "High", - "subcategory": "Segmentation", - "text": "If using Load Balancer with Linux guest operating systems, check that the Linux network parameter net.ipv4.tcp_timestamps is set to 0.", - "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" + "subcategory": "Pre Migration", + "text": "Plan for connection string changes as changing a managed instance name is not supported", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "87585797-5551-4d53-bb7d-a94ee415734d", - "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "There are addional requirements in configuring a vnet and subnet hosting the managed instance.", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi", "services": [ - "VNet", - "SAP" + "SQL", + "VNet" ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "For SAP RISE/ECS deployments, virtual peering is the preferred way to establish connectivity with customer’s existing Azure environment. Both the SAP vnet and customer vnet(s) are protected with network security groups (NSG), enabling communication on SAP and database ports through the vnet peering" + "subcategory": "Pre Migration", + "text": "Review managed instance VNet requirements", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "209d490d-a477-4784-84d1-16785d2fa56c", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Though it's possible to deploy managed instances to a subnet with a number of IP addresses that's less than the output of the subnet formula, always consider using bigger subnets instead. Using a bigger subnet can help avoid future issues stemming from a lack of IP addresses, such as the inability to create additional instances within the subnet or scale existing instances.", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi", "services": [ - "Subscriptions", - "RBAC", - "SAP" + "SQL", + "VNet" ], "severity": "High", - "subcategory": "Governance", - "text": "Customize role-based access control (RBAC) roles for SAP on Azure spoke subscriptions to avoid accidental network-related changes" + "subcategory": "Deployment", + "text": "Ensure managed instance subnet has sufficient IP addresses available", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "56ad4840-8fe7-4273-9c48-6ba280dc0591", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "SQL Managed Instance has characteristics and resource limits that depend on the underlying infrastructure and architecture. SQL Managed Instance can be deployed on multiple hardware configurations.", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics", "services": [ - "PrivateLink", - "NVA", - "SAP" + "SQL" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Isolate DMZs and NVAs from the rest of the SAP estate, configure Azure Private Link, and securely manage and control the SAP on Azure resources" + "severity": "High", + "subcategory": "Pre Migration", + "text": "Plan between General Purpose and Business Critical tiers of MI", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "Performance" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "cf65de8e-1309-4ccc-b579-266bcca275fa", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "The auto-failover groups feature allows you to manage the replication and failover of user databases in a managed instance to a managed instance in another Azure region. Auto-failover groups are designed to simplify deployment and management of geo-replicated databases at scale.", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell", "services": [ - "SQL", - "Backup", - "Storage", - "SAP" + "SQL" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "For SAP database server encryption, use the SAP HANA native encryption technology. If you're using Azure SQL Database, use Transparent Data Encryption (TDE) offered by the DBMS provider to secure your data and log files, and ensure the backups are also encrypted." + "severity": "High", + "subcategory": "Pre Migration", + "text": "Based on your RPO/RTO's , determine if Auto failover Group needs to be implemented. If so, plan for the deployment attributes of the second instance.", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "a1abfe9d-55d0-44c3-a491-9cb1b3d1325a", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "There are multiple ways to connect your application to the managed instance. Review and understand the pros and cons and decide on the best approach for your application.", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", "services": [ - "Storage" + "SQL" + ], + "severity": "Low", + "subcategory": "Pre Migration", + "text": "Review the Connectivity Design between Database and Application, test & validate it", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Operations" + }, + { + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Compare migration options to choose the path that's appropriate to your business needs.", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools", + "services": [ + "SQL" ], "severity": "Medium", - "subcategory": "Governance", - "text": "Azure Storage encryption is enabled by default" + "subcategory": "Pre Migration", + "text": "Plan for the Migration Method. Depending on the DB Size and Application downtime window, select the preferred Migration Method.", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "e124ba34-df68-45ed-bce9-bd3bb0cdb3b5", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [], + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "After you verify that data is the same on both source and target, you can cut over from the source to the target environment. It's important to plan the cutover process with business / application teams to ensure minimal interruption during cutover doesn't affect business continuity.", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover", + "services": [ + "SQL" + ], "severity": "Medium", - "subcategory": "Governance", - "text": " " + "subcategory": "Pre Migration", + "text": "Plan the cutover process with business / application teams to ensure minimal interruption during cutover and it does not affect business continuity.", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "5eb2ec14-eeaa-4359-8829-e2edb2173676", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [], - "severity": "Medium", - "subcategory": "Governance", - "text": " " + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "A time zone of a managed instance can be set during instance creation only. The default time zone is UTC", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone", + "services": [ + "SQL" + ], + "severity": "High", + "subcategory": "Deployment", + "text": "Ensure you customize your time zone setting at the instance creation time. One cannot change it later.", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "ce9bd3bb-0cdb-43b5-9eb2-ec14eeaa3592", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Server-level collation in Azure SQL Managed Instance can be specified when the instance is created and cannot be changed later.Default server-level collation is SQL_Latin1_General_CP1_CI_AS.", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16", "services": [ - "AKV" + "SQL" ], "severity": "High", - "subcategory": "Secrets", - "text": "Use Azure Key Vault to store your secrets and credentials" + "subcategory": "Deployment", + "text": "Ensure you select the right collation setting at the instance creation time. One cannot change it later", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "829e2edb-2173-4676-aff6-691b4935ada4", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "When you're migrating a database protected by Transparent Data Encryption (TDE) to Azure SQL Managed Instance using the native restore option, the corresponding certificate from the SQL Server instance needs to be migrated before database restore.", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell", "services": [ - "AKV" + "SQL", + "VM" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "It is recommended to LOCK the Azure Resources post successful deployment to safeguard against unauthorized changes" + "subcategory": "Deployment", + "text": "For TDE Enabled Database, corresponding certificate from the on-premises or Azure VM SQL Server needs to be migrated before database restore", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "2223ece8-1b12-4318-8a54-17415833fb4a", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "System databases can be restored only from backups that are created on the version of SQL Server that the server instance is currently running. This is not the case when you are migrating to SQL Managed Instance.Azure PowerShell and DBATools PowerShell libraries enable you to easily script and automate and customize all parts of the migration process.", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore", "services": [ - "AzurePolicy", - "AKV" + "SQL", + "Backup" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." + "severity": "Low", + "subcategory": "Migration", + "text": "Restore of system databases is not supported. To migrate instance-level objects (stored in master or msdb databases), we recommend to script them out and run T-SQL scripts on the destination instance.", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "e3c2df74-3165-4c3a-abe0-5bbe209d490d", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "When using migration options that continuously replicate / sync data changes from source to the target, the source data and schema can change and drift from the target. During data sync, ensure that all changes on the source are captured and applied to the target during the migration process.", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", "services": [ - "RBAC", - "AzurePolicy", - "AKV" + "SQL" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Based on existing requirements, regulatory and compliance controls (internal/external) - Determine what Azure Policies and Azure RBAC role are needed" + "severity": "High", + "subcategory": "Migration", + "text": "Ensure that all changes on the source are captured and applied to the target during the migration process.", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "a4777842-4d11-4678-9d2f-a56c56ad4840", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Ensure that the application is able to succesffuly connect to the managed instance post migration of the databases.", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", "services": [ - "AzurePolicy", - "AKV", - "Defender", - "SAP" + "SQL" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "When you enable Microsoft Defender for Cloud Standard for SAP, make sure to exclude the SAP database servers from any policy that installs endpoint protection." + "subcategory": "Migration", + "text": "Test Application Connectivity to MI and Databases", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "8fe72734-c486-4ba2-a0dc-0591cf65de8e", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "High availability is a fundamental part of SQL Managed Instance platform that works transparently for your database applications. Failovers from primary to secondary nodes in case of node degradation or fault detection, or during regular monthly software updates are an expected occurrence for all applications using SQL Managed Instance in Azure.", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql", "services": [ - "RBAC", - "AKV", - "SAP" + "SQL" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Delegate an SAP admin custom role with just-in-time access." + "severity": "High", + "subcategory": "Post Migration", + "text": "Consider executing a manual failover on SQL Managed Instance to test for fault and failover resiliency.", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "1309cccd-5792-466b-aca2-75faa1abfe9d", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Ensuring that your applications are failover resilient prior to deploying to production will help mitigate the risk of application faults in production and will contribute to application availability for your customers.", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover", "services": [ - "AKV", - "SAP" + "SQL", + "EventHubs", + "LoadBalancer" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "encrypt data in transit by integrating the third-party security product with secure network communications (SNC) for DIAG (SAP GUI), RFC, and SPNEGO for HTTPS" + "severity": "High", + "subcategory": "Post Migration", + "text": "If failover groups have been implemented, Test Manual Failover and Failback and test application connectivity behavior during failover/failback", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "55d04c3c-4919-4cb1-a3d1-325ae124ba34", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "This provides more dedicated disk IOPS and throughput", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525", "services": [ - "Entra", - "AKV", - "SAP" + "SQL", + "Storage" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Azure Active Directory (Azure AD) with SAML 2.0 can also provide SSO to a range of SAP applications and platforms like SAP NetWeaver, SAP HANA, and the SAP Cloud Platform" + "severity": "High", + "subcategory": "Post Migration", + "text": "Optimize Storage Performance for General Purpose Managed Instance", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Performance" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "df685edd-ce9b-4d3b-a0cd-b3b55eb2ec14", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "Many organizations have policies that require that certificates or encryption keys be created and managed internally. If your organization has a similar policy, this architecture might apply to you. If your customers require internal management of these items, the architecture also might apply to you.", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk", "services": [ "AKV", - "SAP" + "SQL", + "Backup", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Make sure you harden the operating system to eradicate vulnerabilities that could lead to attacks on the SAP database." + "severity": "Low", + "subcategory": "Post Migration", + "text": "Enable Customer managed TDE for taking your own copy only full backups", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "eeaa3592-829e-42ed-a217-3676aff6691b", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "The maintenance window feature provides you with the ability to onboard Azure SQL resource to prescheduled time blocks outside of business hours.", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql", "services": [ - "AKV" + "SQL" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." + "subcategory": "Post Migration", + "text": "Plan for Azure maintenance events", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "4935ada4-2223-4ece-a1b1-23181a541741", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "By using the long-term retention (LTR) feature, you can store specified SQL Database and SQL Managed Instance full backups in Azure Blob storage with configured redundancy for up to 10 years.", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi", "services": [ - "AKV" + "SQL", + "Storage", + "Backup", + "ARS" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Use an Azure Key Vault per application per environment per region." + "severity": "Low", + "subcategory": "Post Migration", + "text": "Configure Long Term backup retention, view backups and restore from backups", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "5833fb4a-e3c2-4df7-9316-5c3acbe05bbe", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "By using Azure Hybrid Benefit, you can achieve cost savings, modernise and maintain a flexible hybrid environment while optimising business applications.", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview", "services": [ - "AKV" + "SQL", + "Cost" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": " " + "severity": "Low", + "subcategory": "Post Migration", + "text": "Take advantage of Azure Hybrid Benefit and Azure Reservations where applicable.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "Cost" }, { - "category": "Storage", - "checklist": "Azure Landing Zone Review", - "guid": "d579266b-cca2-475f-aa1a-bfe9d55d04c3", + "category": "SQL Managed Instance", + "checklist": "SQL Migration Review", + "description": "If you don't have threat protection Advanced Threat Protection is part of the Microsoft Defender for SQL offering, which is a unified package for advanced SQL security capabilities.", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql", "services": [ "SQL", - "Storage" + "Defender" ], "severity": "Medium", - "subcategory": " ", - "text": "Disk config for Oracle, SQL, HANA" + "subcategory": "Post Migration", + "text": "Leverage Microsoft Defender for Cloud to improve the overall security posture", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { "category": "Security", @@ -14912,10 +14634,10 @@ "guid": "8bcbf59b-ce65-4de8-a03f-97879468d66a", "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-sas#shared-access-authorization-policies", "services": [ - "Entra", - "AzurePolicy", "TrafficManager", "ServiceBus", + "AzurePolicy", + "Entra", "RBAC" ], "severity": "Medium", @@ -14930,12 +14652,12 @@ "guid": "786d60f9-6c96-4ad8-a55d-04c2b39c986b", "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-managed-service-identity", "services": [ - "Entra", - "AKV", + "Storage", "ServiceBus", + "VM", "AppSvc", - "Storage", - "VM" + "AKV", + "Entra" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -14949,11 +14671,11 @@ "guid": "f615658d-e558-4f93-9249-b831112dbd7e", "link": "https://learn.microsoft.com/azure/service-bus-messaging/authenticate-application#azure-built-in-roles-for-azure-service-bus", "services": [ - "Entra", + "Storage", "ServiceBus", "Subscriptions", - "RBAC", - "Storage" + "Entra", + "RBAC" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -14967,9 +14689,9 @@ "guid": "af12e7f9-43f6-4304-922d-929c2b1cd622", "link": "https://learn.microsoft.com/azure/service-bus-messaging/monitor-service-bus-reference", "services": [ + "ServiceBus", "VNet", - "Monitor", - "ServiceBus" + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -14983,9 +14705,9 @@ "guid": "9ae669ca-48e4-4a85-b222-3ece8bb12307", "link": "https://learn.microsoft.com/azure/service-bus-messaging/private-link-service", "services": [ - "PrivateLink", + "ServiceBus", "VNet", - "ServiceBus" + "PrivateLink" ], "severity": "Medium", "subcategory": "Networking", @@ -15131,8 +14853,8 @@ "guid": "4d874a74-8b66-42d6-b150-512a66498f6d", "link": "https://learn.microsoft.com/azure/backup/backup-azure-vms-introduction", "services": [ - "Backup", - "VM" + "VM", + "Backup" ], "severity": "High", "subcategory": "Virtual Machines", @@ -15174,9 +14896,9 @@ "guid": "e0d5973c-d4ce-432c-8881-37f6f7c4c0d4", "link": "https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview#temporary-disk", "services": [ - "SQL", "Storage", - "VM" + "VM", + "SQL" ], "severity": "Medium", "subcategory": "Virtual Machines", @@ -15190,9 +14912,9 @@ "guid": "e514548d-2447-4ec6-9138-b8200f1ce16e", "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "services": [ - "ACR", "Storage", - "VM" + "VM", + "ACR" ], "severity": "Medium", "subcategory": "Virtual Machines", @@ -15235,8 +14957,8 @@ "guid": "2a6bcca2-b5fe-4a1e-af3d-d95d48c7c891", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "services": [ - "AVS", "VM", + "AVS", "ASR" ], "severity": "High", @@ -15378,8 +15100,8 @@ "guid": "2cc88147-0607-4c1c-aa0e-614658dd458e", "link": "https://learn.microsoft.com/azure/backup/backup-azure-immutable-vault-concept?source=recommendations&tabs=recovery-services-vault", "services": [ - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "Low", "subcategory": "Backup", @@ -15491,10 +15213,10 @@ "guid": "8df03a82-2cd4-463c-abbc-8ac299ebc92a", "link": "https://learn.microsoft.com/azure/networking/disaster-recovery-dns-traffic-manager", "services": [ - "TrafficManager", + "DNS", "Monitor", - "ASR", - "DNS" + "TrafficManager", + "ASR" ], "severity": "Low", "subcategory": "DNS", @@ -15508,9 +15230,9 @@ "guid": "43da1dae-2cc8-4814-9060-7c1cca0e6146", "link": "https://learn.microsoft.com/azure/dns/tutorial-dns-private-resolver-failover", "services": [ - "ACR", - "ASR", - "DNS" + "DNS", + "ACR", + "ASR" ], "severity": "Low", "subcategory": "DNS", @@ -15567,9 +15289,9 @@ "guid": "ead53cc7-de2e-48aa-ab35-71549ab9153d", "link": "https://learn.microsoft.com/azure/expressroute/use-s2s-vpn-as-backup-for-expressroute-privatepeering", "services": [ - "VPN", - "Backup", "Cost", + "Backup", + "VPN", "ExpressRoute" ], "severity": "Low", @@ -15598,8 +15320,8 @@ "guid": "b2b38c88-6ba2-4c02-8499-114a5d3ce574", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-standard-availability-zones", "services": [ - "LoadBalancer", - "VM" + "VM", + "LoadBalancer" ], "severity": "Low", "subcategory": "Load Balancers", @@ -15642,8 +15364,8 @@ "guid": "927139b8-2110-42db-b6ea-f11e6f843e53", "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-highlyavailable", "services": [ - "VPN", - "ACR" + "ACR", + "VPN" ], "severity": "Medium", "subcategory": "VPN Gateways", @@ -15688,8 +15410,8 @@ "id": "A01.02", "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", "services": [ - "Entra", "AKV", + "Entra", "AppSvc" ], "severity": "High", @@ -15721,8 +15443,8 @@ "id": "A01.04", "link": "https://learn.microsoft.com/azure/app-service/overview-hosting-plans", "services": [ - "Subscriptions", - "AppSvc" + "AppSvc", + "Subscriptions" ], "severity": "Medium", "subcategory": "Data Protection", @@ -15800,8 +15522,8 @@ "id": "A02.04", "link": "https://learn.microsoft.com/azure/app-service/overview-managed-identity?tabs=portal%2Chttp", "services": [ - "Entra", - "AKV" + "AKV", + "Entra" ], "severity": "High", "subcategory": "Identity and Access Control", @@ -15833,8 +15555,8 @@ "link": "https://learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs", "services": [ "Entra", - "Monitor", - "AppSvc" + "AppSvc", + "Monitor" ], "severity": "Medium", "subcategory": "Logging and Monitoring", @@ -15850,8 +15572,8 @@ "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", "services": [ "Entra", - "Monitor", - "AppSvc" + "AppSvc", + "Monitor" ], "severity": "Medium", "subcategory": "Logging and Monitoring", @@ -15867,9 +15589,9 @@ "link": "https://learn.microsoft.com/azure/app-service/overview-vnet-integration", "services": [ "Firewall", - "Monitor", + "VNet", "NVA", - "VNet" + "Monitor" ], "severity": "Medium", "subcategory": "Network Security", @@ -15884,11 +15606,11 @@ "id": "A04.02", "link": "https://learn.microsoft.com/azure/app-service/networking/nat-gateway-integration", "services": [ - "Firewall", + "Storage", "PrivateLink", + "Firewall", "VNet", - "NVA", - "Storage" + "NVA" ], "severity": "Low", "subcategory": "Network Security", @@ -15919,11 +15641,11 @@ "id": "A04.04", "link": "https://learn.microsoft.com/azure/app-service/networking/app-gateway-with-service-endpoints", "services": [ - "AppGW", + "FrontDoor", "Monitor", + "AppSvc", "WAF", - "FrontDoor", - "AppSvc" + "AppGW" ], "severity": "High", "subcategory": "Network Security", @@ -15972,8 +15694,8 @@ "id": "A04.07", "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-https", "services": [ - "WAF", - "AppSvc" + "AppSvc", + "WAF" ], "severity": "High", "subcategory": "Network Security", @@ -16017,8 +15739,8 @@ "id": "A04.10", "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-app-service-introduction", "services": [ - "AppSvc", - "Defender" + "Defender", + "AppSvc" ], "severity": "Medium", "subcategory": "Network Security", @@ -16033,12 +15755,12 @@ "id": "A04.11", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "services": [ - "AppGW", + "EventHubs", "DDoS", - "VNet", "WAF", + "VNet", "NVA", - "EventHubs" + "AppGW" ], "severity": "Medium", "subcategory": "Network Security", @@ -16186,8 +15908,8 @@ "id": "02.01.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", "services": [ - "ASR", - "AKS" + "AKS", + "ASR" ], "severity": "High", "subcategory": "Disaster Recovery", @@ -16203,9 +15925,9 @@ "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", "services": [ "TrafficManager", - "LoadBalancer", + "AKS", "FrontDoor", - "AKS" + "LoadBalancer" ], "severity": "Medium", "subcategory": "High Availability", @@ -16271,8 +15993,8 @@ "id": "02.02.05", "link": "https://learn.microsoft.com/azure/container-registry/container-registry-geo-replication", "services": [ - "ACR", - "AKS" + "AKS", + "ACR" ], "severity": "High", "subcategory": "High Availability", @@ -16418,8 +16140,8 @@ "link": "https://learn.microsoft.com/azure/container-registry/", "security": 1, "services": [ - "ACR", - "AKS" + "AKS", + "ACR" ], "severity": "Medium", "simple": -1, @@ -16636,8 +16358,8 @@ "security": 1, "services": [ "Entra", - "RBAC", - "AKS" + "AKS", + "RBAC" ], "severity": "Medium", "simple": -1, @@ -16655,8 +16377,8 @@ "security": 1, "services": [ "Entra", - "RBAC", - "AKS" + "AKS", + "RBAC" ], "severity": "High", "simple": -1, @@ -16792,9 +16514,9 @@ "link": "https://azure.github.io/application-gateway-kubernetes-ingress/setup/install-existing/", "security": 1, "services": [ + "AKS", "ACR", - "AppGW", - "AKS" + "AppGW" ], "severity": "Medium", "simple": -1, @@ -16845,8 +16567,8 @@ "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", "scale": 1, "services": [ - "LoadBalancer", - "AKS" + "AKS", + "LoadBalancer" ], "severity": "High", "subcategory": "Best practices", @@ -16878,10 +16600,10 @@ "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", "security": 1, "services": [ - "VNet", - "PrivateLink", "Cost", - "AKS" + "VNet", + "AKS", + "PrivateLink" ], "severity": "Medium", "simple": -1, @@ -16898,8 +16620,8 @@ "id": "06.03.01", "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering", "services": [ - "VPN", - "AKS" + "AKS", + "VPN" ], "severity": "Medium", "subcategory": "HA", @@ -17076,8 +16798,8 @@ "link": "https://learn.microsoft.com/azure/aks/limit-egress-traffic", "security": 2, "services": [ - "NVA", - "AKS" + "AKS", + "NVA" ], "severity": "High", "simple": -2, @@ -17180,8 +16902,8 @@ "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", "security": 2, "services": [ - "WAF", - "AKS" + "AKS", + "WAF" ], "severity": "High", "simple": -1, @@ -17200,8 +16922,8 @@ "security": 2, "services": [ "VNet", - "DDoS", - "AKS" + "AKS", + "DDoS" ], "severity": "Medium", "subcategory": "Security", @@ -17249,8 +16971,8 @@ "id": "07.01.01", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-metric-alerts", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "High", "simple": -1, @@ -17467,8 +17189,8 @@ "id": "07.02.15", "link": "https://learn.microsoft.com/azure/aks/monitor-aks", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "Low", "subcategory": "Compliance", @@ -17533,8 +17255,8 @@ "id": "07.04.01", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "High", "simple": -1, @@ -17551,8 +17273,8 @@ "id": "07.04.02", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "High", "simple": -1, @@ -17568,8 +17290,8 @@ "id": "07.04.03", "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-analyze", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "Medium", "simple": -1, @@ -17585,8 +17307,8 @@ "id": "07.04.04", "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "Medium", "simple": -1, @@ -17603,10 +17325,10 @@ "id": "07.04.05", "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance", "services": [ + "Storage", "Monitor", "ServiceBus", "EventHubs", - "Storage", "AKS" ], "severity": "Medium", @@ -17623,10 +17345,10 @@ "id": "07.04.06", "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", "services": [ - "LoadBalancer", "Monitor", - "NVA", - "AKS" + "AKS", + "LoadBalancer", + "NVA" ], "severity": "Medium", "simple": -1, @@ -17642,8 +17364,8 @@ "id": "07.04.07", "link": "https://learn.microsoft.com/azure/aks/aks-resource-health", "services": [ - "Monitor", - "AKS" + "AKS", + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -17690,8 +17412,8 @@ "id": "07.05.03", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "services": [ - "Subscriptions", - "AKS" + "AKS", + "Subscriptions" ], "severity": "High", "subcategory": "Resources", @@ -17951,8 +17673,8 @@ "id": "A02.01", "link": "https://learn.microsoft.com/azure/storage/common/storage-private-endpoints", "services": [ - "PrivateLink", - "Storage" + "Storage", + "PrivateLink" ], "severity": "High", "subcategory": "Networking", @@ -17967,9 +17689,9 @@ "id": "A03.01", "link": "https://learn.microsoft.com/azure/virtual-machines/migration-classic-resource-manager-overview#migration-of-storage-accounts", "services": [ - "Subscriptions", + "Storage", "RBAC", - "Storage" + "Subscriptions" ], "severity": "Medium", "subcategory": "Governance", @@ -18075,9 +17797,9 @@ "id": "A09.01", "link": "https://learn.microsoft.com/azure/storage/blobs/immutable-storage-overview", "services": [ - "Subscriptions", + "AzurePolicy", "Storage", - "AzurePolicy" + "Subscriptions" ], "severity": "High", "subcategory": "Data Availability, Compliance", @@ -18137,8 +17859,8 @@ "id": "A11.01", "link": "https://learn.microsoft.com/azure/storage/common/authorize-data-access", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18152,9 +17874,9 @@ "guid": "a4b1410d-4395-48a8-a228-9b3d6b57cfc6", "id": "A11.02", "services": [ + "Storage", "Entra", - "RBAC", - "Storage" + "RBAC" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -18169,8 +17891,8 @@ "id": "A11.03", "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json#best-practices-when-using-sas", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18185,10 +17907,10 @@ "id": "A11.04", "link": "https://learn.microsoft.com/rest/api/storageservices/authorize-with-shared-key", "services": [ - "Entra", + "AKV", "Storage", - "Monitor", - "AKV" + "Entra", + "Monitor" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18205,8 +17927,8 @@ "services": [ "AKV", "Storage", - "Monitor", - "AzurePolicy" + "AzurePolicy", + "Monitor" ], "severity": "High", "subcategory": "Monitoring", @@ -18221,10 +17943,10 @@ "id": "A13.01", "link": "https://learn.microsoft.com/azure/storage/common/storage-account-keys-manage?tabs=azure-portal#create-a-key-expiration-policy", "services": [ - "Entra", + "AKV", "Storage", - "AzurePolicy", - "AKV" + "Entra", + "AzurePolicy" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -18239,9 +17961,9 @@ "id": "A13.02", "link": "https://learn.microsoft.com/azure/storage/common/sas-expiration-policy", "services": [ - "Entra", + "AzurePolicy", "Storage", - "AzurePolicy" + "Entra" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -18256,9 +17978,9 @@ "id": "A13.03", "link": "https://learn.microsoft.com/rest/api/storageservices/define-stored-access-policy", "services": [ - "Entra", - "Storage", "AzurePolicy", + "Storage", + "Entra", "AKV" ], "severity": "Medium", @@ -18273,8 +17995,8 @@ "id": "A14.01", "link": "https://microsoft.github.io/code-with-engineering-playbook/continuous-integration/dev-sec-ops/secret-management/recipes/detect-secrets-ado/", "services": [ - "Storage", - "AKV" + "AKV", + "Storage" ], "severity": "Medium", "subcategory": "CI/CD", @@ -18289,8 +18011,8 @@ "id": "A15.01", "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-storage-keys", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18305,9 +18027,9 @@ "id": "A15.02", "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", "services": [ - "Entra", + "AzurePolicy", "Storage", - "AzurePolicy" + "Entra" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18322,8 +18044,8 @@ "id": "A15.03", "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -18338,8 +18060,8 @@ "id": "A15.04", "link": "https://learn.microsoft.com/rest/api/storageservices/create-account-sas", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -18353,8 +18075,8 @@ "guid": "348b263e-6dd6-4051-8a36-498f6dbad38e", "id": "A15.05", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "Low", "subcategory": "Identity and Access Management", @@ -18369,9 +18091,9 @@ "id": "A15.06", "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-support#sftp-permission-model", "services": [ + "Storage", "Entra", - "RBAC", - "Storage" + "RBAC" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18385,8 +18107,8 @@ "id": "A15.07", "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-known-issues#authentication-and-authorization", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "Medium", "subcategory": "Identity and Access Management", @@ -18401,8 +18123,8 @@ "id": "A16.01", "link": "https://learn.microsoft.com/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services", "services": [ - "Storage", - "AzurePolicy" + "AzurePolicy", + "Storage" ], "severity": "High", "subcategory": "Networking", @@ -18460,8 +18182,8 @@ "id": "A18.01", "link": "https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-configure?tabs=portal#allow-or-disallow-public-read-access-for-a-storage-account", "services": [ - "Entra", - "Storage" + "Storage", + "Entra" ], "severity": "High", "subcategory": "Identity and Access Management", @@ -18545,8 +18267,8 @@ "id": "A02.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "Cost" + "Cost", + "Entra" ], "severity": "Medium", "subcategory": "Cloud Solution Provider", @@ -18605,8 +18327,8 @@ "id": "A03.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "Entra", - "Cost" + "Cost", + "Entra" ], "severity": "Medium", "subcategory": "Enterprise Agreement", @@ -18620,9 +18342,9 @@ "id": "A03.05", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "Subscriptions", "Cost", - "Entra" + "Entra", + "Subscriptions" ], "severity": "Low", "subcategory": "Enterprise Agreement", @@ -18665,8 +18387,8 @@ "id": "A04.02", "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "services": [ - "Entra", "Storage", + "Entra", "Cost" ], "severity": "Low", @@ -18681,8 +18403,8 @@ "id": "A04.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Entra", - "Cost" + "Cost", + "Entra" ], "severity": "Low", "subcategory": "Microsoft Customer Agreement", @@ -18774,10 +18496,10 @@ "id": "B03.03", "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "services": [ - "Subscriptions", + "Entra", "ACR", "RBAC", - "Entra" + "Subscriptions" ], "severity": "High", "subcategory": "Identity", @@ -18792,8 +18514,8 @@ "id": "B03.04", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "services": [ - "Entra", - "AzurePolicy" + "AzurePolicy", + "Entra" ], "severity": "Low", "subcategory": "Identity", @@ -18886,9 +18608,9 @@ "id": "B03.10", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "services": [ - "Subscriptions", + "Entra", "RBAC", - "Entra" + "Subscriptions" ], "severity": "Medium", "subcategory": "Identity", @@ -18997,11 +18719,11 @@ "id": "B04.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "services": [ - "Entra", + "Storage", "ACR", "AKV", - "RBAC", - "Storage" + "Entra", + "RBAC" ], "severity": "Medium", "subcategory": "Landing zones", @@ -19074,9 +18796,9 @@ "id": "C02.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "services": [ - "Subscriptions", + "AzurePolicy", "RBAC", - "AzurePolicy" + "Subscriptions" ], "severity": "Medium", "subcategory": "Subscriptions", @@ -19091,8 +18813,8 @@ "id": "C02.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "services": [ - "Subscriptions", "DNS", + "Subscriptions", "VWAN", "ExpressRoute" ], @@ -19124,8 +18846,8 @@ "id": "C02.06", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "services": [ - "Subscriptions", - "RBAC" + "RBAC", + "Subscriptions" ], "severity": "Medium", "subcategory": "Subscriptions", @@ -19154,10 +18876,10 @@ "id": "C02.08", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "services": [ - "Subscriptions", - "RBAC", "AzurePolicy", - "Cost" + "Cost", + "RBAC", + "Subscriptions" ], "severity": "High", "subcategory": "Subscriptions", @@ -19186,10 +18908,10 @@ "id": "C02.10", "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", "services": [ - "Subscriptions", "AzurePolicy", + "Cost", "VM", - "Cost" + "Subscriptions" ], "severity": "High", "subcategory": "Subscriptions", @@ -19222,8 +18944,8 @@ "id": "C02.12", "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", "services": [ - "Subscriptions", - "Cost" + "Cost", + "Subscriptions" ], "severity": "High", "subcategory": "Subscriptions", @@ -19255,8 +18977,8 @@ "id": "C02.14", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", "services": [ - "Subscriptions", - "Cost" + "Cost", + "Subscriptions" ], "severity": "Medium", "subcategory": "Subscriptions", @@ -19417,13 +19139,13 @@ "id": "D03.02", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", "services": [ - "Entra", + "DNS", "Firewall", - "ExpressRoute", + "Entra", "VNet", "NVA", - "DNS", - "VPN" + "VPN", + "ExpressRoute" ], "severity": "High", "subcategory": "Hub and spoke", @@ -19452,8 +19174,8 @@ "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", "services": [ "VPN", - "ARS", - "ExpressRoute" + "ExpressRoute", + "ARS" ], "severity": "Low", "subcategory": "Hub and spoke", @@ -19738,8 +19460,8 @@ "id": "D04.12", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", "services": [ - "Monitor", - "ExpressRoute" + "ExpressRoute", + "Monitor" ], "severity": "Medium", "subcategory": "Hybrid", @@ -19803,8 +19525,8 @@ "id": "D04.16", "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub", "services": [ - "VNet", - "Storage" + "Storage", + "VNet" ], "severity": "High", "subcategory": "Hybrid", @@ -19900,8 +19622,8 @@ "id": "D05.05", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "services": [ - "VNet", - "DNS" + "DNS", + "VNet" ], "severity": "Medium", "subcategory": "IP plan", @@ -19916,9 +19638,9 @@ "id": "D05.06", "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", "services": [ + "DNS", "VNet", - "ACR", - "DNS" + "ACR" ], "severity": "Medium", "subcategory": "IP plan", @@ -19933,8 +19655,8 @@ "id": "D05.07", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "services": [ - "VNet", - "DNS" + "DNS", + "VNet" ], "severity": "Low", "subcategory": "IP plan", @@ -19949,9 +19671,9 @@ "id": "D05.08", "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", "services": [ - "VNet", + "DNS", "VM", - "DNS" + "VNet" ], "severity": "High", "subcategory": "IP plan", @@ -20012,10 +19734,10 @@ "id": "D06.04", "link": "https://learn.microsoft.com/azure/firewall/", "services": [ + "AzurePolicy", "Firewall", "ACR", - "RBAC", - "AzurePolicy" + "RBAC" ], "severity": "Medium", "subcategory": "Internet", @@ -20045,9 +19767,9 @@ "id": "D06.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "services": [ - "ACR", "AzurePolicy", "FrontDoor", + "ACR", "WAF" ], "severity": "Medium", @@ -20063,10 +19785,10 @@ "id": "D06.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "WAF", + "AzurePolicy", "FrontDoor", - "AppGW", - "AzurePolicy" + "WAF", + "AppGW" ], "severity": "Low", "subcategory": "Internet", @@ -20117,8 +19839,8 @@ "id": "D06.10", "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", "services": [ - "Firewall", - "DNS" + "DNS", + "Firewall" ], "severity": "High", "subcategory": "Internet", @@ -20182,11 +19904,11 @@ "id": "D06.14", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "services": [ + "Storage", + "VWAN", "Firewall", "VNet", - "NVA", - "Storage", - "VWAN" + "NVA" ], "severity": "High", "subcategory": "Internet", @@ -20276,10 +19998,10 @@ "id": "D07.05", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "services": [ + "DNS", "Firewall", - "PrivateLink", "NVA", - "DNS" + "PrivateLink" ], "severity": "Medium", "subcategory": "PaaS", @@ -20313,8 +20035,8 @@ "id": "D08.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", "services": [ - "VPN", "VNet", + "VPN", "ExpressRoute" ], "severity": "High", @@ -20375,8 +20097,8 @@ "guid": "9c2299c4-d7b5-47d0-a655-562f2b3e4563", "id": "D08.06", "services": [ - "VNet", - "VM" + "VM", + "VNet" ], "severity": "Medium", "subcategory": "Segmentation", @@ -20500,8 +20222,8 @@ "id": "D09.06", "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", "services": [ - "Monitor", - "VWAN" + "VWAN", + "Monitor" ], "severity": "Medium", "subcategory": "Virtual WAN", @@ -20529,8 +20251,8 @@ "id": "D09.08", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", "services": [ - "VPN", "VWAN", + "VPN", "ExpressRoute" ], "severity": "Medium", @@ -20603,8 +20325,8 @@ "id": "E01.03", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "RBAC", - "AzurePolicy" + "AzurePolicy", + "RBAC" ], "severity": "Medium", "subcategory": "Governance", @@ -20618,8 +20340,8 @@ "id": "E01.04", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Subscriptions", - "AzurePolicy" + "AzurePolicy", + "Subscriptions" ], "severity": "Medium", "subcategory": "Governance", @@ -20647,8 +20369,8 @@ "id": "E01.06", "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "services": [ - "Subscriptions", - "AzurePolicy" + "AzurePolicy", + "Subscriptions" ], "severity": "Low", "subcategory": "Governance", @@ -20677,9 +20399,9 @@ "id": "E01.08", "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "services": [ + "AzurePolicy", "Entra", "RBAC", - "AzurePolicy", "Subscriptions" ], "severity": "Medium", @@ -20694,8 +20416,8 @@ "id": "E01.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Subscriptions", - "AzurePolicy" + "AzurePolicy", + "Subscriptions" ], "severity": "Medium", "subcategory": "Governance", @@ -20766,8 +20488,8 @@ "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "services": [ "TrafficManager", - "VM", - "Cost" + "Cost", + "VM" ], "severity": "Low", "subcategory": "Optimize your cloud investment", @@ -20795,9 +20517,9 @@ "id": "E02.02", "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", "services": [ + "Cost", "TrafficManager", - "Monitor", - "Cost" + "Monitor" ], "severity": "Medium", "subcategory": "Optimize your cloud investment", @@ -20812,8 +20534,8 @@ "id": "F01.01", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "services": [ - "WAF", "FrontDoor", + "WAF", "AppGW" ], "severity": "High", @@ -20828,10 +20550,10 @@ "id": "F01.02", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "services": [ - "WAF", + "Sentinel", "FrontDoor", - "AppGW", - "Sentinel" + "WAF", + "AppGW" ], "severity": "Medium", "subcategory": "App delivery", @@ -20871,10 +20593,10 @@ "id": "F03.01", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ + "AzurePolicy", "Entra", "RBAC", - "Monitor", - "AzurePolicy" + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -20902,8 +20624,8 @@ "id": "F03.03", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "services": [ - "Monitor", - "ARS" + "ARS", + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -20918,8 +20640,8 @@ "id": "F03.04", "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/govern/policy-compliance/regulatory-compliance", "services": [ - "Monitor", - "AzurePolicy" + "AzurePolicy", + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -20934,9 +20656,9 @@ "id": "F03.05", "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "services": [ + "AzurePolicy", "VM", - "Monitor", - "AzurePolicy" + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -20951,8 +20673,8 @@ "id": "F03.06", "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "services": [ - "Monitor", - "VM" + "VM", + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -20998,8 +20720,8 @@ "id": "F03.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "RBAC", "AzurePolicy", + "RBAC", "Monitor" ], "severity": "Low", @@ -21143,8 +20865,8 @@ "id": "F04.01", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "services": [ - "VM", - "AzurePolicy" + "AzurePolicy", + "VM" ], "severity": "Medium", "subcategory": "Operational compliance", @@ -21159,9 +20881,9 @@ "id": "F04.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "services": [ + "AzurePolicy", "VM", - "Monitor", - "AzurePolicy" + "Monitor" ], "severity": "Medium", "subcategory": "Operational compliance", @@ -21175,8 +20897,8 @@ "id": "F05.01", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "services": [ - "ACR", "VM", + "ACR", "ASR" ], "severity": "Medium", @@ -21249,8 +20971,8 @@ "id": "F06.03", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "LoadBalancer", "ACR", + "LoadBalancer", "AppGW" ], "severity": "Medium", @@ -21319,8 +21041,8 @@ "id": "G02.03", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "AzurePolicy", - "AKV" + "AKV", + "AzurePolicy" ], "severity": "Medium", "subcategory": "Encryption and keys", @@ -21334,9 +21056,9 @@ "id": "G02.04", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ + "AKV", "Entra", - "RBAC", - "AKV" + "RBAC" ], "severity": "Medium", "subcategory": "Encryption and keys", @@ -21378,9 +21100,9 @@ "id": "G02.07", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ + "AKV", "VNet", - "PrivateLink", - "AKV" + "PrivateLink" ], "severity": "Medium", "subcategory": "Encryption and keys", @@ -21394,9 +21116,9 @@ "id": "G02.08", "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", "services": [ + "AKV", "Entra", - "Monitor", - "AKV" + "Monitor" ], "severity": "Medium", "subcategory": "Encryption and keys", @@ -21410,8 +21132,8 @@ "id": "G02.09", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "AzurePolicy", - "AKV" + "AKV", + "AzurePolicy" ], "severity": "Medium", "subcategory": "Encryption and keys", @@ -21453,8 +21175,8 @@ "id": "G02.12", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "ACR", "AKV", + "ACR", "ASR" ], "severity": "Medium", @@ -21498,8 +21220,8 @@ "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "services": [ "Storage", - "Monitor", - "ARS" + "ARS", + "Monitor" ], "severity": "Medium", "subcategory": "Operations", @@ -21514,8 +21236,8 @@ "id": "G03.03", "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", "services": [ - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Operations", @@ -21530,8 +21252,8 @@ "id": "G03.04", "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", "services": [ - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Operations", @@ -21546,8 +21268,8 @@ "id": "G03.05", "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", "services": [ - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Operations", @@ -21574,8 +21296,8 @@ "id": "G03.07", "link": "https://learn.microsoft.com/azure/security-center/", "services": [ - "Monitor", - "Defender" + "Defender", + "Monitor" ], "severity": "Medium", "subcategory": "Operations", @@ -21766,8 +21488,8 @@ "id": "H01.06", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "services": [ - "VM", - "AKV" + "AKV", + "VM" ], "severity": "High", "subcategory": "DevOps Team Topologies", @@ -21936,9 +21658,9 @@ "guid": "8210699f-8d43-45c2-8f19-57e54134bd8f", "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-log-event-hubs", "services": [ - "EventHubs", "AzurePolicy", - "APIM" + "APIM", + "EventHubs" ], "severity": "Low", "subcategory": "Performance and scalability", @@ -22014,9 +21736,9 @@ "guid": "a5c45b03-93b6-42fe-b16b-8fccb6a79902", "link": "https://learn.microsoft.com/azure/api-management/policy-fragments", "services": [ - "ACR", "AzurePolicy", - "APIM" + "APIM", + "ACR" ], "severity": "Medium", "subcategory": "Development best practices", @@ -22040,8 +21762,8 @@ "guid": "a7d0840a-c8c4-4e83-adec-5ca578eb4049", "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-use-azure-monitor#resource-logs", "services": [ - "Monitor", - "APIM" + "APIM", + "Monitor" ], "severity": "High", "subcategory": "Monitoring", @@ -22053,8 +21775,8 @@ "guid": "8691fa38-45ed-4299-a247-fecd98d35deb", "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-app-insights", "services": [ - "Monitor", - "APIM" + "APIM", + "Monitor" ], "severity": "Medium", "subcategory": "Monitoring", @@ -22066,8 +21788,8 @@ "guid": "55fd27bb-76ac-4a91-bc37-049e885be6b7", "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-use-azure-monitor", "services": [ - "Monitor", - "APIM" + "APIM", + "Monitor" ], "severity": "High", "subcategory": "Monitoring", @@ -22079,8 +21801,8 @@ "guid": "39460bdb-156f-4dc2-a87f-1e8c11ab0998", "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#certificate-management-in-azure-key-vault", "services": [ - "Entra", "AKV", + "Entra", "APIM" ], "severity": "High", @@ -22146,8 +21868,8 @@ "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#network-security-group-support", "services": [ "VNet", - "Monitor", - "APIM" + "APIM", + "Monitor" ], "severity": "Medium", "subcategory": "Security", @@ -22160,8 +21882,8 @@ "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#azure-private-link", "services": [ "VNet", - "PrivateLink", - "APIM" + "APIM", + "PrivateLink" ], "severity": "Medium", "subcategory": "Security", @@ -22185,8 +21907,8 @@ "guid": "7519e385-a88b-4d34-966b-6269d686e890", "link": "https://learn.microsoft.com/azure/api-management/front-door-api-management", "services": [ - "FrontDoor", - "APIM" + "APIM", + "FrontDoor" ], "severity": "Medium", "subcategory": "Connectivity", @@ -22335,9 +22057,9 @@ "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#ns-6-deploy-web-application-firewall", "services": [ "Entra", + "APIM", "WAF", - "AppGW", - "APIM" + "AppGW" ], "severity": "High", "subcategory": "Network", @@ -22346,7 +22068,7 @@ ], "metadata": { "name": "Master checklist", - "timestamp": "December 08, 2023" + "timestamp": "December 13, 2023" }, "severities": [ { diff --git a/checklists/sql_checklist.en.json b/checklists/sql_checklist.en.json index 7d2b476e4..1136f26f5 100644 --- a/checklists/sql_checklist.en.json +++ b/checklists/sql_checklist.en.json @@ -1,760 +1,759 @@ { - "items": [ - { - "category": "SQL Server on Azure VM", - "subcategory": "VM Size", - "text": "Collect the target workload's performance characteristics and use them to determine the appropriate VM size for your business.", - "description": "When you are creating a SQL Server on Azure VM, carefully consider the type of workload necessary. If you are migrating an existing environment, collect a performance baseline to determine your SQL Server on Azure VM requirements. If this is a new VM, then create your new SQL Server VM based on your vendor requirements.", - "waf": "Performance", - "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", - "id": "A01.01", - "severity": "High", - "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "VM Size", - "text": "Use memory optimized virtual machine sizes for the best performance of SQL Server workloads.", - "description": "The memory optimized virtual machine sizes are a primary target for SQL Server VMs and the recommended choice by Microsoft. The memory optimized virtual machines offer stronger memory-to-CPU ratios and medium-to-large cache options.Consider Ebdsv5-series series first for most SQL Server workloads.", - "waf": "Performance", - "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", - "id": "A01.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Determine storage bandwidth and latency requirements for SQL Server data, log, and tempdb files before choosing the disk type.", - "description": "To find the most effective configuration for SQL Server workloads on an Azure VM, start by measuring the storage performance of your business application. Once storage requirements are known, select a virtual machine that supports the necessary IOPS and throughput with the appropriate memory-to-vCore ratio.", - "waf": "Performance", - "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", - "id": "A02.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Place data, log, and tempdb files on separate drives", - "description": "This provides more dedicated disk IOPS and throughput on the disk level and also allows you to configure the Azure disk host caching setting for each disk to the optimal setting for that data type.", - "waf": "Performance", - "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", - "id": "A02.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "For the data drive, use premium P30 and P40 or smaller disks to ensure the availability of cache support", - "description": "Premium SSD is always recommend as a minimum for SQL Server in order to obtain better performance and lower latency. P30 and P40 are recommended because disk caching is not supported for disks 4 TiB and larger ( P50 and above) and they provide the optimal price to performance ratio", - "waf": "Performance", - "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", - "id": "A02.03", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "For the log drive plan for capacity and test performance versus cost while evaluating the premium P30 - P80 disks", - "description": "Log files have primarily write-heavy operations. Therefore, they do not benefit from the ReadOnly cache. Hence evaluate your price vs performance vs capacity and chose the right storage disk.", - "waf": "Performance", - "guid": "25659d35-58fd-4772-99c9-31112d027fe4", - "id": "A02.04", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Place tempdb on the local ephemeral SSD (default D:\\) drive for most SQL Server workloads that are not part of Failover Cluster Instance (FCI) after choosing the optimal VM size.", - "description": "Placing TempDB on the D drive can help performance. Consider the size required and always test performance.", - "waf": "Performance", - "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", - "id": "A02.05", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Stripe multiple Azure data disks using Storage Spaces to increase I/O bandwidth", - "description": "Striping Data and Log disk can increase bandwidth. Ensure that VM size also matches expected output", - "waf": "Performance", - "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", - "id": "A02.06", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Set host caching to read-only for data file disks and none for log file disks.", - "description": "Your storage caching policy varies depending on the type of SQL Server data files that are hosted on the drive.Enable Read-only caching for the disks hosting SQL Server data files.Reads from cache will be faster than the uncached reads from the data disk.Set the caching policy to None for disks hosting the transaction log. There is no performance benefit to enabling caching for the Transaction log disk.", - "waf": "Performance", - "guid": "05674b5e-985b-4859-a773-e7e261623b77", - "id": "A02.07", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Provision the storage account in the same region as the SQL Server VM", - "description": "Check that you storage is in the same region as your VM. For exaplme if your VM is in EAST US 2 ensure your storage is in East US 2.", - "waf": "Performance", - "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", - "id": "A02.08", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Storage", - "text": "Format your data disk to use 64 KB block size (allocation unit size) for all data files placed on a drive other than the temporary D:\\ drive", - "description": "SQL Server uses extents to store data. These are 64KB in size. Therefore, on a SQL Server machine, the NTFS allocation unit size for hosting SQL database files should be 64 KB.", - "waf": "Performance", - "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", - "id": "A02.09", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "HADR", - "text": "Determine HA/DR requirements for each VM to be migrated.", - "description": "It is recommended that you determine BCDR needs and requirements ensuring that you are able to meet you SLAs of the environment.", - "waf": "Reliability", - "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", - "id": "A03.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "HADR", - "text": "Place your VMs in an availability set or different availability zones.", - "description": "When depoying High Availability you need to use availability sets or availability zones to avoid unexpected outages.", - "waf": "Reliability", - "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", - "id": "A03.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "HADR", - "text": "Deploy your SQL Server VMs to multiple subnets whenever possible to avoid the dependency on an Azure Load Balancer or a distributed network name (DNN) to route traffic to your HADR solution. ( If one is implementing FCI or AG)", - "description": "Prefered option when deploying an Availability Group. The recommended solution is to use multi-subnets when deploying Always on Availability Groups.", - "waf": "Reliability", - "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", - "id": "A03.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "HADR", - "text": "Change the cluster to less aggressive parameters to avoid unexpected outages from transient network failures or Azure platform maintenance. ( If one is implementing FCI or AG)", - "description": "High availability and disaster recovery (HADR) features, such as the Always On availability group and the failover cluster instance rely on underlying Windows Server Failover Cluster technology. Review the best practices for modifying your HADR settings to better support the cloud environment.", - "waf": "Reliability", - "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", - "id": "A03.04", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "HADR", - "text": "Configure cluster quorum voting to use 3 or more odd number of votes. Don't assign votes to DR regions. ( If one is implementing FCI or AG)", - "description": "Ensure that quorum is set correct for the number of instances deployed.", - "waf": "Reliability", - "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", - "id": "A03.05", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "HADR", - "text": "When using the virtual network name (VNN) and Azure Load Balancer to connect to your HADR solution, specify MultiSubnetFailover = true in the connection string, even if your cluster only spans one subnet. ( If one is implementing FCI or AG)", - "description": "On Azure virtual machines, clusters use a load balancer to hold an IP address that needs to be on one cluster node at a time. In this solution, the load balancer holds the IP address for the virtual network name (VNN) listener for the Always On availability group when the SQL Server VMs are in a single subnet.", - "waf": "Reliability", - "guid": "667313c4-0567-44b5-b985-b859c773e7e2", - "id": "A03.06", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Enable database page compression where appropriate.", - "description": "SQL Server, Azure SQL Database, and Azure SQL Managed Instance support row and page compression for rowstore tables and indexes, and support columnstore and columnstore archival compression for columnstore tables and indexes.", - "waf": "Performance", - "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", - "id": "A04.01", - "severity": "Low", - "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Enable instant file initialization for data files.", - "description": "By default, data and log files are initialized to overwrite any existing data left on the disk from previously deleted files. Data and log files are first initialized by zeroing the files (filling with zeros).In SQL Server, for data files only, instant file initialization (IFI) allows for faster execution of the previously mentioned file operations, since it reclaims used disk space without filling that space with zeros. Instead, disk content is overwritten as new data is written to the files.", - "waf": "Operations", - "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", - "id": "A04.02", - "severity": "High", - "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Move all databases to data disks, including system databases.", - "description": "Recommended for best performance and availability migrate all databases to data and log disks", - "waf": "Operations", - "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", - "id": "A04.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Move SQL Server error log and trace file directories to data disks.", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Operations", - "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", - "id": "A04.04", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Set max SQL Server memory limit to leave enough memory for the Operating System.", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Performance", - "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", - "id": "A04.05", - "severity": "High", - "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Enable lock pages in memory.", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Performance", - "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", - "id": "A04.06", - "severity": "High", - "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Enable Query Store on all production SQL Server databases following best practices.", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Performance", - "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", - "id": "A04.07", - "severity": "Low", - "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Ensure that all tempdb best practices are followed.", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Performance", - "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", - "id": "A04.08", - "severity": "High", - "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Schedule SQL Server Agent jobs to run DBCC CHECKDB, index reorganize, index rebuild, and update statistics jobs.", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Operations", - "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", - "id": "A04.09", - "severity": "High", - "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "SQL Server", - "text": "Limit autogrowth of the database and Disable autoshrink", - "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", - "waf": "Operations", - "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", - "id": "A04.10", - "severity": "Medium", - "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Cost Optimization", - "text": "Optimize SQL Server License cost with Constrained vCPU VM's", - "description": "Constrained vCPU virtual machines (VMs) are a type of VM where the vCPU count can be constrained to a half or a quarter of the original VM size. This allows customers to reduce the cost of software licensing while maintaining the same memory, storage, and I/O bandwidth", - "waf": "Cost", - "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", - "id": "A05.01", - "severity": "Low", - "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", - "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Cost Optimization", - "text": "Leverage Azure Hybrid benefit to maximize the value of your on premises licenses in the cloud", - "description": "Azure Hybrid Benefit allows you to exchange your existing licenses for discounted rates on Azure SQL Database and Azure SQL Managed Instance. Y", - "waf": "Cost", - "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", - "id": "A05.02", - "severity": "Low", - "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Azure", - "text": "Register with the SQL IaaS Agent Extension to unlock a number of feature benefits.", - "description": "The SQL Server IaaS Agent extension (SqlIaasExtension) runs on SQL Server on Azure Windows Virtual Machines (VMs) to automate management and administration tasks.", - "waf": "Operations", - "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", - "id": "A06.01", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", - "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Azure", - "text": "Ensure Accelerated Networking is enabled on the virtual machine.", - "description": "Accelerated Networking provides consistent ultra-low network latency via Azure's in-house programmable hardware and technologies", - "waf": "Operations", - "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", - "id": "A06.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat" - }, - { - "category": "SQL Server on Azure VM", - "subcategory": "Azure", - "text": "Leverage Microsoft Defender for Cloud to improve the overall security posture of your virtual machine deployment.", - "description": "Microsoft Defender detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases on the SQL server.", - "waf": "Security", - "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", - "id": "A06.03", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Review the major differences between SQL Server and Managed Instance", - "description": "There are some PaaS limitations that are introduced in SQL Managed Instance and some behavior changes compared to SQL Server. It is important to review and understand these differences.", - "waf": "Operations", - "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", - "id": "B01.01", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Review capacity limits for SQL MI", - "description": "SQL Managed Instance has characteristics and resource limits that depend on the underlying infrastructure and architecture. It is important to review these limits.", - "waf": "Performance", - "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", - "id": "B01.02", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", - "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Compare instance settings on SQL Server and Azure SQL MI that may impact performance", - "description": "The instance settings between managed instance and your source SQL Server can be different . It is important to review those differences that can impact performance.", - "waf": "Performance", - "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", - "id": "B01.03", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", - "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Run Data Migration assistant or Azure Data Studio Migration Extension to detect compatibility issues that can impact database functionality on Managed Instance", - "description": "Assess on-premises SQL Server instance(s) migrating to Azure SQL Managed Instance. The assessment workflow helps you to detect issues that block the migration itself and also partially supported and unsupported features", - "waf": "Operations", - "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", - "id": "B01.04", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", - "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Select the right compute resources for your workload by leveraging the SKU recommendation tools.", - "description": "The SKU recommendation feature can evaluate the source SQL Server performance and utilization characteristics to recommend a right-sized Azure SQL Managed Instance to assist with your migration journey.", - "waf": "Performance", - "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", - "id": "B01.05", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", - "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Review and address the issues highlighted in DMA/Azure Data Studio", - "description": "Review Unsupported Features, Migration Blockers and Breaking Changes for each database from the Assessment", - "waf": "Operations", - "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", - "id": "B01.06", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", - "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Plan for connection string changes as changing a managed instance name is not supported", - "description": "The SQL Managed Instance default DNS zone .database.windows.net can be changed with your own. However, the managed instance hostname part of its FQDN should remain the same.", - "waf": "Operations", - "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", - "id": "B01.07", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Review managed instance VNet requirements", - "description": "There are addional requirements in configuring a vnet and subnet hosting the managed instance.", - "waf": "Operations", - "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", - "id": "B01.08", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Deployment", - "text": "Ensure managed instance subnet has sufficient IP addresses available", - "description": "Though it's possible to deploy managed instances to a subnet with a number of IP addresses that's less than the output of the subnet formula, always consider using bigger subnets instead. Using a bigger subnet can help avoid future issues stemming from a lack of IP addresses, such as the inability to create additional instances within the subnet or scale existing instances.", - "waf": "Operations", - "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", - "id": "B02.01", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Plan between General Purpose and Business Critical tiers of MI", - "description": "SQL Managed Instance has characteristics and resource limits that depend on the underlying infrastructure and architecture. SQL Managed Instance can be deployed on multiple hardware configurations.", - "waf": "Performance", - "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", - "id": "B03.01", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Based on your RPO/RTO's , determine if Auto failover Group needs to be implemented. If so, plan for the deployment attributes of the second instance.", - "description": "The auto-failover groups feature allows you to manage the replication and failover of user databases in a managed instance to a managed instance in another Azure region. Auto-failover groups are designed to simplify deployment and management of geo-replicated databases at scale.", - "waf": "Reliability", - "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", - "id": "B03.02", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Review the Connectivity Design between Database and Application, test & validate it", - "description": "There are multiple ways to connect your application to the managed instance. Review and understand the pros and cons and decide on the best approach for your application.", - "waf": "Operations", - "guid": "5d226886-d30b-466c-97be-595190f83845", - "id": "B03.03", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Plan for the Migration Method. Depending on the DB Size and Application downtime window, select the preferred Migration Method.", - "description": "Compare migration options to choose the path that's appropriate to your business needs.", - "waf": "Operations", - "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", - "id": "B03.04", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", - "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Pre Migration", - "text": "Plan the cutover process with business / application teams to ensure minimal interruption during cutover and it does not affect business continuity.", - "description": "After you verify that data is the same on both source and target, you can cut over from the source to the target environment. It's important to plan the cutover process with business / application teams to ensure minimal interruption during cutover doesn't affect business continuity.", - "waf": "Reliability", - "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", - "id": "B03.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", - "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Deployment", - "text": "Ensure you customize your time zone setting at the instance creation time. One cannot change it later.", - "description": "A time zone of a managed instance can be set during instance creation only. The default time zone is UTC", - "waf": "Operations", - "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", - "id": "B04.01", - "severity": "High", - "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Deployment", - "text": "Ensure you select the right collation setting at the instance creation time. One cannot change it later", - "description": "Server-level collation in Azure SQL Managed Instance can be specified when the instance is created and cannot be changed later.Default server-level collation is SQL_Latin1_General_CP1_CI_AS.", - "waf": "Operations", - "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", - "id": "B04.02", - "severity": "High", - "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Deployment", - "text": "For TDE Enabled Database, corresponding certificate from the on-premises or Azure VM SQL Server needs to be migrated before database restore", - "description": "When you're migrating a database protected by Transparent Data Encryption (TDE) to Azure SQL Managed Instance using the native restore option, the corresponding certificate from the SQL Server instance needs to be migrated before database restore.", - "waf": "Operations", - "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", - "id": "B04.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Migration", - "text": "Restore of system databases is not supported. To migrate instance-level objects (stored in master or msdb databases), we recommend to script them out and run T-SQL scripts on the destination instance.", - "description": "System databases can be restored only from backups that are created on the version of SQL Server that the server instance is currently running. This is not the case when you are migrating to SQL Managed Instance.Azure PowerShell and DBATools PowerShell libraries enable you to easily script and automate and customize all parts of the migration process.", - "waf": "Operations", - "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", - "id": "B05.01", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Migration", - "text": "Ensure that all changes on the source are captured and applied to the target during the migration process.", - "description": "When using migration options that continuously replicate / sync data changes from source to the target, the source data and schema can change and drift from the target. During data sync, ensure that all changes on the source are captured and applied to the target during the migration process.", - "waf": "Operations", - "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", - "id": "B05.02", - "severity": "High" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Migration", - "text": "Test Application Connectivity to MI and Databases", - "description": "Ensure that the application is able to succesffuly connect to the managed instance post migration of the databases.", - "waf": "Operations", - "guid": "b5887952-5d22-4688-9d30-b66c57be5951", - "id": "B05.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Consider executing a manual failover on SQL Managed Instance to test for fault and failover resiliency.", - "description": "High availability is a fundamental part of SQL Managed Instance platform that works transparently for your database applications. Failovers from primary to secondary nodes in case of node degradation or fault detection, or during regular monthly software updates are an expected occurrence for all applications using SQL Managed Instance in Azure.", - "waf": "Reliability", - "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", - "id": "B06.01", - "severity": "High", - "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "If failover groups have been implemented, Test Manual Failover and Failback and test application connectivity behavior during failover/failback", - "description": "Ensuring that your applications are failover resilient prior to deploying to production will help mitigate the risk of application faults in production and will contribute to application availability for your customers.", - "waf": "Reliability", - "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", - "id": "B06.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Optimize Storage Performance for General Purpose Managed Instance", - "description": "This provides more dedicated disk IOPS and throughput", - "waf": "Performance", - "guid": "aa359272-8e6e-4205-8726-76ae46691e88", - "id": "B06.03", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", - "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Enable Customer managed TDE for taking your own copy only full backups", - "description": "Many organizations have policies that require that certificates or encryption keys be created and managed internally. If your organization has a similar policy, this architecture might apply to you. If your customers require internal management of these items, the architecture also might apply to you.", - "waf": "Security", - "guid": "35ad9422-23e1-4381-8523-081a94174158", - "id": "B06.04", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Plan for Azure maintenance events", - "description": "The maintenance window feature provides you with the ability to onboard Azure SQL resource to prescheduled time blocks outside of business hours.", - "waf": "Operations", - "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", - "id": "B06.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Configure Long Term backup retention, view backups and restore from backups", - "description": "By using the long-term retention (LTR) feature, you can store specified SQL Database and SQL Managed Instance full backups in Azure Blob storage with configured redundancy for up to 10 years.", - "waf": "Reliability", - "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", - "id": "B06.06", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", - "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Take advantage of Azure Hybrid Benefit and Azure Reservations where applicable.", - "description": "By using Azure Hybrid Benefit, you can achieve cost savings, modernise and maintain a flexible hybrid environment while optimising business applications.", - "waf": "Cost", - "guid": "ad88408f-3727-434c-a76b-a28021459014", - "id": "B06.07", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", - "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview" - }, - { - "category": "SQL Managed Instance", - "subcategory": "Post Migration", - "text": "Leverage Microsoft Defender for Cloud to improve the overall security posture", - "description": "If you don't have threat protection Advanced Threat Protection is part of the Microsoft Defender for SQL offering, which is a unified package for advanced SQL security capabilities.", - "waf": "Security", - "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", - "id": "B06.08", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql" + "items": [ + { + "category": "SQL Server on Azure VM", + "subcategory": "VM Size", + "text": "Collect the target workload's performance characteristics and use them to determine the appropriate VM size for your business.", + "description": "When you are creating a SQL Server on Azure VM, carefully consider the type of workload necessary. If you are migrating an existing environment, collect a performance baseline to determine your SQL Server on Azure VM requirements. If this is a new VM, then create your new SQL Server VM based on your vendor requirements.", + "waf": "Performance", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "severity": "High", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "VM Size", + "text": "Use memory optimized virtual machine sizes for the best performance of SQL Server workloads.", + "description": "The memory optimized virtual machine sizes are a primary target for SQL Server VMs and the recommended choice by Microsoft. The memory optimized virtual machines offer stronger memory-to-CPU ratios and medium-to-large cache options.Consider Ebdsv5-series series first for most SQL Server workloads.", + "waf": "Performance", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Determine storage bandwidth and latency requirements for SQL Server data, log, and tempdb files before choosing the disk type.", + "description": "To find the most effective configuration for SQL Server workloads on an Azure VM, start by measuring the storage performance of your business application. Once storage requirements are known, select a virtual machine that supports the necessary IOPS and throughput with the appropriate memory-to-vCore ratio.", + "waf": "Performance", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Place data, log, and tempdb files on separate drives", + "description": "This provides more dedicated disk IOPS and throughput on the disk level and also allows you to configure the Azure disk host caching setting for each disk to the optimal setting for that data type.", + "waf": "Performance", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "For the data drive, use premium P30 and P40 or smaller disks to ensure the availability of cache support", + "description": "Premium SSD is always recommend as a minimum for SQL Server in order to obtain better performance and lower latency. P30 and P40 are recommended because disk caching is not supported for disks 4 TiB and larger ( P50 and above) and they provide the optimal price to performance ratio", + "waf": "Performance", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "For the log drive plan for capacity and test performance versus cost while evaluating the premium P30 - P80 disks", + "description": "Log files have primarily write-heavy operations. Therefore, they do not benefit from the ReadOnly cache. Hence evaluate your price vs performance vs capacity and chose the right storage disk.", + "waf": "Performance", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Place tempdb on the local ephemeral SSD (default D:\\) drive for most SQL Server workloads that are not part of Failover Cluster Instance (FCI) after choosing the optimal VM size.", + "description": "Placing TempDB on the D drive can help performance. Consider the size required and always test performance.", + "waf": "Performance", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Stripe multiple Azure data disks using Storage Spaces to increase I/O bandwidth", + "description": "Striping Data and Log disk can increase bandwidth. Ensure that VM size also matches expected output", + "waf": "Performance", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Set host caching to read-only for data file disks and none for log file disks.", + "description": "Your storage caching policy varies depending on the type of SQL Server data files that are hosted on the drive.Enable Read-only caching for the disks hosting SQL Server data files.Reads from cache will be faster than the uncached reads from the data disk.Set the caching policy to None for disks hosting the transaction log. There is no performance benefit to enabling caching for the Transaction log disk.", + "waf": "Performance", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Provision the storage account in the same region as the SQL Server VM", + "description": "Check that you storage is in the same region as your VM. For exaplme if your VM is in EAST US 2 ensure your storage is in East US 2.", + "waf": "Performance", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Storage", + "text": "Format your data disk to use 64 KB block size (allocation unit size) for all data files placed on a drive other than the temporary D:\\ drive", + "description": "SQL Server uses extents to store data. These are 64KB in size. Therefore, on a SQL Server machine, the NTFS allocation unit size for hosting SQL database files should be 64 KB.", + "waf": "Performance", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "HADR", + "text": "Determine HA/DR requirements for each VM to be migrated.", + "description": "It is recommended that you determine BCDR needs and requirements ensuring that you are able to meet you SLAs of the environment.", + "waf": "Reliability", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "HADR", + "text": "Place your VMs in an availability set or different availability zones.", + "description": "When depoying High Availability you need to use availability sets or availability zones to avoid unexpected outages.", + "waf": "Reliability", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "HADR", + "text": "Deploy your SQL Server VMs to multiple subnets whenever possible to avoid the dependency on an Azure Load Balancer or a distributed network name (DNN) to route traffic to your HADR solution. ( If one is implementing FCI or AG)", + "description": "Prefered option when deploying an Availability Group. The recommended solution is to use multi-subnets when deploying Always on Availability Groups.", + "waf": "Reliability", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "HADR", + "text": "Change the cluster to less aggressive parameters to avoid unexpected outages from transient network failures or Azure platform maintenance. ( If one is implementing FCI or AG)", + "description": "High availability and disaster recovery (HADR) features, such as the Always On availability group and the failover cluster instance rely on underlying Windows Server Failover Cluster technology. Review the best practices for modifying your HADR settings to better support the cloud environment.", + "waf": "Reliability", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "HADR", + "text": "Configure cluster quorum voting to use 3 or more odd number of votes. Don't assign votes to DR regions. ( If one is implementing FCI or AG)", + "description": "Ensure that quorum is set correct for the number of instances deployed.", + "waf": "Reliability", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "HADR", + "text": "When using the virtual network name (VNN) and Azure Load Balancer to connect to your HADR solution, specify MultiSubnetFailover = true in the connection string, even if your cluster only spans one subnet. ( If one is implementing FCI or AG)", + "description": "On Azure virtual machines, clusters use a load balancer to hold an IP address that needs to be on one cluster node at a time. In this solution, the load balancer holds the IP address for the virtual network name (VNN) listener for the Always On availability group when the SQL Server VMs are in a single subnet.", + "waf": "Reliability", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Enable database page compression where appropriate.", + "description": "SQL Server, Azure SQL Database, and Azure SQL Managed Instance support row and page compression for rowstore tables and indexes, and support columnstore and columnstore archival compression for columnstore tables and indexes.", + "waf": "Performance", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "severity": "Low", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Enable instant file initialization for data files.", + "description": "By default, data and log files are initialized to overwrite any existing data left on the disk from previously deleted files. Data and log files are first initialized by zeroing the files (filling with zeros).In SQL Server, for data files only, instant file initialization (IFI) allows for faster execution of the previously mentioned file operations, since it reclaims used disk space without filling that space with zeros. Instead, disk content is overwritten as new data is written to the files.", + "waf": "Operations", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "severity": "High", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Move all databases to data disks, including system databases.", + "description": "Recommended for best performance and availability migrate all databases to data and log disks", + "waf": "Operations", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Move SQL Server error log and trace file directories to data disks.", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Operations", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Set max SQL Server memory limit to leave enough memory for the Operating System.", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Performance", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "severity": "High", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Enable lock pages in memory.", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Performance", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "severity": "High", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Enable Query Store on all production SQL Server databases following best practices.", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Performance", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "severity": "Low", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Ensure that all tempdb best practices are followed.", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Performance", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "severity": "High", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Schedule SQL Server Agent jobs to run DBCC CHECKDB, index reorganize, index rebuild, and update statistics jobs.", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Operations", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "severity": "High", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "SQL Server", + "text": "Limit autogrowth of the database and Disable autoshrink", + "description": "Part of the SQL Server Feature checklist in the link that is recommended when SQL Server Instance is in an Azure VM.", + "waf": "Operations", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "severity": "Medium", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Cost Optimization", + "text": "Optimize SQL Server License cost with Constrained vCPU VM's", + "description": "Constrained vCPU virtual machines (VMs) are a type of VM where the vCPU count can be constrained to a half or a quarter of the original VM size. This allows customers to reduce the cost of software licensing while maintaining the same memory, storage, and I/O bandwidth", + "waf": "Cost", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "severity": "Low", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Cost Optimization", + "text": "Leverage Azure Hybrid benefit to maximize the value of your on premises licenses in the cloud", + "description": "Azure Hybrid Benefit allows you to exchange your existing licenses for discounted rates on Azure SQL Database and Azure SQL Managed Instance. Y", + "waf": "Cost", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "severity": "Low", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Azure", + "text": "Register with the SQL IaaS Agent Extension to unlock a number of feature benefits.", + "description": "The SQL Server IaaS Agent extension (SqlIaasExtension) runs on SQL Server on Azure Windows Virtual Machines (VMs) to automate management and administration tasks.", + "waf": "Operations", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Azure", + "text": "Ensure Accelerated Networking is enabled on the virtual machine.", + "description": "Accelerated Networking provides consistent ultra-low network latency via Azure's in-house programmable hardware and technologies", + "waf": "Operations", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat" + }, + { + "category": "SQL Server on Azure VM", + "subcategory": "Azure", + "text": "Leverage Microsoft Defender for Cloud to improve the overall security posture of your virtual machine deployment.", + "description": "Microsoft Defender detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases on the SQL server.", + "waf": "Security", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Review the major differences between SQL Server and Managed Instance", + "description": "There are some PaaS limitations that are introduced in SQL Managed Instance and some behavior changes compared to SQL Server. It is important to review and understand these differences.", + "waf": "Operations", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Review capacity limits for SQL MI", + "description": "SQL Managed Instance has characteristics and resource limits that depend on the underlying infrastructure and architecture. It is important to review these limits.", + "waf": "Performance", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Compare instance settings on SQL Server and Azure SQL MI that may impact performance", + "description": "The instance settings between managed instance and your source SQL Server can be different . It is important to review those differences that can impact performance.", + "waf": "Performance", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Run Data Migration assistant or Azure Data Studio Migration Extension to detect compatibility issues that can impact database functionality on Managed Instance", + "description": "Assess on-premises SQL Server instance(s) migrating to Azure SQL Managed Instance. The assessment workflow helps you to detect issues that block the migration itself and also partially supported and unsupported features", + "waf": "Operations", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Select the right compute resources for your workload by leveraging the SKU recommendation tools.", + "description": "The SKU recommendation feature can evaluate the source SQL Server performance and utilization characteristics to recommend a right-sized Azure SQL Managed Instance to assist with your migration journey.", + "waf": "Performance", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Review and address the issues highlighted in DMA/Azure Data Studio", + "description": "Review Unsupported Features, Migration Blockers and Breaking Changes for each database from the Assessment", + "waf": "Operations", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Plan for connection string changes as changing a managed instance name is not supported", + "description": "The SQL Managed Instance default DNS zone .database.windows.net can be changed with your own. However, the managed instance hostname part of its FQDN should remain the same.", + "waf": "Operations", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Review managed instance VNet requirements", + "description": "There are addional requirements in configuring a vnet and subnet hosting the managed instance.", + "waf": "Operations", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Deployment", + "text": "Ensure managed instance subnet has sufficient IP addresses available", + "description": "Though it's possible to deploy managed instances to a subnet with a number of IP addresses that's less than the output of the subnet formula, always consider using bigger subnets instead. Using a bigger subnet can help avoid future issues stemming from a lack of IP addresses, such as the inability to create additional instances within the subnet or scale existing instances.", + "waf": "Operations", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Plan between General Purpose and Business Critical tiers of MI", + "description": "SQL Managed Instance has characteristics and resource limits that depend on the underlying infrastructure and architecture. SQL Managed Instance can be deployed on multiple hardware configurations.", + "waf": "Performance", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Based on your RPO/RTO's , determine if Auto failover Group needs to be implemented. If so, plan for the deployment attributes of the second instance.", + "description": "The auto-failover groups feature allows you to manage the replication and failover of user databases in a managed instance to a managed instance in another Azure region. Auto-failover groups are designed to simplify deployment and management of geo-replicated databases at scale.", + "waf": "Reliability", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Review the Connectivity Design between Database and Application, test & validate it", + "description": "There are multiple ways to connect your application to the managed instance. Review and understand the pros and cons and decide on the best approach for your application.", + "waf": "Operations", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Plan for the Migration Method. Depending on the DB Size and Application downtime window, select the preferred Migration Method.", + "description": "Compare migration options to choose the path that's appropriate to your business needs.", + "waf": "Operations", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Pre Migration", + "text": "Plan the cutover process with business / application teams to ensure minimal interruption during cutover and it does not affect business continuity.", + "description": "After you verify that data is the same on both source and target, you can cut over from the source to the target environment. It's important to plan the cutover process with business / application teams to ensure minimal interruption during cutover doesn't affect business continuity.", + "waf": "Reliability", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Deployment", + "text": "Ensure you customize your time zone setting at the instance creation time. One cannot change it later.", + "description": "A time zone of a managed instance can be set during instance creation only. The default time zone is UTC", + "waf": "Operations", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "severity": "High", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Deployment", + "text": "Ensure you select the right collation setting at the instance creation time. One cannot change it later", + "description": "Server-level collation in Azure SQL Managed Instance can be specified when the instance is created and cannot be changed later.Default server-level collation is SQL_Latin1_General_CP1_CI_AS.", + "waf": "Operations", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "severity": "High", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Deployment", + "text": "For TDE Enabled Database, corresponding certificate from the on-premises or Azure VM SQL Server needs to be migrated before database restore", + "description": "When you're migrating a database protected by Transparent Data Encryption (TDE) to Azure SQL Managed Instance using the native restore option, the corresponding certificate from the SQL Server instance needs to be migrated before database restore.", + "waf": "Operations", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Migration", + "text": "Restore of system databases is not supported. To migrate instance-level objects (stored in master or msdb databases), we recommend to script them out and run T-SQL scripts on the destination instance.", + "description": "System databases can be restored only from backups that are created on the version of SQL Server that the server instance is currently running. This is not the case when you are migrating to SQL Managed Instance.Azure PowerShell and DBATools PowerShell libraries enable you to easily script and automate and customize all parts of the migration process.", + "waf": "Operations", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Migration", + "text": "Ensure that all changes on the source are captured and applied to the target during the migration process.", + "description": "When using migration options that continuously replicate / sync data changes from source to the target, the source data and schema can change and drift from the target. During data sync, ensure that all changes on the source are captured and applied to the target during the migration process.", + "waf": "Operations", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", + "severity": "High" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Migration", + "text": "Test Application Connectivity to MI and Databases", + "description": "Ensure that the application is able to succesffuly connect to the managed instance post migration of the databases.", + "waf": "Operations", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Consider executing a manual failover on SQL Managed Instance to test for fault and failover resiliency.", + "description": "High availability is a fundamental part of SQL Managed Instance platform that works transparently for your database applications. Failovers from primary to secondary nodes in case of node degradation or fault detection, or during regular monthly software updates are an expected occurrence for all applications using SQL Managed Instance in Azure.", + "waf": "Reliability", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "severity": "High", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "If failover groups have been implemented, Test Manual Failover and Failback and test application connectivity behavior during failover/failback", + "description": "Ensuring that your applications are failover resilient prior to deploying to production will help mitigate the risk of application faults in production and will contribute to application availability for your customers.", + "waf": "Reliability", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Optimize Storage Performance for General Purpose Managed Instance", + "description": "This provides more dedicated disk IOPS and throughput", + "waf": "Performance", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Enable Customer managed TDE for taking your own copy only full backups", + "description": "Many organizations have policies that require that certificates or encryption keys be created and managed internally. If your organization has a similar policy, this architecture might apply to you. If your customers require internal management of these items, the architecture also might apply to you.", + "waf": "Security", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Plan for Azure maintenance events", + "description": "The maintenance window feature provides you with the ability to onboard Azure SQL resource to prescheduled time blocks outside of business hours.", + "waf": "Operations", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Configure Long Term backup retention, view backups and restore from backups", + "description": "By using the long-term retention (LTR) feature, you can store specified SQL Database and SQL Managed Instance full backups in Azure Blob storage with configured redundancy for up to 10 years.", + "waf": "Reliability", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Take advantage of Azure Hybrid Benefit and Azure Reservations where applicable.", + "description": "By using Azure Hybrid Benefit, you can achieve cost savings, modernise and maintain a flexible hybrid environment while optimising business applications.", + "waf": "Cost", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview" + }, + { + "category": "SQL Managed Instance", + "subcategory": "Post Migration", + "text": "Leverage Microsoft Defender for Cloud to improve the overall security posture", + "description": "If you don't have threat protection Advanced Threat Protection is part of the Microsoft Defender for SQL offering, which is a unified package for advanced SQL security capabilities.", + "waf": "Security", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql" + } + ], + "categories": [ + { + "name": "SQL Server on Azure VM" + }, + { + "name": "SQL Managed Instance" + } + ], + "waf": [ + { + "name": "Reliability" + }, + { + "name": "Security" + }, + { + "name": "Cost" + }, + { + "name": "Operations" + }, + { + "name": "Performance" + } + ], + "yesno": [ + { + "name": "Yes" + }, + { + "name": "No" + } + ], + "status": [ + { + "name": "Not verified", + "description": "This check has not been looked at yet" + }, + { + "name": "Open", + "description": "There is an action item associated to this check" + }, + { + "name": "Fulfilled", + "description": "This check has been verified, and there are no further action items associated to it" + }, + { + "name": "Not required", + "description": "Recommendation understood, but not needed by current requirements" + }, + { + "name": "N/A", + "description": "Not applicable for current design" + } + ], + "severities": [ + { + "name": "High" + }, + { + "name": "Medium" + }, + { + "name": "Low" + } + ], + "metadata": { + "name": "SQL Migration Review", + "state": "Preview", + "timestamp": "December 13, 2023" } - ], - "categories": [ - { - "name": "SQL Server on Azure VM" - }, - { - "name": "SQL Managed Instance" - } - ], - "waf": [ - { - "name": "Reliability" - }, - { - "name": "Security" - }, - { - "name": "Cost" - }, - { - "name": "Operations" - }, - { - "name": "Performance" - } - ], - "yesno": [ - { - "name": "Yes" - }, - { - "name": "No" - } - ], - "status": [ - { - "name": "Not verified", - "description": "This check has not been looked at yet" - }, - { - "name": "Open", - "description": "There is an action item associated to this check" - }, - { - "name": "Fulfilled", - "description": "This check has been verified, and there are no further action items associated to it" - }, - { - "name": "Not required", - "description": "Recommendation understood, but not needed by current requirements" - }, - { - "name": "N/A", - "description": "Not applicable for current design" - } - ], - "severities": [ - { - "name": "High" - }, - { - "name": "Medium" - }, - { - "name": "Low" - } - ], - "metadata": { - "name": "SQL Migration Review", - "state": "Preview", - "timestamp": "December 12, 2023" - } -} - +} \ No newline at end of file diff --git a/checklists/sql_checklist.es.json b/checklists/sql_checklist.es.json new file mode 100644 index 000000000..324327c5d --- /dev/null +++ b/checklists/sql_checklist.es.json @@ -0,0 +1,759 @@ +{ + "categories": [ + { + "name": "SQL Server en máquinas virtuales de Azure" + }, + { + "name": "SQL Managed Instance" + } + ], + "items": [ + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Al crear una máquina virtual de SQL Server en Azure, considere detenidamente el tipo de carga de trabajo necesaria. Si va a migrar un entorno existente, recopile una línea base de rendimiento para determinar los requisitos de máquina virtual de SQL Server en Azure. Si se trata de una nueva máquina virtual, cree la nueva máquina virtual de SQL Server en función de los requisitos del proveedor.", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16", + "severity": "Alto", + "subcategory": "Tamaño de la máquina virtual", + "text": "Recopile las características de rendimiento de la carga de trabajo de destino y utilícelas para determinar el tamaño de máquina virtual adecuado para su empresa.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Los tamaños de máquina virtual optimizados para memoria son un destino principal para las máquinas virtuales de SQL Server y la opción recomendada por Microsoft. Las máquinas virtuales optimizadas para memoria ofrecen proporciones de memoria a CPU más sólidas y opciones de caché de mediana a grande. Considere primero la serie Ebdsv5 para la mayoría de las cargas de trabajo de SQL Server.", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized", + "severity": "Medio", + "subcategory": "Tamaño de la máquina virtual", + "text": "Use tamaños de máquina virtual optimizados para memoria para obtener el mejor rendimiento de las cargas de trabajo de SQL Server.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Para encontrar la configuración más eficaz para las cargas de trabajo de SQL Server en una máquina virtual de Azure, empiece por medir el rendimiento del almacenamiento de la aplicación empresarial. Una vez conocidos los requisitos de almacenamiento, seleccione una máquina virtual que admita las IOPS y el rendimiento necesarios con la relación de memoria a núcleo virtual adecuada.", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements", + "severity": "Medio", + "subcategory": "Almacenamiento", + "text": "Determine los requisitos de ancho de banda y latencia de almacenamiento para los archivos de datos, registro y tempdb de SQL Server antes de elegir el tipo de disco.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Esto proporciona más IOPS de disco dedicado y rendimiento en el nivel de disco y también le permite configurar la configuración de almacenamiento en caché del host de disco de Azure para cada disco en la configuración óptima para ese tipo de datos.", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Coloque los archivos de datos, registro y tempdb en unidades independientes", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Siempre se recomienda un SSD prémium como mínimo para SQL Server con el fin de obtener un mejor rendimiento y una menor latencia. Se recomiendan P30 y P40 porque el almacenamiento en caché de disco no es compatible con discos de 4 TiB y más grandes (P50 y superior) y proporcionan la relación precio-rendimiento óptima", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Para la unidad de datos, utilice discos premium P30 y P40 o más pequeños para garantizar la disponibilidad de la compatibilidad con caché", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Los archivos de registro tienen principalmente operaciones de escritura intensiva. Por lo tanto, no se benefician de la caché de solo lectura. Por lo tanto, evalúe su precio, rendimiento y capacidad y elija el disco de almacenamiento adecuado.", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Para el plan de la unidad de registro para la capacidad y el rendimiento de las pruebas frente al costo mientras se evalúan los discos P30 - P80 premium", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Colocar TempDB en la unidad D puede mejorar el rendimiento. Tenga en cuenta el tamaño requerido y pruebe siempre el rendimiento.", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Medio", + "subcategory": "Almacenamiento", + "text": "Coloque tempdb en la unidad SSD efímera local (D:\\ predeterminada) para la mayoría de las cargas de trabajo de SQL Server que no forman parte de la instancia de clúster de conmutación por error (FCI) después de elegir el tamaño óptimo de máquina virtual.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "La división de datos y disco de registro puede aumentar el ancho de banda. Asegúrese de que el tamaño de la máquina virtual también coincida con el resultado esperado", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Seccione varios discos de datos de Azure mediante Espacios de almacenamiento para aumentar el ancho de banda de E/S", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "La directiva de almacenamiento en caché varía en función del tipo de archivos de datos de SQL Server que se hospedan en la unidad. Habilite el almacenamiento en caché de solo lectura para los discos que hospedan archivos de datos de SQL Server. Las lecturas de la memoria caché serán más rápidas que las lecturas no almacenadas en caché del disco de datos. Establezca la directiva de almacenamiento en caché en Ninguno para los discos que hospedan el registro de transacciones. No hay ninguna ventaja de rendimiento al habilitar el almacenamiento en caché para el disco de registro de transacciones.", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Establezca el almacenamiento en caché del host en solo lectura para los discos de archivos de datos y ninguno para los discos de archivos de registro.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Compruebe que el almacenamiento se encuentra en la misma región que la máquina virtual. Por ejemplo, si la máquina virtual está en el ESTE DE EE. UU. 2, asegúrese de que el almacenamiento esté en el Este de EE. UU. 2.", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Aprovisionamiento de la cuenta de almacenamiento en la misma región que la máquina virtual de SQL Server", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "SQL Server usa extensiones para almacenar datos. Estos tienen un tamaño de 64 KB. Por lo tanto, en un equipo con SQL Server, el tamaño de la unidad de asignación NTFS para hospedar archivos de base de datos SQL debe ser de 64 KB.", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Almacenamiento", + "text": "Formatee el disco de datos para usar un tamaño de bloque de 64 KB (tamaño de unidad de asignación) para todos los archivos de datos colocados en una unidad que no sea la unidad temporal D:\\", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Se recomienda que determine las necesidades y los requisitos de BCDR para asegurarse de que puede cumplir con los SLA del entorno.", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions", + "severity": "Medio", + "subcategory": "HADR", + "text": "Determine los requisitos de alta disponibilidad y recuperación ante desastres para cada máquina virtual que se va a migrar.", + "waf": "Fiabilidad" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Al desactivar la alta disponibilidad, debe usar conjuntos de disponibilidad o zonas de disponibilidad para evitar interrupciones inesperadas.", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set", + "severity": "Alto", + "subcategory": "HADR", + "text": "Coloque las máquinas virtuales en un conjunto de disponibilidad o en diferentes zonas de disponibilidad.", + "waf": "Fiabilidad" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Opción preferida al implementar un grupo de disponibilidad. La solución recomendada es usar varias subredes al implementar grupos de disponibilidad AlwaysOn.", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli", + "severity": "Medio", + "subcategory": "HADR", + "text": "Implemente las máquinas virtuales de SQL Server en varias subredes siempre que sea posible para evitar la dependencia de Azure Load Balancer o de un nombre de red distribuida (DNN) para enrutar el tráfico a la solución HADR. ( Si se está implementando FCI o AG)", + "waf": "Fiabilidad" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Las características de alta disponibilidad y recuperación ante desastres (HADR), como el grupo de disponibilidad AlwaysOn y la instancia de clúster de conmutación por error, se basan en la tecnología subyacente de clúster de conmutación por error de Windows Server. Revise las prácticas recomendadas para modificar la configuración de HADR para que sea más compatible con el entorno de nube.", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration", + "severity": "Alto", + "subcategory": "HADR", + "text": "Cambie el clúster a parámetros menos agresivos para evitar interrupciones inesperadas debido a errores transitorios de red o mantenimiento de la plataforma Azure. ( Si se está implementando FCI o AG)", + "waf": "Fiabilidad" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Asegúrese de que el quórum esté establecido correctamente para el número de instancias implementadas.", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting", + "severity": "Alto", + "subcategory": "HADR", + "text": "Configure la votación de quórum de clúster para usar 3 o más números impares de votos. No asigne votos a regiones de recuperación ante desastres. ( Si se está implementando FCI o AG)", + "waf": "Fiabilidad" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "En las máquinas virtuales de Azure, los clústeres usan un equilibrador de carga para contener una dirección IP que debe estar en un nodo de clúster a la vez. En esta solución, el equilibrador de carga contiene la dirección IP del agente de escucha del nombre de red virtual (VNN) para el grupo de disponibilidad AlwaysOn cuando las máquinas virtuales de SQL Server están en una sola subred.", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb", + "severity": "Alto", + "subcategory": "HADR", + "text": "Al usar el nombre de red virtual (VNN) y Azure Load Balancer para conectarse a la solución HADR, especifique MultiSubnetFailover = true en la cadena de conexión, incluso si el clúster solo abarca una subred. ( Si se está implementando FCI o AG)", + "waf": "Fiabilidad" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "SQL Server, Azure SQL Database y Azure SQL Managed Instance admiten la compresión de filas y páginas para tablas e índices de almacén de filas, y admiten la compresión de archivado de almacén de columnas y almacén de columnas para tablas e índices de almacén de columnas.", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16", + "severity": "Bajo", + "subcategory": "Servidor SQL", + "text": "Habilite la compresión de páginas de la base de datos cuando corresponda.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "De forma predeterminada, los archivos de datos y de registro se inicializan para sobrescribir los datos existentes que quedan en el disco de los archivos eliminados anteriormente. Los archivos de datos y de registro se inicializan primero poniendo a cero los archivos (rellenándolos con ceros). En SQL Server, solo para archivos de datos, la inicialización instantánea de archivos (IFI) permite una ejecución más rápida de las operaciones de archivo mencionadas anteriormente, ya que recupera el espacio en disco usado sin llenar ese espacio con ceros. En su lugar, el contenido del disco se sobrescribe a medida que se escriben nuevos datos en los archivos.", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16", + "severity": "Alto", + "subcategory": "Servidor SQL", + "text": "Habilite la inicialización instantánea de archivos para archivos de datos.", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Recomendado para obtener el mejor rendimiento y disponibilidad: migrar todas las bases de datos a discos de datos y de registro", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16", + "severity": "Medio", + "subcategory": "Servidor SQL", + "text": "Mueva todas las bases de datos a discos de datos, incluidas las bases de datos del sistema.", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features", + "severity": "Bajo", + "subcategory": "Servidor SQL", + "text": "Mueva el registro de errores de SQL Server y los directorios de archivos de seguimiento a discos de datos.", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-", + "severity": "Alto", + "subcategory": "Servidor SQL", + "text": "Establezca el límite máximo de memoria de SQL Server para dejar suficiente memoria para el sistema operativo.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows", + "severity": "Alto", + "subcategory": "Servidor SQL", + "text": "Habilite las páginas de bloqueo en la memoria.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store", + "severity": "Bajo", + "subcategory": "Servidor SQL", + "text": "Habilite el Almacén de consultas en todas las bases de datos de SQL Server de producción siguiendo los procedimientos recomendados.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server", + "severity": "Alto", + "subcategory": "Servidor SQL", + "text": "Asegúrese de que se siguen todas las prácticas recomendadas de tempdb.", + "waf": "Rendimiento" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "Alto", + "subcategory": "Servidor SQL", + "text": "Programe trabajos del Agente SQL Server para ejecutar trabajos de DBCC CHECKDB, reorganización de índices, regeneración de índices y actualización de estadísticas.", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Parte de la lista de comprobación de características de SQL Server en el vínculo que se recomienda cuando SQL Server Instance está en una máquina virtual de Azure.", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "Medio", + "subcategory": "Servidor SQL", + "text": "Limitar el crecimiento automático de la base de datos y deshabilitar la reducción automática", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Las máquinas virtuales (VM) de vCPU restringidas son un tipo de máquina virtual en la que el recuento de vCPU se puede restringir a la mitad o a un cuarto del tamaño original de la máquina virtual. Esto permite a los clientes reducir el costo de las licencias de software mientras mantienen la misma memoria, almacenamiento y ancho de banda de E/S", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu", + "severity": "Bajo", + "subcategory": "Optimización de costos", + "text": "Optimice el costo de la licencia de SQL Server con máquinas virtuales de vCPU restringidas", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "Costar" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "La Ventaja híbrida de Azure le permite intercambiar las licencias existentes por tarifas con descuento en Azure SQL Database y Azure SQL Managed Instance. Y", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/", + "severity": "Bajo", + "subcategory": "Optimización de costos", + "text": "Aproveche la ventaja híbrida de Azure para maximizar el valor de sus licencias locales en la nube", + "waf": "Costar" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "La extensión del Agente de IaaS de SQL Server (SqlIaasExtension) se ejecuta en SQL Server en máquinas virtuales (VM) Windows de Azure para automatizar las tareas de administración y administración.", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli", + "severity": "Medio", + "subcategory": "Celeste", + "text": "Regístrese con la extensión del agente de IaaS de SQL para desbloquear una serie de ventajas de características.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Las redes aceleradas proporcionan una latencia de red ultrabaja constante a través del hardware y las tecnologías programables internos de Azure", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "severity": "Alto", + "subcategory": "Celeste", + "text": "Asegúrese de que las redes aceleradas estén habilitadas en la máquina virtual.", + "waf": "Operaciones" + }, + { + "category": "SQL Server en máquinas virtuales de Azure", + "description": "Microsoft Defender detecta actividades anómalas que indican intentos inusuales y potencialmente dañinos de acceder a bases de datos o explotar bases de datos en el servidor SQL.", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", + "severity": "Alto", + "subcategory": "Celeste", + "text": "Aproveche Microsoft Defender for Cloud para mejorar la posición de seguridad general de la implementación de máquinas virtuales.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Seguridad" + }, + { + "category": "SQL Managed Instance", + "description": "Hay algunas limitaciones de PaaS que se introducen en SQL Managed Instance y algunos cambios de comportamiento en comparación con SQL Server. Es importante revisar y comprender estas diferencias.", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Revisión de las principales diferencias entre SQL Server e Instancia administrada", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance tiene características y límites de recursos que dependen de la infraestructura y la arquitectura subyacentes. Es importante revisar estos límites.", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Revisión de los límites de capacidad de SQL MI", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "Rendimiento" + }, + { + "category": "SQL Managed Instance", + "description": "La configuración de instancia entre la instancia administrada y el SQL Server de origen puede ser diferente. Es importante revisar las diferencias que pueden afectar al rendimiento.", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Compare la configuración de instancia en SQL Server y Azure SQL MI que puede afectar al rendimiento", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "Rendimiento" + }, + { + "category": "SQL Managed Instance", + "description": "Evalúe las instancias de SQL Server locales que migran a Azure SQL Managed Instance. El flujo de trabajo de evaluación le ayuda a detectar problemas que bloquean la migración en sí y también características parcialmente admitidas y no admitidas", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Ejecute el Asistente para migración de datos o la extensión de migración de Azure Data Studio para detectar problemas de compatibilidad que pueden afectar a la funcionalidad de la base de datos en Instancia administrada", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "La característica de recomendación de SKU puede evaluar el rendimiento y las características de uso de SQL Server de origen para recomendar una instancia de Azure SQL Managed Instance del tamaño adecuado para ayudar con el recorrido de migración.", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Seleccione los recursos informáticos adecuados para su carga de trabajo aprovechando las herramientas de recomendación de SKU.", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "Rendimiento" + }, + { + "category": "SQL Managed Instance", + "description": "Revise las características no admitidas, los bloqueadores de migración y los cambios importantes para cada base de datos de la evaluación", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Revisión y solución de los problemas resaltados en DMA/Azure Data Studio", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "La zona DNS predeterminada de SQL Managed Instance .database.windows.net se puede cambiar por la suya propia. Sin embargo, la parte del nombre de host de la instancia administrada de su FQDN debe seguir siendo la misma.", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Planear los cambios en la cadena de conexión, ya que no se admite el cambio de un nombre de instancia administrada", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Existen requisitos adicionales en la configuración de una red virtual y una subred que hospeda la instancia administrada.", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi", + "severity": "Medio", + "subcategory": "Pre Migración", + "text": "Revisión de los requisitos de red virtual de la instancia administrada", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Aunque es posible implementar instancias administradas en una subred con un número de direcciones IP menor que el resultado de la fórmula de subred, considere siempre la posibilidad de usar subredes más grandes en su lugar. El uso de una subred más grande puede ayudar a evitar problemas futuros derivados de la falta de direcciones IP, como la imposibilidad de crear instancias adicionales dentro de la subred o escalar las instancias existentes.", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi", + "severity": "Alto", + "subcategory": "Despliegue", + "text": "Asegúrese de que la subred de la instancia administrada tenga suficientes direcciones IP disponibles", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance tiene características y límites de recursos que dependen de la infraestructura y la arquitectura subyacentes. SQL Managed Instance se puede implementar en varias configuraciones de hardware.", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "Planifique entre los niveles de MI de uso general y crítico para el negocio", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "Rendimiento" + }, + { + "category": "SQL Managed Instance", + "description": "La característica de grupos de conmutación por error automática permite administrar la replicación y la conmutación por error de las bases de datos de usuario de una instancia administrada a una instancia administrada de otra región de Azure. Los grupos de conmutación por error automática están diseñados para simplificar la implementación y la administración de bases de datos con replicación geográfica a escala.", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell", + "severity": "Alto", + "subcategory": "Pre Migración", + "text": "En función de su RPO/RTO, determine si es necesario implementar el grupo de conmutación por error automática. Si es así, planifique los atributos de implementación de la segunda instancia.", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "Fiabilidad" + }, + { + "category": "SQL Managed Instance", + "description": "Hay varias formas de conectar la aplicación a la instancia administrada. Revise y comprenda los pros y los contras y decida cuál es el mejor enfoque para su aplicación.", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "Bajo", + "subcategory": "Pre Migración", + "text": "Revise el diseño de conectividad entre la base de datos y la aplicación, pruébelo y valídelo", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Compare las opciones de migración para elegir la ruta que mejor se adapte a las necesidades de su empresa.", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools", + "severity": "Medio", + "subcategory": "Pre Migración", + "text": "Planear el método de migración. En función del tamaño de la base de datos y de la ventana de tiempo de inactividad de la aplicación, seleccione el método de migración preferido.", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Después de comprobar que los datos son los mismos tanto en el origen como en el destino, puede pasar del entorno de origen al de destino. Es importante planificar el proceso de transición con los equipos de negocios/aplicaciones para garantizar que la interrupción mínima durante la transición no afecte la continuidad del negocio.", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover", + "severity": "Medio", + "subcategory": "Pre Migración", + "text": "Planifique el proceso de transición con los equipos de negocios/aplicaciones para garantizar una interrupción mínima durante la transición y que no afecte la continuidad del negocio.", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "Fiabilidad" + }, + { + "category": "SQL Managed Instance", + "description": "La zona horaria de una instancia administrada solo se puede establecer durante la creación de la instancia. La zona horaria predeterminada es UTC", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone", + "severity": "Alto", + "subcategory": "Despliegue", + "text": "Asegúrese de personalizar la configuración de la zona horaria en el momento de la creación de la instancia. No se puede cambiar después.", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "La intercalación de nivel de servidor en Azure SQL Managed Instance se puede especificar cuando se crea la instancia y no se puede cambiar más adelante. La intercalación predeterminada de nivel de servidor es SQL_Latin1_General_CP1_CI_AS.", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16", + "severity": "Alto", + "subcategory": "Despliegue", + "text": "Asegúrese de seleccionar la configuración de intercalación correcta en el momento de la creación de la instancia. No se puede cambiar más tarde", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Al migrar una base de datos protegida por el cifrado de datos transparente (TDE) a Azure SQL Managed Instance mediante la opción de restauración nativa, es necesario migrar el certificado correspondiente de la instancia de SQL Server antes de la restauración de la base de datos.", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell", + "severity": "Medio", + "subcategory": "Despliegue", + "text": "En el caso de la base de datos habilitada para TDE, es necesario migrar el certificado correspondiente de la máquina virtual local o de Azure SQL Server antes de la restauración de la base de datos", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Las bases de datos del sistema solo se pueden restaurar a partir de copias de seguridad creadas en la versión de SQL Server que la instancia de servidor está ejecutando actualmente. Este no es el caso cuando se migra a SQL Managed Instance.Las bibliotecas de PowerShell y PowerShell de Azure PowerShell y DBATools permiten crear scripts, automatizar y personalizar fácilmente todas las partes del proceso de migración.", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore", + "severity": "Bajo", + "subcategory": "Migración", + "text": "No se admite la restauración de bases de datos del sistema. Para migrar objetos de nivel de instancia (almacenados en bases de datos master o msdb), se recomienda crear scripts de ellos y ejecutar scripts de T-SQL en la instancia de destino.", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Cuando se utilizan opciones de migración que replican o sincronizan continuamente los cambios de datos del origen al destino, los datos y el esquema de origen pueden cambiar y desviarse del destino. Durante la sincronización de datos, asegúrese de que todos los cambios en el origen se capturan y aplican al destino durante el proceso de migración.", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", + "severity": "Alto", + "subcategory": "Migración", + "text": "Asegúrese de que todos los cambios en el origen se capturan y aplican al destino durante el proceso de migración.", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Asegúrese de que la aplicación pueda conectarse correctamente a la instancia administrada después de la migración de las bases de datos.", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "Medio", + "subcategory": "Migración", + "text": "Probar la conectividad de la aplicación con MI y bases de datos", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "La alta disponibilidad es una parte fundamental de la plataforma de SQL Managed Instance que funciona de forma transparente para las aplicaciones de base de datos. Las conmutaciones por error de los nodos principales a los secundarios en caso de degradación de nodos o detección de errores, o durante las actualizaciones de software mensuales periódicas son una ocurrencia esperada para todas las aplicaciones que usan SQL Managed Instance en Azure.", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql", + "severity": "Alto", + "subcategory": "Después de la migración", + "text": "Considere la posibilidad de ejecutar una conmutación por error manual en SQL Managed Instance para probar la resistencia a errores y conmutación por error.", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "Fiabilidad" + }, + { + "category": "SQL Managed Instance", + "description": "Asegurarse de que las aplicaciones sean resistentes a la conmutación por error antes de implementarlas en producción ayudará a mitigar el riesgo de errores de las aplicaciones en producción y contribuirá a la disponibilidad de las aplicaciones para los clientes.", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover", + "severity": "Alto", + "subcategory": "Después de la migración", + "text": "Si se han implementado grupos de conmutación por error, pruebe la conmutación por error manual y la conmutación por recuperación y pruebe el comportamiento de conectividad de la aplicación durante la conmutación por error o la conmutación por recuperación", + "waf": "Fiabilidad" + }, + { + "category": "SQL Managed Instance", + "description": "Esto proporciona más IOPS de disco dedicado y rendimiento", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525", + "severity": "Alto", + "subcategory": "Después de la migración", + "text": "Optimización del rendimiento del almacenamiento para instancias administradas de uso general", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Rendimiento" + }, + { + "category": "SQL Managed Instance", + "description": "Muchas organizaciones tienen directivas que requieren que los certificados o las claves de cifrado se creen y administren internamente. Si su organización tiene una directiva similar, es posible que esta arquitectura se aplique a usted. Si sus clientes requieren la administración interna de estos elementos, es posible que la arquitectura también se aplique a usted.", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk", + "severity": "Bajo", + "subcategory": "Después de la migración", + "text": "Habilitación del TDE administrado por el cliente para realizar copias de seguridad completas solo de su propia copia", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Seguridad" + }, + { + "category": "SQL Managed Instance", + "description": "La característica de ventana de mantenimiento proporciona la capacidad de incorporar recursos de Azure SQL a bloques de tiempo programados previamente fuera del horario comercial.", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql", + "severity": "Medio", + "subcategory": "Después de la migración", + "text": "Planeación de eventos de mantenimiento de Azure", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operaciones" + }, + { + "category": "SQL Managed Instance", + "description": "Mediante el uso de la característica de retención a largo plazo (LTR), puede almacenar copias de seguridad completas de SQL Database y SQL Managed Instance especificadas en Azure Blob Storage con redundancia configurada durante un máximo de 10 años.", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi", + "severity": "Bajo", + "subcategory": "Después de la migración", + "text": "Configure la retención de copias de seguridad a largo plazo, vea las copias de seguridad y restaure a partir de copias de seguridad", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "Fiabilidad" + }, + { + "category": "SQL Managed Instance", + "description": "Con la Ventaja híbrida de Azure, puede ahorrar costos, modernizar y mantener un entorno híbrido flexible a la vez que optimiza las aplicaciones empresariales.", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview", + "severity": "Bajo", + "subcategory": "Después de la migración", + "text": "Aproveche la Ventaja híbrida de Azure y las reservas de Azure cuando corresponda.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "Costar" + }, + { + "category": "SQL Managed Instance", + "description": "Si no tiene protección contra amenazas, Advanced Threat Protection forma parte de la oferta de Microsoft Defender para SQL, que es un paquete unificado para funcionalidades avanzadas de seguridad de SQL.", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql", + "severity": "Medio", + "subcategory": "Después de la migración", + "text": "Aproveche Microsoft Defender for Cloud para mejorar la posición de seguridad general", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Seguridad" + } + ], + "metadata": { + "name": "SQL Migration Review", + "state": "Preview", + "timestamp": "December 13, 2023" + }, + "severities": [ + { + "name": "Alto" + }, + { + "name": "Medio" + }, + { + "name": "Bajo" + } + ], + "status": [ + { + "description": "Esta comprobación aún no se ha examinado", + "name": "No verificado" + }, + { + "description": "Hay un elemento de acción asociado a esta comprobación", + "name": "Abrir" + }, + { + "description": "Esta comprobación se ha verificado y no hay más elementos de acción asociados a ella", + "name": "Cumplido" + }, + { + "description": "Recomendación entendida, pero no necesaria por los requisitos actuales", + "name": "No es necesario" + }, + { + "description": "No aplicable para el diseño actual", + "name": "N/A" + } + ], + "waf": [ + { + "name": "Fiabilidad" + }, + { + "name": "Seguridad" + }, + { + "name": "Costar" + }, + { + "name": "Operaciones" + }, + { + "name": "Rendimiento" + } + ], + "yesno": [ + { + "name": "Sí" + }, + { + "name": "No" + } + ] +} \ No newline at end of file diff --git a/checklists/sql_checklist.ja.json b/checklists/sql_checklist.ja.json new file mode 100644 index 000000000..f8d9a4d75 --- /dev/null +++ b/checklists/sql_checklist.ja.json @@ -0,0 +1,759 @@ +{ + "categories": [ + { + "name": "Azure VM 上の SQL Server" + }, + { + "name": "SQL Managed Instance" + } + ], + "items": [ + { + "category": "Azure VM 上の SQL Server", + "description": "Azure VM 上に SQL Server を作成する場合は、必要なワークロードの種類を慎重に検討してください。既存の環境を移行する場合は、パフォーマンス ベースラインを収集して、Azure VM 上の SQL Server の要件を決定します。これが新しい VM の場合は、ベンダーの要件に基づいて新しい SQL Server VM を作成します。", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16", + "severity": "高い", + "subcategory": "VM サイズ", + "text": "ターゲット ワークロードのパフォーマンス特性を収集し、それらを使用してビジネスに適した VM サイズを決定します。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "メモリ最適化仮想マシンのサイズは、SQL Server VM の主要なターゲットであり、Microsoft が推奨する選択肢です。メモリ最適化仮想マシンは、より強力なメモリと CPU の比率と、中規模から大規模のキャッシュ オプションを提供します。ほとんどの SQL Server ワークロードでは、最初に Ebdsv5 シリーズ シリーズを検討してください。", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized", + "severity": "中程度", + "subcategory": "VM サイズ", + "text": "メモリ最適化された仮想マシン サイズを使用して、SQL Server ワークロードのパフォーマンスを最大にします。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "Azure VM 上の SQL Server ワークロードの最も効果的な構成を見つけるには、まず、ビジネス アプリケーションのストレージ パフォーマンスを測定します。ストレージ要件がわかったら、適切なメモリと仮想コアの比率で必要な IOPS とスループットをサポートする仮想マシンを選択します。", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements", + "severity": "中程度", + "subcategory": "貯蔵", + "text": "ディスクの種類を選択する前に、SQL Server のデータ ファイル、ログ ファイル、および tempdb ファイルのストレージ帯域幅と待機時間の要件を決定します。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "これにより、ディスク レベルでより専用のディスク IOPS とスループットが提供され、各ディスクの Azure ディスク ホスト キャッシュ設定をそのデータ型に最適な設定に構成することもできます。", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "データ、ログ、および tempdb ファイルを別々のドライブに配置する", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "Premium SSD は、パフォーマンスの向上と待機時間の短縮を実現するために、SQL Server の最小要件として常に推奨されます。P30 と P40 は、ディスク 4 TiB 以上 (P50 以上) のディスク キャッシュではサポートされておらず、最適な価格対性能比を提供するためです", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "データ ドライブの場合は、Premium P30 および P40 以下のディスクを使用して、キャッシュ サポートの可用性を確保します", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "ログ ファイルには、主に書き込み負荷の高い操作があります。そのため、ReadOnly キャッシュの恩恵を受けません。したがって、価格、パフォーマンス、容量を評価し、適切なストレージディスクを選択してください。", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "Premium P30 - P80 ディスクを評価する際の容量とテストのパフォーマンスとコストのログ ドライブ計画の場合", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "TempDB を D ドライブに配置すると、パフォーマンスが向上します。必要なサイズを検討し、常にパフォーマンスをテストしてください。", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "中程度", + "subcategory": "貯蔵", + "text": "最適な VM サイズを選択した後、フェールオーバー クラスター インスタンス (FCI) の一部ではないほとんどの SQL Server ワークロードでは、ローカルのエフェメラル SSD (既定値は D:\\) ドライブに tempdb を配置します。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "データディスクとログディスクをストライピングすると、帯域幅を増やすことができます。VM のサイズも予想される出力と一致していることを確認します", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "記憶域スペースを使用して複数の Azure データ ディスクをストライピングし、I/O 帯域幅を増やす", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "記憶域キャッシュ ポリシーは、ドライブでホストされている SQL Server データ ファイルの種類によって異なります。SQL Server データ ファイルをホストしているディスクの読み取り専用キャッシュを有効にします。キャッシュからの読み取りは、データ ディスクからのキャッシュされていない読み取りよりも高速になります。トランザクション ログをホストしているディスクのキャッシュ ポリシーを [なし] に設定します。トランザクション ログ ディスクのキャッシュを有効にしても、パフォーマンス上の利点はありません。", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "ホスト・キャッシュを、データ・ファイル・ディスクの場合は読み取り専用に設定し、ログ・ファイル・ディスクの場合はなしに設定します。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "ストレージが VM と同じリージョンにあることを確認します。たとえば、VM が米国東部 2 にある場合は、ストレージが米国東部 2 にあることを確認します。", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "SQL Server VM と同じリージョンにストレージ アカウントをプロビジョニングするProvision the storage account in the same region as the SQL Server VM", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server は、エクステントを使用してデータを格納します。これらのサイズは 64 KB です。したがって、SQL Server マシンでは、SQL データベース ファイルをホストするための NTFS アロケーション ユニット サイズは 64 KB である必要があります。", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高い", + "subcategory": "貯蔵", + "text": "一時 D:\\ ドライブ以外のドライブに配置されたすべてのデータ ファイルに対して 64 KB のブロック サイズ (アロケーション ユニット サイズ) を使用するようにデータ ディスクをフォーマットします", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "BCDR のニーズと要件を決定し、環境の SLA を満たすことができるようにすることをお勧めします。", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions", + "severity": "中程度", + "subcategory": "ハドル", + "text": "移行する各 VM の HA/DR 要件を決定します。", + "waf": "確実" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "高可用性を無効にする場合は、予期しない停止を回避するために、可用性セットまたは可用性ゾーンを使用する必要があります。", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set", + "severity": "高い", + "subcategory": "ハドル", + "text": "VM を可用性セットまたは異なる可用性ゾーンに配置します。", + "waf": "確実" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "可用性グループをデプロイするときに推奨されるオプション。推奨される解決策は、Always on 可用性グループをデプロイするときにマルチサブネットを使用することです。", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli", + "severity": "中程度", + "subcategory": "ハドル", + "text": "可能な限り SQL Server VM を複数のサブネットにデプロイして、トラフィックを HADR ソリューションにルーティングするための Azure Load Balancer または分散ネットワーク名 (DNN) への依存を回避します。(FCIまたはAGを実装している場合)", + "waf": "確実" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "高可用性とディザスター リカバリー (HADR) 機能 (Always On 可用性グループやフェールオーバー クラスター インスタンスなど) は、基になる Windows Server フェールオーバー クラスター テクノロジに依存しています。クラウド環境をより適切にサポートするために HADR 設定を変更するためのベスト・プラクティスを確認します。", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration", + "severity": "高い", + "subcategory": "ハドル", + "text": "クラスターをアグレッシブでないパラメーターに変更して、一時的なネットワーク障害や Azure プラットフォームのメンテナンスによる予期しない停止を回避します。(FCIまたはAGを実装している場合)", + "waf": "確実" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "クォーラムがデプロイされたインスタンスの数に対して正しく設定されていることを確認します。", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting", + "severity": "高い", + "subcategory": "ハドル", + "text": "クラスター クォーラム投票を構成して、3 つ以上の奇数票を使用します。DR リージョンに投票を割り当てないでください。(FCIまたはAGを実装している場合)", + "waf": "確実" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "Azure 仮想マシンでは、クラスターはロード バランサーを使用して、一度に 1 つのクラスター ノード上に存在する必要がある IP アドレスを保持します。このソリューションでは、SQL Server VM が 1 つのサブネット内にある場合、ロード バランサーは Always On 可用性グループの仮想ネットワーク名 (VNN) リスナーの IP アドレスを保持します。", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb", + "severity": "高い", + "subcategory": "ハドル", + "text": "仮想ネットワーク名 (VNN) と Azure Load Balancer を使用して HADR ソリューションに接続する場合は、クラスターが 1 つのサブネットにしかまたがっていない場合でも、接続文字列で MultiSubnetFailover = true を指定します。(FCIまたはAGを実装している場合)", + "waf": "確実" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server、Azure SQL Database、Azure SQL Managed Instance では、行ストア テーブルとインデックスの行とページの圧縮がサポートされており、列ストア テーブルとインデックスの列ストアと列ストアのアーカイブ圧縮がサポートされています。", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16", + "severity": "低い", + "subcategory": "SQL Serverの", + "text": "必要に応じて、データベース・ページ圧縮を有効にします。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "既定では、データ ファイルとログ ファイルは、以前に削除されたファイルからディスクに残っている既存のデータを上書きするように初期化されます。データ ファイルとログ ファイルは、最初にファイルをゼロにする (ゼロで埋める) ことによって初期化されます。SQL Server では、データ ファイルの場合のみ、ファイルの瞬時初期化 (IFI) を使用すると、使用済みのディスク領域をゼロで埋めることなく再利用されるため、前述のファイル操作をより高速に実行できます。代わりに、新しいデータがファイルに書き込まれると、ディスクの内容が上書きされます。", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16", + "severity": "高い", + "subcategory": "SQL Serverの", + "text": "データファイルの瞬時ファイル初期化を有効にします。", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "最適なパフォーマンスと可用性を実現するために推奨 すべてのデータベースをデータ ディスクとログ ディスクに移行する", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16", + "severity": "中程度", + "subcategory": "SQL Serverの", + "text": "システム データベースを含むすべてのデータベースをデータ ディスクに移動します。", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features", + "severity": "低い", + "subcategory": "SQL Serverの", + "text": "SQL Server のエラー ログとトレース ファイルのディレクトリをデータ ディスクに移動します。", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-", + "severity": "高い", + "subcategory": "SQL Serverの", + "text": "SQL Server の最大メモリ制限を設定して、オペレーティング システムに十分なメモリを残します。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows", + "severity": "高い", + "subcategory": "SQL Serverの", + "text": "メモリ内のロック ページを有効にします。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store", + "severity": "低い", + "subcategory": "SQL Serverの", + "text": "ベスト プラクティスに従って、すべての運用 SQL Server データベースでクエリ ストアを有効にします。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server", + "severity": "高い", + "subcategory": "SQL Serverの", + "text": "tempdb のすべてのベスト プラクティスに従っていることを確認します。", + "waf": "パフォーマンス" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "高い", + "subcategory": "SQL Serverの", + "text": "SQL Server エージェント ジョブをスケジュールして、DBCC CHECKDB、インデックスの再編成、インデックスの再構築、および統計の更新ジョブを実行します。", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server インスタンスが Azure VM 内にある場合に推奨されるリンクの SQL Server 機能チェックリストの一部。", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "中程度", + "subcategory": "SQL Serverの", + "text": "データベースの自動拡張を制限し、自動圧縮を無効にする", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "制約付き vCPU 仮想マシン (VM) は、vCPU 数を元の VM サイズの半分または 4 分の 1 に制限できる VM の一種です。これにより、お客様は同じメモリ、ストレージ、およびI/O帯域幅を維持しながら、ソフトウェアライセンスのコストを削減できます", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu", + "severity": "低い", + "subcategory": "コストの最適化", + "text": "制約付き vCPU VM による SQL Server ライセンス コストの最適化", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "費用" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "Azure ハイブリッド特典を使用すると、既存のライセンスを Azure SQL Database と Azure SQL Managed Instance の割引料金に交換できます。Y", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/", + "severity": "低い", + "subcategory": "コストの最適化", + "text": "Azure ハイブリッド特典を活用して、クラウドのオンプレミス ライセンスの価値を最大化します", + "waf": "費用" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "SQL Server IaaS Agent 拡張機能 (SqlIaasExtension) は、Azure Windows 仮想マシン (VM) 上の SQL Server 上で実行され、管理タスクを自動化します。", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli", + "severity": "中程度", + "subcategory": "紺碧", + "text": "SQL IaaS Agent 拡張機能に登録すると、さまざまな機能の利点を享受できます。", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "高速ネットワークは、Azure の社内でプログラム可能なハードウェアとテクノロジを介して、一貫した超低ネットワーク待機時間を提供します", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "severity": "高い", + "subcategory": "紺碧", + "text": "仮想マシンで高速ネットワークが有効になっていることを確認します。", + "waf": "オペレーションズ" + }, + { + "category": "Azure VM 上の SQL Server", + "description": "Microsoft Defender は、SQL Server 上のデータベースにアクセスしたり、データベースを悪用したりしようとする、通常とは異なる、害を及ぼす可能性のある試みを示す異常なアクティビティを検出します。", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", + "severity": "高い", + "subcategory": "紺碧", + "text": "Microsoft Defender for Cloud を活用して、仮想マシンのデプロイの全体的なセキュリティ体制を改善します。", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "安全" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance には、いくつかの PaaS の制限と、SQL Server と比較していくつかの動作の変更があります。これらの違いを確認して理解することが重要です。", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql", + "severity": "高い", + "subcategory": "移行前", + "text": "SQL Server と Managed Instance の主な違いを確認する", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance には、基になるインフラストラクチャとアーキテクチャに依存する特性とリソース制限があります。これらの制限を確認することが重要です。", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits", + "severity": "高い", + "subcategory": "移行前", + "text": "SQL MI の容量制限を確認する", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "パフォーマンス" + }, + { + "category": "SQL Managed Instance", + "description": "マネージド インスタンスとソース SQL Server のインスタンス設定は異なる場合があります。パフォーマンスに影響を与える可能性のある違いを確認することが重要です。", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08", + "severity": "高い", + "subcategory": "移行前", + "text": "パフォーマンスに影響を与える可能性のある SQL Server と Azure SQL MI のインスタンス設定を比較する", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "パフォーマンス" + }, + { + "category": "SQL Managed Instance", + "description": "Azure SQL Managed Instance に移行するオンプレミスの SQL Server インスタンスを評価します。評価ワークフローは、移行自体をブロックする問題や、部分的にサポートされている機能とサポートされていない機能を検出するのに役立ちます", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "高い", + "subcategory": "移行前", + "text": "Data Migration Assistant または Azure Data Studio Migration Extension を実行して、Managed Instance のデータベース機能に影響を与える可能性のある互換性の問題を検出します", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "SKU レコメンデーション機能では、ソース SQL Server のパフォーマンスと使用率の特性を評価して、移行プロセスを支援する適切なサイズの Azure SQL Managed Instance を推奨できます。", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "高い", + "subcategory": "移行前", + "text": "ワークロードに適したコンピューティング リソースを選択するには、SKU レコメンデーション ツールを活用します。", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "パフォーマンス" + }, + { + "category": "SQL Managed Instance", + "description": "評価から各データベースのサポートされていない機能、移行の阻害要因、破壊的変更を確認する", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "高い", + "subcategory": "移行前", + "text": "DMA/Azure Data Studio で強調表示されている問題を確認して対処する", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance の既定の DNS ゾーン .database.windows.net は、独自のゾーンで変更できます。ただし、FQDN のマネージド インスタンスのホスト名の部分は同じままにする必要があります。", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance", + "severity": "高い", + "subcategory": "移行前", + "text": "マネージド インスタンス名の変更がサポートされていないため、接続文字列の変更を計画する", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "マネージド インスタンスをホストする vnet とサブネットの構成には、追加の要件があります。", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi", + "severity": "中程度", + "subcategory": "移行前", + "text": "マネージド インスタンスの VNet 要件を確認する", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "サブネット式の出力よりも少ない数の IP アドレスを持つサブネットにマネージド インスタンスをデプロイすることは可能ですが、代わりにより大きなサブネットを使用することを常に検討してください。より大きなサブネットを使用すると、サブネット内に追加のインスタンスを作成できない、既存のインスタンスをスケーリングできないなど、IP アドレスの不足に起因する将来の問題を回避できます。", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi", + "severity": "高い", + "subcategory": "配備", + "text": "マネージド インスタンス サブネットに十分な IP アドレスがあることを確認する", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance には、基になるインフラストラクチャとアーキテクチャに依存する特性とリソース制限があります。SQL Managed Instance は、複数のハードウェア構成にデプロイできます。", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics", + "severity": "高い", + "subcategory": "移行前", + "text": "MI の General Purpose レベルと Business Critical レベルの間の計画", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "パフォーマンス" + }, + { + "category": "SQL Managed Instance", + "description": "自動フェールオーバー グループ機能を使用すると、マネージド インスタンス内のユーザー データベースから別の Azure リージョンのマネージド インスタンスへのレプリケーションとフェールオーバーを管理できます。自動フェールオーバー グループは、geo レプリケートされたデータベースの大規模なデプロイと管理を簡略化するように設計されています。", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell", + "severity": "高い", + "subcategory": "移行前", + "text": "RPO/RTO に基づいて、自動フェールオーバー グループを実装する必要があるかどうかを判断します。その場合は、2 番目のインスタンスのデプロイ属性を計画します。", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "確実" + }, + { + "category": "SQL Managed Instance", + "description": "アプリケーションをマネージド インスタンスに接続する方法は複数あります。長所と短所を確認して理解し、アプリケーションに最適なアプローチを決定します。", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "低い", + "subcategory": "移行前", + "text": "データベースとアプリケーション間の接続設計をレビューし、テストと検証を行う", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "移行オプションを比較して、ビジネス ニーズに適したパスを選択します。", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools", + "severity": "中程度", + "subcategory": "移行前", + "text": "移行方法を計画します。[DB サイズ] と [アプリケーションのダウンタイム] ウィンドウに応じて、優先する移行方法を選択します。", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "ソースとターゲットの両方でデータが同じであることを確認したら、ソースからターゲット環境にカットオーバーできます。ビジネス/アプリケーション チームとカットオーバー プロセスを計画して、カットオーバー中の中断がビジネス継続性に影響を与えないようにすることが重要です。", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover", + "severity": "中程度", + "subcategory": "移行前", + "text": "ビジネス/アプリケーションチームと切替プロセスを計画して、切替中の中断を最小限に抑え、ビジネス継続性に影響を与えないようにします。", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "確実" + }, + { + "category": "SQL Managed Instance", + "description": "マネージド インスタンスのタイム ゾーンは、インスタンスの作成時にのみ設定できます。デフォルトのタイムゾーンはUTCです", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone", + "severity": "高い", + "subcategory": "配備", + "text": "インスタンスの作成時にタイムゾーン設定をカスタマイズしてください。後で変更することはできません。", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "Azure SQL Managed Instance のサーバー レベルの照合順序は、インスタンスの作成時に指定でき、後で変更することはできません。既定のサーバー レベルの照合順序は SQL_Latin1_General_CP1_CI_AS です。", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16", + "severity": "高い", + "subcategory": "配備", + "text": "インスタンスの作成時に適切な照合順序設定を選択してください。後で変更することはできません", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "ネイティブ復元オプションを使用して、Transparent Data Encryption (TDE) によって保護されているデータベースを Azure SQL Managed Instance に移行する場合は、データベースの復元前に、SQL Server インスタンスから対応する証明書を移行する必要があります。", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell", + "severity": "中程度", + "subcategory": "配備", + "text": "TDE 対応データベースの場合、データベースを復元する前に、オンプレミスまたは Azure VM SQL Server の対応する証明書を移行する必要があります", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "システム データベースは、サーバー インスタンスが現在実行している SQL Server のバージョンで作成されたバックアップからのみ復元できます。これは、SQL Managed Instance に移行する場合には当てはまりません。Azure PowerShell と DBATools の PowerShell ライブラリを使用すると、移行プロセスのすべての部分を簡単にスクリプト化、自動化、カスタマイズできます。", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore", + "severity": "低い", + "subcategory": "移動", + "text": "システム データベースの復元はサポートされていません。インスタンス レベルのオブジェクト (master または msdb データベースに格納されている) を移行するには、それらをスクリプト化し、移行先インスタンスで T-SQL スクリプトを実行することをお勧めします。", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "ソースからターゲットにデータの変更を継続的にレプリケート/同期する移行オプションを使用する場合、ソース データとスキーマが変更され、ターゲットからドリフトする可能性があります。データ同期中に、移行プロセス中にソース上のすべての変更がキャプチャされ、ターゲットに適用されていることを確認します。", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", + "severity": "高い", + "subcategory": "移動", + "text": "移行プロセス中に、ソース上のすべての変更がキャプチャされ、ターゲットに適用されていることを確認します。", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "データベースの移行後に、アプリケーションがマネージド インスタンスに正常に接続できることを確認します。", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "中程度", + "subcategory": "移動", + "text": "MIおよびデータベースへのアプリケーション接続のテスト", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "高可用性は、データベース アプリケーションに対して透過的に動作する SQL Managed Instance プラットフォームの基本的な部分です。ノードの機能低下や障害検出の場合、または毎月の定期的なソフトウェア更新中に、プライマリ ノードからセカンダリ ノードへのフェールオーバーは、Azure で SQL Managed Instance を使用するすべてのアプリケーションで予期されることです。", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql", + "severity": "高い", + "subcategory": "移行後", + "text": "SQL Managed Instance で手動フェールオーバーを実行して、障害とフェールオーバーの回復性をテストすることを検討してください。", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "確実" + }, + { + "category": "SQL Managed Instance", + "description": "運用環境にデプロイする前に、アプリケーションがフェールオーバーの回復性を備えていることを確認すると、運用環境でのアプリケーション障害のリスクを軽減し、顧客のアプリケーションの可用性に貢献します。", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover", + "severity": "高い", + "subcategory": "移行後", + "text": "フェールオーバー グループが実装されている場合は、手動フェールオーバーとフェールバックをテストし、フェールオーバー/フェールバック中のアプリケーションの接続動作をテストします", + "waf": "確実" + }, + { + "category": "SQL Managed Instance", + "description": "これにより、専用ディスクの IOPS とスループットが向上します", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525", + "severity": "高い", + "subcategory": "移行後", + "text": "汎用マネージド インスタンスのストレージ パフォーマンスを最適化する", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "パフォーマンス" + }, + { + "category": "SQL Managed Instance", + "description": "多くの組織には、証明書または暗号化キーを内部で作成および管理することを要求するポリシーがあります。組織に同様のポリシーがある場合は、このアーキテクチャが適用される可能性があります。顧客がこれらの項目の内部管理を必要とする場合は、アーキテクチャも適用される可能性があります。", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk", + "severity": "低い", + "subcategory": "移行後", + "text": "顧客管理の TDE を有効にして、独自のコピーのみの完全バックアップを作成", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "安全" + }, + { + "category": "SQL Managed Instance", + "description": "メンテナンス期間機能を使用すると、営業時間外に事前にスケジュールされたタイム ブロックに Azure SQL リソースをオンボードできます。", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql", + "severity": "中程度", + "subcategory": "移行後", + "text": "Azure メンテナンス イベントを計画する", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "オペレーションズ" + }, + { + "category": "SQL Managed Instance", + "description": "長期保有 (LTR) 機能を使用すると、指定した SQL Database と SQL Managed Instance の完全バックアップを、最大 10 年間、冗長性が構成された状態で Azure Blob Storage に格納できます。", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi", + "severity": "低い", + "subcategory": "移行後", + "text": "長期バックアップ保持の構成、バックアップの表示、バックアップからの復元", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "確実" + }, + { + "category": "SQL Managed Instance", + "description": "Azure ハイブリッド特典を使用すると、ビジネス アプリケーションを最適化しながら、コスト削減を実現し、柔軟なハイブリッド環境を最新化して維持できます。", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview", + "severity": "低い", + "subcategory": "移行後", + "text": "該当する場合は、Azure ハイブリッド特典と Azure 予約をご利用ください。", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "費用" + }, + { + "category": "SQL Managed Instance", + "description": "脅威の防止がない場合、Advanced Threat Protection は、高度な SQL セキュリティ機能の統合パッケージである Microsoft Defender for SQL オファリングの一部です。", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql", + "severity": "中程度", + "subcategory": "移行後", + "text": "Microsoft Defender for Cloud を活用して全体的なセキュリティ体制を改善する", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "安全" + } + ], + "metadata": { + "name": "SQL Migration Review", + "state": "Preview", + "timestamp": "December 13, 2023" + }, + "severities": [ + { + "name": "高い" + }, + { + "name": "中程度" + }, + { + "name": "低い" + } + ], + "status": [ + { + "description": "このチェックはまだ検討されていません", + "name": "未確認" + }, + { + "description": "このチェックにはアクションアイテムが関連付けられています", + "name": "開ける" + }, + { + "description": "このチェックは検証済みで、これ以上のアクションアイテムは関連付けられていません", + "name": "達成" + }, + { + "description": "推奨事項は理解されているが、現在の要件では不要", + "name": "必要なし" + }, + { + "description": "現在のデザインには適用されません", + "name": "該当なし" + } + ], + "waf": [ + { + "name": "確実" + }, + { + "name": "安全" + }, + { + "name": "費用" + }, + { + "name": "オペレーションズ" + }, + { + "name": "パフォーマンス" + } + ], + "yesno": [ + { + "name": "はい" + }, + { + "name": "いいえ" + } + ] +} \ No newline at end of file diff --git a/checklists/sql_checklist.ko.json b/checklists/sql_checklist.ko.json new file mode 100644 index 000000000..6cf3f8683 --- /dev/null +++ b/checklists/sql_checklist.ko.json @@ -0,0 +1,759 @@ +{ + "categories": [ + { + "name": "Azure VM의 SQL Server" + }, + { + "name": "SQL Managed Instance" + } + ], + "items": [ + { + "category": "Azure VM의 SQL Server", + "description": "Azure VM에서 SQL Server를 만들 때 필요한 워크로드 유형을 신중하게 고려합니다. 기존 환경을 마이그레이션하는 경우 성능 기준을 수집하여 Azure VM의 SQL Server 요구 사항을 확인합니다. 새 VM인 경우 공급업체 요구 사항에 따라 새 SQL Server VM을 만듭니다.", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16", + "severity": "높다", + "subcategory": "VM 크기", + "text": "대상 워크로드의 성능 특성을 수집하고 이를 사용하여 비즈니스에 적합한 VM 크기를 결정합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "메모리 최적화 가상 머신 크기는 SQL Server VM의 기본 대상이며 Microsoft에서 권장하는 선택입니다. 메모리 최적화 가상 머신은 더 강력한 메모리 대 CPU 비율과 중대형 캐시 옵션을 제공합니다. 대부분의 SQL Server 워크로드에 대해 Ebdsv5 시리즈 시리즈를 먼저 고려합니다.", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized", + "severity": "보통", + "subcategory": "VM 크기", + "text": "SQL Server 워크로드의 최상의 성능을 위해 메모리 최적화 가상 머신 크기를 사용합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "Azure VM에서 SQL Server 워크로드에 가장 효과적인 구성을 찾으려면 먼저 비즈니스 애플리케이션의 스토리지 성능을 측정합니다. 스토리지 요구 사항이 알려지면 적절한 메모리 대 vCore 비율로 필요한 IOPS 및 처리량을 지원하는 가상 머신을 선택합니다.", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements", + "severity": "보통", + "subcategory": "보관", + "text": "디스크 유형을 선택하기 전에 SQL Server 데이터, 로그 및 tempdb 파일에 대한 저장소 대역폭 및 대기 시간 요구 사항을 확인합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "이렇게 하면 디스크 수준에서 더 많은 전용 디스크 IOPS 및 처리량이 제공되며 각 디스크에 대한 Azure 디스크 호스트 캐싱 설정을 해당 데이터 형식에 대한 최적의 설정으로 구성할 수도 있습니다.", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "데이터, 로그 및 tempdb 파일을 별도의 드라이브에 배치", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "프리미엄 SSD는 더 나은 성능과 더 짧은 대기 시간을 얻기 위해 항상 SQL Server 최소로 권장됩니다. P30 및 P40은 디스크 캐싱이 4TiB 이상의 디스크(P50 이상)에 대해 지원되지 않으며 최적의 가격 대비 성능 비율을 제공하기 때문에 권장됩니다", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "데이터 드라이브의 경우 프리미엄 P30 및 P40 이하의 디스크를 사용하여 캐시 지원의 가용성을 보장합니다", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "로그 파일에는 주로 쓰기가 많은 작업이 있습니다. 따라서 ReadOnly 캐시의 이점을 얻을 수 없습니다. 따라서 가격 대비 성능 대 용량을 평가하고 올바른 스토리지 디스크를 선택하십시오.", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "프리미엄 P30 - P80 디스크를 평가하는 동안 용량 및 테스트 성능 대 비용에 대한 로그 드라이브 계획", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "D 드라이브에 TempDB를 배치하면 성능에 도움이 될 수 있습니다. 필요한 크기를 고려하고 항상 성능을 테스트합니다.", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "보통", + "subcategory": "보관", + "text": "최적의 VM 크기를 선택한 후 FCI(장애 조치(failover) 클러스터 인스턴스)에 속하지 않는 대부분의 SQL Server 워크로드에 대해 tempdb를 로컬 임시 SSD(기본값 D:\\) 드라이브에 배치합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "데이터 및 로그 디스크를 스트라이핑하면 대역폭이 증가할 수 있습니다. VM 크기도 예상 출력과 일치하는지 확인합니다.", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "저장소 공간을 사용하여 여러 Azure 데이터 디스크를 스트라이프하여 I/O 대역폭 늘리기", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "저장소 캐싱 정책은 드라이브에서 호스팅되는 SQL Server 데이터 파일의 형식에 따라 달라집니다. SQL Server 데이터 파일을 호스트하는 디스크에 대해 읽기 전용 캐싱을 사용하도록 설정합니다. 캐시에서의 읽기는 데이터 디스크에서 캐시되지 않은 읽기보다 빠릅니다. 트랜잭션 로그를 호스팅하는 디스크에 대해 캐싱 정책을 없음으로 설정합니다. 트랜잭션 로그 디스크에 캐싱을 사용하도록 설정해도 성능상의 이점은 없습니다.", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "데이터 파일 디스크의 경우 호스트 캐싱을 읽기 전용으로 설정하고 로그 파일 디스크의 경우 없음으로 설정합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "스토리지가 VM과 동일한 지역에 있는지 확인합니다. 예를 들어 VM이 미국 동부 2에 있는 경우 스토리지가 미국 동부 2에 있는지 확인합니다.", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "SQL Server VM과 동일한 지역에 저장소 계정 프로비전Provision the storage account in the same region as the SQL Server VM", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server는 익스텐트를 사용하여 데이터를 저장합니다. 크기는 64KB입니다. 따라서 SQL Server 컴퓨터에서 SQL 데이터베이스 파일을 호스팅하기 위한 NTFS 할당 단위 크기는 64KB여야 합니다.", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "높다", + "subcategory": "보관", + "text": "임시 D:\\ 드라이브 이외의 드라이브에 있는 모든 데이터 파일에 대해 64KB 블록 크기(할당 단위 크기)를 사용하도록 데이터 디스크를 포맷합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "BCDR 요구 사항 및 요구 사항을 확인하여 환경의 SLA를 충족할 수 있도록 하는 것이 좋습니다.", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions", + "severity": "보통", + "subcategory": "하드르", + "text": "마이그레이션할 각 VM에 대한 HA/DR 요구 사항을 결정합니다.", + "waf": "신뢰도" + }, + { + "category": "Azure VM의 SQL Server", + "description": "고가용성을 제거할 때 예기치 않은 중단을 방지하기 위해 가용성 집합 또는 가용성 영역을 사용해야 합니다.", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set", + "severity": "높다", + "subcategory": "하드르", + "text": "VM을 가용성 집합 또는 다른 가용성 영역에 배치합니다.", + "waf": "신뢰도" + }, + { + "category": "Azure VM의 SQL Server", + "description": "가용성 그룹을 배포할 때 선호되는 옵션입니다. 권장되는 해결 방법은 Always On 가용성 그룹을 배포할 때 다중 서브넷을 사용하는 것입니다.", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli", + "severity": "보통", + "subcategory": "하드르", + "text": "HADR 솔루션으로 트래픽을 라우팅하기 위해 Azure Load Balancer 또는 DNN(분산 네트워크 이름)에 대한 종속성을 방지하기 위해 가능하면 SQL Server VM을 여러 서브넷에 배포합니다. (FCI 또는 AG를 구현하는 경우)", + "waf": "신뢰도" + }, + { + "category": "Azure VM의 SQL Server", + "description": "Always On 가용성 그룹 및 장애 조치(failover) 클러스터 인스턴스와 같은 HADR(고가용성 및 재해 복구) 기능은 기본 Windows Server 장애 조치(failover) 클러스터 기술을 사용합니다. 클라우드 환경을 더 잘 지원하기 위해 HADR 설정을 수정하기 위한 우수 사례를 검토하십시오.", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration", + "severity": "높다", + "subcategory": "하드르", + "text": "일시적인 네트워크 오류 또는 Azure 플랫폼 유지 관리로 인한 예기치 않은 중단을 방지하기 위해 클러스터를 덜 공격적인 매개 변수로 변경합니다. (FCI 또는 AG를 구현하는 경우)", + "waf": "신뢰도" + }, + { + "category": "Azure VM의 SQL Server", + "description": "쿼럼이 배포된 인스턴스 수에 맞게 올바르게 설정되었는지 확인합니다.", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting", + "severity": "높다", + "subcategory": "하드르", + "text": "3개 이상의 홀수 투표를 사용하도록 클러스터 쿼럼 투표를 구성합니다. DR 지역에 투표를 할당하지 마세요. (FCI 또는 AG를 구현하는 경우)", + "waf": "신뢰도" + }, + { + "category": "Azure VM의 SQL Server", + "description": "Azure 가상 머신에서 클러스터는 부하 분산 장치를 사용하여 한 번에 하나의 클러스터 노드에 있어야 하는 IP 주소를 보유합니다. 이 솔루션에서 부하 분산 장치는 SQL Server VM이 단일 서브넷에 있을 때 Always On 가용성 그룹에 대한 VNN(가상 네트워크 이름) 수신기의 IP 주소를 보유합니다.", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb", + "severity": "높다", + "subcategory": "하드르", + "text": "VNN(가상 네트워크 이름) 및 Azure Load Balancer를 사용하여 HADR 솔루션에 연결하는 경우 클러스터가 하나의 서브넷에만 걸쳐 있더라도 연결 문자열에 MultiSubnetFailover = true를 지정합니다. (FCI 또는 AG를 구현하는 경우)", + "waf": "신뢰도" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server, Azure SQL Database 및 Azure SQL Managed Instance는 rowstore 테이블 및 인덱스에 대한 행 및 페이지 압축을 지원하고, columnstore 테이블 및 인덱스에 대한 columnstore 및 columnstore 보관 압축을 지원합니다.", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16", + "severity": "낮다", + "subcategory": "SQL 서버", + "text": "적절한 경우 데이터베이스 페이지 압축을 사용하도록 설정합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "기본적으로 데이터 및 로그 파일은 이전에 삭제된 파일에서 디스크에 남아 있는 기존 데이터를 덮어쓰도록 초기화됩니다. 데이터 및 로그 파일은 먼저 파일을 0으로 설정하여(0으로 채우기) 초기화됩니다. SQL Server에서 데이터 파일에 대해서만 IFI(인스턴트 파일 초기화)를 사용하면 사용된 디스크 공간을 0으로 채우지 않고 회수하므로 앞서 언급한 파일 작업을 더 빠르게 실행할 수 있습니다. 대신 새 데이터가 파일에 기록될 때 디스크 내용을 덮어씁니다.", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16", + "severity": "높다", + "subcategory": "SQL 서버", + "text": "데이터 파일에 대한 즉각적인 파일 초기화를 활성화합니다.", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "최상의 성능 및 가용성을 위해 권장: 모든 데이터베이스를 데이터 및 로그 디스크로 마이그레이션", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16", + "severity": "보통", + "subcategory": "SQL 서버", + "text": "시스템 데이터베이스를 포함하여 모든 데이터베이스를 데이터 디스크로 이동합니다.", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features", + "severity": "낮다", + "subcategory": "SQL 서버", + "text": "SQL Server 오류 로그 및 추적 파일 디렉터리를 데이터 디스크로 이동합니다.", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-", + "severity": "높다", + "subcategory": "SQL 서버", + "text": "최대 SQL Server 메모리 제한을 설정하여 운영 체제에 충분한 메모리를 남겨 둡니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows", + "severity": "높다", + "subcategory": "SQL 서버", + "text": "메모리에서 페이지 잠금을 활성화합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store", + "severity": "낮다", + "subcategory": "SQL 서버", + "text": "모범 사례에 따라 모든 프로덕션 SQL Server 데이터베이스에서 쿼리 저장소를 사용하도록 설정합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server", + "severity": "높다", + "subcategory": "SQL 서버", + "text": "모든 tempdb 모범 사례를 따라야 합니다.", + "waf": "공연" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "높다", + "subcategory": "SQL 서버", + "text": "SQL Server 에이전트 작업을 예약하여 DBCC CHECKDB, 인덱스 재구성, 인덱스 다시 작성 및 통계 업데이트 작업을 실행합니다.", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server 인스턴스가 Azure VM에 있을 때 권장되는 링크에 있는 SQL Server 기능 검사 목록의 일부입니다.", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "보통", + "subcategory": "SQL 서버", + "text": "데이터베이스의 자동 증가를 제한하고 자동 축소 사용 안 함", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "제한된 vCPU VM(가상 머신)은 vCPU 수를 원래 VM 크기의 절반 또는 1/4로 제한할 수 있는 VM 유형입니다. 이를 통해 고객은 소프트웨어 라이선스 비용을 절감하는 동시에 동일한 메모리, 스토리지 및 I/O 대역폭을 유지할 수 있습니다", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu", + "severity": "낮다", + "subcategory": "비용 최적화", + "text": "제한된 vCPU VM을 사용하여 SQL Server 라이선스 비용 최적화", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "비용" + }, + { + "category": "Azure VM의 SQL Server", + "description": "Azure 하이브리드 혜택을 사용하면 기존 라이선스를 Azure SQL Database 및 Azure SQL Managed Instance에서 할인된 가격으로 교환할 수 있습니다. Y", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/", + "severity": "낮다", + "subcategory": "비용 최적화", + "text": "Azure 하이브리드 혜택을 활용하여 클라우드에서 온-프레미스 라이선스의 가치 극대화", + "waf": "비용" + }, + { + "category": "Azure VM의 SQL Server", + "description": "SQL Server IaaS 에이전트 확장(SqlIaasExtension)은 Azure Windows VM(Virtual Machines)의 SQL Server에서 실행되어 관리 작업을 자동화합니다.", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli", + "severity": "보통", + "subcategory": "하늘빛", + "text": "SQL IaaS 에이전트 확장에 등록하여 다양한 기능 혜택을 누리세요.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "가속화된 네트워킹은 Azure의 사내 프로그래밍 가능한 하드웨어 및 기술을 통해 일관되게 매우 짧은 네트워크 대기 시간을 제공합니다", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "severity": "높다", + "subcategory": "하늘빛", + "text": "가상 머신에서 가속화된 네트워킹이 사용하도록 설정되어 있는지 확인합니다.", + "waf": "작업" + }, + { + "category": "Azure VM의 SQL Server", + "description": "Microsoft Defender는 SQL Server 데이터베이스에 액세스하거나 악용하려는 비정상적이고 잠재적으로 유해한 시도를 나타내는 비정상적인 활동을 검색합니다.", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", + "severity": "높다", + "subcategory": "하늘빛", + "text": "클라우드용 Microsoft Defender를 활용하여 가상 머신 배포의 전반적인 보안 태세를 개선합니다.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "안전" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance에 도입된 몇 가지 PaaS 제한 사항과 SQL Server에 비해 일부 동작 변경 사항이 있습니다. 이러한 차이점을 검토하고 이해하는 것이 중요합니다.", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "SQL Server와 Managed Instance의 주요 차이점 검토", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance에는 기본 인프라 및 아키텍처에 따라 달라지는 특성 및 리소스 제한이 있습니다. 이러한 제한을 검토하는 것이 중요합니다.", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "SQL MI에 대한 용량 제한 검토", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "공연" + }, + { + "category": "SQL Managed Instance", + "description": "관리되는 인스턴스와 원본 SQL Server 간의 인스턴스 설정은 다를 수 있습니다. 성능에 영향을 줄 수 있는 차이점을 검토하는 것이 중요합니다.", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "성능에 영향을 줄 수 있는 SQL Server 및 Azure SQL MI의 인스턴스 설정 비교", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "공연" + }, + { + "category": "SQL Managed Instance", + "description": "Azure SQL Managed Instance로 마이그레이션하는 온-프레미스 SQL Server 인스턴스를 평가합니다. 평가 워크플로는 마이그레이션 자체와 부분적으로 지원되거나 지원되지 않는 기능을 차단하는 문제를 감지하는 데 도움이 됩니다", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "Data Migration Assistant 또는 Azure Data Studio Migration Extension을 실행하여 Managed Instance의 데이터베이스 기능에 영향을 줄 수 있는 호환성 문제를 검색합니다", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "SKU 권장 사항 기능은 원본 SQL Server 성능 및 사용률 특성을 평가하여 마이그레이션 과정을 지원하기 위해 적절한 크기의 Azure SQL Managed Instance를 추천할 수 있습니다.", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "SKU 권장 사항 도구를 활용하여 워크로드에 적합한 컴퓨팅 리소스를 선택합니다.", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "공연" + }, + { + "category": "SQL Managed Instance", + "description": "평가에서 각 데이터베이스에 대해 지원되지 않는 기능, 마이그레이션 차단기 및 호환성이 손상되는 변경 내용을 검토합니다.", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "DMA/Azure Data Studio에서 강조 표시된 문제 검토 및 해결", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance 기본 DNS 영역 .database.windows.net 은 사용자 고유의 것으로 변경할 수 있습니다. 그러나 FQDN의 관리되는 인스턴스 호스트 이름 부분은 동일하게 유지되어야 합니다.", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "관리되는 인스턴스 이름 변경은 지원되지 않으므로 연결 문자열 변경 계획", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "관리되는 인스턴스를 호스트하는 vnet 및 서브넷을 구성하는 데에는 추가 요구 사항이 있습니다.", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi", + "severity": "보통", + "subcategory": "마이그레이션 전", + "text": "관리되는 인스턴스 VNet 요구 사항 검토", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "서브넷 수식의 출력보다 작은 IP 주소 수를 사용하여 관리되는 인스턴스를 서브넷에 배포할 수 있지만 항상 더 큰 서브넷을 대신 사용하는 것이 좋습니다. 더 큰 서브넷을 사용하면 서브넷 내에 추가 인스턴스를 만들거나 기존 인스턴스를 확장할 수 없는 것과 같이 IP 주소 부족으로 인해 발생하는 향후 문제를 방지할 수 있습니다.", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi", + "severity": "높다", + "subcategory": "전개", + "text": "관리되는 인스턴스 서브넷에 사용 가능한 충분한 IP 주소가 있는지 확인", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "SQL Managed Instance에는 기본 인프라 및 아키텍처에 따라 달라지는 특성 및 리소스 제한이 있습니다. SQL Managed Instance는 여러 하드웨어 구성에 배포할 수 있습니다.", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "MI의 범용 계층과 중요 비즈니스용 계층 간 계획", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "공연" + }, + { + "category": "SQL Managed Instance", + "description": "자동 장애 조치(failover) 그룹 기능을 사용하면 관리되는 인스턴스의 사용자 데이터베이스를 다른 Azure 지역의 관리되는 인스턴스로 복제 및 장애 조치(failover)하는 작업을 관리할 수 있습니다. 자동 장애 조치(failover) 그룹은 지리적으로 복제된 데이터베이스의 배포 및 관리를 대규모로 간소화하도록 설계되었습니다.", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell", + "severity": "높다", + "subcategory": "마이그레이션 전", + "text": "RPO/RTO에 따라 자동 장애 조치(failover) 그룹을 구현해야 하는지 여부를 결정합니다. 그렇다면 두 번째 인스턴스의 배포 특성을 계획합니다.", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "신뢰도" + }, + { + "category": "SQL Managed Instance", + "description": "응용 프로그램을 관리되는 인스턴스에 연결하는 방법에는 여러 가지가 있습니다. 장단점을 검토 및 이해하고 응용 프로그램에 가장 적합한 접근 방식을 결정합니다.", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "낮다", + "subcategory": "마이그레이션 전", + "text": "데이터베이스와 응용 프로그램 간의 연결 설계를 검토하고 테스트 및 검증합니다.", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "마이그레이션 옵션을 비교하여 비즈니스 요구 사항에 적합한 경로를 선택합니다.", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools", + "severity": "보통", + "subcategory": "마이그레이션 전", + "text": "마이그레이션 방법을 계획합니다. DB 크기 및 애플리케이션 가동 중지 시간 기간에 따라 원하는 마이그레이션 방법을 선택합니다.", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "원본과 대상 모두에서 데이터가 동일한지 확인한 후 원본에서 대상 환경으로 전환할 수 있습니다. 비즈니스/애플리케이션 팀과 함께 컷오버 프로세스를 계획하여 컷오버 중 중단을 최소화해도 비즈니스 연속성에 영향을 미치지 않도록 하는 것이 중요합니다.", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover", + "severity": "보통", + "subcategory": "마이그레이션 전", + "text": "비즈니스/애플리케이션 팀과 함께 컷오버 프로세스를 계획하여 컷오버 중 중단을 최소화하고 비즈니스 연속성에 영향을 미치지 않도록 합니다.", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "신뢰도" + }, + { + "category": "SQL Managed Instance", + "description": "관리되는 인스턴스의 표준 시간대는 인스턴스를 만드는 동안에만 설정할 수 있습니다. 기본 시간대는 UTC입니다", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone", + "severity": "높다", + "subcategory": "전개", + "text": "인스턴스 생성 시 시간대 설정을 사용자 지정해야 합니다. 나중에 변경할 수 없습니다.", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "Azure SQL Managed Instance의 서버 수준 데이터 정렬은 인스턴스를 만들 때 지정할 수 있으며 나중에 변경할 수 없습니다. 기본 서버 수준 데이터 정렬은 SQL_Latin1_General_CP1_CI_AS입니다.", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16", + "severity": "높다", + "subcategory": "전개", + "text": "인스턴스를 만들 때 올바른 데이터 정렬 설정을 선택해야 합니다. 나중에 변경할 수 없습니다", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "네이티브 복원 옵션을 사용하여 TDE(투명한 데이터 암호화)로 보호되는 데이터베이스를 Azure SQL Managed Instance로 마이그레이션하는 경우 데이터베이스 복원 전에 SQL Server 인스턴스의 해당 인증서를 마이그레이션해야 합니다.", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell", + "severity": "보통", + "subcategory": "전개", + "text": "TDE 사용 데이터베이스의 경우 데이터베이스를 복원하기 전에 온-프레미스 또는 Azure VM SQL Server의 해당 인증서를 마이그레이션해야 합니다", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "시스템 데이터베이스는 서버 인스턴스가 현재 실행 중인 SQL Server 버전에서 만든 백업에서만 복원할 수 있습니다. SQL Managed Instance로 마이그레이션하는 경우에는 그렇지 않습니다.Azure PowerShell 및 DBATools PowerShell 라이브러리를 사용하면 마이그레이션 프로세스의 모든 부분을 쉽게 스크립팅하고 자동화하고 사용자 지정할 수 있습니다.", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore", + "severity": "낮다", + "subcategory": "이주", + "text": "시스템 데이터베이스 복원은 지원되지 않습니다. master 또는 msdb 데이터베이스에 저장된 인스턴스 수준 개체를 마이그레이션하려면 해당 개체를 스크립팅하고 대상 인스턴스에서 T-SQL 스크립트를 실행하는 것이 좋습니다.", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "원본에서 대상으로 데이터 변경 내용을 지속적으로 복제/동기화하는 마이그레이션 옵션을 사용하는 경우 원본 데이터 및 스키마가 변경되고 대상에서 드리프트될 수 있습니다. 데이터를 동기화하는 동안 원본의 모든 변경 내용이 캡처되어 마이그레이션 프로세스 중에 대상에 적용되는지 확인합니다.", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", + "severity": "높다", + "subcategory": "이주", + "text": "원본의 모든 변경 사항이 캡처되어 마이그레이션 프로세스 중에 대상에 적용되는지 확인합니다.", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "애플리케이션이 데이터베이스 마이그레이션 후 관리되는 인스턴스에 성공적으로 연결할 수 있는지 확인합니다.", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "보통", + "subcategory": "이주", + "text": "MI 및 데이터베이스에 대한 애플리케이션 연결 테스트", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "고가용성은 데이터베이스 애플리케이션에서 투명하게 작동하는 SQL Managed Instance 플랫폼의 기본 부분입니다. 노드 성능 저하 또는 오류 감지의 경우 또는 정기적인 월별 소프트웨어 업데이트 중에 주 노드에서 보조 노드로의 장애 조치(failover)는 Azure에서 SQL Managed Instance를 사용하는 모든 애플리케이션에서 발생할 것으로 예상됩니다.", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql", + "severity": "높다", + "subcategory": "마이그레이션 후", + "text": "SQL Managed Instance에서 수동 장애 조치(failover)를 실행하여 오류 및 장애 조치(failover) 복원력을 테스트하는 것이 좋습니다.", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "신뢰도" + }, + { + "category": "SQL Managed Instance", + "description": "프로덕션에 배포하기 전에 응용 프로그램이 장애 조치(failover) 복원력이 있는지 확인하면 프로덕션에서 응용 프로그램 오류의 위험을 완화하는 데 도움이 되며 고객의 응용 프로그램 가용성에 기여할 수 있습니다.", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover", + "severity": "높다", + "subcategory": "마이그레이션 후", + "text": "장애 조치(failover) 그룹이 구현된 경우 수동 장애 조치(failover) 및 장애 복구(failback)를 테스트하고 장애 조치(failover)/장애 복구(failback) 중 응용 프로그램 연결 동작을 테스트합니다", + "waf": "신뢰도" + }, + { + "category": "SQL Managed Instance", + "description": "이렇게 하면 더 많은 전용 디스크 IOPS 및 처리량이 제공됩니다", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525", + "severity": "높다", + "subcategory": "마이그레이션 후", + "text": "범용 Managed Instance에 대한 스토리지 성능 최적화", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "공연" + }, + { + "category": "SQL Managed Instance", + "description": "많은 조직에는 인증서 또는 암호화 키를 내부적으로 만들고 관리해야 하는 정책이 있습니다. 조직에 유사한 정책이 있는 경우 이 아키텍처가 적용될 수 있습니다. 고객이 이러한 항목에 대한 내부 관리를 필요로 하는 경우 아키텍처도 적용될 수 있습니다.", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk", + "severity": "낮다", + "subcategory": "마이그레이션 후", + "text": "고객 관리형 TDE를 사용하여 사용자 고유의 복사본만 전체 백업을 수행할 수 있습니다.", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "안전" + }, + { + "category": "SQL Managed Instance", + "description": "유지 관리 기간 기능은 Azure SQL 리소스를 업무 시간 외에 미리 예약된 시간 블록에 온보딩하는 기능을 제공합니다.", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql", + "severity": "보통", + "subcategory": "마이그레이션 후", + "text": "Azure 유지 관리 이벤트 계획", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "작업" + }, + { + "category": "SQL Managed Instance", + "description": "LTR(장기 보존) 기능을 사용하면 지정된 SQL Database 및 SQL Managed Instance 전체 백업을 최대 10년 동안 구성된 중복성을 사용하여 Azure Blob Storage에 저장할 수 있습니다.", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi", + "severity": "낮다", + "subcategory": "마이그레이션 후", + "text": "장기 백업 보존 구성, 백업 보기 및 백업에서 복원", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "신뢰도" + }, + { + "category": "SQL Managed Instance", + "description": "Azure 하이브리드 혜택을 사용하면 비즈니스 애플리케이션을 최적화하면서 비용을 절감하고, 유연한 하이브리드 환경을 현대화 및 유지 관리할 수 있습니다.", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview", + "severity": "낮다", + "subcategory": "마이그레이션 후", + "text": "해당하는 경우 Azure 하이브리드 혜택 및 Azure Reservations를 활용하세요.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "비용" + }, + { + "category": "SQL Managed Instance", + "description": "위협 방지 기능이 없는 경우 Advanced Threat Protection은 고급 SQL 보안 기능을 위한 통합 패키지인 SQL용 Microsoft Defender 제품의 일부입니다.", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql", + "severity": "보통", + "subcategory": "마이그레이션 후", + "text": "클라우드용 Microsoft Defender를 활용하여 전반적인 보안 태세 개선", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "안전" + } + ], + "metadata": { + "name": "SQL Migration Review", + "state": "Preview", + "timestamp": "December 13, 2023" + }, + "severities": [ + { + "name": "높다" + }, + { + "name": "보통" + }, + { + "name": "낮다" + } + ], + "status": [ + { + "description": "이 검사는 아직 검토되지 않았습니다", + "name": "확인되지 않음" + }, + { + "description": "이 검사와 연관된 작업 항목이 있습니다", + "name": "열다" + }, + { + "description": "이 검사는 확인되었으며 이와 관련된 추가 작업 항목이 없습니다", + "name": "성취" + }, + { + "description": "권장 사항은 이해되었지만 현재 요구 사항에 필요하지 않음", + "name": "필요 없음" + }, + { + "description": "현재 설계에는 적용되지 않습니다.", + "name": "해당 없음" + } + ], + "waf": [ + { + "name": "신뢰도" + }, + { + "name": "안전" + }, + { + "name": "비용" + }, + { + "name": "작업" + }, + { + "name": "공연" + } + ], + "yesno": [ + { + "name": "예" + }, + { + "name": "아니요" + } + ] +} \ No newline at end of file diff --git a/checklists/sql_checklist.pt.json b/checklists/sql_checklist.pt.json new file mode 100644 index 000000000..4fc2dd0e7 --- /dev/null +++ b/checklists/sql_checklist.pt.json @@ -0,0 +1,759 @@ +{ + "categories": [ + { + "name": "SQL Server na VM do Azure" + }, + { + "name": "Instância gerenciada do SQL" + } + ], + "items": [ + { + "category": "SQL Server na VM do Azure", + "description": "Ao criar um SQL Server na VM do Azure, considere cuidadosamente o tipo de carga de trabalho necessária. Se você estiver migrando um ambiente existente, colete uma linha de base de desempenho para determinar seus requisitos de VM do SQL Server no Azure. Se esta for uma nova VM, crie sua nova VM do SQL Server com base nos requisitos do fornecedor.", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16", + "severity": "Alto", + "subcategory": "Tamanho da VM", + "text": "Colete as características de desempenho da carga de trabalho de destino e use-as para determinar o tamanho apropriado da VM para sua empresa.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Os tamanhos de máquina virtual otimizados para memória são um destino primário para VMs do SQL Server e a escolha recomendada pela Microsoft. As máquinas virtuais otimizadas para memória oferecem taxas de memória para CPU mais fortes e opções de cache de médio a grande. Considere a série Ebdsv5 primeiro para a maioria das cargas de trabalho do SQL Server.", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized", + "severity": "Média", + "subcategory": "Tamanho da VM", + "text": "Use tamanhos de máquina virtual otimizados para memória para obter o melhor desempenho das cargas de trabalho do SQL Server.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Para encontrar a configuração mais eficaz para cargas de trabalho do SQL Server em uma VM do Azure, comece medindo o desempenho de armazenamento do seu aplicativo de negócios. Depois que os requisitos de armazenamento forem conhecidos, selecione uma máquina virtual que ofereça suporte às IOPS e à taxa de transferência necessárias com a proporção apropriada de memória para vCore.", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements", + "severity": "Média", + "subcategory": "Armazenamento", + "text": "Determine os requisitos de largura de banda de armazenamento e latência para dados, log e arquivos tempdb do SQL Server antes de escolher o tipo de disco.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Isso fornece IOPS de disco mais dedicadas e taxa de transferência no nível do disco e também permite que você defina a configuração de cache de host de disco do Azure para cada disco para a configuração ideal para esse tipo de dados.", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Coloque dados, log e arquivos tempdb em unidades separadas", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "O SSD Premium é sempre recomendado como mínimo para o SQL Server, a fim de obter melhor desempenho e menor latência. P30 e P40 são recomendados porque o cache de disco não é suportado para discos de 4 TiB ou maiores (P50 e acima) e eles fornecem a relação preço/desempenho ideal", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Para a unidade de dados, use discos premium P30 e P40 ou menores para garantir a disponibilidade do suporte a cache", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Os arquivos de log têm principalmente operações pesadas de gravação. Portanto, eles não se beneficiam do cache ReadOnly. Portanto, avalie seu preço vs desempenho vs capacidade e escolha o disco de armazenamento certo.", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Para o plano de unidade de log para capacidade e teste de desempenho versus custo ao avaliar os discos P30 - P80 premium", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Colocar o TempDB na unidade D pode ajudar no desempenho. Considere o tamanho necessário e sempre teste o desempenho.", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Média", + "subcategory": "Armazenamento", + "text": "Coloque tempdb na unidade SSD efêmera local (padrão D:\\) para a maioria das cargas de trabalho do SQL Server que não fazem parte da FCI (Instância de Cluster de Failover) depois de escolher o tamanho ideal da VM.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "A distribuição de dados e o disco de log podem aumentar a largura de banda. Verifique se o tamanho da VM também corresponde à saída esperada", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Distribua vários discos de dados do Azure usando Espaços de Armazenamento para aumentar a largura de banda de E/S", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Sua política de cache de armazenamento varia dependendo do tipo de arquivos de dados do SQL Server hospedados na unidade. Habilite o cache somente leitura para os discos que hospedam arquivos de dados do SQL Server. As leituras do cache serão mais rápidas do que as leituras não armazenadas em cache do disco de dados. Defina a política de cache como Nenhum para discos que hospedam o log de transações. Não há nenhum benefício de desempenho em habilitar o cache para o disco de log de transações.", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Defina o cache do host como somente leitura para discos de arquivo de dados e nenhum para discos de arquivo de log.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Verifique se o armazenamento está na mesma região que sua VM. Para exaplme, se sua VM estiver em EAST US 2, verifique se seu armazenamento está em East US 2.", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Provisionar a conta de armazenamento na mesma região que a VM do SQL Server", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "O SQL Server usa extensões para armazenar dados. Estes são 64KB de tamanho. Portanto, em um computador do SQL Server, o tamanho da unidade de alocação NTFS para hospedar arquivos de banco de dados SQL deve ser de 64 KB.", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "Alto", + "subcategory": "Armazenamento", + "text": "Formate o disco de dados para usar o tamanho do bloco de 64 KB (tamanho da unidade de alocação) para todos os arquivos de dados colocados em uma unidade diferente da unidade temporária D:\\", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "É recomendável determinar as necessidades e os requisitos de BCDR, garantindo que você seja capaz de atender aos SLAs do ambiente.", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions", + "severity": "Média", + "subcategory": "HADR", + "text": "Determine os requisitos de HA/DR para cada VM a ser migrada.", + "waf": "Fiabilidade" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Ao definir Alta Disponibilidade, você precisa usar conjuntos de disponibilidade ou zonas de disponibilidade para evitar interrupções inesperadas.", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set", + "severity": "Alto", + "subcategory": "HADR", + "text": "Coloque suas VMs em um conjunto de disponibilidade ou zonas de disponibilidade diferentes.", + "waf": "Fiabilidade" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Opção preferencial ao implantar um Grupo de Disponibilidade. A solução recomendada é usar várias sub-redes ao implantar grupos de disponibilidade Always on.", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli", + "severity": "Média", + "subcategory": "HADR", + "text": "Implante suas VMs do SQL Server em várias sub-redes sempre que possível para evitar a dependência de um Balanceador de Carga do Azure ou de um DNN (nome de rede distribuído) para rotear o tráfego para sua solução HADR. ( Se alguém está implementando FCI ou AG)", + "waf": "Fiabilidade" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Os recursos HADR (Alta disponibilidade e recuperação de desastres), como o grupo de disponibilidade Always On e a instância de cluster de failover, dependem da tecnologia subjacente do Cluster de Failover do Windows Server. Analise as práticas recomendadas para modificar suas configurações HADR para oferecer melhor suporte ao ambiente de nuvem.", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration", + "severity": "Alto", + "subcategory": "HADR", + "text": "Altere o cluster para parâmetros menos agressivos para evitar interrupções inesperadas de falhas de rede transitórias ou manutenção da plataforma Azure. ( Se alguém está implementando FCI ou AG)", + "waf": "Fiabilidade" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Certifique-se de que o quorum esteja definido corretamente para o número de instâncias implantadas.", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting", + "severity": "Alto", + "subcategory": "HADR", + "text": "Configure a votação de quórum de cluster para usar 3 ou mais números ímpares de votos. Não atribua votos a regiões de DR. ( Se alguém está implementando FCI ou AG)", + "waf": "Fiabilidade" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Nas máquinas virtuais do Azure, os clusters usam um balanceador de carga para manter um endereço IP que precisa estar em um nó de cluster por vez. Nesta solução, o balanceador de carga mantém o endereço IP do ouvinte de nome de rede virtual (VNN) para o grupo de disponibilidade Always On quando as VMs do SQL Server estão em uma única sub-rede.", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb", + "severity": "Alto", + "subcategory": "HADR", + "text": "Ao usar o nome da rede virtual (VNN) e o Balanceador de Carga do Azure para se conectar à sua solução HADR, especifique MultiSubnetFailover = true na cadeia de conexão, mesmo que o cluster abranja apenas uma sub-rede. ( Se alguém está implementando FCI ou AG)", + "waf": "Fiabilidade" + }, + { + "category": "SQL Server na VM do Azure", + "description": "O SQL Server, o Banco de Dados SQL do Azure e a Instância Gerenciada SQL do Azure oferecem suporte à compactação de linha e página para tabelas e índices de armazenamento de linhas e oferecem suporte à compactação de arquivamento columnstore e columnstore para tabelas e índices columnstore.", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16", + "severity": "Baixo", + "subcategory": "SQL Server", + "text": "Habilite a compactação de página do banco de dados quando apropriado.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Por padrão, os arquivos de dados e de log são inicializados para substituir quaisquer dados existentes deixados no disco de arquivos excluídos anteriormente. Os arquivos de dados e de log são inicializados primeiro zerando os arquivos (preenchendo com zeros). No SQL Server, somente para arquivos de dados, a inicialização instantânea de arquivos (IFI) permite a execução mais rápida das operações de arquivo mencionadas anteriormente, uma vez que recupera o espaço em disco usado sem preencher esse espaço com zeros. Em vez disso, o conteúdo do disco é substituído à medida que novos dados são gravados nos arquivos.", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16", + "severity": "Alto", + "subcategory": "SQL Server", + "text": "Habilite a inicialização instantânea de arquivos para arquivos de dados.", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Recomendado para melhor desempenho e disponibilidade Migrar todos os bancos de dados para discos de dados e de log", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16", + "severity": "Média", + "subcategory": "SQL Server", + "text": "Mova todos os bancos de dados para discos de dados, incluindo bancos de dados do sistema.", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features", + "severity": "Baixo", + "subcategory": "SQL Server", + "text": "Mova o log de erros do SQL Server e os diretórios de arquivos de rastreamento para discos de dados.", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-", + "severity": "Alto", + "subcategory": "SQL Server", + "text": "Defina o limite máximo de memória do SQL Server para deixar memória suficiente para o sistema operacional.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows", + "severity": "Alto", + "subcategory": "SQL Server", + "text": "Habilite páginas de bloqueio na memória.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store", + "severity": "Baixo", + "subcategory": "SQL Server", + "text": "Habilite o Repositório de Consultas em todos os bancos de dados de produção do SQL Server seguindo as práticas recomendadas.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server", + "severity": "Alto", + "subcategory": "SQL Server", + "text": "Certifique-se de que todas as práticas recomendadas do tempdb sejam seguidas.", + "waf": "Desempenho" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "Alto", + "subcategory": "SQL Server", + "text": "Agende trabalhos do SQL Server Agent para executar trabalhos DBCC CHECKDB, reorganizar índice, recriar índice e atualizar trabalhos de estatísticas.", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "Parte da lista de verificação de recursos do SQL Server no link que é recomendado quando a Instância do SQL Server está em uma VM do Azure.", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "Média", + "subcategory": "SQL Server", + "text": "Limitar o crescimento automático do banco de dados e Desabilitar a redução automática", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "As máquinas virtuais (VMs) vCPU restritas são um tipo de VM em que a contagem de vCPU pode ser restrita a metade ou um quarto do tamanho original da VM. Isso permite que os clientes reduzam o custo do licenciamento de software e, ao mesmo tempo, mantenham a mesma memória, armazenamento e largura de banda de E/S", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu", + "severity": "Baixo", + "subcategory": "Otimização de Custos", + "text": "Otimize o custo da licença do SQL Server com VMs vCPU restritas", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "Custar" + }, + { + "category": "SQL Server na VM do Azure", + "description": "O Benefício Híbrido do Azure permite que você troque suas licenças existentes por taxas com desconto no Banco de Dados SQL do Azure e na Instância Gerenciada SQL do Azure. Y", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/", + "severity": "Baixo", + "subcategory": "Otimização de Custos", + "text": "Aproveite o benefício do Azure Hybrid para maximizar o valor de suas licenças locais na nuvem", + "waf": "Custar" + }, + { + "category": "SQL Server na VM do Azure", + "description": "A extensão do SQL Server IaaS Agent (SqlIaasExtension) é executada no SQL Server em VMs (Máquinas Virtuais) do Windows do Azure para automatizar tarefas de gerenciamento e administração.", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli", + "severity": "Média", + "subcategory": "Azul", + "text": "Registre-se com a Extensão do Agente IaaS do SQL para desbloquear uma série de benefícios de recursos.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "A Rede Acelerada fornece latência de rede ultrabaixa consistente por meio do hardware e das tecnologias programáveis internos do Azure", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "severity": "Alto", + "subcategory": "Azul", + "text": "Verifique se a Rede Acelerada está habilitada na máquina virtual.", + "waf": "Operações" + }, + { + "category": "SQL Server na VM do Azure", + "description": "O Microsoft Defender detecta atividades anômalas que indicam tentativas incomuns e potencialmente prejudiciais de acessar ou explorar bancos de dados no SQL Server.", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", + "severity": "Alto", + "subcategory": "Azul", + "text": "Aproveite o Microsoft Defender for Cloud para melhorar a postura geral de segurança da implantação da máquina virtual.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Segurança" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Há algumas limitações de PaaS que são introduzidas na Instância Gerenciada do SQL e algumas alterações de comportamento em comparação com o SQL Server. É importante rever e entender essas diferenças.", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Analise as principais diferenças entre o SQL Server e a instância gerenciada", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "A Instância Gerenciada do SQL tem características e limites de recursos que dependem da infraestrutura e da arquitetura subjacentes. É importante rever esses limites.", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Revisar os limites de capacidade do SQL MI", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "Desempenho" + }, + { + "category": "Instância gerenciada do SQL", + "description": "As configurações de instância entre a instância gerenciada e o SQL Server de origem podem ser diferentes. É importante rever as diferenças que podem afetar o desempenho.", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Comparar configurações de instância no SQL Server e no Azure SQL MI que podem afetar o desempenho", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "Desempenho" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Avalie a(s) instância(s) local(is) do SQL Server migrando para a Instância Gerenciada SQL do Azure. O fluxo de trabalho de avaliação ajuda a detectar problemas que bloqueiam a migração em si e também recursos parcialmente suportados e sem suporte", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Execute o Assistente de Migração de Dados ou a Extensão de Migração do Azure Data Studio para detectar problemas de compatibilidade que podem afetar a funcionalidade do banco de dados na Instância Gerenciada", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "O recurso de recomendação de SKU pode avaliar o desempenho e as características de utilização do SQL Server de origem para recomendar uma Instância Gerenciada SQL do Azure de tamanho correto para ajudar em sua jornada de migração.", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Selecione os recursos de computação certos para sua carga de trabalho aproveitando as ferramentas de recomendação de SKU.", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "Desempenho" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Revise recursos sem suporte, bloqueadores de migração e alterações de quebra para cada banco de dados da avaliação", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Revise e resolva os problemas destacados no DMA/Azure Data Studio", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "A zona DNS padrão .database.windows.net da Instância Gerenciada SQL pode ser alterada com a sua. No entanto, a parte do nome do host da instância gerenciada de seu FQDN deve permanecer a mesma.", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Planejar alterações na cadeia de conexão, pois não há suporte para a alteração de um nome de instância gerenciada", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Há requisitos adicionais na configuração de uma vnet e sub-rede que hospeda a instância gerenciada.", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi", + "severity": "Média", + "subcategory": "Pré-migração", + "text": "Revisar os requisitos de rede virtual de instância gerenciada", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Embora seja possível implantar instâncias gerenciadas em uma sub-rede com um número de endereços IP menor do que a saída da fórmula de sub-rede, sempre considere o uso de sub-redes maiores. O uso de uma sub-rede maior pode ajudar a evitar problemas futuros decorrentes da falta de endereços IP, como a incapacidade de criar instâncias adicionais dentro da sub-rede ou dimensionar instâncias existentes.", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi", + "severity": "Alto", + "subcategory": "Implantação", + "text": "Verifique se a sub-rede da instância gerenciada tem endereços IP suficientes disponíveis", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "A Instância Gerenciada do SQL tem características e limites de recursos que dependem da infraestrutura e da arquitetura subjacentes. A Instância Gerenciada do SQL pode ser implantada em várias configurações de hardware.", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Planejar entre os níveis de Uso Geral e Crítico de Negócios de MI", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "Desempenho" + }, + { + "category": "Instância gerenciada do SQL", + "description": "O recurso de grupos de failover automático permite gerenciar a replicação e o failover de bancos de dados de usuários em uma instância gerenciada para uma instância gerenciada em outra região do Azure. Os grupos de failover automático são projetados para simplificar a implantação e o gerenciamento de bancos de dados replicados geograficamente em escala.", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell", + "severity": "Alto", + "subcategory": "Pré-migração", + "text": "Com base em seus RPO/RTOs, determine se o Grupo de failover automático precisa ser implementado. Em caso afirmativo, planeje os atributos de implantação da segunda instância.", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "Fiabilidade" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Há várias maneiras de conectar seu aplicativo à instância gerenciada. Analise e entenda os prós e contras e decida sobre a melhor abordagem para sua aplicação.", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "Baixo", + "subcategory": "Pré-migração", + "text": "Revise o Design de Conectividade entre Banco de Dados e Aplicativo, teste e valide-o", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Compare as opções de migração para escolher o caminho adequado às suas necessidades de negócios.", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools", + "severity": "Média", + "subcategory": "Pré-migração", + "text": "Planejar o método de migração. Dependendo da janela Tamanho do banco de dados e Tempo de inatividade do aplicativo, selecione o Método de migração preferido.", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Depois de verificar se os dados são os mesmos na origem e no destino, você pode cortar da origem para o ambiente de destino. É importante planejar o processo de substituição com as equipes de negócios/aplicativos para garantir que a interrupção mínima durante a transição não afete a continuidade dos negócios.", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover", + "severity": "Média", + "subcategory": "Pré-migração", + "text": "Planeje o processo de transição com as equipes de negócios/aplicativos para garantir o mínimo de interrupção durante a transição e não afetar a continuidade dos negócios.", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "Fiabilidade" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Um fuso horário de uma instância gerenciada pode ser definido somente durante a criação da instância. O fuso horário padrão é UTC", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone", + "severity": "Alto", + "subcategory": "Implantação", + "text": "Certifique-se de personalizar sua configuração de fuso horário no momento da criação da instância. Não se pode mudar depois.", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "O agrupamento no nível do servidor na Instância Gerenciada SQL do Azure pode ser especificado quando a instância é criada e não pode ser alterado posteriormente. O agrupamento padrão no nível do servidor é SQL_Latin1_General_CP1_CI_AS.", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16", + "severity": "Alto", + "subcategory": "Implantação", + "text": "Certifique-se de selecionar a configuração de agrupamento correta no momento da criação da instância. Não se pode mudá-lo mais tarde", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Quando você está migrando um banco de dados protegido por TDE (Criptografia de Dados Transparente) para a Instância Gerenciada SQL do Azure usando a opção de restauração nativa, o certificado correspondente da instância do SQL Server precisa ser migrado antes da restauração do banco de dados.", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell", + "severity": "Média", + "subcategory": "Implantação", + "text": "Para o Banco de Dados Habilitado para TDE, o certificado correspondente do SQL Server local ou da VM do Azure precisa ser migrado antes da restauração do banco de dados", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Os bancos de dados do sistema podem ser restaurados somente a partir de backups criados na versão do SQL Server que a instância do servidor está executando no momento. Esse não é o caso quando você está migrando para a Instância Gerenciada do SQL.As bibliotecas do PowerShell do Azure PowerShell e do DBATools permitem que você crie scripts e automatize e personalize facilmente todas as partes do processo de migração.", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore", + "severity": "Baixo", + "subcategory": "Migração", + "text": "Não há suporte para a restauração de bancos de dados do sistema. Para migrar objetos em nível de instância (armazenados em bancos de dados master ou msdb), recomendamos criá-los e executar scripts T-SQL na instância de destino.", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Ao usar opções de migração que replicam/sincronizam continuamente as alterações de dados da origem para o destino, os dados de origem e o esquema podem ser alterados e desviados do destino. Durante a sincronização de dados, certifique-se de que todas as alterações na origem sejam capturadas e aplicadas ao destino durante o processo de migração.", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", + "severity": "Alto", + "subcategory": "Migração", + "text": "Certifique-se de que todas as alterações na origem sejam capturadas e aplicadas ao destino durante o processo de migração.", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Certifique-se de que o aplicativo seja capaz de se conectar com sucesso à instância gerenciada após a migração dos bancos de dados.", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "Média", + "subcategory": "Migração", + "text": "Testar a conectividade do aplicativo com MI e bancos de dados", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "A alta disponibilidade é uma parte fundamental da plataforma de Instância Gerenciada SQL que funciona de forma transparente para seus aplicativos de banco de dados. Failovers de nós primários para secundários em caso de degradação de nó ou detecção de falhas, ou durante atualizações de software mensais regulares são uma ocorrência esperada para todos os aplicativos que usam a Instância Gerenciada SQL no Azure.", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql", + "severity": "Alto", + "subcategory": "Pós-migração", + "text": "Considere a execução de um failover manual na Instância Gerenciada do SQL para testar a resiliência de falha e failover.", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "Fiabilidade" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Garantir que seus aplicativos sejam resilientes a failover antes da implantação em produção ajudará a reduzir o risco de falhas de aplicativos na produção e contribuirá para a disponibilidade de aplicativos para seus clientes.", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover", + "severity": "Alto", + "subcategory": "Pós-migração", + "text": "Se os grupos de failover tiverem sido implementados, teste o failover manual e o failback e teste o comportamento da conectividade do aplicativo durante o failover/failback", + "waf": "Fiabilidade" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Isso fornece IOPS de disco e taxa de transferência mais dedicadas", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525", + "severity": "Alto", + "subcategory": "Pós-migração", + "text": "Otimize o desempenho do armazenamento para instância gerenciada de uso geral", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Desempenho" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Muitas organizações têm políticas que exigem que certificados ou chaves de criptografia sejam criados e gerenciados internamente. Se sua organização tiver uma política semelhante, essa arquitetura poderá se aplicar a você. Se seus clientes precisarem de gerenciamento interno desses itens, a arquitetura também poderá se aplicar a você.", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk", + "severity": "Baixo", + "subcategory": "Pós-migração", + "text": "Habilite o TDE gerenciado pelo cliente para fazer sua própria cópia somente com backups completos", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Segurança" + }, + { + "category": "Instância gerenciada do SQL", + "description": "O recurso de janela de manutenção fornece a capacidade de integrar o recurso SQL do Azure a blocos de tempo pré-agendados fora do horário comercial.", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql", + "severity": "Média", + "subcategory": "Pós-migração", + "text": "Planejar eventos de manutenção do Azure", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operações" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Usando o recurso de retenção de longo prazo (LTR), você pode armazenar backups completos especificados do Banco de Dados SQL e da Instância Gerenciada SQL no armazenamento de Blobs do Azure com redundância configurada por até 10 anos.", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi", + "severity": "Baixo", + "subcategory": "Pós-migração", + "text": "Configurar a retenção de backup de longo prazo, exibir backups e restaurar backups de backups", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "Fiabilidade" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Usando o Benefício Híbrido do Azure, você pode obter economia de custos, modernizar e manter um ambiente híbrido flexível enquanto otimiza aplicativos de negócios.", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview", + "severity": "Baixo", + "subcategory": "Pós-migração", + "text": "Aproveite o Benefício Híbrido do Azure e as Reservas do Azure, quando aplicável.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "Custar" + }, + { + "category": "Instância gerenciada do SQL", + "description": "Se você não tiver proteção contra ameaças, a Proteção Avançada contra Ameaças faz parte da oferta Microsoft Defender for SQL, que é um pacote unificado para recursos avançados de segurança SQL.", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql", + "severity": "Média", + "subcategory": "Pós-migração", + "text": "Aproveite o Microsoft Defender for Cloud para melhorar a postura geral de segurança", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Segurança" + } + ], + "metadata": { + "name": "SQL Migration Review", + "state": "Preview", + "timestamp": "December 13, 2023" + }, + "severities": [ + { + "name": "Alto" + }, + { + "name": "Média" + }, + { + "name": "Baixo" + } + ], + "status": [ + { + "description": "Esta verificação ainda não foi analisada", + "name": "Não verificado" + }, + { + "description": "Há um item de ação associado a essa verificação", + "name": "Abrir" + }, + { + "description": "Essa verificação foi verificada e não há outros itens de ação associados a ela", + "name": "Cumprido" + }, + { + "description": "Recomendação compreendida, mas não necessária pelos requisitos atuais", + "name": "Não é necessário" + }, + { + "description": "Não aplicável ao projeto atual", + "name": "N/A" + } + ], + "waf": [ + { + "name": "Fiabilidade" + }, + { + "name": "Segurança" + }, + { + "name": "Custar" + }, + { + "name": "Operações" + }, + { + "name": "Desempenho" + } + ], + "yesno": [ + { + "name": "Sim" + }, + { + "name": "Não" + } + ] +} \ No newline at end of file diff --git a/checklists/sql_checklist.zh-Hant.json b/checklists/sql_checklist.zh-Hant.json new file mode 100644 index 000000000..f2d48f7da --- /dev/null +++ b/checklists/sql_checklist.zh-Hant.json @@ -0,0 +1,759 @@ +{ + "categories": [ + { + "name": "Azure VM 上的 SQL Server" + }, + { + "name": "SQL 託管實例" + } + ], + "items": [ + { + "category": "Azure VM 上的 SQL Server", + "description": "在 Azure VM 上創建 SQL Server 時,請仔細考慮所需的工作負載類型。如果要遷移現有環境,請收集性能基線以確定 Azure VM 上的 SQL Server 要求。如果這是新的 VM,請根據供應商要求創建新的 SQL Server VM。", + "guid": "1fc3fc14-eea6-4e69-b8d9-a3eec218e687", + "id": "A01.01", + "link": "https://learn.microsoft.com/sql/dma/dma-sku-recommend-sql-db?view=sql-server-ver16", + "severity": "高", + "subcategory": "VM 大小", + "text": "收集目標工作負載的性能特徵,並使用它們來確定適合業務的 VM 大小。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "記憶體優化虛擬機大小是 SQL Server VM 的主要目標,也是 Microsoft 的建議選擇。記憶體優化虛擬機提供更強的記憶體與CPU比率和大中型緩存選項。對於大多數 SQL Server 工作負載,首先考慮 Ebdsv5 系列系列。", + "guid": "e04abe1f-8d39-4fda-9776-8424c116775c", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-vm-size?view=azuresql#memory-optimized", + "severity": "中等", + "subcategory": "VM 大小", + "text": "使用記憶體優化的虛擬機大小,以獲得 SQL Server 工作負載的最佳性能。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "若要為 Azure VM 上的 SQL Server 工作負載找到最有效的配置,請首先測量業務應用程式的存儲性能。瞭解存儲要求后,選擇支援必要 IOPS 和輸送量的虛擬機,並具有適當的記憶體與 vCore 比率。", + "guid": "2ea55b56-ad48-4408-be72-734b476ba18f", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance#counters-to-measure-application-performance-requirements", + "severity": "中等", + "subcategory": "存儲", + "text": "在選擇磁碟類型之前,請確定 SQL Server 數據、日誌和 tempdb 檔的儲存頻寬和延遲要求。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "這會在磁碟級別提供更多專用磁碟 IOPS 和輸送量,還允許將每個磁碟的 Azure 磁碟主機快取設定配置為該數據類型的最佳設置。", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "將數據、日誌和tempdb檔放在單獨的驅動器上", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "始終建議將高級 SSD 作為 SQL Server 的最低要求,以獲得更好的性能和更低的延遲。建議使用 P30 和 P40,因為 4 TiB 及更大(P50 及更高版本)的磁碟不支援磁碟緩存,並且它們提供最佳性價比", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "對於數據驅動器,請使用高級 P30 和 P40 或更小的磁碟,以確保緩存支援的可用性", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "日誌檔主要具有寫入密集型操作。因此,它們不會從 ReadOnly 快取中受益。因此,請評估您的價格、性能和容量,並選擇合適的存儲磁碟。", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "對於在評估高級 P30 - P80 磁碟時制定容量和測試性能與成本的日誌驅動器計劃", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "將 TempDB 放在 D 驅動器上有助於提高性能。考慮所需的大小,並始終測試性能。", + "guid": "12f70983-f630-4472-8ee6-9d6b5c2622f5", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "中等", + "subcategory": "存儲", + "text": "選擇最佳 VM 大小時後,將 tempdb 放在本地臨時 SSD(預設為 D:\\)驅動器上,以處理不屬於故障轉移群集實例 (FCI) 的大多數 SQL Server 工作負載。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "條帶化數據和日誌磁碟可以增加頻寬。確保 VM 大小也與預期輸出匹配", + "guid": "4b69bad3-4aad-45e8-a78e-1d76667313c4", + "id": "A02.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "使用存儲空間對多個 Azure 數據磁碟進行條帶化,以增加 I/O 頻寬", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "存儲快取策略因驅動器上託管的 SQL Server 資料檔的類型而異。為承載 SQL Server 資料檔的磁碟啟用唯讀緩存。從緩存中讀取的速度將比從數據磁盤中讀取未緩存的速度更快。將承載事務日誌的磁碟的緩存策略設置為“無”。為事務日誌磁碟啟用緩存沒有性能優勢。", + "guid": "05674b5e-985b-4859-a773-e7e261623b77", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "將數據檔磁碟的主機緩存設置為唯讀,將日誌檔磁碟的主機緩存設置為無。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "檢查存儲是否與 VM 位於同一區域。例如,如果 VM 位於美國東部 2 中,請確保儲存位於美國東部 2 中。", + "guid": "5a917e1f-348e-4f35-9c27-d42e8bbac868", + "id": "A02.08", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "在與 SQL Server VM 相同的區域中預配存儲帳戶Provision the storage account in the same region as the SQL Server VM", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "SQL Server 使用盤區來存儲數據。這些大小為 64KB。因此,在 SQL Server 計算機上,用於承載 SQL 資料庫檔的 NTFS 分配單元大小應為 64 KB。", + "guid": "155abb91-63e9-4908-ae28-c84c33b6b780", + "id": "A02.09", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql#storage", + "severity": "高", + "subcategory": "存儲", + "text": "格式化數據磁碟,以便對放置在臨時 D:\\ 驅動器以外的驅動器上的所有數據檔使用 64 KB 塊大小(分配單元大小)", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "建議確定BCDR需求和要求,確保能夠滿足環境的SLA。", + "guid": "8b9fe5c4-2049-4d41-9a92-3c3474d11028", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#azure-only-disaster-recovery-solutions", + "severity": "中等", + "subcategory": "HADR型", + "text": "確定要遷移的每個 VM 的 HA/DR 要求。", + "waf": "可靠性" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "取消高可用性時,需要使用可用性集或可用性區域來避免意外中斷。", + "guid": "ac6aae01-e6a8-44de-9df4-3d1992481718", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/business-continuity-high-availability-disaster-recovery-hadr-overview?view=azuresql#high-availability-nodes-in-an-availability-set", + "severity": "高", + "subcategory": "HADR型", + "text": "將 VM 放置在可用性集或其他可用性區域中。", + "waf": "可靠性" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "部署可用性組時的首選選項。建議的解決方案是在部署 Always On 可用性組時使用多子網。", + "guid": "d5d1e5f6-2565-49d3-958f-d77249c93111", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-azure-portal-configure?view=azuresql&tabs=azure-cli", + "severity": "中等", + "subcategory": "HADR型", + "text": "盡可能將 SQL Server VM 部署到多個子網,以避免依賴 Azure 負載均衡器或分散式網路名稱 (DNN) 將流量路由到 HADR 解決方案。(如果正在實施FCI或 AG)", + "waf": "可靠性" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "高可用性和災難恢復 (HADR) 功能(如 Always On 可用性組和故障轉移群集實例)依賴於基礎 Windows Server 故障轉移群集技術。查看修改HADR設置以更好地支援雲環境的最佳實踐。", + "guid": "2d027fe4-12f7-4098-9f63-04722ee69d6b", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#hadr-configuration", + "severity": "高", + "subcategory": "HADR型", + "text": "將群集更改為不太激進的參數,以避免因暫時性網路故障或 Azure 平臺維護而導致意外中斷。(如果正在實施FCI或 AG)", + "waf": "可靠性" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "確保為部署的實例數設置了正確的仲裁。", + "guid": "5c2622f5-4b69-4bad-94aa-d5e8c78e1d76", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/hadr-cluster-best-practices?view=azuresql-vm&tabs=windows2012#quorum-voting", + "severity": "高", + "subcategory": "HADR型", + "text": "將群集仲裁投票配置為使用 3 票或更多奇數票。不要將選票分配給DR區域。(如果正在實施FCI或 AG)", + "waf": "可靠性" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "在 Azure 虛擬機上,群集使用負載均衡器來保存一次需要位於一個群集節點上的 IP 位址。在此解決方案中,當 SQL Server VM 位於單個子網中時,負載均衡器會保存 Always On 可用性組的虛擬網路名稱 (VNN) 偵聽器的 IP 位址。", + "guid": "667313c4-0567-44b5-b985-b859c773e7e2", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/availability-group-vnn-azure-load-balancer-configure?view=azuresql-vm&tabs=ilb", + "severity": "高", + "subcategory": "HADR型", + "text": "使用虛擬網路名稱 (VNN) 和 Azure 負載均衡器連接到 HADR 解決方案時,請在連接字串中指定 MultiSubnetFailover = true,即使群集僅跨一個子網也是如此。(如果正在實施FCI或 AG)", + "waf": "可靠性" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "SQL Server、Azure SQL 資料庫和 Azure SQL 託管實例支援對行存儲表和索引進行行和頁壓縮,並支援對列儲存表和索引進行列存儲和列存儲存檔壓縮。", + "guid": "61623b77-5a91-47e1-b348-ef354c27d42e", + "id": "A04.01", + "link": "https://learn.microsoft.com/sql/relational-databases/data-compression/data-compression?view=sql-server-ver16", + "severity": "低", + "subcategory": "SQL 伺服器", + "text": "在適當的情況下啟用資料庫頁面壓縮。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "默認情況下,數據和日誌檔被初始化,以覆蓋以前刪除的檔留在磁碟上的任何現有數據。首先通過對文件進行清零(用零填充)來初始化數據和日誌檔。在 SQL Server 中,僅對於數據檔,即時檔初始化 (IFI) 允許更快地執行前面提到的檔操作,因為它會回收已用的磁碟空間,而不會用零填充該空間。相反,當新數據寫入檔時,磁碟內容將被覆蓋。", + "guid": "8bbac868-155a-4bb9-863e-9908ae28c84c", + "id": "A04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/database-instant-file-initialization?view=sql-server-ver16", + "severity": "高", + "subcategory": "SQL 伺服器", + "text": "為資料檔案啟用即時檔案初始化。", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "建議獲得最佳性能和可用性:將所有資料庫遷移到數據磁碟和日誌磁碟", + "guid": "33b6b780-8b9f-4e5c-9204-9d413a923c34", + "id": "A04.03", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/move-database-files?view=sql-server-ver16", + "severity": "中等", + "subcategory": "SQL 伺服器", + "text": "將所有資料庫移動到數據磁碟,包括系統資料庫。", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "b824546c-e1ae-4e34-93ae-c8239248725d", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices-checklist?view=azuresql-vm#sql-server-features", + "severity": "低", + "subcategory": "SQL 伺服器", + "text": "將 SQL Server 錯誤紀錄和追蹤檔案目錄移至資料磁碟。", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "d68c5b5c-2925-4394-a69a-9d2799c42bb6", + "id": "A04.05", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/server-memory-server-configuration-options#use-", + "severity": "高", + "subcategory": "SQL 伺服器", + "text": "設置最大 SQL Server 記憶體限制,以便為作業系統留出足夠的記憶體。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "8d1d7555-6246-4b43-a563-b4dc74a748b6", + "id": "A04.06", + "link": "https://learn.microsoft.com/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows", + "severity": "高", + "subcategory": "SQL 伺服器", + "text": "在記憶體中啟用鎖定頁。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "633ad2a0-916a-4664-a8fa-d0e278ee293c", + "id": "A04.07", + "link": "https://learn.microsoft.com/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store", + "severity": "低", + "subcategory": "SQL 伺服器", + "text": "按照最佳做法在所有生產 SQL Server 資料庫上啟用查詢存儲。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "1bc352ba-aab7-4571-a49a-b8093dc9ec9d", + "id": "A04.08", + "link": "https://learn.microsoft.com/sql/relational-databases/databases/tempdb-database#optimizing-tempdb-performance-in-sql-server", + "severity": "高", + "subcategory": "SQL 伺服器", + "text": "確保遵循所有tempdb最佳做法。", + "waf": "性能" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "1bb73b36-a5a6-47fb-a9ed-5b35478c3479", + "id": "A04.09", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "高", + "subcategory": "SQL 伺服器", + "text": "計劃 SQL Server 代理作業以運行 DBCC CHECKDB、索引重組、索引重新生成和更新統計資訊作業。", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "連結中 SQL Server 功能清單的一部分,當 SQL Server 實例位於 Azure VM 中時,建議使用該清單。", + "guid": "816b2863-cffe-41ca-a599-ef0d5a73dd4c", + "id": "A04.10", + "link": "https://docs.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "severity": "中等", + "subcategory": "SQL 伺服器", + "text": "限制資料庫的自動增長並禁用自動收縮", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "受約束的 vCPU 虛擬機 (VM) 是一種 VM,其中 vCPU 計數可以限製為原始 VM 大小的一半或四分之一。這使客戶能夠降低軟體許可成本,同時保持相同的記憶體、存儲和 I/O 頻寬", + "guid": "e36c1c81-770a-4fbc-9c0d-43918648d285", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/constrained-vcpu", + "severity": "低", + "subcategory": "成本優化", + "text": "使用受約束的 vCPU VM 優化 SQL Server 許可證成本", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "成本" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "Azure 混合權益允許你以 Azure SQL 資料庫和 Azure SQL 託管實例的折扣價交換現有許可證。Y", + "guid": "7ed67178-b824-4546-ae1a-ee3453aec823", + "id": "A05.02", + "link": "https://azure.microsoft.com/en-ca/pricing/hybrid-benefit/", + "severity": "低", + "subcategory": "成本優化", + "text": "利用 Azure 混合權益,最大限度地提高雲中本地許可證的價值", + "waf": "成本" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "SQL Server IaaS 代理擴展 (SqlIaasExtension) 在 Azure Windows 虛擬機 (VM) 上的 SQL Server 上運行,以自動執行管理任務。", + "guid": "9248725d-d68c-45b5-a292-5394a69a9d27", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/virtual-machines/windows/sql-agent-extension-automatic-registration-all-vms?view=azuresql-vm&tabs=azure-cli", + "severity": "中等", + "subcategory": "天藍色", + "text": "註冊 SQL IaaS 代理擴展,解鎖許多功能優勢。", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "加速網路通過 Azure 的內部可程式設計硬體和技術提供一致的超低網路延遲", + "guid": "99c42bb6-8d1d-4755-9624-6b438563b4dc", + "id": "A06.02", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "severity": "高", + "subcategory": "天藍色", + "text": "確保在虛擬機上啟用了加速網路。", + "waf": "操作" + }, + { + "category": "Azure VM 上的 SQL Server", + "description": "Microsoft Defender 檢測異常活動,指示訪問或利用 SQL Server 上的資料庫的異常和潛在有害嘗試。", + "guid": "74a748b6-633a-4d2a-8916-a66498fad0e2", + "id": "A06.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", + "severity": "高", + "subcategory": "天藍色", + "text": "利用 Microsoft Defender for Cloud 改善虛擬機部署的整體安全狀況。", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "安全" + }, + { + "category": "SQL 託管實例", + "description": "與 SQL Server 相比,SQL 託管實例中引入了一些 PaaS 限制,並且存在一些行為更改。回顧和理解這些差異非常重要。", + "guid": "78ee293c-1bc3-452b-aaab-7571849ab809", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/transact-sql-tsql-differences-sql-server?view=azuresql", + "severity": "高", + "subcategory": "遷移前", + "text": "查看 SQL Server 和託管實例之間的主要區別", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "SQL 託管實例具有取決於底層基礎結構和體系結構的特徵和資源限制。查看這些限制非常重要。", + "guid": "3dc9ec9d-1bb7-43b3-9a5a-67fba9ed5b35", + "id": "B01.02", + "link": "https://docs.microsoft.com/azure/azure-sql/managed-instance/resource-limits", + "severity": "高", + "subcategory": "遷移前", + "text": "查看 SQL MI 的容量限制", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "性能" + }, + { + "category": "SQL 託管實例", + "description": "託管實例和源 SQL Server 之間的實例設置可以不同。請務必查看可能影響性能的差異。", + "guid": "8bc178bd-c5a0-46ca-9144-351e19dd3442", + "id": "B01.03", + "link": "https://medium.com/azure-sqldb-managed-instance/compare-environment-settings-on-sql-server-and-azure-sql-that-may-impact-performance-e90c21fa9b08", + "severity": "高", + "subcategory": "遷移前", + "text": "比較 SQL Server 和 Azure SQL MI 上可能影響性能的實例設置", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "性能" + }, + { + "category": "SQL 託管實例", + "description": "評估遷移到 Azure SQL 託管實例的本地 SQL Server 實例。評估工作流可説明你檢測阻止遷移本身的問題,以及部分支援和不支援的功能", + "guid": "9eb72281-37a1-451c-9bb4-e4f1814287d5", + "id": "B01.04", + "link": "https://docs.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "高", + "subcategory": "遷移前", + "text": "運行數據遷移助手或 Azure Data Studio 遷移擴展,以檢測可能影響託管實例上的資料庫功能的相容性問題", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "SKU 建議功能可以評估源 SQL Server 性能和利用率特徵,以推薦大小合適的 Azure SQL 託管實例,以説明完成遷移過程。", + "guid": "ca8c26c9-b32a-4b5b-afc6-898a135e3378", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "高", + "subcategory": "遷移前", + "text": "利用 SKU 建議工具為工作負載選擇合適的計算資源。", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "性能" + }, + { + "category": "SQL 託管實例", + "description": "查看評估中每個資料庫的不支援的功能、遷移阻止程式和重大更改", + "guid": "97e31c67-d68c-4b69-82ac-19f906d697c8", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/dms/ads-sku-recommend", + "severity": "高", + "subcategory": "遷移前", + "text": "查看並解決 DMA/Azure Data Studio 中突出顯示的問題", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "可以使用自己的 SQL 託管實例預設 DNS 區域 .database.windows.net 進行更改。但是,其 FQDN 的託管實例主機名部分應保持不變。", + "guid": "eaded26b-dd18-46f0-ac25-1b999a68af87", + "id": "B01.07", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/frequently-asked-questions-faq?view=azuresql-mi#can-a-managed-instance-have-the-same-name-as-a-sql-server-on-premises-instance", + "severity": "高", + "subcategory": "遷移前", + "text": "由於不支援更改託管實例名稱,因此規劃連接字串更改", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "在配置託管託管實例的 VNet 和子網時,還有其他要求。", + "guid": "c9a7f821-b8eb-48c0-aa77-e25e4d5aeaa8", + "id": "B01.08", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-existing-add-subnet?view=azuresql-mi", + "severity": "中等", + "subcategory": "遷移前", + "text": "查看託管實例 VNet 要求", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "儘管可以將託管實例部署到IP位址數小於子網公式輸出的子網,但請始終考慮改用更大的子網。使用更大的子網有助於避免將來因缺少IP位址而引起的問題,例如無法在子網中創建其他實例或擴展現有實例。", + "guid": "dc4e2436-bb33-46d7-85f1-7960eee0b9b5", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/vnet-subnet-determine-size?view=azuresql-mi", + "severity": "高", + "subcategory": "部署", + "text": "確保託管實例子網具有足夠的可用IP位址", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "SQL 託管實例具有取決於底層基礎結構和體系結構的特徵和資源限制。SQL 託管實例可以部署在多個硬體配置上。", + "guid": "c8defc4d-721d-431d-850f-b707ae9eab40", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/resource-limits?view=azuresql-mi#service-tier-characteristics", + "severity": "高", + "subcategory": "遷移前", + "text": "在 MI 的「常規用途」層和「業務關鍵」層之間進行規劃", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "性能" + }, + { + "category": "SQL 託管實例", + "description": "使用自動故障轉移組功能,可以管理託管實例中的用戶資料庫到另一個 Azure 區域中的託管實例的複製和故障轉移。自動故障轉移組旨在大規模簡化異地複製資料庫的部署和管理。", + "guid": "ed329079-8bc1-478b-bc5a-06ca7144351e", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-sql-mi?view=azuresql-mi&tabs=azure-powershell", + "severity": "高", + "subcategory": "遷移前", + "text": "根據 RPO/RTO,確定是否需要實施自動故障轉移組。如果是這樣,請規劃第二個實例的部署屬性。", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "可靠性" + }, + { + "category": "SQL 託管實例", + "description": "可通過多種方式將應用程式連接到託管實例。查看並瞭解優缺點,併為您的應用程式確定最佳方法。", + "guid": "5d226886-d30b-466c-97be-595190f83845", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "低", + "subcategory": "遷移前", + "text": "查看資料庫和應用程式之間的連接設計,對其進行測試和驗證", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "比較遷移選項,選擇適合業務需求的路徑。", + "guid": "c586cb29-1ec1-46a1-b076-ef9f141acdce", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-overview?view=azuresql-mi#migration-tools", + "severity": "中等", + "subcategory": "遷移前", + "text": "規劃遷移方法。根據「資料庫大小」和「應用程式停機時間」視窗,選擇首選的遷移方法。", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "驗證源和目標上的數據相同后,可以從源環境切換到目標環境。請務必與業務/應用程式團隊一起規劃直接轉換過程,以確保直接轉換期間的最小中斷不會影響業務連續性。", + "guid": "579377bc-db37-451a-a2ac-1fad66e15d4d", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/dms/tutorial-sql-server-managed-instance-online#performing-migration-cutover", + "severity": "中等", + "subcategory": "遷移前", + "text": "與業務/應用程式團隊一起規劃割接過程,以確保割接期間的中斷最小,並且不會影響業務連續性。", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "可靠性" + }, + { + "category": "SQL 託管實例", + "description": "託管實例的時區只能在實例創建期間設置。默認時區為UTC", + "guid": "4a2adb1c-3d23-426a-b225-ca44e1695fdd", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/timezones-overview?view=azuresql#set-a-time-zone", + "severity": "高", + "subcategory": "部署", + "text": "確保在實例創建時自定義時區設置。以後無法更改它。", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "Azure SQL 託管實例中的伺服器級排序規則可以在創建實例時指定,以後無法更改。默認伺服器級排序規則為 SQL_Latin1_General_CP1_CI_AS。", + "guid": "deace4cb-1deb-44c6-90c3-fc14eebb3693", + "id": "B04.02", + "link": "https://learn.microsoft.com/sql/relational-databases/collations/set-or-change-the-server-collation?view=sql-server-ver16", + "severity": "高", + "subcategory": "部署", + "text": "確保在創建實例時選擇正確的排序規則設置。以後無法更改它", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "使用本機還原選項將受透明數據加密 (TDE) 保護的資料庫遷移到 Azure SQL 託管實例時,需要在資料庫還原之前遷移 SQL Server 實例中的相應證書。", + "guid": "829e3eec-2183-4687-a007-7a2b5945bda4", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/tde-certificate-migrate?view=azuresql-mi&tabs=azure-powershell", + "severity": "中等", + "subcategory": "部署", + "text": "對於已啟用 TDE 的資料庫,在資料庫還原之前,需要遷移本地或 Azure VM SQL Server 中的相應證書", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "只能從在伺服器實例當前運行的 SQL Server 版本上創建的備份還原系統資料庫。遷移到 SQL 託管實例時,情況並非如此。Azure PowerShell 和 DBATools PowerShell 庫使你能夠輕鬆地編寫腳本,並自動執行和自定義遷移過程的所有部分。", + "guid": "3334fdf9-1c23-4418-8b65-275269440b4b", + "id": "B05.01", + "link": "https://learn.microsoft.com/azure/azure-sql/migration-guides/managed-instance/sql-server-to-managed-instance-guide?view=azuresql-mi#backup-and-restore", + "severity": "低", + "subcategory": "遷移", + "text": "不支援還原系統資料庫。若要遷移實例級物件(存儲在 master 或 msdb 資料庫中),建議編寫腳本,並在目標實例上運行 T-SQL 腳本。", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "使用將資料更改從源持續複製/同步到目標的遷移選項時,源數據和架構可能會更改並從目標偏移。在數據同步期間,請確保在遷移過程中捕獲源上的所有更改並將其應用於目標。", + "guid": "e3d3e084-3276-4d4b-bc01-5bcf219e4a1e", + "id": "B05.02", + "severity": "高", + "subcategory": "遷移", + "text": "確保在遷移過程中捕獲源上的所有更改並將其應用於目標。", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "確保應用程式能夠在資料庫遷移后成功連接到託管實例。", + "guid": "b5887952-5d22-4688-9d30-b66c57be5951", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connect-application-instance?view=azuresql-mi", + "severity": "中等", + "subcategory": "遷移", + "text": "測試應用程式與 MI 和資料庫的連接", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "高可用性是 SQL 託管實例平臺的基本部分,它對資料庫應用程式透明地工作。在節點降級或故障檢測的情況下,或者在每月定期軟體更新期間,在 Azure 中使用 SQL 託管實例的所有應用程式都會發生從主節點到輔助節點的故障轉移。", + "guid": "90f83845-c586-4cb2-a1ec-16a1d076ef9f", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/user-initiated-failover?view=azuresql", + "severity": "高", + "subcategory": "遷移後", + "text": "請考慮在 SQL 託管實例上執行手動故障轉移,以測試故障和故障轉移復原能力。", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "可靠性" + }, + { + "category": "SQL 託管實例", + "description": "在部署到生產環境之前,確保應用程式具有故障轉移復原能力,將有助於降低生產環境中應用程式故障的風險,並有助於提高客戶的應用程式可用性。", + "guid": "141acdce-5793-477b-adb3-751ab2ac1fad", + "id": "B06.02", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/auto-failover-group-configure-sql-mi?view=azuresql&tabs=azure-portal#test-failover", + "severity": "高", + "subcategory": "遷移後", + "text": "如果已實現故障轉移組,則在故障轉移/故障恢復期間測試手動故障轉移和故障回復,並測試應用程式連接行為", + "waf": "可靠性" + }, + { + "category": "SQL 託管實例", + "description": "這提供了更多的專用磁碟 IOPS 和輸送量", + "guid": "aa359272-8e6e-4205-8726-76ae46691e88", + "id": "B06.03", + "link": "https://techcommunity.microsoft.com/t5/azure-sql-blog/storage-performance-best-practices-and-considerations-for-azure/ba-p/305525", + "severity": "高", + "subcategory": "遷移後", + "text": "優化常規用途託管實例的存儲性能", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "性能" + }, + { + "category": "SQL 託管實例", + "description": "許多組織都有要求在內部創建和管理證書或加密金鑰的策略。如果你的組織具有類似的策略,則此體系結構可能適用於你。如果你的客戶需要對這些項目進行內部管理,則體系結構也可能適用於你。", + "guid": "35ad9422-23e1-4381-8523-081a94174158", + "id": "B06.04", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/data/sql-managed-instance-cmk", + "severity": "低", + "subcategory": "遷移後", + "text": "啟用客戶託管的 TDE,以便僅創建自己的副本完整備份", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "安全" + }, + { + "category": "SQL 託管實例", + "description": "通過維護時段功能,可以將 Azure SQL 資源加入到工作時間之外的預計劃時間塊。", + "guid": "33ef7ad7-c6d3-4733-865c-7acbe44bbe60", + "id": "B06.05", + "link": "https://learn.microsoft.com/azure/azure-sql/database/planned-maintenance?view=azuresql", + "severity": "中等", + "subcategory": "遷移後", + "text": "規劃 Azure 維護事件", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "操作" + }, + { + "category": "SQL 託管實例", + "description": "通過使用長期保留 (LTR) 功能,可以將指定的 SQL 資料庫和 SQL 託管實例完整備份存儲在 Azure Blob 儲存中,並配置冗餘長達 10 年。", + "guid": "9d89f2e8-7778-4424-b516-785c6fa96b96", + "id": "B06.06", + "link": "https://learn.microsoft.com/azure/azure-sql/database/long-term-retention-overview?view=azuresql-mi", + "severity": "低", + "subcategory": "遷移後", + "text": "配置長期備份保留、查看備份和從備份還原", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "可靠性" + }, + { + "category": "SQL 託管實例", + "description": "通過使用 Azure 混合權益,可以節省成本、現代化和維護靈活的混合環境,同時優化業務應用程式。", + "guid": "ad88408f-3727-434c-a76b-a28021459014", + "id": "B06.07", + "link": "https://azure.microsoft.com/en-gb/pricing/hybrid-benefit/#overview", + "severity": "低", + "subcategory": "遷移後", + "text": "利用 Azure 混合權益和 Azure 預留(如果適用)。", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "成本" + }, + { + "category": "SQL 託管實例", + "description": "如果沒有威脅防護,高級威脅防護是 Microsoft Defender for SQL 產品/服務的一部分,它是高級 SQL 安全功能的統一包。", + "guid": "65d38e53-f9cc-4bd8-9926-6acca274faa1", + "id": "B06.08", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-overview?view=azuresql", + "severity": "中等", + "subcategory": "遷移後", + "text": "利用 Microsoft Defender for Cloud 改善整體安全態勢", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "安全" + } + ], + "metadata": { + "name": "SQL Migration Review", + "state": "Preview", + "timestamp": "December 13, 2023" + }, + "severities": [ + { + "name": "高" + }, + { + "name": "中等" + }, + { + "name": "低" + } + ], + "status": [ + { + "description": "此檢查尚未查看", + "name": "未驗證" + }, + { + "description": "有一個與此檢查關聯的操作項", + "name": "打開" + }, + { + "description": "此檢查已經過驗證,沒有與之關聯的其他操作項", + "name": "實現" + }, + { + "description": "建議已理解,但當前要求不需要", + "name": "不需要" + }, + { + "description": "不適用於當前設計", + "name": "不適用" + } + ], + "waf": [ + { + "name": "可靠性" + }, + { + "name": "安全" + }, + { + "name": "成本" + }, + { + "name": "操作" + }, + { + "name": "性能" + } + ], + "yesno": [ + { + "name": "是的" + }, + { + "name": "不" + } + ] +} \ No newline at end of file diff --git a/spreadsheet/macrofree/checklist.en.master.xlsx b/spreadsheet/macrofree/checklist.en.master.xlsx index ecb012a76551329fa4c40f878d6d921d9ce6daf0..edbf25bc9c1796caaaf5f8adf577a442dda32d6f 100644 GIT binary patch literal 297125 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%0D&s$QUcnIIzo8rZNdT93jf8-TzT?aSv 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%0ApRbZ>B>?ERuwi41 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 z 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 UE&6Nlh6nrtsbWVM$Ugx74@tIn^8f$< literal 294225 zcmZ6yWmsHY6D=4lcyJHylHiiy4#5I67A&~CdvJFem*DR1!QG{CcXyZRy!VE0W_~m@ zobz;5tyQx2-lxAyK|y1_d-o3Row{j|ir9}1Bp>i!mEadD_@!^9_ubaY+Ky4j+WNDz zg}F?G3}Pn}s>tiN{bfs~GZJQ!>Fl)uHwjLTD1Bi^|0j3Fj>tux6{fHztU=XoawqnH z?tD+Q0r7Wrh+zwUl)Vc($L zFRu4bOtnuiWv01HFuRQK2elB_S>5Zvw8uWceERH(u z{B_trTHef;3Df^I(s9vgl((Beo(8drL5PF=!MJ&BpLvFm1)(P6f(q@pj??!-y1 z0a&Af4_iK}YCY#2dDBG9li)~riux&kdWg_?JvIv0r;%9}5lOB-SGk|D5+*r!Kg3iZ z6B@x48oe2H6R&W~r)IS*;7D)~JaH_~_SFu=e$n={%Q8(0|ppP$Tsp*vQSvLfI_ZNu5~ zQa#d~uO|}Q68ItMGGB?tO>3K@5*Lr{L>m=nK??VsB3}yuQzBFg;c8Y`o=pIXZ7-L< zSHOqk87)n-H69%}7mSfpKq=5n(T?YtiuXahS*1LUVw$T{12ukDW;etFpDSE7A?LZt z#j0JgC^;aC=9p|yL4&hTH4((Y|9V8X5XCH80dY|{C*Z&uZ`+`wM&@HlQC2}Jt5eeF z>_frkvU*@^kK~GB+E}Mqhc2QpB_R)K>g39cuA|4VvcC{v6t}j~w6kNL#o?a;2q_`Y za%UXO47sY(a9Y#HVa6ui?nTRTz}Pvh+VpTIlkp`Z)%k6?aNk$MQU1e@ln&I7z4i6p zh>jC$@57Qt#4XB>PaE;wcCSV|_e6V$naaYpqe~eh>~9($C2ssQEY7R^IY?vM;)&&= z8XoZuoGUl_JFzGatd{yekMwu4)EaXY?~<3^)8GA8GphqUcR*@ub*LPP4VBZ}eZ*9Z z`Jg=R`2D7H-gGyLD4Vn9?8llD-3ex!fSSKVN`L+ZgH6J3;a=`{qlDoUlE`0(Hi$w5 zs6^sETI-redm;&PiO^zCg3jP0)vzD9HE;=D%BcGzT_ zr!61d#tE5yP71e%t+gAQ-x>8+piUT8ax-R2_ybqZWPk76JH7BZC?U*d%h({+4%bO% zfiNnvAF)TVP=z>6g6L;Ms^X{`rE`XlZ4>%{{5Jnc0EIcChyxw7(y%iaxNkLK@uOMQ=!x}85e&(I@F&~qb zD6Xsp$7m9y8fRyJIiSyM^=B6CD+sN$InDbp79cJ6pp2xp{eE_S2U|gp-7H^KfEGBz zh2Mvs>32kQQqAsO*C!Qh6gCNc?vQ+nG#zEqMVl{^%gu&QQy6zUr}(a$8WfYde=ZmKy@|RH(<-sP`?Eyn^by#i}k7p;Gm5wO!YgA1#~bvR3TqA(iE%Jm&AJn4MBnP z{5@dgA=5ZEcE#4<9AH((XLT(aEf7V|%N^XQPX{k2oVAe_?x&}X8JZj*I^%+YSiFYC zRe%)7%a8H|PY%ZmcWSwlAN(}jjB~Q@&zrgk&s1x{+wjc z?{7|uCinAxT>lw9I*}lb0`*XobKJgT#D@MRU#iT|%Qe0_J}u0R_u~LNZzxrmOq{X! zDn=^%9Gt{y&$8a;uZTNM=l}#dS;Ie{(QGY8KCk<)X{p-KYRc4SU7#CQilPzr8oOp; z#@<7xua50w&PKCpY5{Xu*9F_{(DF|f{o`YHlA&^{I6^%dgxmfMPE{k+G?ppXuDX9~ zdG-GOTX{zD@@jfEjSxo_6*G^%yfUSEHs#a>pFzA-set)%b}+@t(Hbs#)o0K_BsY@ zM!+S0TFk1cvQ%xw5<~5vPVS6}zhLdGi$1>impLovOl?aQDFbRGDbM-Qc!g3RUE3kY z)3@w}8-mC@M_BsdGFHXikDRanKMioa!Sc284(gq_F5Wxb|1-**tZdEfj13Iz?HK?2 z_1`?}Zna2Qtc$O^SK&%xPrG6u$Cf-hzS_TJ=rd5a>Ey&^{(AFp z-PRC$tNW_g3M9x?x<1kRIPG;}sSQ%9rQ4Fx{CK*(bGDE&(h1^j#12$yonI}jdpun* z=BT_`Ov5x#^nY|9IM6ELSbg3+9a-f&P0jke&A6fUvg?%e5?Y+|;H+BCp%DDI`P@3^ z@hDk#SpIsS_Ne(9Xz$?WWc+gWK|qMkI+#b00a>tPI}x#jiLs!>QVSNwyUTkUz* z$!e+Hz;dnLKN;n@Ek^s+=+*JY=^BL6taM-9)Y8;G?=&j7m83DWK{B-C`dW1OSb}P% zwCe15lhMAHqE+uTEyr7a$nVe}nfoETYyx`10qwx6t-s#3l<%2Jq5g{B;yCM+$h2H4 z{k6G#>v3nI=yAA5tF08|RWjI>*0kp&OG|H~K}_@#pZXF%tG!$0_H#Yb#x5yK>on!{ z)ZK#rq^KRI?>V#Wbnr0H<1X)X>T$GD+akGrDYX3|-&2dj+hDn@1O&YPJmk6(*>*bO z4npiF@x<}tM-WmW*&BSHV1V(WhkC{oad!O(i|WYSIfTpiI*~@%CK^PfaX z_KQp^!Yx0|bEJ-r<+DRW3(Ccw(f+7s*d~*0sb$WqcT=QiCLNMVv|{25=K)m4lhsf=~t0{kB`sh6ME>4Df=|;xqEV{hQ za?Z!|^~SUqTWxPnEp-Sbm+RdbF;1U(o%}6e(fvB{Y0t~qqAaG@*P>vDm8Zjo*wIC9 zwWmg{V-znhkME#qVjiVS3j#TH;hx2sNO?p~3Fkn++q6H7{wQgv8VGh2?nfsqxIBid zSBbn+dN<-k)n2Y~o^H|NoEO;e|L0~tS1O6SIe!G$`cawslN8Ie$fd7VUOJZcH;87< zh~a{ty==d_TD$&me+s;nd_K!LC<=d`T|kYrynp}nOnCR`c6N)hc6wQM5J|+&$$RkU zs-SUSK83H*StGDR#o9HUA7%vhS)8Bm?3Uo{)@kkZbg?}!k_i3ovG3+|WewX4K?a4K zi5F>#8Yl9Q!x?vdU&n7v=U4mcul9B*FE3)BK!}$YZIV&Qr)SX3X}TM&yI3bWJS{ql zFOze!JjfH8e<691*8^gNL>L(E-Q1TPl@V0MY1`hUq=(Nw$Vv&5W$!pFKS7YSM{Kpi zy*T6g$uXewwBT@X8Hc@lnINQ%IwY^E;B=;<$~>Se;2rTEwepd&`gd2^*{9H@(hsXh zqWlV?C>z#n%NJhq?U6eHGVKvC@)wGwt~A9mN(6&1(s4?JX)}hkjqI4u(^xVB6DZu3 zt#T4%lqz+skN_{gmz5&&jt-@hg zv(}zQD#l6pdo)kUpKNm62Z^5C z^m-hR0@DZCFQ1ISZW_7K9s!Nf;fw2alZFv{(1q2fo?W>a{Vsv@)6E?Zz;x zX)*pyzaxJ<%cVtWAhaX-^{K?>T1%1gDr4IGaqb|e>g3U_RL9h%>hcNnrfsd!X`Rp3 zdXFA2ArT#g=jR=YL4ZRIYD}cDT-PP@2@l2C(oIR}`dn8w|5AYg>tcp*;SF~&CR0c> zA!t50TAlxM^rhfM>L?ARxa+a@LF_Q?Wmm(Y>dGtmqqGL%7u@F?TG;HqHiY0qM~SXLq5ocI?dP*>d|k!M zG&@n=pn75=g3jiKPM95m`ZCE4v(nSBZ!4&&j*Ec#1|w^wFbJ0R|jb)_QW3G?y1lT7=L>Exk5X8fO}gNtYyvw=iE@Rqd9W7JR|sNF}5?Kkx5Y*Vuu^jnTtT3^Jnz zzS_k-`aY~O(wmqv@PF6g8(1!V@gO$cmGuy{1+kCYo(6qu=jU}Vbx3h9x2Q1toJ~}6 zVvM+JXL`k9Bf4j?B`~?TN3Uu>C}Pz-zWDj7j{C$S8dFP^0_Ku8nw4maGBlJ)N0Nbu z=-X-}h93QL54#HityDqI_W|j_@x^pteJg#dOkDjr2U_RgBGFad2y%pT3Y`|FZTqR! znEVRQ(m+`)M{;V=Et4*`#g;B^V|~lSsK}9Al?LHyc)(2_K0fcQXudRC4J`7pps?F! zKtzt|@9YA79Ss`cz)rnN8jW~BFhRTyIXFQiIu!7Wn_bQq zEcm)2W7jw~Qdh%J*(75j;^gr_s;fR3n!%zgvYGgAoDuf?YE0`eL__`(7fjgITpYKF z9>zjB44E-Pl&rME7`F5n7xXd`arMlkXd9QZzCQl6+sjBpAEe>3(vzYZPOMJ7yo$BS z*bSw(>sHD?)Y_13Lt!153p~;kO(cr6WP~$T@;RpVKx=39HSEO&w{49le0+$Bd}Kkh z!E)0Y)lH%fORyXj!BiSXG$85H*nwn=`1pYS27Q7zkkOakLlO)l+%kn4`r zMw8X)fopk7HgVF666dY_pT|3a-s01GA>LsWdMwLTe1M+8>cQsd{K>&3u>!o-b z+F}+O@|{LXqoq&0@xz8Np+@prlnPt!%6JxdLh591Wx`TbWniECsdO-ME`~;Kk;SJD zI&;iiQsb#J{_)td_Df>8q{!e0T_@|SnEZUmJ+vLnT!zUQ8HSiX`z#?5x}bjb8APX}1+c`jT;*cfZ)w64 z&I5_hDPgW_K8+e5?h9_fiSl1k+B{beL~_>C&n!K+IaTQzeLV4S7GgriTN>)pY%Q}I z8GlU;2?$JE0a(NF4fs1Db8QJ)_xr9ziT@JT+JN!ww8N$v0fZ1UlOl{hwZLsoe##z4 z+H*tw_&?+MSX^M^AO0Grme-PlJo(U{h>9bmGZrSPaVK_kYO86HjTYQ#<)rX&TJKPg zYau4%u-x``O56yv6f++aJ3(wk_W+f#-r4;A`JCioQ}C)Udz?5j@QaFtJ}RBItyVn4 zI+?DZf=K4+ZZ5S(HYMo;6!8D%o3SMQRbMmub0s~$u4L9z110I5Z)dt%OpA5y%Vb;g zfarO?=|b2JMPu#`7HR}jK3UkDHQf_b#v<6*%Q?x@rr=#)_8KuGx_m#3lwo7QR_<7g z>bD(A&-I;L;s<||!kcm;Kd;~ax~qjT%&W6XC%@yixVc0eaXqPs*Y`PA0)^>GQ!mWJ znRd2JySn9+i4e@9>V+ql^Ut$OpV4i^kiGyPyydLdHHDv@qaMylt~b%9BT-#2Mam9x zsgiBvrrTqxBvh3sa#MDh$DaF*B_y5&{v{UvWXQvLS&rw?pqG|KuJUj?g;1Cqx-LJ> zQ4;k4;-LeX>?PTqQ)3w-Yr>;<$dtKNL0^P+6N#qPjPamJP$VbTx%ZgWx~A`)GwS&{ z$;KvHkQ`AEQ&C9j{(w~86HW!iWVyBrg)Sq*)l%+6H0rtcznrqq!P?l=48EHK5<5{K zFVOH49d4$(KO)!=+lRBdE$Dn*Jdq6>&9TfORNx3Vs9iWl(VN%-u(6SE$iR54O{qJB ze(@1Od+@+LI79DE2}4PbX|ZTEn&Q&xW&l}ea*45BFD8v;;U3;1O`bxyIxmCvI2w#h ziS4y8AA!&OYsyZcAcAFAu5YHv{zLQ3ap_W0a}^-2ltFohQ`|E;rAwiWORVOqYc>azF&PyX0zvB;KHanmJtA{|E&T z|6MXOCMhmcsdSF`^xI8e*;9iOEo9$HQ52LAh^v}TDRc+oAanQia%XBRpPS_Y2$!4B zl0p)=K)X=KZWZ VzHj8Ahyw6Z@*}ix%O+)$t+Yjt4!8f~)T3T;4ITFOQHe;ImC15fd-Lpz|ou#5bxsHNl`;G>2MPChwY*6Z)-sf6!a@ zx5p5Gr-kJYvTh7%Lo8xFejnns5N-w}_{vh@Frs_ELM%wN7M_6C; zA+yivYEVsN;gIh^0>XTL0q)>;&}`F+aMEMZEJU>0A^P#GUt&Emr3&*U!gu_}QQxTk zQu>?p^_y`&nCdTosZK>D17prgt%*3JIfJaJS4!Yg{?cczLZ)B@>f~5UMc|qYkrfSI zi`BRT{TAU933d-czlZ)dZHFK|mc~LPGFZif#vr%U%@`^omxdpXAW!x-jRSB@NMECHG#B%F|(VKx<7P>c7@^^XLF}=FOg}4cQ~}Adp}O5RH{pKL3bBWT>DHxXH>;C9)+||3rC(bQ!-yj?2P&IlNkv)v5**_ zUzj^2%RwbfUcTHlRijWl!#CCH7e&U`xE)O?cR0MaNtZm0z;aRU7xuSIwjCk)j^2KlZdI4{s7xmCLS#OPp4<>IweDndb(a z!LkFQ+-BWlj<>XOJB3cPLE2XxV!g|u{P$5V7w|iU;?#-hH3shSI1IEJ^TP|huIGg~ z1USQYQ7&&_Nuw$c$9hp->Z^G22+py}iTM2L$7t$S^C6*|&{At|Y$VqUAQAd_>k4&L z`$Pt4UT&A=8$vnIhU`vPtQ5EH20$b5jre;ZLv9O04+g@;$&q~L)eE*0OvVXiAl2>fLR*c5r}sN#ioc$2GO zH=f}_BHg|JzSCp%C$3{L(To~@i-1a!q6%K+34j8DZwYJ`T@;JRY$c_=wXJ+;^9TF9 z1;*!Zb<3q~C9@YL{;$16H|}m0=98qJ+ZcCBV-`%jiY1(5D2Zq2k?e?i*G+SiEfs$P z@38*Wf=+TpXZaKTIX$@lm~;}glTAYBl#f%6PD0BEqgab2(#&o9=eegK9z1uj;Gt%U z$8-Sp5coR5e%Q|hve#^)HsRB~_jQbWKULl7+D5A{xn(oU5Ia+>?_xp}C%pH+@P8|h z1HCBi|AznjW*kfBd%p%ae7xxcz7=B5p3M0+T+S_#-=h^c=QVayPV-iyDPzPoXJ4>B z3dFnsHW2tGz$R@(vGNE`OSzVgwaXu}1!T#s9lhMVemb%lm z+sr+f>C2ke1~9|71aAQ-2uNRXx>l63HVpY!gmSm(n4r%kWzjJ zes`*{eB3gg3Pu40Sz744Zn&GjBG6&FdXMJ&sGm)Ix?^9%R+?+uY|{)yc9Vd}YSFe( ze)L_coC36|R^LRC=uz#Rp4m|0(gjG5Lr_c0IkFNJdBKy~&X!=!O8H}e8k~KE6_EaA z1rvs9wC>Y4h2gR%XR6;q1*dn5I!cKMtJZ#;t-?BEOLE7SGj1Hf$IXYer@B~z%>WL- z?+pm#8PW%5ZI$g(w$C5(AU8a@GX{e@U>ny!*17S+dACXXDEmf5Rr+N;LDFo|X-q4!!w8Vfe&8 zMqr(B9*oGzP5D}f(UakNdTyA|TiIw&mwGU0enp{)Az?M`T9C$=Zy|8CLfHF}2~TiS z5smFm8s`ZgI-Jg&8+%WCvo`Hl8rO95$?@{N`*Lae@5LY)(ve^Y1*_EGE3SzF`vdN+ zIOhE^x*U2VwtJS0MtZuxrU~A1RJS5)sCXA!283lf&oh&(W}p0E_RCyKWBYCY!*>j9a=e1J_e=mEJoP!Os0mg#n9$m*qn8I zzGHX)sC4(5qVn>w$~pDtxoceD{=R$oeK$iyHlA6$j+2`tfg-g2`5Q8depsP><@)E~ zu9qLQt9#C+e-5q_1wY=G_Gwl?Fd5FHQinadHdYae%^>E8B;F1MgqnbC3TY_m1_>hCJ81XfLJj_a(cW8n$0u^El z8gedMSlSngj?tNPXo$&hgznN(*g{Y17aYkO6 zJs@IU=SR+n8QFn1@T(iG+ARDY*twr&xY`GJ=KwacJsbqd+hV%0ZZI7}>28`#P6eR`k zkihAv5JhLcIPIi}lsoXAYm-Aq>G=iY6# zzS&;QqbHb_i~eReajuV*{y?j+U>z3r{(J@BGaJS`_GuEOyMa>-Mi3&NA`~=w;Na%L zl^@#F8N{a62J89`r5X03(_OVrL*En+RD z;ZVijc#wee#)`nz2qs?u63f5=f-2iOD~?>~1muYoARLx4d~*VBZ|NJ37h#)TP~x5H zvMYB03`;MtijpFCa5x?86l6+w`#^*eUfHmK znWz7|cs7MC0S41j{c0vJlsJ zBy;a>uageG!>y5o+^KOpS5qBxRunqaJqT#UbK$!=><;!jQm_Z`0_OFmA7_Y`y0^4p zNAR!VSPl!JsxL`nxBy5`#^N~4BREW2gTJ;XRYv)_X;=2#gDBo|;_E7cBvP3On2`2) zLS-O+KVG<8tUGc)qBsmh4!Zmv>#gFK7!qtqP-nM8o%2wmGWA*s4`$M^7%<=cKl9 zZ^GG~ev7FA{Ywo!zo~mN7eyF~q%h{g@Le}}1N8FR)C+XNsP45~VkRH4JQA1>%>dwb zY)OdNs~$3CU13f{B6zQ;BYbBL=AnXAX-@a?ciO=jvA)gtE9onGQ|zA`|D~YiB2N$e z_d!+W%?K$m!0T4kBu~K%ND0FC&<=CL!qOPfVK_yRQ4~Z*BPUSH9M`=J5QV~Tv@qz1 z624ba2m~*atD%tz(bXV318A<);z>Tg44wPhFi*f1{mej4emAO&>BZ5k##xNjZH%IW zFM}(c3%@?44hx^R~|nqLPHIupFM>6&^+s^bjzA#2%7eu+3`8`r{oOq5PV?xW4e31?wnsK2JVx84CB5SVKT`UW*`3RWB6{NNZ3%Rs9?}c(hb;%N8evgZ-CGd-C+CpBvEqvIpxa<@gn{ zC4*7P4XgqTU|({WDqXWt2-pOz0TcYmmtJPOZOG^CVY9Wtl?%7b$|>rKiC?hZTQp%v zi!QH0X+nd3TY?v&!laQLe;1!bkkD83CI{m?hLm5u_~mwQf;HgZ}zy4E@$fsh`3 zS$rWmZHAz6FSDcL!Sx7GL}R`q!C7Yy!UdNPc7ZovlV$IrgNIu(_3W$R_MGmb+_NTc z-RpN|BpdECUzm|EXiGQ@5naF7&4!vk9mw3EkbZdo4}N1W`i~4P=&;#?i*p&BRlP?j zHcXh;!!PzTtZIp;k5Ec?H9YpUc&ztZ;d`Bh6u9oXp=bE$B`A*#Feg~PFz}y?#hDV* zy_G&yY%##cp`;irE#I7qAqss){HHU=eUvqnohcJUf%TOn;Ei#gr~x7QF$M`0O}xVQ z*c1rui)_cow7qM!lX>=hB_A&JENdvy@M>EXI~c&tdY%0zSo6B-HKcd_Jov_4$$u1q z9NTeFYQD;od}|6vnuvw|Q#n$Ji5II_tk<(MhDTbpI-+?|1>7y+4BwWG;BGmLP!3&P zaKSN}ubRiaD@+p_lKgVDQ@Y=SrBr63^hmwoUeMleNG+u2_*%7b*ak6n%kAX}y7WRVp+GYMg8E^(zgYffjOpt~AS*yN*kTyvE??yezbeW&8>D zf6Mh$todsAfqtq2)^T{5$^00UB`Q>TmpZQESQQOX)W~A+%&={pQu+x-P}CUySrfig zuT&+4AtwaE0v$LXDmv^KW)tCpRQdN;Tb2kC3^nC%sQj3)v96bQDp=RKPYZpF9?Lyu zF6F(-rrQq&=Rt>h)%0EU4|lCBqSgCRED!WXUJNH6E1fP*#O5*$pWD-jJuf^TZdIU4 zH|w2#xD~U_7#M%BP<|iP4Bp94h^QM-sf;bhUwf4GI6lUyRauR*A5>BrFqCZIW3JOA zyvb&^%k1OKPlrqvM$Grosh|TV5fg*oPgS^%il}#84Toa#=+GrGHa!jeLrGE5eJyH* z?@@I=j(sD?#TH_ED>@SHT0)FJBtI!2eG4|8P`(uPUQ^TY|onFu5Trv)gJ_$(Uvn#_6>Gd%(Q>1_u_W| z{+UMklY0O8<;vi9r3$xS8TGrbW%5>vGg38C1ZGn*7xpHVReoCmvwDesV{lJRBJwS} zTxUaw5NUb#Y14BBikQb_|9a&P_Uf`^*}Eis3Ly1kFXGNabI?IgpwVQfT;*WCM5R6j zydY`pXg|ePu}F#6s(mg8AI|L09SgCBz$oLW_s?f?(S;gZWp zG_!YI11^#>7fy{?if;YhW^HGO^E`^u_n$_!FTs++R_LEm{3z9p?{IWg_4fd-&!@mB zg0hTz&vK|M&HQWEsMw&wroLMvRx$@(1K?TqI&&{y>r5w?`_HJ=gIB8CGcuRc#*hnt z;}A@F>NkglnW^RWN$#S(5tS63M`ed>rF!+}YvtK`@JYEk)@ako4U)0?sYmIp-q)oh z#doekb{CI*+0TUy_$9++E$>whyYOS)bb%-MEo_QNWvA?j&uoVE)iZSoNRKtU*W@X@(fTXAv(^6sVwp*yYE^`YR99q4l zCf{=s9t_B3P|lssP;|+XdEZlC=doJMA1uuJ75f3x(ZD&4{py3M_SNLd=8Al+(qY8bmr~273J4c*o)SPAGV!u zZ_KGh3j=!G3Im41iM=j7ZBNG17xx|1A2~D$Uc5cs)K`n2z86&1UP>Ol#KE$se$JT~ zJmcHls)sB6Czj{QQ9lX{ll4;vu_UjDm`ghlM}}sx$Af{4mg9?u1fJM*gZUX z0Zy#>2O+)F6M!aUWdk%#;lJqR`P+lht7&JU(^sP!2C~kiVY3*K4SI0c(c@8hpJ7<0 z&PI?d|8M;Kpl|w=b<^k?ViK$xXHrh*i6J|vvBWM+Hn| z1&!RbdZ}4nu{W)Mao`>YDZ+nI1&Z1ulY%wM9e$M=T1VLc#hC^g^f1Q5aUBjOLz(*k z0)N?{TE`F_%ZFI<{<60^e^?0745ev1pl!>uX6^*3V6_L6^aem?+$U3<`ugPz+t88Z(Jb-&5cYP)MJo#;O%OM5+qKRD0mQRZ`MMqnp1ef?eC zUL1KiIglHBTfS;P%jLE0=&C-;zF*F^bDVT2m;gTb_#7#+UL~$I zm?SD7D}6q8A)>T0-*M$NzIox^B0pVkDy~eac+Q$uTiMKoe(bsEVMqpwq0J<{XEYa8 zFq;mJV6qVIKLp+jhLZST3qpS)L#>&++|=FaV~B6;1E4JE*=W5t<>3nr^|LFt9w{Fp z^?561u#|`XRVwvHzclC!);S*f*_O6XsWIXQ%JpDd}@#tQ+YJHEb#Q0V+#6 zW;(CGHf*2dH8D82t~^>zbwW|IV*m8|bx*50K;gm0uKm&d)~8hsH^%Fb>Q7IeN24dB zKh@-HF@LU|V};Bu{_j`p$iQaT`iF!+@KBIu(|X?UdUR#)i>rdlI%Xa!0{kFsYBO~c zwJ(>fsf<{$d*O|il;FvOa~|Y4X&MW*@sxDOL(t?th>@-NbVwuNo@qu=F>B0m}E*vM_C&IwAUnqj`m zDyxpEwcN6bG|L=|bW9!!(ws-jFOq+m?XzrxcSQlvqKKt*88PLbpw>2>12F$~Yi-}G zYaQa078Rlt_X3`_pWm^3VEy$)xA#GdJz>G)^jF*`-9!GT7u^kJx=8YDZ$dLxJ=6G{ zHOm-KA|I=56K9A-%0_oE!kAPTD~sjkHcPq+#~xuRXJ*T>p;c$6xgpg`m&Vw4Eq1cN zsZF2D_PncLZVCDdTM$~0e8YS?NZg&FAQ!^DVU608v7=0|a-3SkQF959_|HSA!X8wG zP|_T1jHqOO41@IHZ`hBy2O@}aRTLj6FIx+Ww!(%aaCPEwg-qWTb&hpD(;G&9(*>&8 zj_F!AQ~}QTA+EEA7$6Vra?pXx&D7juDZ_Mmv$bVpag~YVHS`VCs)9SKI_ib~)@2~! zt}~td-|kyZI;blV*Aqn(3ZKPr@lEYPXCP$!_S%Gia!Bf=ibm2eA+B?`(uRUSIO|QE zj{EV-V?W`BH=f}|v(U{hx_ViAE)yx=E~nsR6K0V1%OIVzq@49S#&0dtKt6#y%Rg5- zt~@KzsF~vM!yMnRABUl1Ii;G^uAyB1yjTi01`K&{9_-b>5HDHI)X`dUmqv5ULPv z+9P<-R*M;)!!Sy;qLXnWX^fJqM0j4SW!LyM^|+X6X zts4}j%}mj*E8*D#eUAm(#z@DnLyxIT6>AbY?jI&g~k3iMV6JremsSR z;bR@bpLmu@aCS*RIr*BUHl`HxJSx?9yMfF-;zO_ZpIr`rELWebRCD)P6u#fz4f>(Q zzW{Ah@&1UdSj%gf>w2Cr!)x%!1uiLCoAc%gFpLD&*4n;FV0D-tm^cr9qDl}v$Ak_p zx#>US$+g66OJY@U1?zDZ_?-z??~)q+Z=Sf&4}*yq4hy-49^+TZNzuvi-Yw+r+dcb% zZE?|&hVMde<>U;0B74^3Ed4XD`XH^p>DeN+1qVy_RKdZYhI{RK{snO!@H32P*qx880o$aFv$--zr=WV_2EM^u!(lL zru^nHd&x|?6lgy+fwo(`ye9hW>d+2p!S0S~cOm$v?rRc4e#an#>vrWp=0)Lutr(YT zyeQQz7fuyRyv#HRDua^cI~9(OQW4UcE$FV3!FvnuO>qpA_E&G=4Y1P9Vo1MeL|dXu zH`SBlcz}M4*XQY9$;rv zgEXmvp45jIjK!)ZyYNe4-M5?38TFV^i7;Zmq)^c`tdHVhImw9;Nd8}=%Ti`jy9i^$ z1Lq002RKjQDMrTGM;X2mIxa{%^0xeOed--Fq%wC}GGFkvuP1M0iSmT4JADNCJ|~R2 zPM4>0SJH@roU-NHlT zqMO~VmbqS4I)E*EED&S3o+n$TKn)NEaY+%X=vnQ!@(tPJwp4ymvX~=HL}=|O0-O6? z4=rQ`@3(>u=~`^qsJ?Ab0y4%93tcj5w3nh9q)8RcRoMpaV|&SvT>URsP3iYOxrptB zgL75oZ>~abSb-n5D5Ekxubfv9WL$N;DY8)hOr&dCp1j$Z?5II}kz3E8VyGm%J5y?T z$LOe_B;!1BLolim21*IsUJDtxIhYKx(CXTCF?*451f1o|qe zQGhCJ;q|xC`v)nZ>34gB53yT*29I5%>5v$OhNx`>7e%#21Eoml-?m#5aZ6Mi zxA4@yfU^d@3*6cyN!Z0T$+@SwZOob`ZUGYnh3}zm4b=vtrDTQ9<;Rf z(i@SZG&%5(MAetIx$}6WGVi6;565~XP42ta>$6Z-I~q}BthWY&NZY6@>~ zTZ{!?)Z8p_5}4j#V_pec4~%&BTy1P~i##}exHEg1S!||Fm-CY;UHw!jjO(v%IIj_E=^Gm`Gz46 z-5I>qvV{-H=nbs}3E$#Ja+U)J$(I5w`IZ%PE&vxVZaM0H;=)sot`fhL2q5wPADDm= zxE8;K!;;Ex?dj9|y`xr-(G|?~TLFbnyDEf^BO*0K5tDz*A`G*{`zg5QJK;y6#Xz-}3WwqO2 zQMU6m{(RcH5}^5#n|{-tviw1fr|Mh7vt@|v6*u&St4Yx+X^c~hv?uj%9=sjq1eTvw z8-u602~6wfiH*?&34;5|f(8_34}Zkkg&9z!XyaM3?bn^?*~;(dsvpyWOb(sMh83Sa z!1Ff4{@isUn{0Ng{81m|UVnc7()baD^lOy@KS+DTF=KFi9Xy##ik3;mz}6h81->!{ z`G^#W@rD`2oYUN>l7;x)r|&*&OP?MZAJyD?hdTz+5XLJo7>Mn6o+xu^URD~_bGz*1 zr!CVKoWMH<0@54|Mm`WT9z8j7PU40_teCu=Ih2IiIrS|`Qt|Oe#_~0 zQ||fjY`{lC7ka($dqDgLkkN#c;xe*LQ>?x%C&YB47S>2iw^8*tsJXY>6)h}GRUtrB z^&#_gM5wx%R6a15^8Y%rtgQOi5hqTMcLl&^+J+POlK}g_j-2GxfNM$YgvEz8@C7Pm1B(b4P`|=NubS1=Ho#MC9bu-jMMmKIPwd#xJ<8$x)tC# z;@YMhCwsQp_tFDnLB6sbRCdz5U0k%dGqMUCu@PTQJ=$!RGb|P^3NJzN9N++&cGap~ zO#-roD~>6W!eoD2RFi~Vg|F+9-=oMlOwCUg9D(kuCLrt~n&EU@CmZXC;tLe2S&o$+% z)P)p&>AqU`KMrZJ30DLShQ`Kul?I%Up8g!S~%!~~g zfv)IF=34#fZ`PQ~v3||EAI*E?a=P{qb7rS-l0T@OuFq_95cKWY6@%l$Z-m2 z`}gr^|9w0}(zQLpRP1utVHW^B+Ig7qiDV#OpWi0g8z^5pRJCf2}akXeyHHS=S>Qf2Y2 zgM&4aMp(#nneZV;1UENe4$XgMOcQDsC8dGWsE9p3IrL%(Mm`&bV`awdasmB`ZFdXm zm!i31G?zw_D5K2C=co{F$-E;WYny{miHj-(wNX87M&_hSt|h_L(qJ$U=sZmlYm;^zYdvqi@RCaTI*R%~7W%?X zJ>&*S9UAy$_X~0G_iQE_AMozn@OL&l1t-TLSk0}!kGOn94m97AMFHL5(PjXh)B zbrejiwYVju7zALn)^@=S$jz?#%z?e2*UvgW9rf$C7aAXxKUs< zt4|$@XvzN0QI9Nkws@2(m4alBx8?uu- zI!Pka!eit|6Wy<*y*TbOCQ;gK z8tTU6f?sZ{Aky8y7oX{K{)b13^<#!QX_F;NY^~8dycQVwsLwZS4b$rGbY;s_*8-?} zH4hL^&ys>vxhUyMp9IpX*597P)Y;C7tJ0zvmT7F}w`eKd!p!v7YKBWCF`YPXNt`Eb zHaV%BQ!4-|~V7 z?kEQ_%*mbE^Dne=Q@SBif*^TfA&wL_`HrB017hCEWcTypnpdxBM56miU+^v`K=NQh zJIbi(QFY20Mbq96g|8`G!VZDYpr6v z{B;f)t_Ex0=Re#>2=0yWUBZs=QD>PWz73O}*w4qApt+p5oIMx!ygy(dehCgR)Ew;f z>A1QvNjBO|K(?-rDw{u1Vo2Ftyk*bdt_w@GBrqPrz?#o6@uTCzp7Z&e4}$cqhC7#1 zBs^W5RAb~iypK6XNucA)Nl`RoFx|CkG(Nocu7<#xdzM4jn%ipF4bmzMfV_2nUWnt- z264y8tnk?)zicuzQs5`ntr?u1*87LvYa5N--yYW{ja&r=rw0$(Hp<-mJ-7SIxSubn zm`AeaE$3dS-Q`mL;KqjaUF=Pd&B}rfhN{DYwSDo15!pb4yv`qav4VXV}a^hlgy%6=k<9ro>%WY+A5=UgW z6a5KylA?$}!Tn8&%6@$-%f6%wd_qieaZV2H`jZQ9Lg};j&iH{Z&SJ6 zs}0E~+ZH{f#%`uz!aKt)e%1y-yZ*N!{hlfOkrM;N5fBgi624BeNp2QAH|rbeM9Z19bbO*EU{6RpEQ z2js5&hu4W1OEz_NhDkhmn`uQTeSE*mrm49te~j5I>Q845ZWC6}jeD~J~a$e=m2&Iwt-ZYWZjq2ZsM&rCs9P?=tnY~FDR}@(_Xty^-#H| z^f1FXI;e;pOB{aL1FAc%s#sES#_C5w14Wr5ei}f*+CME4yyXeLa00$UsE|HVfg?sy zS4m(Yv5*u0(gkfRN8<>X7c!nl@nGgQVW+TLmF=kXBitwum2exe3fm7MH zv#sxM#uBSH&ffpdp(-$54ZFqYP;U43!5JsKQM}xdo_|{gvU(6e98qlH-jub&c8Oxg zE_uoF8w?VibE5cU?YB(!(7FFF{oF2#FMx9bZy59vZXf;Ts|?LpA?&u9%cgP#J> zIyK$-GguPFOSFp-A6*W2+Dx~OeyCeYi;&$IS7$HO)X8M-Hq)`~8h8z*sc6#ht^IoQ zu85D9i4}FNsTj?Ua!gm zuWqcug6A0necJMcAr|)a2|(f!w3#Y>!J{IgC9B5`m`lfddUDua2v96gqDML593&%l z);p`Maj0i5o=s_oHR_usXgA@e_u2PK7&jk~SP`s*Rr88kw9rT2Sv;m0v7?}C`q#)m z)--02U*+y-B@2DK(!USv#Ui}Z!USsQAf4dhcC1t}9apDUfxg`=Y(Zc*W>M_YB+Mic zU4j^EEeu7Sg*OB3ScLzDQ4p=3|FIK;=P_WRGKAMKMz06d?F6n_d<6+>L6$B$J`*t73}yH@*civtvgK4Z{=^?-EDxt7cJ`NvaE!r z7ZhN(zl>($HgJ9(*?R-?o1%^QSCES;Dh$~wi(8<1E1D9iwaS{-wzE!ev41V!e?cR( zduy+e`Us_wswvraqY&<~@Kbab)c>+T+K+SrNo~Amqw$BbvJpm6_oNKX;46yhCX91k=epEm8MwX`*;c*f zUSE#xYa{a)W%QxWQoJ(;v3Wg}&`#73DwsOVc-)Y=tzaU|L#^&wdHKe}xb0D7h;FE7PLy&(4$N==l)1j1nD2bMl z_CuF{ZyUzA{QQmhT=67Lsi|!1MH74W?SaGYEO&A8-bU=$hTF|VbBywQpe8u4CGk|2 zwZqM`_a|Y&;2-$mMY;2l-@AIB?KiiME5`h5@fe<(S+$Qgau0@FVO`yw;(+DedGu9Bh+Eug>U}(SHHOPQ>NWb`2uZ! zNG2&b#+0i791?_~bjm=QFiad|#!dKv8-f3N(H@X}0RW-`07TUMGCC=W?k!7%*n}65 zT}a;O@3}OSQdZWd@tl8H+4K1m(B(9wJ>>XF?Ylm1wAkn0r!KM|Qe14D3mj=}t~IWF zYBivL^*13(h1I?%1bgwd!e0CYjiFulo$(kQ(+@|J> zIQ{`-p|dv~#)i(wFCvfAw&@VLQZsFQcj_JdkCO}B#!dYulx3?YV?4}fC*1FEeM~ex z%=xd6LR-wN8;%JS1_=N4bR7&5ANO->TH(@FKcsmVyY=x65+S8B5Jp6n-H%i z04})u{|7FVvr}z|v%la}T&zhUeA55z(#3{&s+d?z1 zP`qA9*~B@|mDx=g>k*%N0PiXdE;E^$i@N4kNd#QL%D!>vI0La^R9 z7hp2fkIiuBP2nuKU}iC}`0N74YJ88)W(W@;-7vGm_N&I@wmTZ!8Oc04Ro|p@jq(?> zc_buTyv_va+13$E1y!0<-g>!L<{u_Iw^!W^Hj_KAZ}gieTPE<@4xb8E!^q66L7!o5 zti4=vWsL9rTM&=Cdd4?sF|R{=_k#0BkOU{DB(S$?@8Wen?pbG{dL23!X>X8Wb?B2n zhr0-0iT=qQrp^g~x$C8X#M$^$NVv0}D=EG$lqKd(s2~J4i1}*5Swkcx+fQ0>-1f}k z@TNcuoEzFnsmTzJC-K8pkq_KRov^)cNz)~yeNS`3L++Ovt#y$1iQADbO!m2h66&_$ zjt*^x5C_z^qDAlMD{Uu&?v6ah?PgQF*T~O0NxTUYF{+?P&*R?6AT->}>vG<`HP<|- zm#@0TJXLqgG#cJ>Po3*zisdHDZ$5XsB2?fV*gaj|AL`{2Ts-X^$Nv*>mH=gT<+({YpTvTxI&U~062e9 zzJ5~mnt%jwP1j}f-9wj|UC?M<$*B-HuaU1y@9{7jY?hp-#a=u`Fw~A#zhaTeK0g{} zM1$f?h*Dn7WFe-A=;Fd`@nofit{VLA8hi>XZs4*8Z^o4ZtMejto*q?H(!SXU1`<_K zi>>%s+feI&k}OoU?_VJ;*#nYT%9|y9uV!))>*7E3L)$ep(@Um{bDBbx4;!ihI_T@u8O4L_pril`)p zvnFjA4Y@&&s;a2r`j?;d?3VeROfvBQg()%g6r|l9tS47}oC4gBno5hV9V9M$ik+qVfnG#iX=%}Aoj>F1 zi7_m{Rp5a^jEya&81;KUYr%C9veAFN>#2ZcC7f`79ieZhw(@cm&VVB{9=EG z{6Uq_;uX>lO8{sN@&ab_A=~UbsK&EPkH;JLIm6u~@l2PKcQ@1O!Oh*Uhx#$!xf!?@6f&kky>JHU5Fq{{d;UP1 zkxa)Z)ESwBOwwrMuWwm_4~k+Xsl0SHZl>+CviHxhi1a=#@0{lNB*A}7Gu|Jdf@A?d zdsfaHpQT&dGaexQOc?5K=He|=Nu6Xeh$U3pjGOZ!rydj+Lzeu;#pQdOt+ex>VoW-; zKiApUq`_@AowjG$SDha$b(CvCL7>1L<{;|NO2ZvKA?yOHVV5jw|HV;J>NjKOqED5N z0sRWIsVu##)Uj`W%i95iw4-M=M=reZ9Wfgq90Bet;YDA&FIvE}Fd^x32Fp6@*i&0^ zFA*X=E)>~>(m&jhcsQDZ%hX2ZS`F&{S`=+?9-b|(J{Ea{KpZZwDpB9q+4)oDwwF%2 z3<{`LGE$ZJY%l589Awt+bKJzuh87`dc@_am$0yEsTFlL1YKNIMgquSc-c{Gloc#?opqFwk^TRYa*dh#Qe`q4u3Td&i0h+15lU9Z!Y zjv>&EYG26Q{$Pf&BR9BAaB3u~l>I4nzw26n3T}jjxtP>vlpOxSauCzkZ-HKBbe^l_ ziZeWr-3gE7@^5hTnR}1U5pr*kp4{*=F@o-A5|R@>QbAb8`psj%m~8 zgTlo`qxbhd|IE^GzmVI!-{#{KjOunPVEw`4ky6LNYY1qt z?bS?!+IQ-!A{UyXVQ+3(t9kp^L*2uRhxnWR<@|1U!D`^(R$0Xsf|TIaC!+9Yg2U87 zrYB;oA^586?5troY}kWpiBV$Ym#6iE+V@)1(UXbenJ5UV+LydBTb6R-2qoqbu$AK* z$dDe%+4c164hBVjr5Og~9J2W*=Z0OR(AV;RGZM)q!IP>iI!CSWnKO6DZ?v63ac;bw zbi4sBRWdIx2j9Y+*__tddC4A(?EMgCE`36=S)!WcoP9E;P(QlU~ zUwsO-qqtxsMr_Pi21&z0vT(YYU8_z5c`NDp(9dZYZY?9p!xlk7!fjPF>*o8*No zjpZ#>7KwJ_P2DQealR1-al5_W#bhNacDPj@Qrbhg>72>W8a%j6lzFU0bA~o{GaE2E zI-JN-AxyN}-m$!NZjL8cPhybgwZna%)$$G3Zk0nGH~@blN_m}*!dS_8@Aq@QG$*9A z21AI-hA$>sFIBX@MP55?i+K&?6Emky;OKO{eCFf468$+q>^VT}TyILA7;45LQ4#!) z=)%2;6Ix+?6T`NPMasL?)^ij7bveKHf9=yvQG*J6=5NfPkb`wu^SGv3qI6lGB8>6t zgmbTf4wTYq?J$WphGdLDt0S>yOb5EL2%iL07}7993j}_<$$wP+_2K2dPUR7-4lDIW zjz?}A$pbzH{#9&X;Jrkw+1_l(;AQ^oOO~dSThDxU3I-@m>`z$(e--`p-A%`b#-(?u zFU{cn2jff=dEQjma$>!PV2K!Iui=$+E8~W5ecs><8X?K}=W5(46Wjh=L5?ogsHp#TLR2xGm#4=}K{8Pm6Niaf_9ScJZuSw|#o~+*o>j&j%OJIGVX#Nd zC&OXq_A`iQ$6^PWmiJJU-wY;$YcDT~7hx9V7ok?ECd%k+f2EIa6MvK7ODM-_)4< z|K9g;1+VUzOax%M%!gRAS(}C_#yCs5hfBfLT=`C~U^!$^e+6dv4*$*Y=jb|W)ITg) z*eH?fYUCBUDfk7~D-OXFqbhZIDc9<*DbF>ekapDktCWIfmo1i&mMnni4np%w{cIiF zD2us6`^kFCHm=d#JHeD{oJ0dX@0ZrRrJojk*6v~vl4aJ=1l{`Lz}Rk{Ch*3b{my)$ z4F27N!FcGG*gg^y(jP2PTdn#BA$8D6sN`VF61G3{O;pB947~$7(i-*&b>)4RoCx-0 zRHN2lGLiK%VoYLMpQ)hMvg21^%YPp7#=itSbos|aFaCH4MzRU;&~_^t+2Tb(9Usl;Hr#pr#`XTJ-%srw{&U?x;O;^@cJ*3$l6yCBpWeNQbV=dCV0UJFVnUQ+`$bA{ z#}frLGNEGXkT<;DNPDj@-k-5j)(s(=&0F#{LGN%09_cq0a-|(FC0KK$iDSCu z7{7ZrGBQZ8qj)_sz5SQ1AMJfLuAqGJ(7|($Z~7-KD^8Amzb7PzS#zGC*63C@unf+6 zsBQ~|KW^L=H6HKlden^NUz$J0XAM7YW<4Mp?J!b{O~6-gM9Fggr4~CD(RIP#K0g@h z-O*bhfl%vY2A@?VJcv}Aifa440mqw`R9_1V?NXt zN!!ylLobv&S#Q)VIkc4h1a;ihah5vt)~)iojH}1rCyr~Fd-1VO)x(sh`B1C38dq?? zx=dwTb0NXqBFCwQ6&rX<^C0+j}iD(n2iurVx4&B{EAbPkL?`Lk5RFnbiA^o4G}c)C|pwqRlSHV zwM8oMz{N|+;5jaBrMBFJC@j0k&(3i8y6Wzh3nS?NyV4#1HW@*+ZGLJQ4Jr{soFBeheT=3?Pa$xr>8ZpDvMEEK=bK*IU9iTw7O5EF!yyDp_Oo)?4*S4jnY zY>x&dPnGImSZf`EkKJp?$#d>DrpEPXt!XvJh*&056x-2FPN%kkHBqdBXByLW=Psdl zhAasUCs zyv>eIbc;B6L&NU{J zMt*`mpXBwJSqG0iXS$Lad_ln2f`GBBIi#wl)$yQhF=7QU2pPT*Bto=ti^tS$e73h$O0#o-BeL6?21&AYyJzh@(v9YJKUloiT z#pg$L+430=Z1e0~SIh2R5r&ptS*C6`X@Sp!$sFwap5tZ?$lbEP#P&W#n=PaRH!dko z%P`&(pxyV>#?vnLsyBAh%#>nJx_r{Y56hr9ePUn}^?_!QIFBHNhr-2+knLP>*S#=v z#8Eh_7}<7Ir1z_LzvDdqxmBI}fzBE70mx1k>VY0;xA(uDmGkoUGM(0)eAC#e>&P}f z`SlKIf3>{D+3mU=VcFrn=I@>;(j6z{S`l$8b|!+--975sFbF9rrU08ig}CWJrAVA< z5JFL5wq{%krE*iKYm8W#!Jz7g8%olMxM8+1#@}%NO-|Z=+iR$wL22LuJoj5z7gt;V zXGkF5D4slb3spZ~0Sn#vFW=gNv%~7d?a6-C3y%w9!crr`i}^;9P=D@wjyj*&voJS@ z#e0`SvmK$w$vbTuG+T8*ZUnq=_bD3h=3a~7V8>>$dh#C9 zxDNYpw;1g`e-7I%mb|%wp;bO_yvb97#?;RP%1C5KD%xaI<==8TrOKG#$#3+G<*4Imarvw*gF*x zcfNZ##?8lw6hifGr){b@it628c0Z@d8Ua{M*;{az2`wu-<9s=tKmrlFWaAa78=Ty- zmlCG@=l{U=)jedNvf>Js@*Pk#YUj571ZLrI?wNY}&2nU8-C|!;_Sed8h!dkiJ7%ua z?iUID+>7}0ew{S$4hJq5F`OHj^98?Jm`y5p`_7&xp6;*0!upq9FS`!Nd`kTzTc_{^ z+s=Y3`SyS6eN@e}S0()Vb6C(u;#Bk%lTrV(k+Eh&>4LO9=>Q|+CQ?e`;tClm?7h~P zuWvYic|4pSfvcXnI9O_eKEpEWjz(7rR&8>CnKNwoE;!^y{j4PrvXK%-Ovg);J< z4>-OWeh0t93Lb9aE6f=fOw8)Sg8gS=MeaAW?vQVS0TU~x9}R9d6r*Wr?6Tf5(vlvKPL1Wc zi`?$kdLCmNt4(ci#b#h116MT6W?#crUr7xGgoK#H?w>@|&qg{sU+m$3@K(gh7j8^9 zaA<6HkAM(}pe2pUDhO!ez+^GMeI5Bx{2Br#Wnlc5Uf5?1V$pblIN$DAFVmB94@LBt z@ny7wL-@Hxmy8Ue#TwblPcCR&=DHqZAg(Fer6zH?7cYHBlzEmx_P?l%a?I+gUaXUhjKd25_k9 zzb^gAm#ZP6xW1J=o&R`#9QM2La&^U4MoP45oqfVYc%Vc3R_?pH>|p2nol48^flP+q zwef}By^#wuk_LzEV)qJRe~DR1FCY*+M6GM*up>cBz4Xv{Kwmv6jtlp=)?Ie7Zc|mb zve`}+VUoz;&_50LCvd<&ps+V|2<~r|`5YibgQupRrgaq-<$ZQpXAEXPS?w08t(2(yRbNXn-$LS2 zCWw4)r28W`B7~+xPvb2H8e*x8ug0fkzSRQ_#>Ei1>-2qcTAQTtV<>j?HZ2IIE_A(r zmMZI}>R6$n>;NnkA%*;K(9^Z9H=fxgdZ7}Q?=hex74haeG{p25|B}UG)NkBy|Bk42 zogDr@3hQa0V657d#D)6|W{|#I;V@3`A)*m#5&GU@TTW1xWDzEzOTZf zd;ooY0DXPpu(c_+rt|J@7I0T5{Bi#lPcnb;R|Nph|rG>=%|@O@{8f9 zXiKX^-w`?GC{=caEyXkhb0h?`F5(Z?oCMX4PkqiJSPuHE_2orepvgq$5Aco|=!?d+ zh^EKqz?6b}!FyG#&n7afGYrtv-U%b_=xrat6g}%n8UyjE@ZP;&xQv@f8b++kXus`M zBI#?~`Uy(lsV$GpAf9_WCtc7qd0zyTapH}4EFGelXdsGenwZIe5=)KcLciIbuc@nV zTW}X)pI#bFW9=Xwl zt37^T<0OJh52&bpiJg3TmsU}kktjJ-^a)t2*%7a)!v}sZ{aMxsC{z@E&V_h zq`F0xhIve61-^Z4=Z)0)&xe#@Xn|zPuL1!d3dI9HObg!a`r|{xo!1va(*wh`GMd%P z9JGE}0`NU;D-)bSqXcs`Wx*#fpo88%=D&`FV=tnWurgE?r0gfAM{Si)9Yne=+pq6U zBKw$BHW09)&}4e*^f@&fO+)or-*a!5q%zuC@3LUPvU43v;AwNxIBOAXLuWHa`D*xi z4%jux1mVw=uN{|cOx(A|k&DCf*)2P8uPtrX?^)hGaQ8iamfGHZ>?WA+IA2WZr!t^W z84$WA*|R_R2!<}+?lq9YxuK&&e)k>CN=nV!bQD!Es*9xivav)T+Y2*xXLi!3rcVb?Q;*GLxC zgi&q?KVS{S%+Dx~R%RCNPfl7-er6gyxLiXH_h|F#u79sRroZyooL76M9S5^a_BR&yw*2q`$1Ea! z`{k7s{lxc0P~V|ZipQF^VGdGhq9H2Zq~58sUkm6&h_e8f4Ss@E@{TN(<76jPVv>@< zf8(S#opn4F2*@rTdNm2FUuuHiCPxc;1Z&g%$I3mg+fG$bDPE(cMES`Qbg2e5G_0oo zKlx5qg#r150r~hnc!3KD&6-!MD@>DP^<3sw16gN!Ukgb0Pqb9VH!ROg7lx;`5x%#} zOQkirhd#LDb<%a+NTHQ^vd)`Ts7e^j95Ubc=0hy(R%60ViKpS$Obl3IWxmHX-!v&g zL~uwfw`<iPLm6pR|9?PNbVlS2a^! zah%D|<;1)-zb=^EH+-w#;B7Qt2*Hn7TNI1N$ttTP{7T%*tj$9L`6xqp75`K3#@>h$usz(#~9p_w1(5(r-EIPdq{l2{f`mlO(n zR1-L`!MuwB^Y4)75S*}qMgLO4TK9{&NE(DW%0zu3_o-k_eJF|1>3!v<=>+VFA=sL| zkc)*OSowzgY}ZbAF7vR&d!?LQd|^hD2Y;SJ^Iq`1bS_6;pm>LyTg%~YN<(qlRBC~b z&|fCqTjk<_p4LkpX|2^=xjh{>&OIWEP#D0z)efqo^}tf?dPwNQRWq{D|~u%Qan-=*DrqN z#m|rsV7ALTu)H~rTDSU}tU??$P>hMxJJ4)u+U!u5!Ttg7zO5sBTGl^Us#hiNKa6y(Wh1vhS&u;J57Ul6a5z*)1>&&duzgR`UixjM{^r?6VK_4o#hkMsoT!cUtlb>xVUeTGZGsmy^X^fHr`_%PzQTqgi0 z;_rvX%>M!@W}{Xo^5Z?NolV5eWHN*P)Srbf{gpT>sstNz@W}+^32&EWC8qFjD;1b3 z4+GQ`!r0no6Q`3YJLoatUGC%p>*r;8@UCQ4NTw7RScjq4maBGMTMm~~Y$3yTa*0{y z{+1!E)Xb(t>I!JY<&1I0S`oeHm9MByh7z82$_pyMkLGVTb`_J@gXZq48ROyIco)8W=v8ahKTtb(!bRsqvT=Z zDYj#O@8)Ul3F_!wN}3@6)*$=;R}FQZQTE2)Oo76-35hvL27`mYDA=*JNxMjbK;_NE z&9k|IS&uV&CnxHxQD_%FBgVsY_wl2lLa^i6az#8S#6BJ{R5KVqzficv_DHbi31y_N zwn&^S;Nu(&10{?P!9*HsINjC@d^HRVo)=@jemwsA)E+~Q%OV3IJp4f!jO+Bw5gARs48OkLbA($=y$-MPD!UMaz@@@|{*#c$stF#8=y}OCLYS{ou(&uMCTmjdzlG* z+-hPz5Or_m1V>hQ!a>?RaTN-rpeO z0RR=NyQ_pO^rb<-D!qX!lMrsvyBBeByU>Q%-9<_HjYQV^>=D^ci$`q+Ng8@h&@FgfPO#hNO+4K2ZuU zvz5Am6|6ayA($3hQeIt(3|fOubRHxCM?%w@%M$Lufj zo%6Kie51785z6M*hX-v`7Xq5VZ=13h8(M4As|3p5pJi&Sxm2_EfZYaUGMfV>UjMQV z3+msxErsV{DzHA^c6ELE@-Tloe`0m{IYr;61 z-O*NBDfOxQuCqRm_sJi|6LiCX<*}AqE@=zW-@pWiS@S!n#@wdGW`0TNv>(g?mi+4x zY;OyTB32cu^t!V3MM+ADuFc{*)>n^i&NIW~jreDr z)yS?cI;&9c`d;&tP#}%`bqdZ@4a8t8>}Qm>?}O$^m%hX>`rn?+^KOD;Y~Dh12i*^Z zjWULWuXEAA7fK`hFVo;xK;0rzv-E9DwGgnKW4TV23Fr}%C(MLg`ygyGo%(8UAqr)cmQl6rt20nk zDPXjanWE6Ef)RQXqB0v^>B1Q=*f>kuXwxq^warnUM)nNj8(ZuTn3zTer3G_iZ%7ho*kIjWjKB2>cs!GF z&t;{%p)KO{9xJ}R{>Di0O_P3X^fhf`eTfrs@QBK*U z_$T#~HIcNvd1L0CDWKJ(d<`5hvWF&*)2rKA!QwuL)~aWW_h7BJcSu?7*W|q95=9Od ziI<`%C7|h5I63haRhMt8f^2>B+WqqzDgTRnz3)O2~J zGw&XKkJ!n=`;+6`s0od#xtrYhEXu^u73D51L6#bmqMYCSFAY?2|2DYoxUrR-H3frj z4a`*u)-yXb4P-PUE2*F1JRt z<0@BcE*-eoSd9^_!6c0BP#Ul9;QeY?ujbXTZpF1T;36VNpr7{NCFR7% zFRD2RafPu|W-pJBXP$^0hdGSJUkl>tV-RlgbgEB%AW`qY=5p;$Qy5S*SS!q&Xu0X-Q1)P5VtKM#QP@j&@iD?9;8j(mBq#lbFlOU+-yzzn?%?>$a?jOV*>GNSr$LqeW_D5A)q z6-r56c-qK*ed8h3=u=8`n@l{!+u7nE)2V+U{J!d)*#Y`HGoX+3B!zny4!n8{oR zQD>#$fyfLq=I@x=nyP`!3d7piYo1NofU;*^bQIrT8=^Q#Y1o&E9FZxt&o#;YOK%j|h z&|tR_<4z^7nYB6Adf&(ymn!~KPt?;np-W$c0)AnqLUh7|$zwDpO`>v$c%4ma@F}e? z^-9p{cDEoXzx|&T)~d#J575VT0W0*7!7Uz>_=kIrrH?M4R~u*G7U|z;p)wS%rc9gL z&-GAUe8RW=4nF~=;Pz+6L%ctG!4|H2>PW`?mOuINr;)yl^XA-)7*caJ(B#|l_a)Op zJoT{1}usnxnKx+mR7A9DBLk#vP$M}NS6ZhU;6Hh96Ly4a>$NCs^orYjMs`GzS zN)wH{^_3Nd*jFBzA2}|0hK)tEdSVx7!Ky30Jwsz7*2LW}quQ$BS?M1HpBYtP9@V2( z`PH8(rB4DD4|R_9+uyKFjfB@F3h(kK9g@G@3mgaaS5Y1wT_w}b3jUp4+^v++VaA%* z`kI-h+$6cwc6ab3^k3?->wP@PrVWs%_@IBl72t+B-D#-)uK{&eFQdCeETik&u)0I_ z5$j~2Z^hZgm9_ZB%%UK;B__g5-<00aPU2K{h4?h^3=S&R&~RNxUCCGB(26j?mH-pZ zjMu%Da75B?%UKlDy!VBYqOL>V4Fgh<((+PJ4g!p{LKNYpK3m(~&Pb73-#@FHYxa z)3+~cc+!R`s6QXsAV^hEYyH~kb%&RZYRvk8^k@VI8w zIi1sY7g#5B00%|@4)id7%V{pn-oEzP?LIrmm(#NqQo=*rA`gZJf*{j-{#5#Xxf}*v2CIj*f zE0=D$kKA9us3VCD6!*d;(}}coe}SS$irXIZfi0XYvVNrBlxr@GH`SQ-SR?kjhyn}q zI4Lufnyd|aF`yt~Z#kXjpWeN6zrH)b{`#YLB%n7j@E@R_^p5zj@SWTK`{%As)#zf! zchXA6PgP8UwOx#VemRd|GCKT63=!t9B+Fk6SxAgqEP~T@c3` zCuk#vtH0ix>(4BAuwzN~SFl7G{n0)zXN|RlIq%|wsX0hMU96`7k>QAiJ<_tG=v#bhR?;y?a6B3ej}#iknXlWIy=CVAr;ImUJfKYcA7x-X zJO}#P4V5sjE>iI3UbccP_hId14i9>fmfmuxQa(ZPRfnG(0e$odLYe}zbdA+&aHsnQ z)1rh>7fEeah@IcdMLSng80)k*&x#n*5d&>j@ig-s0NeN!>REUfs@Muuld08Ij zw%Xs@(p3L2ky{^ju=cE%k(ikzALo?nA?T=K46Nhl`9^`1@dO&+gT8iPtoJs!&#ikk zV7GJtiFo6-wtb}*mnB6YAh?!9&_ep%k(KWM+j}L35!jpY&)ywtI&{O;Vhly!>RNIy z*Otg-PUS?`iVD<=tgl0Br}>7No7k64LE;+w!kSJ*K`n^|4o{PKl@(_S&~I)h--X^` zk#NkWZX5QGYdF8dRPnsDWWQHY3bG^Y6B__4{?)-HX4}aPG+W7C)9<zcB=EX*E%+QV1g}Q$+6ba+Y+pQ&7hw%0>ee&`>fQ})SjnK0i^7o6 zYo`Z;;K`UAomQ^*nmg0(RGS=(^z3=|?MqlpW9quQg`Auj2Ls^g&mo)rTt<<2lqe*= zKbbneMxnPoQ=H(f;>juPiPKttwe07iC8u!i{!L~bAp$>l)ZyBFJ`eVcU%Dr{frO3jEQXdTjGe@iyD zgz0hY21H^RfT)62NAy)?5hzww!%6L@eZqp`{#6sS)xv;0!hhuHX4ciypj}nVD!n+* zyAf?Jbf>RQ9LPFxlb#t9dX#0Slk6*_7eP7`)hk}r|Mn_Wx^@(;GG%$-t-|~k@B-eoV{j8X|9z= zXhO<4@oIbnti6KzW4dMtUzf?}X~%Os&_XMpQ~5Ms$ieL`2bm`4sJFE{luf?)n`{4k z;Ht5^hNhNHbn1wA?0wDST~SYLG$$b!1LhBGQ{iwoDxTU}RipUF(oJ-QQ68{`V*mn{ zCE~C!n`+j+6x_dFmQZ1iKrDNOojhAuB$AOmr}5@w^#YA}{MO|p!SUy(7~v<*mb3mC z9VU_PDu}ucqx;5S1c3uVZsYc?@mv^^Qiq1H6Y1S}b?U3@8dAjP5ELZNMQRrI~IShE$yakE)F_a)i`_RBcnt~4&W#&>vmHC!eI_qeq>mFty_6m&h-k8zEd8t3SF zxE9|t`HI(HRo(c)lXjnL?;i*DXHbIRP>k+-p{V|z4T;jyho4w`MN1?6Oz&9LO%NzA ze5doE@sk!~TSL?=1;**srtH@OFKe%VsUm19=6zqY_j?n7y}sd7>EeW{Xb`hbHu0(i zw0iIm82lXKI|$XQpXd3eN&Wx{^;$-5&Z2W!&BkV%e$plin)OB(u|xx71v}c2wbMTdfQEwykbvip1Vs3` znm8zO8n}NX_z=)KNz^!R(Qj!(?U&8wa(*ap=j)7`2o)&AlRsfa{T|0IZ_R(ojKs*r znzFAQt)fi`Mc10{%{nnbf7ExGr)iF%#tTCtby_s>oE~t4Egwh)tJm`a|5`lpYR*_7 z(kX(1IKsb&3Z=;RIbiEb@hYNaTG69r0FZSt8|o?0I)vEjITg5>(#rchUR4lC76{$f zQAlMlVM!`6{>3sAT!^j&GENVwkLK1otI%(WM#d%NoeD;N30R4>yx4WG)OA^{8se({ z5NM57-~W!2&-F?&br6ew=-?QGIp92ey{THzCH41b^~165jt^K~`_|wDl!d@A8?Zjn zkIyS*64)9XDx&cZRQ?)Zif|UfSTtSY$LMdQx~FkLJVUPhXeqo1)~x@>)K`Z^`FwAy zfPi!e(nxnVOGrw0cT308DJ25Z-Q6YK-MQ4#ozmU)t{;D2egC_;_UyH19%jy*=bm%! zLI0P9bj9ORH~8WH-kgXZ(JXRbsgZ`&+M;w(zsbF_t@nA%Sw0#gOmA5D?tp^=8nht& zlTlHYbG);wRS+x;Q{=qba7(SqT?d&EgM(Q_k#rH zfjjaUCxZychf8l`M8*EpIml}pW3G|pd_~3CHjm$71|<$Reof^bGepiKX@~)?n`%Ti zT)*lS75lej1+_?W^iv1E-0dAF024XRxIM1!GKFU9EYA?k9~0_bXgxf`&n+O_uFv_@ zj2MPXE)tM4zVqZ)=dc`SwVvzsc1?TIGQ)FCKU1E-Bs8lBgIthC@sB;8?BeVCIg_B> zRvs~xJ4f-`P9HQ7xO5|Mt~fmI5_l`y*Rf{+uJ@iQ^(CFJH zT~Xbp^Pn4+{AFcqlH-I>%gjH#e-5w~wlyWn66YMKbR)OfI=xToYFFn+StUsPCg2@t zE4vKSAP;rLUQ)Ug${AmAmHwz1bn9NVK-U2_?G&}Bex;TI)388CJZ)-#iDiJ!Wpx}_ z>A8vqA9GNWYLedH-7|_#NPu2<3Q*u8l^aAH^ASuw8*^YUNldp%VQUr znqK3Oses%h@v26NT_vW(e03SHhJ(2-ZPI{uAC;w3ot75V?+rBTE|65-*PA&-c21PI z_gsowJYUD*qVdmxWu}#N*f#s3IuOAJYJ)%9HjTFp5yEGyz!jQk*kqZ_kl5!}=Cp9& zCcG`*Xfi8iTYYkTg$>-PE*L#_#EfS3aeK>+GCm_StH&;`!cKo;ijr-7E^}5he0N+Z zcz0{IS0_!&x7>jUMAc+~zRQgyY1_qfZH|3pO#4)5>yA^cU**Tx@!qpj^j+I4wNsb| zKSp9q&n~3YIV6I3cXNt_V(!O5p!zRS(fu9KL$|=Rdpj7Szl$)ZE#8muL%~|gXRiSJ z)cZnTsA=(Q6Z~v`i_R+xMp8z9-3 z>5E5DRD|aDx(fR#jTA7&sA!d0ZKO1>Tdg+Z$A}cl*HX(%TqO-!^f4%=)8-kp;%i~L z&!M+c&tGKBUVpd{h|4>SIw9P$=0DTsb6%v3bCr@o>y?mb9XWi}>x3#vo_=3&o{}a< zIZOwoZHl8!R*h(vWbzgAmyoGOk4EhFl1cgi>5hl!Py=g5HP=A(lKq`Fad69PhH8<& zgoWoqw8q;_<9Lj_*izDj#b3YZx$WrH=+9+-GFarn!B~N{f}GRIdEJrE=-6HF24zcn z8hnPhj+Ujav%t05&LMT^rBTC}W|UQTaaY=&fqA`7=XE=!+UadxVd z=*efcBGFaSX}k#5idxCsYBK|bYEp!q-Tlg`&!1YJ-4gHLI7Cr}oa?7TIZvK+F2trY zp2uj~uZ(c)KdC9Jw5rG1c~!5HDZMCz-En|9wx*}2w@D}Ad7kczqu9WcV!-pg>kwz& z&i#JPYC@0^d&wn6#d2)Lk=#R>tDn{@ye8-n?N_!eqTNGk$X6l7VcOI_eAX@-9aBhF zO1~86qc<%xXzyGzSBSeRrkpA}jdiTP9vJ$EI##|e4@I)mu@c-fWKGAsfLyhZAUr9t z#&UO@Ua8&FwW~p#J+8Y&*5Oq7H>5=vYBkO2r!qK`^rH8vU@ln~mnv7-hfvqI6mOwW zbPu_-wT6IsC-<3Pl>C|BQS^DOoa@wYJe9h*Xc{cGwqF}!s~Shw6pz|ps8I1&VbHG+ z^rtOwDyL*ETN3p6q-{lCN`Tj1Jb9=Tmz4Lr9{eLuZhj8Yf#VNS=1=4SXUb_VXoXty z)7Ul|sv9plMw1`DN?%V+mFx1lEZ7LX*EoSa*b~C9=5${*q!cONk!tkD(!0CPbumbfBT(T{T;3oR z0Km19(tAxFgXM&LY8o3A`S{a)0z=aY;@hR)vW97o4@-#B*R7vF>;%Y9w$Gh)=f|?@ zd3~qW6WfvsSy<<{Mcq#8pyqI}nSZPw=f7-A7Fr>gK3s>j8kK!49%p|rMsm3cS%%*x zL8@oAN|Coia>1^`pS=T8CQ?!Zh1F!Kybr4b#9=mj0WRAa*;HcJf_6xpe^+pdye96k ze(E=mjR2PXq~nT~dlH|Q>&8tMD3@H{b#p)5A2Jv{TKNM(v3+}G_13k7Z=7fZ4sdeP3EUEIV6727n;Ll zZ@*$#HE?f5dZemB;xD--fnu=$30{TKev)54J$2LL3{yD2$}w(l-X-vf-o$)X7N|Vh zF^4KSVR#8`-@=f8zyOU>a_-ZdLM~JrY}Pu{4|zqJPt@zIH{Tv{Khb@leABg8J@X-5 zPipNTI%8P0)@`n{{5}V-BGLxQ^30Ycmfo;PIjfw{-fz1$?+5Iw zA6$-v%WmbdWSf;>whffdsAiA14eAmKxejU6PeKW-vN#FxuSN&8A*V(0? zbkf)cBCL`Yn0IML(dO=hZ7+2*E^lUKoT*BxxHwkp7fK-t;&kmvULH#WDTOf9=SN1g zx1XM`N(#eMU{|D_m~yu9o^JN3wlLptU{0kZ$vxQaTJ39z_Li=11wj1_yK9iyZb`k#(PM_e}j@(5j$;9|(oE3wIfqnh^!Gup3$)nOL6WZoM&8=otxGtKCIo^Km4gMEE`<|?|-#UCIm0+a=$J< z&tc}Na!_Zg)ySp%FsEa#*(fFDJ+PPp%Zhr;A?|8HU50Wr&GI16E}kEfZJF%FAh-Js zX8>#)yUp6j>Cjp3EUGE+a#2w$az zBbgslR+i}9*=5#g_GK2T+D=J>|yE$nm6jf$tbCHzIDuf@*_^V1ZQ=l)+!UMim#>yf@g#f|3y z@WD8hh7)5)9mrmdqKrU>K0KQ3{&=p7ey!BG zl9%=Y-l)6hGtx7%A(?aH;Mb3<~`Ylb*pWuvVn~4U1c9ThCw6ZgvoLvRCQsFM~k1SEqQ^WtqRB&=(|;@Zr%b z*F!>=ko&`Dmqbf=1lly$eAUDd!QqVu^?JyqQz>m4v&kw}m3PCkJ<5u+9W!R3Hp~=( zAQ}qyMl^XORHo01#SEeQM~bIgcuPsv)s3y@NbPcW_@gmAwq&U^^xj|6v$7pq*=fHW zrFi-F6{blP#2cefQVs^XMr*q&L~DQl13!}un%HAuhHtWnLj!lP6?)LQzxT?b=X%En zA=l4BawanFzm!3LZW&qQX|jYv?3v5x$L2IC>eaf{TOhlKS+x2QzPrREKKF+S3HeQa ztT1B9wxe{E5dojaLKH~3?=in60@-vlnuER;iGPZQJI~mPMQ7KYh6Vg5nPTGFIE6&N zbC;4;XItE~Bz||$Fa=WMi^x?}tGmdXXQ$!zcg8x8X{&KymX=N+*S5tjcL`}pCPt#5@`gv=z8x3 znbgw2N-kwj47$Sq8V6RCryyUfNQ(W8Q;?5qc#9BS3t~?&rjGUp`(}>ib|aX}t3Gql zR#lo8RE$D(IsnHjW}=)N>nYH6&J0GB?gg7}88ep>hL7>Qp@S6WIGUZ|$d6 z6kHonAxi=+Hgo)>P+-GqUdJ%>QHDU03r^{Zs&4UHlcv}<8!Zd+@X79sqISuN^jYZ6 zYaF+lWX|N8^SaQc#6F!O%J1{tZ%r|OmJVEfx-Tqts}WkLmfLBo$>?q{FKB`n+9p5o$ z^l8eQp&Yu2uM#}p{KZuv z`OEh|@N;gkDUcB(9Ghi*`}IX2MrDm16va6iT)^q3n@s`@#G2|~R<^Ebp1saKB|^P9 zjVO+&w$(68uM`)Ml6=50h)E6`F*;B{6k^!yo08HR?RbxS`w}`w1dC8Si9Hp#GpV}b z^)RG4xZGZ)YI4Jpmt1yfn6vN(9QTG;;`gqDs$U)VW(xWzqmn9^E|$}{(&M*W>`G@AWw-%68f#-SJN~}!pl-}Bh^euJ)Snrpw%z~T9u8xbgDnC z6bdG^%d9P?O_V07*^-90E=t?vIB8q@nUa^*Uq2w;@ziBoI_O+o&-PkMEw{|mx|Pj} z)#Y;_aPU%1ygukNy3l7ytDP-1@ALZ>Jc7mhOjYkvZx1e8 zzGitrc^@DYt&#uI(u(Rh=0Z@{U8%X~PU4N(;epzezNmsDd_(As8F9 z+mVQ>A7@XE%RJ6PqUOC7Sy5E13SvmobK)zHLsv`2D?OLSQo1NVLL&$v4YlORO- z69RLq#Cpnn^+^=L=wL*tIB^&E^hbwa>&L#LlDAZ6q zETWhB%k(%CDtZ)Xs|{Y7_wx~Eu7uc65?@Crbb9Swh}lxI4X?!Tm_EV5$Vl%O)V-0C zl2M9(uyuA{gL0x*+GFRW=QYb1w%zy{PkVe6Hn>q5RiD96LdIEZCeOva`_p5Pp;sps z_yuv13K_(G2ubX4M13>9U3`U6h!QT^jqNSptn3(VA&U?_G{g+r#n1jvNR z!45>G-XsDS#m1?wgkK(VC~0}PIJ5)-$xkDYj&$ zrgn5GmEa4)cDXCaj}O$Xh@Y3BH{`~TFcsQ;Gv64}RP76+!Nxsb?lFO^C5lbHh|`T# z#}XM>))cv|!y~cD7F#h^bHTWw*NNo3VB6UkfK!_pflw3M^R{TApMj zjzeTxqL3bDR3a69G|)-#`uvqOn)Av&Pxn$wV%_b*x_tWez51`)veH@t!0-@8OT=rh z!T`Eqg;1KRwsg_0eUZ1DlVLD%GDN7?Eddu%~nFYr}7m;3uio7PvtcI`XjR2 ze9sq=hmewbF}{STBynAx+`E#2eBvvTh_}7a<%)D)o=TBja9M3l88c$*e8zBIkDa8y zW=AQy`Mi=?QT|eMa3ElFJ(|B&^gyN@mJJN4AA9PUi*p?iKIDO@kak_HWQU%wkO2OJ zBqS%JGKMb4L!3I4E^AJlAvoBBsqX_pqC@_TprarjwDg;Q%-LLR+zplv>q!_3|44Zb z0I$D1VXHODKe(1SNrPhbQhKiea~)NZYBVRK z%iXmP4py-0%Y?48qd+9F=3r=$*Gtp{68hz47srT+)f zq6Xrz2{R~#el{iuWh{}I+W!)ju1fE&CZSrI)2;g0g)#px-vZU5&qFSVtb*iQZsGg& zCL&Zahx6RW(U=?-KeIViOrK1hADr{TjcrUz^lVlaxFg)>Xr9Yd;O><#N)xjH1WJvu zBOqE9dZkJwqAN1CVTtM&vd?3f7++qv9I0Wu`z=<>0W^bU=*MizSCTDmu2TX}uFLpT z-8kQQWNqHT9=wYqr!w$ar8cPGv7H6ujoFS`6P984tmD7?b#w4-78?+&l|_k?PlU-T zuFP)05mJ6#W^Iv#@vB~0p<%yrXLr4z=OcDrGT$KH(qTP)lWOg8_?5K?whl!xVio$vql*9JgBQZ05Y4n!!x%7tTppT*>6p`(-j=*KfZ97M^b{bY1U_jOP2hzii8mfYBfW1Xw_o+=A(A6yzI0+4VJv-cM~ z!|YBkO&un-0F7{NS~$gNb9v{JdNcHD6vwwBS82V*kMNWxYo7QQ zb!k<38G{;hQ}_hC`(hoxHCwv`mQC&6x4++% z^tuA_a6C^b&?|fUri>68@DvAm^T(cw7RmCKEjH~2X`7g(U<&aG*o3b>(6&xgD6Vc9 z7Z%eHh403I?%zh4Te^?wuyOA)bODdELmiGu0RKS}l3g2yjgE_rMo*8=+;BKsc-dN8 zbOR)e_ElV{Nqnum5c9ulcBKY9)Ch^nKuA`Em2aJ*S20+>J9+mzdFMV_h_7#xhSJ<%z*^~sc2N7yXFuqSNs6%DyZ#*}+6 zm?b$Z7rv$KmU}AyMiDc(XN{J=f~6C?g0=n!qU~9?ppNs+7)eA94+faQ`}@D%acjgV zNT&_y(RHHknp*rfF5^i_TgbRp#3196{+>ky&VQAEo+pMPM{0yV|8~`z3Ti%QK(5L0 zr-t!9Q_&6UmUiZ(0*VYX1$RQB93UlE|M6Jhhv(tZJ5keuLdzxTcj!-VO;YeWjA=Nr zpdTR@k%fg}xf~?}Ohtv$=HIZ?X#oSTK6Z#<;-^a@M6X`)_IxThf1@PiFE*ENvG3is zH60mdcJ(n>;sKv)y$j#HAFV?y^Q?tWU7!YZCuY_TB^Nk{FKxR>rGEvZ9WZ?q|)y$X=>%nW=!}9nMz{ zmD_yC&BCmVq-~SK-wkLpx274fakn#eT|7Xxs|OOme~^Tvz2ZBtohlQ+wu^I7O=oPr zl}{I%Mi(Z`d8)HD_Xc$GZ`THj(zY`;nR*kMcz!8QgjcEI!ui=pTA@P3PlDlQcbKlr@m4U z&y2iHTaYzq0~6 z`FVVtO#WvW^}z#kYmMWObBXEfapUnDs8%y%#t^xVj}tOF1+|OcmsC$S^3m{}##6ir ze!Ts}*#*Wd_`4z&v@B*n zaz@ZnEs!a_FzD~mEmuQaA+`>yLIewcPiN0~+<2J45uK-mB7{mXGB8|f#D58;dEE7u z%r19t+D#GmnDxUJkBq39>D*6S8Ea5p{0t_l)0HY|jooe4^}^lcbUG07cGVz3hO4`- zsMTcmOSRU(>5G<{ZL-bS0$I@}Bl(+Jk0id^h+z4SQ&K{*T=R~ET}D4e@n+Kv9q85!TVk8+;&gN9c2{3OGBY~oV{8r7Te^Uk3!_z& z;23T?hn8tzD4E0#T*dml+h49MVRl2+S=V#)5HNIGaK8T9a$k~1)kUNZ9gp2La&Dk= zwKh#g!%`}T9$gfeVnJG09&DtEzUL5Mj1v{NCgxKgKU}1Fu2O>dq*e=Gmh3S=S)jL_ z5zB9{X67v@fmc0Ob3ES8oiZ!Mzcz>w8}pW2-x4-!@S}ngo-k&@#vSmy*f0}uXdCr|&miVoUk-=Tk@jGs1@jVBbB;^i-Sq)-PuF!HkmiY~SdoB7Etl zdQvXNd7gS)oBqApqa^}IX@NGqMbFmuIF6CF$mB{qc%wMu<&&-A6+;&Y~? zzJuOAF?6QQGHWDExDa%^&1QhB{^mZ$dY4JQ>7Temd=K6Ue>~0158hE_e?1eo#seyt z>Qft5r*oN<8g#W`-=8$=s(l&yxnG7n+RQP(Gshnn3sBz)o6!xv<=uZanqTE$X5UR7 zeDaiAP+LidyR^nL(~s9bOe-Q<@x*b+=i-cEiu<|#N*C1pqcv&10G1{8$l}S>q3X*I z%FsS+^3XolKTxFVOY}GIWEf!lHz1YeE({$#$=DLt1w@=5yC`A=$+hbLBMR^|2eZ%E zV?-g(5eNl&j!SkD&Q$CT>`0EgLAn=K*?T7_n@glCr+f)xpwJ!NKy!A1F;$kEL;ZHvv&bg6@yX9{8{; zI^g&HK>;l=>tr#HmN|VXZH!yO)njdpW8ohdR;JnMcWHlad46&>q1=&D)Ew+A z%cgRkAqN_^yNEJOV+E+9%vhc^!5B76o3Z1$(-3`bUzx>y&sCx{YePQiAGDLatJl?! zCDRp~sj)K)%!^f9i(>e=ig^DN$@i|7CD5S0wx^=*C(AB$#Ttihdr~bCmeo?nMWGg5 zvCd7xBKCs87k*XjNOPWTNm_Z`ym}BM!)zOoEruNx)+v%plTDUoXu7Mgp^eXAL5;Cm zC(fA;dvnRo6={Ekkl1=;ISpp^4o09EC8$T|0bQx zPPD7+ZKiFsCZ3T+MX6H;`E6v&arn|K>;`KdGyP8OsJxIPKIw)tPO_a8V9}OXQyEsP z_#D?H9*BK;hKEZf{p4l*4uK~lofA)PEG6u$W&Sq1W&Q)`KbSa>a+RikoF_U$B4^&0 z#=R-3_%ri+h;*(mQ9xkY*jbClUwT)3w+!;tWVhbeuHcjFZjG@Bu-;w+Bm*G( zODH$OBLFjLGlWVItI$>QUo11KQI$0D9F3J6y0zVaOVOb!in2y@>fNePXF)X4Pn_-B zQugMzY8(3gSTpZc$%UR7QuxbTI$S~{5wL(d<3i_r z*S6HrrC_3`TwQ^uL#TJ~%k{cY5hX>8_UdQa^ZGzW#&ff`dIhM;1hCzHT|vnEWOYQm_My-FwaygxU!->JKQABy{No!$kQp*tvkPYfu)?lmJO$t z94PU<;ClAuzW3xcjtf>J?I+1Hf9|8YVl*2mA0-#wQamePhaIyr#c39I-MA*wZH>X4 z=HkSduF*EgSACJnC8b=582BJQE)1X_VvBeuo@hUfQX~Ng9<{dAFD}3|3O4-;X zntcMb2kO@ocxk)eysj5`o@jDhc9)-0WNoCf;Xu5;lYa)|Pp7#x&Ae+%DhigHvRah~ zuRE1ve0^S+&ifGMFQ8uOvkBUPtBg`V9>TBVTe0D63Ie|!;)m2v>e>j-y?!6Ag)QG0%?NZY`{n+=SnY?TAwuBM+1k(Q1lH0=1gLeceEl^y?tH?v(z@wHcQ3^lfErWIp1AnOA8y#^;Nj$ z8$e1H7VavwF^pj@p19fC!h!Kycd6V4Sgt^|t&6$zD2&adZ~q3arec->OG?74-p{usX(sT(#e@Vcr9!r*;HPS8gf{p3XDGxH9s(6{ z>7`QeVJ!D`37-;E%cR5I!o5tJsBN7%Mbcod&p|v~lfYVdNgt+|E^KParBj&E&~6`Z zWTh{zjNOId65%|4rW3&Yy`z_2y>_8AV~5;NZr0{y;evzu?QYq$5cX_v_B)CVSQ{Q7!@F69B< zZY5%NyA&x`m9iffoZY+m;eUBn7o}gS=?|q=2Dnkoy+y!3td$!cq#RU`LeOs zn#8R3(;#33Yl@X?a}XzWIn;SKG?axa%wW;e*UZitQdK^p2nzEgWL^*CzUY24v+3Y= z9Ms4O+5liz%DjJQX0}RWJVliK)4J%i8=4!}nWW9?AHyO$f<1kzZ~%_UB!A(E*>({%(hrmb9Ok8%_O4Oi~Ti3|((d`^L%= zjA<18N3-+l-!F|y-zlx+rnwfGCiSkFo9H0b72Pc;M5OU*-JnE`BwvC?*Wr@C-_tU^ zc(&!Sa)ODteV&MvyL(0+;SNvU7`3gRI{*0n~qOI($j^F)6@t7 zr*&L9k5P%rK3uo#34D^Y?1j`RTl-cvTRXJee=y+l1@MV!*a&1IiaJ8xjRlN1jsmfy z=W2gv3m5iqYKEBod%;Cql)R8CPuda3Dfkfof&ZHUqi(%1?W?!fr|f7p3Uw-RPg<$Q+hRnkM2&_xz@T zfpe^Mg_!Wvt)~*;o!A4~OpYfCpNV?}t z@!Now?esi9FuFzH3ceGH?ubYWstkt5a&t8E)+M8WypAr+A{k||JC%DQj z^mU4LEqV~g4nF;Lf_Cidgtb2q701ruhzo@nO138nPaM- zmCFm(c7d+=hAYCPv22WfOlF>p>Lzo#N-}q$UFbmx_AJu`%kGPbb4EmM2m&TNDTAAA z&VjnWGvigBhL^cBoyJMVf+7c1%=CThNY&^^UhD9E{{5@QN7?nVEO#r~5mVdIYr8Va zZ&E1F#y0mrjt2KO6FXpeLy0VJ224EBwB3+T+H$vA>b1(p=Xn!zzDw zmpta;0v#a0*hnS7*!c&3Jikbtv*%N|{V{ySegU;!$wdPl`cB|9lxZMlpd4HF6q2I- zPY;B1zUKTQ+Hz-Cp|5E0+lLi5k9x?lcJ5x3KM07FhnX+k>43K!!c|e7lJn%f5g5ia z{YmWt%XayTsOnOVH#(mZqs}DtMs&IXNhA;?fp#Qzu+V0IbeW_~f3H(rV9713RQs^D zg+|tSHFGODjrD^;V^1_zvH|N593!oxUz6r^ro6-BZ>j_i=G*-hF-YwPpH7mf9ZQn9_6MR;`+ZvLi8}G1`vH}3Cz@PMHYgMiZ+i?Q z5qma}ewhj}`?nP;Yf<|RvMWJDw!$LxZt=){a&EsZeZ@t=dQE)cydy8kv_sphb7Y$@a2s`R zk5ocMdcBcce5Eaw%y?9rc-QA^zLXVjpR2VJ)|_J=xHP%X|2SQ`jQ={gCC3Nco0t+XgY9nLp#wG=gN9a8hgl9z8KQ7j~HvMbNHfmCB(r_4cWF6w_ zb?iAslXj74!{JUe=AlWmM4Z}_{iJD93ohUmCd;j3vYFN@jUoWol1Zg~d)=>i)!uPT z?zuGfE#TtCqO5YPKs5efsN|AEJyRra+_pPT(yP4D#^w7gIn75$K=g5?h558%vL!nfY~z0_G*gzpo{wUBhXWhX?4BQv(ZHd zi>Gl{$|mehzpf-#Cvf@S7|QA#mLZF-2{H!Fy!+{i8h43oJZ@KYfK(mKp^cqQ$Vuju zv!Q>QW>JOHSIrkFX!Vk3Ru$ZVKM;c6=pTl|ODiq2_T|?AzAdN0waJMUSxP&HXoD z_AxaWX;N5!-Rnk18&a&06Qn)Ncf5XUg{OYQCZXp|U*b%gil@XP*4{x#ekPdn&|fv( zx_#LhY$_6p;Dpf_3m)Cg%91Nj05O7UL2eqm-nn@#gZ>s)@A_}#lJjN!m6nkgqPI=G zJk4%KD84KM{byOq-!##-e&KiF^5M2PxGEXnt9ntT)Ur-kJb8+a++M&v?u=dHt``T7 zWi0zz=&R5gl^R|4UDwWXlq7H#FA92?_ni)FWcxy@|M&*7_rfOSb1(d0d=pp&!V$18607NCCP{(;cPKNPOh$7oQfvP^ zo^RFYG9N`(8xbcBi%2D>qTThQxlY>fOJ#Fs;!yGw7YFF<2OhlJOo9Du9H^!}H{i*` zH@eTa(gl4c+u=h7wFl1J$E69km~{XqK0!E`z@h^E3@*4?eIf&&uR`q)W$sR^?~qRx zc82{}i*x1~!EKhl@2!IN!@yPi$%+|j8B5d-Y#KuZ5fPBuWNIv|EGwU9(bVSp;`>aR zT_HUrXQ}-=$&+6}E@*4l;kRsDHHII)v%1K=uDlXse$ljXaFs3gzR)|>5wZ^jY7hscQkqp4WntXm zjGD5JD|?Go&*KjCfkZg8rTM+TAenfoar@9rC+oJ}V@~K1UTdDlY_)C1mhyix zVSL`sT92N+RveSJpS|--y4B22j$RVY6KNwIWb(t?|i19TF96^!;}VXSTGx z%wZ=WH;BmOF5AksMdPa+2cEgByR*pC#TK|ol?iYsG)s*Mw}Kb8g{n72%rB^4I)+UOWtEEb!cNNOAU3H zr;LlDIAR@wN%GuUYtp;kPgtzKrVjk@GNYVXVWDEvIU21n#vlMr6u zoG(Z;3!Pw#ItD+wN;*K6#E}0cq-PB0%Q^1f;cOzd_u`1)4*JBi!kOjU^?iWSo0+TuOFG3ueYAG%d(1eHSV{44i0DI>C~UDsuxF4j##hDyWh%7Xa*pNL zX}o+`I{IzGAby%JB(F2gnIQ64ufE_)L(Ri|{p`Q)_OUAS^M?qX!gK01xyJ4{{Ge>1 ztxw15Km<~{%KF)=<5=*J$=Tl!E*r^{vzupYr6!$%i?piSdeW?3w==Vpzj1VY7zeBvW|Dv&z zdCo+^)DQU|>@*P520|!PSmriUj$I|q_NyLc!j%129*;>oJg~U;knS( z`rL1Cax;X*HI#sacE9z?B=NtD2}8|)_aAUeyr3ICC-d{G|9CM)XSNjjhGVyAc&agB z3!i&P2x9)ficCWL9{LSp%=s6M4dT=!A$(Gqh2TxUSa=6J8T|TCfuojBh%fKM%Q#-j z+S4vRMy&YVUaQZ@v@Im5RYRrfB(9{-zaF#O2f*-Z=}+EyEHuBaOQhNEfBHQ)v@#W+ z-&R$^eB1^>2}D$J8Q4S*n|x!9P{(yG_xyyGg=f5U15-63nD_WsN-}~z8cPc`dHaP< z3w2D|AQZA(tn5Egyy8yOHvMsHsyXDlGhegt^K0GCwXCIqT00(vuhD9}pIDhBYE#Gb z_D!yfup_g|QTW4e(W@pw@G)d=A_yH3_W9cB%o+hO?CPS1>e0EAs(-)+VqnRxA%JAD z3l|9f>I_Z>PAN9?1~^{{NMgsbwzJQBJ~(Lc15!jzv)=XFN|d;`Y%dI9O?P~%%X~X) zWzS%YVv`6x>a*NNG?8UDolv0iL4V13;_>l}6*EU59RdC5YIQnc7L>|HeVCu-dN9!A z7|%hp7rztaLf}SJO!Z8MVb`n$&Z=0Z8XrC~TS+?_;ME0zX%ge0Pnim(t! zMOb!Iq{(ochrvc4gOmta;t9{kP$Ri#y&eRC9}P-9*PCjv37R?o+eP_8EF{VZggWms z@(S(CgxV6aKZAkJu6=KI!twc~l?T>#9^B;?+Ltwr4LjcLZXk>6$Oz>b0}3Yv$~K~X zJT*Zgz|i~c0tGRb{nVlmf&!f<0||;7pU1QLwi$aSq+>oefnU!htQu%PeoG1{<95F9 zL@tMOh7yhxaQP;1VTqQ8F^9m zPfTqIVpPE;G{Y7$Ds7~&C^2wg(KlFZCn(#;u4?hH4~C{aH%b*u9b<@ydoD!kCW3Cv zcJfvS;fUZI&0bKYlJPi%gAA9oJ1Ty-yMG!HK5ZR0zqR>t0WG`yq{4k-7oI^T$^Zvc|7;0`P z?w*h_vjaXQ%28`MZTJ{UAZ)a=|=LqU`uVT;=~d%@q;KKRMYU6$^in4;zd1eIvsu z|5=zb)(7drE}eo{uv!W7x#<7eecY!fCo_3`D3NHkM?@^Lj0^pz9fA?#a6MOY%~i&l zlAf-2%hGfU@u+J&bE&u0W_^lL5>niYQqqdMOQVgG+iFbDCfR%fA5$`lo7n3a{J^V) zjYYF!tXX=k_fJMsW;qcamHwoAaw`;FiVa-x?$E+?>>7ljzZEQ$nw)?@_q*hSm3T_lW)F;G?YJh>nhA5qMH9j94e0z>OR2eu}oS0E1T(L)?? z$a*&)L7X7P)<9ZOv07=fT7HPgy5UiLpf*!~QRHn>tVYe~fm2k5H+3N%QC9t`#Q9+} zpAxLKye^AxN_+Nd0oM|K9feP=8I!f~wi%Zv%GfTh92g}z+o{roTt4Xp7gvrp%{)HA zBrs&yw@hYM#2Rtl0sJIpM2VxF7y9=g@pFFOq|>u3jm}WgY6^{slU-(U(pmgruEXG| z%hqWVMr)c3mA!4rqHM{in~qHx*ucA5N-pIHExauw;4vsBH~a#3Tj}mJ(}EgbbL-4r z&77OC#gXq9ugG_3wIfB&uN5j3md*xHzQ}wvrF>+iia|rDIZ2phsP=? z+H}8w+hTXdg?##Nev4@)>+GK7&gZ4xA>-m$56Y4zAo>I$+h!W?6xJOzyR%>6d_S5|Cj zuT`vfbCP?Xmx?1tw@I%Nyq&#%GO!NiRVn86vBc-8Jz6Oi$t&7w<;zGB5*cYSim_Js zHlkAnc>T=~(hr2C!E?>&q(EN^2VZ8Z^*2x&4VefUSUBdf7hJSkB&4ySi0jaFR~KK; zQYjVE-MX$0AuTfu75`?u_IUJc6J*IjX1t5tYn`V#$ClcdPSMTPtWB-qAIx&zdOI># z_E-Cr%K+=}vL|_+++5EE;m{l4t|KvASql-5p}l<=-S$!kZ4j>p`JYwK(V64xGgNVeQ?wCfEJ&5x6L-srWVyll7eSFH;P@yiF-9J)@U_bS-u)?0uEXb z%y!E1aDIt6dx>NoEUTVAjdOH|8#vU#+ZX~~ZR z8>(i{5+8y5{p4qMOl|(AW&fIJt%n5fUwpv~ax!Ie`?B%5*}pF;i7T*^C=QiU)Deo_ zCv(H)u^GYVj0LdY?EZM5HuF9Xb_3ijQ`Ic*p7j0vZA$a*j~X`s9Gwf9bP|vq$>kK& zAb6`Nw69&bzkZgdhy1vPWO{reXKisa$NQ^_PCd?;1!vL_i1$0+s-RjOCHWgmEPzE! z_uO2++NK|&g&n5`Iekfjl&mhSF` z1*E&XV_7=h760;kKX4A{?wQ$%Yp$7l_PMFA2H8qS6L|O1*MgRtyqABHYJV7VI%qMXpM$e- zWfGN$;eg~HcJ4mBq#p+oz!7HBu(zbB-VuL4jO6e6QZnQm3uSM}M@58+vq7=>pr)MK zcG9{!H_dJ&*`I8FZksBfIRA=h+Ct4^zN0{TL5P#374FwzDf?F$Ke#S2-LT*~I2z*M zUszcMZou4YDnO=+ksj9TproFc zc50UvWjCE|aYy^lHH&I}rSIw&k8c6aOc)GNr<7mQs^_dG*N@(s`#IGQ=jTs!w)@qk z$eWNW1=riaPJ0x-rb=Ju#mmL=F>?C(XIq@+~WQyBteqZiIl2o!)%;(lyL&;XG zbYHRp&f?tYqmUEP)7rY2v_4zwv@LyROk8>KG)=-aMvT%P==*+ckB(Vmu$HtRiI(n` zUC}a#ml<$`D=ov6rO_8Q@{$?aqI@p-Od+qU;UzORXSCgR!O5iYrM~Mi^uho`PHgzh zseybXZFgqpI)2iAMP*y&0Pp3*oW+l!fo+nw^OO1fo3hAR=y8*t%5Z;e9Rd~`tCDo3 zqouklmkP>k`KPQ}k>~HT3XM^S;Z$bY3}x9~LznM6FyI{8UKdC!G5B|oaDKLk}AJdQy|Z}k3iQvv0LhG)IxPWk)t`Z?En`>k7v;T3K_Y>bM{ zD`csoycVdNloLks^h-!Q&K!)|)^?MUufB=fM1!hK^e*=#uSReOwRk2V`fTvzjH9rwR8*gexf`!ryXqt2 zQqz3l7;=pprG4=x*-o9kC$jwWB6RkU25*|_FH6e$Hp`N4l+Oo0EyhU{*%8mvjwC|jj zc`cSa&E|LA%?-=`jk{g*ykKRHVS!|m5C}Q^`^Dl=IsrrVvb1FgE%e};UvLN~#qAv= z_sl7II=oAsLj`pZ>_X_DMQ&!i+@2iX)^_$M@Q+&P3IdfhBHsaS+alXj>Y1wgeJ`D& zN@{W`@sY4myUSxUS#6+hgaH8~FJ$Pyv;X8kA{WG+xQo0TBqqzD%=nEi+OQTkLLVp+Toqbo2kLuX3I>y?lb@24SF~yR<6M4^ zQl#`jRsDFg>X$?w=2m~k@ffznAyXZIJIuY4=Ri9s>*@}6n8h-!^~W`genIgB7weW9 zTOIhHu3n$>$Ba!+=i9>=|J^Uo@OuuH&T}dn?%5QlKtk*Pg zG8MtO#;BgNS%((5^U2o64o(aKt>~i_StwfhuMY%AVt zKN-BXL>Z>hmLC$Jw6f;4LN5U(C1S1n2VkGEh}^b7=TtxPRg8qHKSPsl(lE1Gdc^t`gBTHKc} z7#Gp?G_U4Xd=mX6Hd6(%)YWVG5tr*v$!vc@Bd*Q+*#))^tHy_AIZ05=>>$}nnE5h7K?2nFe z%)+NJsgt$A-rqt*xz8p#51cG?^~UqM)SwKT=lpb6WeYU1AH2W+P=4))Oyw5!6}kKi`>jjS!*HR%kh6KvcGs$t zYTtB#VUN1Ut*l#bYxnW8Q@6}^?Co8Ue0oaN&g++o=-;|mZl-(aEC({{@YS5z&|8hn(3kU-vM0O1sUwd!!q*;q=pAt2FCWp{ z*#KN)$l8A@AKTOSsY2iQJfH1Y(lcd$Lgkh2;SDvaHx3|sEw3bwQpMU0hvxWSF8h;@ zZQp-Tq#Xwy1K-hHF*zw<8ra)A4m#_%x81&argV=uok!Jwow~iKy`mVW){Cj*bjy&F zkV}!@gp!4eCtQT-C|wd?*X%@#%frlNf*PLBs-#X?M=+vr273(DCI4Kn{)%!VPG)mH zncLS4-#mq#(qV9Wx}4`<56ZTVzci5#4Y~eoujZm_M z9*d!&bmY~k_v@WlbFho-4~>C+z0?=nh;f(t9&-2-RAG!t^hSpgUBozEINbS$)$=wc zz|Xs*l3M&i9*afqdyr0QRtzeJ>&;Gh)dcmyA02)*2B2{WwBpi1nW#u8?<`SptIS|g z?uVTH&QsRs3J!iIMnx7t09FXmS;uEg{K*pjMMqp0_~-v0Rq~aJdlccQuNT|EXxakjh_Lv(Bv`yfl9@B)LAR&LR=U zF62txmUg*>11%>A@?H6N(t0HuQSuMXhu>W-BC76J358&`DU-y#n`*VCg>D%E%(&)| zA4m=Wu^r}We$QtImLkmAis&1gJ5@D0gQ0zM{eBsJczFN}e!>I)$J)a$STlMby(AA} zTLo;Ara{7Nn!W{GmuJ#LCl$LKaJQYLysUqU+`7Rh*i;AF(m&Cm$h8Wja1*RtXq>jn zLNuv~YTdA_#Ai6qQzYE#!7q%IQruzd^6jvE@juJK(TI4;`d+~y&tz)JDv^K*iVR#2 z_?S-G=+;!TGSD5OT3*xrgL9Fnt>}!qNHO1!;Y64(He1roJRqE!HN4R$3z>t93I!h| zeb4r8wu3Kj@|=qu8}XIB(;eqA*xnhpe5IWRMfb3h9Qi+BcF)(R3KY-Ngr2%o<$f3C zUMuJ%fbTcTG2k-^?3-E^GsuU3p7w}H(LWGfu7qDKNpYGAu&1j)JY6O9 z_^jV@4(FktScU5n^bB*qf;*Tl(~%t}X4i!+9hs@~5^6 z_mXXbuzc?hb|4&j+jN=4>;XRSw1)nE-6o>RnQNZpj#s1F$6WvWGRzU<9j{MrdBQ|O zb?!O(TgwW1j)}5gDERjaAh?{yGoM_aWkt}qt+xpmDGJG7_S^pBf&G%sjA+X~B?Cuh zYUsYzWluGKZ!)ta@(F{O5aT~iLM+HLM*FGhDqY`csZ)Kox?kZWJ)OOI`b13i!hT(* zY;UtZr;(2V;3S|5?D1u5UZ&VOuP*A14zF-=KQ6C(W@58{Sk>*AH_5oGjY%lnGwCsT zy;Q%qG8B5Q<`msneRp9`<;BiVT%M$|+hvMYZYTFp=QugLIJJ9?&7V!mf?A|*UIRq- zX28|&lRNFGHCi2nk5(w@W!@HT8|gfnEiccHyod-(YynkPPL1IENO#Hcu8oKU$B>+J|B@|1?s_7qVl57E(o^o36%{2*ODD z_EeRjpOJR&(v0aY$^z$aRPayIwl`6jw2MgZnls533cA84jT2XX0I_^s*Dos zrT}YmM-4$zH(GZfq1%%o=Iyh3zWFm25B0f1auIJ*1Ev`BRbaiDU-W}^yVhtD2!vs1 zNUUWs@3-fU1vl^`44NpuG4=AAnb5DKT#I+`+HxaMJ?b?#|D5VM1Me#8oZu^csxREC z__fJ&lBwBgiyN56(+Alve=L1{Uv9Ul1@FBSaN?d<|GDw1i{jF}FtJnKs%(qKL#CZg$K01*&bT>J8z<<44Bv~F^o`c{` zD15n;$P^GplpMKf;GfH)Ai&XY**Bxii#ZMd*ku#`V%cT1+}o^XLO3I$(v_WXH&kW# zv!0C}>2DWbQ!j~vfV*+_%vrf+9$24O)-x~0YcC-5pj*Opg4@hoeQ$ANi_RwZZ@o8F zl17HWNWUwERKE0LR8xrKgJ&$%z?1O6VpOCiW@M{q+FAp76LoMgiX=v{V4$k_I<6|E zfIe`t7PcsMrbi}H_X(?Cs_*a9)$k%IEs8y}`?DXR-SbJZEXf*n*I z6Yu(o&>!dYEbH^tGEJ=kkLQ=R2bf5U1qj+Iu@yn_JEDaW-m6P7m--IX&+~CROrf zuRW9Pg@>aiK(t@k+dy6=k4)6J4P1BKVx>hBQ(Yf9tV&$MWTi&@H$O0dl2a34A&tot z$VZzRspa%h=BFpl*m@-k|1KV^)3;JP?{+tl%h98a^&W8tyEV$*uZd`>JO7^l)UXmz zMG>-tG+3Uhvf7x$)ReSx-Wv$;AgML-+aW z*$-oK&zee2BWAMcn$|yiW1SzG4B!4>oU5$Wx8D;%$2=jqd}*64oScNp%1MwSJ^&AV z_zi1J=ObTQ7%Meu!*7d&^TGb0AZWVz!EHkE5L>C z8C2Gs$4GwvnNP`C{5!QIUis`T%(+7asc2(}kTjp_i4pNseG@Bx8)1y5r7sQdJkFaF!Zg9OS;>JH%``3k)x@RtIDfU7t_8j$ zW+Owk%hlL5fztSdZV^FiPlO^=`yyVlXj(&p zf?wMG6sUT>$eHsLh1K)%V)L;!K%@|=ex%S((A9g=u_^gG2xlFT;V$`-<||{_%kiHv z#ZPQk*C1YX{yjup1M(JvrF75$DtvUaRnvz&`aBH7Usy|FF#HF9nf89a>GOZfdo+-! z-$}kIaIW!jtx6ppuzX?qj-#W7=n-AS-D@;2+-ita@l2E$lt?S+T*cV|!_&aIz&w*e zx$`}cvz6;xNR?Vp9@`1ok5QdvOH(vhjh6bR#2g1R@tW{6Bpe+_zY#Y9q%}J3BLV!` zfVvqDdWOYF`vYLPRsbQ=f1#<5iG&LK`3cIrk;Lu3Jl766?b^CM}z9kse(Gz38)p})GA?iDf5|1iaR8$>J zrP+*&AtOC&WTGN%cGX0-))E99_Wef;Sq&qHQS>8+GeMbQA8@-R1RyASpc{heqhn

^L*2vF$H-GXZ?o+-d}6! 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

TJzjQsj|^v_FUlbFm)(^}1w1aG^Fu+`}Vf5q7s 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∨J{r}TsNM;O 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

!R6jf-B{x?fISkY-=n|6S3S|v!s@)31T2(uB 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 literal 0 HcmV?d00001 diff --git a/spreadsheet/macrofree/sql_checklist.ja.xlsx b/spreadsheet/macrofree/sql_checklist.ja.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..89963dbbdb82a9a13f238675aa275b033aba3df0 GIT binary patch literal 34481 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 literal 0 HcmV?d00001 diff --git a/spreadsheet/macrofree/sql_checklist.pt.xlsx b/spreadsheet/macrofree/sql_checklist.pt.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c3a3308de0f89747642cd199a95808c8a9e9c607 GIT binary patch literal 32275 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

*iG&Z6TTkGGoEUR|u}783PCQhi^< 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 literal 0 HcmV?d00001 diff --git a/spreadsheet/macrofree/sql_checklist.zh-Hant.xlsx b/spreadsheet/macrofree/sql_checklist.zh-Hant.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..46295b2a74651e9cd7c127f21da5b4779df47874 GIT binary patch literal 32915 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 A?f?J) literal 0 HcmV?d00001 diff --git a/workbooks/alz_checklist.en_network_counters.json b/workbooks/alz_checklist.en_network_counters.json index db6450ccf..3214b523f 100644 --- a/workbooks/alz_checklist.en_network_counters.json +++ b/workbooks/alz_checklist.en_network_counters.json @@ -749,7 +749,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query10Stats:$.Success}+{Query11Stats:$.Success}" + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}" } } ] @@ -768,7 +768,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query10Stats:$.Total}+{Query11Stats:$.Total}" + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}" } } ] @@ -806,7 +806,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" + "resultVal": "{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}" } } ] @@ -825,7 +825,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" + "resultVal": "{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}" } } ] @@ -863,7 +863,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}" } } ] @@ -882,7 +882,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}" } } ] @@ -920,7 +920,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}" + "resultVal": "{Query10Stats:$.Success}+{Query11Stats:$.Success}" } } ] @@ -939,7 +939,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}" + "resultVal": "{Query10Stats:$.Total}+{Query11Stats:$.Total}" } } ] @@ -977,7 +977,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Success}" + "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}" } } ] @@ -996,7 +996,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Total}" + "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}" } } ] @@ -1034,7 +1034,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}" + "resultVal": "{Query18Stats:$.Success}" } } ] @@ -1053,7 +1053,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}" + "resultVal": "{Query18Stats:$.Total}" } } ] @@ -1091,7 +1091,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" } } ] @@ -1110,7 +1110,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" } } ] @@ -1148,7 +1148,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query23Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}" + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" } } ] @@ -1167,7 +1167,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query23Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}" + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" } } ] @@ -1241,66 +1241,66 @@ "style": "tabs", "links": [ { - "id": "170ab09f-8d73-44de-9764-27150783e9fb", + "id": "4c46a3ac-7659-46a7-a5da-7cc37b0cff77", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan ({Tab0Success:value}/{Tab0Total:value})", + "linkLabel": "Hybrid ({Tab0Success:value}/{Tab0Total:value})", "subTarget": "tab0", - "preText": "IP plan", + "preText": "Hybrid", "style": "primary" }, { - "id": "ecacab8c-012f-4191-9d52-1487856a5a7e", + "id": "33603386-35d7-4e89-9f03-933ca972dfe9", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke ({Tab1Success:value}/{Tab1Total:value})", + "linkLabel": "Segmentation ({Tab1Success:value}/{Tab1Total:value})", "subTarget": "tab1", - "preText": "Hub and spoke", + "preText": "Segmentation", "style": "primary" }, { - "id": "2de4800a-6d67-4aac-b6b0-8494cecc4d87", + "id": "b30e142c-ef12-44ca-9c56-2e849ef36073", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet ({Tab2Success:value}/{Tab2Total:value})", + "linkLabel": "Virtual WAN ({Tab2Success:value}/{Tab2Total:value})", "subTarget": "tab2", - "preText": "Internet", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "347626c4-8998-4d90-a8ab-bd28f4c5c5a0", + "id": "0131a919-127a-4fe5-9724-9be82a74a43e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN ({Tab3Success:value}/{Tab3Total:value})", + "linkLabel": "IP plan ({Tab3Success:value}/{Tab3Total:value})", "subTarget": "tab3", - "preText": "Virtual WAN", + "preText": "IP plan", "style": "primary" }, { - "id": "db0cf4ec-9709-4a90-85af-572f25b9ddde", + "id": "5437de58-7b52-4bf5-b2de-c31dfaaf9b72", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS ({Tab4Success:value}/{Tab4Total:value})", + "linkLabel": "Internet ({Tab4Success:value}/{Tab4Total:value})", "subTarget": "tab4", - "preText": "PaaS", + "preText": "Internet", "style": "primary" }, { - "id": "17992c42-0116-43a0-bc47-9b1766377282", + "id": "69bbea89-a89e-4edf-b79c-05f9bddb357f", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation ({Tab5Success:value}/{Tab5Total:value})", + "linkLabel": "PaaS ({Tab5Success:value}/{Tab5Total:value})", "subTarget": "tab5", - "preText": "Segmentation", + "preText": "PaaS", "style": "primary" }, { - "id": "13947877-2f8f-4420-8638-86d22735f6ed", + "id": "0caa7f93-db65-4b53-a678-f78893ad98d0", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid ({Tab6Success:value}/{Tab6Total:value})", + "linkLabel": "Hub and spoke ({Tab6Success:value}/{Tab6Total:value})", "subTarget": "tab6", - "preText": "Hybrid", + "preText": "Hub and spoke", "style": "primary" } ] @@ -1316,22 +1316,22 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Hybrid" }, "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": "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": "querytext10" + "name": "querytext4" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/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", @@ -1380,20 +1380,20 @@ ] } }, - "name": "query10" + "name": "query4" }, { "type": 1, "content": { - "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Ensure that you're using 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": "querytext11" + "name": "querytext5" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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/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", @@ -1442,42 +1442,20 @@ ] } }, - "name": "query11" - } - ] - }, - "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": "query5" }, { "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": "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": "querytext0" + "name": "querytext6" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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/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", @@ -1526,20 +1504,20 @@ ] } }, - "name": "query0" + "name": "query6" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "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": "querytext1" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier 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", @@ -1588,20 +1566,20 @@ ] } }, - "name": "query1" + "name": "query7" }, { "type": 1, "content": { - "json": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use 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": "querytext2" + "name": "querytext8" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -1650,20 +1628,20 @@ ] } }, - "name": "query2" + "name": "query8" }, { "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 you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) for further information." }, - "name": "querytext3" + "name": "querytext9" }, { "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,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1712,16 +1690,16 @@ ] } }, - "name": "query3" + "name": "query9" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab1" + "value": "tab0" }, - "name": "tab1" + "name": "tab0" }, { "type": 12, @@ -1732,22 +1710,22 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Segmentation" }, - "name": "tab2title" + "name": "tab1title" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." + "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext12" + "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 == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1796,20 +1774,20 @@ ] } }, - "name": "query12" + "name": "query19" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." }, - "name": "querytext13" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1858,20 +1836,20 @@ ] } }, - "name": "query13" + "name": "query20" }, { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." }, - "name": "querytext14" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1920,20 +1898,20 @@ ] } }, - "name": "query14" + "name": "query21" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." }, - "name": "querytext15" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1982,20 +1960,42 @@ ] } }, - "name": "query15" + "name": "query22" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab1" + }, + "name": "tab1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Virtual WAN" + }, + "name": "tab2title" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext16" + "name": "querytext23" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2044,20 +2044,42 @@ ] } }, - "name": "query16" + "name": "query23" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab2" + }, + "name": "tab2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## IP plan" + }, + "name": "tab3title" }, { "type": 1, "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext17" + "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,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2106,42 +2128,20 @@ ] } }, - "name": "query17" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab2" - }, - "name": "tab2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Virtual WAN" - }, - "name": "tab3title" + "name": "query10" }, { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext23" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -2190,7 +2190,7 @@ ] } }, - "name": "query23" + "name": "query11" } ] }, @@ -2210,22 +2210,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Internet" }, "name": "tab4title" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext18" + "name": "querytext12" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2274,42 +2274,20 @@ ] } }, - "name": "query18" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab4" - }, - "name": "tab4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Segmentation" - }, - "name": "tab5title" + "name": "query12" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext19" + "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 == '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.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", @@ -2358,20 +2336,20 @@ ] } }, - "name": "query19" + "name": "query13" }, { "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 Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext20" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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", @@ -2420,20 +2398,20 @@ ] } }, - "name": "query20" + "name": "query14" }, { "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": "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" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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", @@ -2482,20 +2460,20 @@ ] } }, - "name": "query21" + "name": "query15" }, { "type": 1, "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext22" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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", @@ -2544,42 +2522,20 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab5" - }, - "name": "tab5" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hybrid" - }, - "name": "tab6title" + "name": "query16" }, { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, - "name": "querytext4" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -2628,20 +2584,42 @@ ] } }, - "name": "query4" + "name": "query17" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab5title" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Don't 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": "querytext5" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/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", @@ -2690,20 +2668,42 @@ ] } }, - "name": "query5" + "name": "query18" + } + ] + }, + "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": "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": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." }, - "name": "querytext6" + "name": "querytext0" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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", @@ -2752,20 +2752,20 @@ ] } }, - "name": "query6" + "name": "query0" }, { "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": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." }, - "name": "querytext7" + "name": "querytext1" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2814,20 +2814,20 @@ ] } }, - "name": "query7" + "name": "query1" }, { "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": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." }, - "name": "querytext8" + "name": "querytext2" }, { "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/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2876,20 +2876,20 @@ ] } }, - "name": "query8" + "name": "query2" }, { "type": 1, "content": { - "json": "If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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": "querytext9" + "name": "querytext3" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | 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", @@ -2938,7 +2938,7 @@ ] } }, - "name": "query9" + "name": "query3" } ] }, diff --git a/workbooks/alz_checklist.en_network_counters_template.json b/workbooks/alz_checklist.en_network_counters_template.json index 519d5469f..171a6e1da 100644 --- a/workbooks/alz_checklist.en_network_counters_template.json +++ b/workbooks/alz_checklist.en_network_counters_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation))| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"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 | 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\": \"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' | 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\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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.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\": \"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.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\": \"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.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\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"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 = 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\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"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 == '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\": \"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/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\": \"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,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\": \"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/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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query10Stats:$.Success}+{Query11Stats:$.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\": \"{Query10Stats:$.Total}+{Query11Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query23Stats:$.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\": \"{Query23Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}\"\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\": \"{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query23Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.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\": \"{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query23Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.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\": \"170ab09f-8d73-44de-9764-27150783e9fb\",\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\": \"ecacab8c-012f-4191-9d52-1487856a5a7e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2de4800a-6d67-4aac-b6b0-8494cecc4d87\",\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\": \"347626c4-8998-4d90-a8ab-bd28f4c5c5a0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"db0cf4ec-9709-4a90-85af-572f25b9ddde\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"17992c42-0116-43a0-bc47-9b1766377282\",\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\": \"13947877-2f8f-4420-8638-86d22735f6ed\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"query10\"\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\": \"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 | 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\": \"query11\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext12\"\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\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext23\"\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\": \"query23\"\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\": \"## PaaS\"\n },\n \"name\": \"tab4title\"\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\": \"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 = 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\": \"query18\"\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\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query19\"\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\": \"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 == '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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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 },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation))| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"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 | 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\": \"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' | 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\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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.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\": \"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.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\": \"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.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\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"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 = 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\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"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 == '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\": \"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/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\": \"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,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\": \"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/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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.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}\"\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\": \"{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query23Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query23Stats:$.Total}\"\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\": \"{Query10Stats:$.Success}+{Query11Stats:$.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\": \"{Query10Stats:$.Total}+{Query11Stats:$.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\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query18Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}\"\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}\"\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}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.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}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.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 - 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\": \"4c46a3ac-7659-46a7-a5da-7cc37b0cff77\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"33603386-35d7-4e89-9f03-933ca972dfe9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b30e142c-ef12-44ca-9c56-2e849ef36073\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0131a919-127a-4fe5-9724-9be82a74a43e\",\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\": \"5437de58-7b52-4bf5-b2de-c31dfaaf9b72\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"69bbea89-a89e-4edf-b79c-05f9bddb357f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0caa7f93-db65-4b53-a678-f78893ad98d0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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 },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query19\"\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\": \"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 == '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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext23\"\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\": \"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\": 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\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"query10\"\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\": \"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 | 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\": \"query11\"\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\": \"## Internet\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext12\"\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\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"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 = 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\": \"query18\"\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\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/alz_checklist.en_network_tabcounters.json b/workbooks/alz_checklist.en_network_tabcounters.json index bee2cb6e9..90bec7074 100644 --- a/workbooks/alz_checklist.en_network_tabcounters.json +++ b/workbooks/alz_checklist.en_network_tabcounters.json @@ -70,34 +70,34 @@ "style": "tabs", "links": [ { - "id": "cadc2d37-a1a3-4f78-ab00-27767ae2e042", + "id": "deffcc58-0168-4f2c-b868-95a6acecafd7", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Segmentation", "subTarget": "tab0", - "preText": "IP plan", + "preText": "Segmentation", "style": "primary" }, { - "id": "6b41c621-13ad-4581-8aaa-20d15a9ea78f", + "id": "a91c92bf-3726-4409-9167-03c9d57708f4", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "PaaS", "subTarget": "tab1", - "preText": "Virtual WAN", + "preText": "PaaS", "style": "primary" }, { - "id": "5bfecebf-fec0-415f-9485-730d5725a909", + "id": "b154723a-88e7-4587-8668-8d051476ee5d", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "Hybrid", "subTarget": "tab2", - "preText": "PaaS", + "preText": "Hybrid", "style": "primary" }, { - "id": "77018017-35a0-43a5-b37a-979ec045173f", + "id": "9f40f0a7-3b86-4a90-b571-c69b08cb5b25", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Internet", @@ -106,25 +106,25 @@ "style": "primary" }, { - "id": "9b15d4c9-04a2-4327-833f-631cf717110a", + "id": "a23170d0-c872-42d1-b586-cd81e006ae6a", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "IP plan", "subTarget": "tab4", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "24778d3c-c3ee-4c82-b465-b8dabb6eafa5", + "id": "8644cbea-9034-4656-89ae-e76240c683bc", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Virtual WAN", "subTarget": "tab5", - "preText": "Hybrid", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "3848bbaf-c95f-4abe-a21e-c09b7efe8d3a", + "id": "e5d729ca-0d04-4754-8718-421ce3dd6298", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Hub and spoke", @@ -153,9 +153,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query10Stats", + "name": "Query19Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -169,9 +169,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query10FullyCompliant", + "name": "Query19FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query10Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -181,9 +181,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11Stats", + "name": "Query20Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -197,9 +197,65 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11FullyCompliant", + "name": "Query20FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query21Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query21FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query22Stats", + "type": 1, + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query22FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -220,7 +276,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query10Stats:$.Success}+{Query11Stats:$.Success}" + "resultVal": "{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}" } } ] @@ -239,7 +295,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query10Stats:$.Total}+{Query11Stats:$.Total}" + "resultVal": "{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}" } } ] @@ -273,7 +329,7 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Segmentation" }, "customWidth": "50", "name": "tab0title" @@ -314,15 +370,15 @@ { "type": 1, "content": { - "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext10" + "name": "querytext19" }, { "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", @@ -371,20 +427,20 @@ ] } }, - "name": "query10" + "name": "query19" }, { "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": "querytext11" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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", @@ -433,7 +489,131 @@ ] } }, - "name": "query11" + "name": "query20" + }, + { + "type": 1, + "content": { + "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." + }, + "name": "querytext21" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query21" + }, + { + "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": "querytext22" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query22" } ] }, @@ -461,9 +641,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23Stats", + "name": "Query18Stats", "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 = 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}" ], @@ -477,9 +657,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23FullyCompliant", + "name": "Query18FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -500,7 +680,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}" + "resultVal": "{Query18Stats:$.Success}" } } ] @@ -519,7 +699,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}" + "resultVal": "{Query18Stats:$.Total}" } } ] @@ -553,7 +733,7 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## PaaS" }, "customWidth": "50", "name": "tab1title" @@ -594,15 +774,15 @@ { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." }, - "name": "querytext23" + "name": "querytext18" }, { "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 = 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", @@ -651,7 +831,7 @@ ] } }, - "name": "query23" + "name": "query18" } ] }, @@ -679,9 +859,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query18Stats", + "name": "Query4Stats", "type": 1, - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -695,9 +875,149 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query18FullyCompliant", + "name": "Query4FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query5Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query5FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query6Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query6FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query7Stats", + "type": 1, + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query7FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query8Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query8FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query9Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation))| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query9FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query9Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -718,7 +1038,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Success}" + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}" } } ] @@ -737,7 +1057,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Total}" + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}" } } ] @@ -771,7 +1091,7 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Hybrid" }, "customWidth": "50", "name": "tab2title" @@ -812,15 +1132,15 @@ { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext18" + "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/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", @@ -869,333 +1189,37 @@ ] } }, - "name": "query18" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab2" - }, - "name": "tab2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query4" + }, { - "type": 9, + "type": 1, "content": { - "version": "KqlParameterItem/1.0", + "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + }, + "name": "querytext5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", "crossComponentResources": [ "{Subscription}" ], - "parameters": [ - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query12Stats", - "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": "Query12FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query12Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query13Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "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", - "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query14FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query15Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query15FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query16Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query16FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query17Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/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": "Query17FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab3Success", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab3Total", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.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": "## Internet" - }, - "customWidth": "50", - "name": "tab3title" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", - "size": 3, - "queryType": 8, - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 4, - "formatOptions": { - "min": 0, - "max": 100, - "palette": "redGreen" - }, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - "subtitleContent": { - "columnMatch": "Column2" - }, - "showBorder": true - } - }, - "customWidth": "50", - "name": "TabPercentTile" - }, - { - "type": 1, - "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." - }, - "name": "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 == '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" - } - } + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } }, { "columnMatch": "compliant", @@ -1227,82 +1251,20 @@ ] } }, - "name": "query12" - }, - { - "type": 1, - "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." - }, - "name": "querytext13" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query13" + "name": "query5" }, { "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": "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": "querytext14" + "name": "querytext6" }, { "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/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", @@ -1351,20 +1313,20 @@ ] } }, - "name": "query14" + "name": "query6" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Deploy 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": "querytext15" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier 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", @@ -1413,20 +1375,20 @@ ] } }, - "name": "query15" + "name": "query7" }, { "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 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": "querytext16" + "name": "querytext8" }, { "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' | 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", @@ -1475,20 +1437,20 @@ ] } }, - "name": "query16" + "name": "query8" }, { "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": "If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) for further information." }, - "name": "querytext17" + "name": "querytext9" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1537,16 +1499,16 @@ ] } }, - "name": "query17" + "name": "query9" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab3" + "value": "tab2" }, - "name": "tab3" + "name": "tab2" }, { "type": 12, @@ -1565,9 +1527,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,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,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}" ], @@ -1581,9 +1543,9 @@ { "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 @@ -1593,9 +1555,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query20Stats", + "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 == '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/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}" ], @@ -1609,9 +1571,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query20FullyCompliant", + "name": "Query13FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1621,9 +1583,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21Stats", + "name": "Query14Stats", "type": 1, - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/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}" ], @@ -1637,9 +1599,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21FullyCompliant", + "name": "Query14FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1649,9 +1611,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22Stats", + "name": "Query15Stats", "type": 1, - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/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}" ], @@ -1665,9 +1627,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22FullyCompliant", + "name": "Query15FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1677,7 +1639,63 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Success", + "name": "Query16Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query16FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query17Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/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": "Query17FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab3Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1688,7 +1706,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}" + "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}" } } ] @@ -1696,7 +1714,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Total", + "name": "Tab3Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1707,7 +1725,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}" + "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}" } } ] @@ -1715,7 +1733,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Percent", + "name": "Tab3Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1726,7 +1744,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab4Success}/{Tab4Total})" + "resultVal": "round(100*{Tab3Success}/{Tab3Total})" } } ] @@ -1741,16 +1759,16 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## Internet" }, "customWidth": "50", - "name": "tab4title" + "name": "tab3title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -1769,28 +1787,152 @@ "style": "decimal" } } - }, - "subtitleContent": { - "columnMatch": "Column2" - }, - "showBorder": true + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true + } + }, + "customWidth": "50", + "name": "TabPercentTile" + }, + { + "type": 1, + "content": { + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." + }, + "name": "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 == '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": "query12" + }, + { + "type": 1, + "content": { + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + }, + "name": "querytext13" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] } }, - "customWidth": "50", - "name": "TabPercentTile" + "name": "query13" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext19" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -1839,20 +1981,20 @@ ] } }, - "name": "query19" + "name": "query14" }, { "type": 1, "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." + "json": "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": "querytext20" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -1901,20 +2043,20 @@ ] } }, - "name": "query20" + "name": "query15" }, { "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": "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": "querytext21" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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", @@ -1963,20 +2105,20 @@ ] } }, - "name": "query21" + "name": "query16" }, { "type": 1, "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "For 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": "querytext22" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -2025,16 +2167,16 @@ ] } }, - "name": "query22" + "name": "query17" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab3" }, - "name": "tab4" + "name": "tab3" }, { "type": 12, @@ -2053,121 +2195,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4Stats", - "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query4FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query5Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query5FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query6Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query6FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query7Stats", - "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query7FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query8Stats", + "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/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}" ], @@ -2181,9 +2211,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8FullyCompliant", + "name": "Query10FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query10Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2193,9 +2223,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query9Stats", + "name": "Query11Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation))| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==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}" ], @@ -2209,9 +2239,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query9FullyCompliant", + "name": "Query11FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query9Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2221,7 +2251,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Success", + "name": "Tab4Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2232,7 +2262,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}" + "resultVal": "{Query10Stats:$.Success}+{Query11Stats:$.Success}" } } ] @@ -2240,7 +2270,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Total", + "name": "Tab4Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2251,7 +2281,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}" + "resultVal": "{Query10Stats:$.Total}+{Query11Stats:$.Total}" } } ] @@ -2259,7 +2289,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Percent", + "name": "Tab4Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2270,7 +2300,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab5Success}/{Tab5Total})" + "resultVal": "round(100*{Tab4Success}/{Tab4Total})" } } ] @@ -2285,16 +2315,16 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## IP plan" }, "customWidth": "50", - "name": "tab5title" + "name": "tab4title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -2320,83 +2350,21 @@ "showBorder": true } }, - "customWidth": "50", - "name": "TabPercentTile" - }, - { - "type": 1, - "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." - }, - "name": "querytext4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query4" + "customWidth": "50", + "name": "TabPercentTile" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext5" + "name": "querytext10" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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", @@ -2445,20 +2413,20 @@ ] } }, - "name": "query5" + "name": "query10" }, { "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 IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext6" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -2507,144 +2475,176 @@ ] } }, - "name": "query6" - }, - { - "type": 1, - "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." - }, - "name": "querytext7" - }, + "name": "query11" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ { - "type": 3, + "type": 9, "content": { - "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/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", + "version": "KqlParameterItem/1.0", "crossComponentResources": [ "{Subscription}" ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" + "parameters": [ + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query23Stats", + "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": "Query23FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab5Success", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query23Stats:$.Success}" } } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab5Total", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query23Stats:$.Total}" + } } - } - ] - } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab5Percent", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "round(100*{Tab5Success}/{Tab5Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" }, - "name": "query7" + "name": "TabInvisibleParameters" }, { "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": "## Virtual WAN" }, - "name": "querytext8" + "customWidth": "50", + "name": "tab5title" }, { "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" - } - } + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "size": 3, + "queryType": 8, + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 4, + "formatOptions": { + "min": 0, + "max": 100, + "palette": "redGreen" }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true } }, - "name": "query8" + "customWidth": "50", + "name": "TabPercentTile" }, { "type": 1, "content": { - "json": "If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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": "querytext9" + "name": "querytext23" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | 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", @@ -2693,7 +2693,7 @@ ] } }, - "name": "query9" + "name": "query23" } ] }, diff --git a/workbooks/alz_checklist.en_network_tabcounters_template.json b/workbooks/alz_checklist.en_network_tabcounters_template.json index 6dfeefd64..c38da525c 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\": \"cadc2d37-a1a3-4f78-ab00-27767ae2e042\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab0\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6b41c621-13ad-4581-8aaa-20d15a9ea78f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5bfecebf-fec0-415f-9485-730d5725a909\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab2\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"77018017-35a0-43a5-b37a-979ec045173f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"9b15d4c9-04a2-4327-833f-631cf717110a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"24778d3c-c3ee-4c82-b465-b8dabb6eafa5\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3848bbaf-c95f-4abe-a21e-c09b7efe8d3a\",\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 },\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\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"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 | 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\": \"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\": \"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\": \"{Query10Stats:$.Success}+{Query11Stats:$.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\": \"{Query10Stats:$.Total}+{Query11Stats:$.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\": \"## IP plan\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use 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\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"query10\"\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\": \"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 | 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\": \"query11\"\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\": \"Query23Stats\",\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\": \"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\": \"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\": \"{Query23Stats:$.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\": \"{Query23Stats:$.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\": \"## Virtual WAN\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"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\": \"querytext23\"\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\": \"query23\"\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\": \"Query18Stats\",\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\": \"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\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}\"\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\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab2title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab2Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"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\": \"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 = 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\": \"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\": 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' | 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\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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.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\": \"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.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\": \"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.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\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext12\"\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\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"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 == '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\": \"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/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\": \"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,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\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab4title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab4Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query19\"\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\": \"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 == '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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation))| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\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\": \"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\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.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\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab5title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab5Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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 },\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\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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}\"\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}\"\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 successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"deffcc58-0168-4f2c-b868-95a6acecafd7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a91c92bf-3726-4409-9167-03c9d57708f4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab1\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b154723a-88e7-4587-8668-8d051476ee5d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"9f40f0a7-3b86-4a90-b571-c69b08cb5b25\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a23170d0-c872-42d1-b586-cd81e006ae6a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab4\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8644cbea-9034-4656-89ae-e76240c683bc\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e5d729ca-0d04-4754-8718-421ce3dd6298\",\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 },\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\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"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 == '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\": \"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/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\": \"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,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\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query19\"\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\": \"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 == '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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\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\": \"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\": \"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\": \"{Query18Stats:$.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\": \"{Query18Stats:$.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 successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"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 = 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\": \"query18\"\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\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation))| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\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\": \"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\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.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\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab2title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab2Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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 },\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\": \"Query12Stats\",\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\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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.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\": \"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.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\": \"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.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\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext12\"\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\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"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 | 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\": \"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\": \"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\": \"{Query10Stats:$.Success}+{Query11Stats:$.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\": \"{Query10Stats:$.Total}+{Query11Stats:$.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 successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"query10\"\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\": \"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 | 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\": \"query11\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query23Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/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\": \"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\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query23Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query23Stats:$.Total}\"\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 successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext23\"\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\": \"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\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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}\"\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}\"\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 successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/alz_checklist.en_network_workbook.json b/workbooks/alz_checklist.en_network_workbook.json index 5b0bf7a0d..c5cad05c3 100644 --- a/workbooks/alz_checklist.en_network_workbook.json +++ b/workbooks/alz_checklist.en_network_workbook.json @@ -70,66 +70,66 @@ "style": "tabs", "links": [ { - "id": "39bf5f38-ecfa-4cd4-8999-0a6b8a58f604", + "id": "87c89a28-e84a-45ab-9add-3cc8e8f6566d", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Hub and spoke", "subTarget": "tab0", - "preText": "IP plan", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "37f0847e-02e3-43d8-9d51-fa5c1f601fdf", + "id": "a78cc609-eb83-44aa-8ac7-e93665eb00c9", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Segmentation", "subTarget": "tab1", - "preText": "Hybrid", + "preText": "Segmentation", "style": "primary" }, { - "id": "b307eae6-59a6-47e5-b3c6-c279564858b9", + "id": "48a4285c-00d5-4226-b9f6-257e6dfc586c", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "PaaS", "subTarget": "tab2", - "preText": "Segmentation", + "preText": "PaaS", "style": "primary" }, { - "id": "b60d81bc-a5e9-4944-8e77-71f0e0b69d6e", + "id": "217e9414-fe7d-4430-ba73-395df6b1dd97", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "IP plan", "subTarget": "tab3", - "preText": "PaaS", + "preText": "IP plan", "style": "primary" }, { - "id": "ccce3323-1ee7-4f02-9af4-10749fb39e7d", + "id": "05a59fa4-a54d-4e9b-9859-b5e4b4c23cb1", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "Virtual WAN", "subTarget": "tab4", - "preText": "Internet", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "5a5e2ab2-cfe4-482a-a744-64483e3a3ffe", + "id": "d7e398c5-f270-48ef-9713-8428ddf28bca", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Internet", "subTarget": "tab5", - "preText": "Virtual WAN", + "preText": "Internet", "style": "primary" }, { - "id": "95e15a0a-4e51-4f7a-b4b4-65e1a69d9ea5", + "id": "5c578132-7cc5-4c3e-8d4b-cbc4da235ebc", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "Hybrid", "subTarget": "tab6", - "preText": "Hub and spoke", + "preText": "Hybrid", "style": "primary" } ] @@ -145,22 +145,22 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Hub and spoke" }, "name": "tab0title" }, { "type": 1, "content": { - "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." }, - "name": "querytext10" + "name": "querytext0" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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", @@ -209,20 +209,20 @@ ] } }, - "name": "query10" + "name": "query0" }, { "type": 1, "content": { - "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." }, - "name": "querytext11" + "name": "querytext1" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -271,42 +271,20 @@ ] } }, - "name": "query11" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hybrid" - }, - "name": "tab1title" + "name": "query1" }, { "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": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." }, - "name": "querytext4" + "name": "querytext2" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -355,20 +333,20 @@ ] } }, - "name": "query4" + "name": "query2" }, { "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 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": "querytext3" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -417,20 +395,42 @@ ] } }, - "name": "query5" + "name": "query3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab0" + }, + "name": "tab0" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Segmentation" + }, + "name": "tab1title" }, { "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 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": "querytext6" + "name": "querytext19" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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", @@ -479,20 +479,20 @@ ] } }, - "name": "query6" + "name": "query19" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "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": "querytext7" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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", @@ -541,20 +541,20 @@ ] } }, - "name": "query7" + "name": "query20" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "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": "querytext8" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -603,20 +603,20 @@ ] } }, - "name": "query8" + "name": "query21" }, { "type": 1, "content": { - "json": "If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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": "querytext9" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | 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", @@ -665,7 +665,7 @@ ] } }, - "name": "query9" + "name": "query22" } ] }, @@ -685,22 +685,22 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## PaaS" }, "name": "tab2title" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "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": "querytext19" + "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/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", @@ -749,82 +749,42 @@ ] } }, - "name": "query19" - }, + "name": "query18" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab2" + }, + "name": "tab2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ { "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": "querytext20" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "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" - } - ] - } - } - ] - } + "json": "## IP plan" }, - "name": "query20" + "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": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext21" + "name": "querytext10" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -873,20 +833,20 @@ ] } }, - "name": "query21" + "name": "query10" }, { "type": 1, "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext22" + "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,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -935,16 +895,16 @@ ] } }, - "name": "query22" + "name": "query11" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab2" + "value": "tab3" }, - "name": "tab2" + "name": "tab3" }, { "type": 12, @@ -955,22 +915,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Virtual WAN" }, - "name": "tab3title" + "name": "tab4title" }, { "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": "querytext18" + "name": "querytext23" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = 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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1019,16 +979,16 @@ ] } }, - "name": "query18" + "name": "query23" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab3" + "value": "tab4" }, - "name": "tab3" + "name": "tab4" }, { "type": 12, @@ -1041,7 +1001,7 @@ "content": { "json": "## Internet" }, - "name": "tab4title" + "name": "tab5title" }, { "type": 1, @@ -1420,9 +1380,9 @@ "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab5" }, - "name": "tab4" + "name": "tab5" }, { "type": 12, @@ -1433,22 +1393,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Hybrid" }, - "name": "tab5title" + "name": "tab6title" }, { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext23" + "name": "querytext4" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1497,42 +1457,82 @@ ] } }, - "name": "query23" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab5" - }, - "name": "tab5" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query4" + }, { "type": 1, "content": { - "json": "## Hub and spoke" + "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": "tab6title" + "name": "querytext5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 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": "query5" }, { "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": "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": "querytext0" + "name": "querytext6" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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/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", @@ -1581,20 +1581,20 @@ ] } }, - "name": "query0" + "name": "query6" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "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": "querytext1" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier 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", @@ -1643,20 +1643,20 @@ ] } }, - "name": "query1" + "name": "query7" }, { "type": 1, "content": { - "json": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use 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": "querytext2" + "name": "querytext8" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -1705,20 +1705,20 @@ ] } }, - "name": "query2" + "name": "query8" }, { "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 you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) for further information." }, - "name": "querytext3" + "name": "querytext9" }, { "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,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1767,7 +1767,7 @@ ] } }, - "name": "query3" + "name": "query9" } ] }, diff --git a/workbooks/alz_checklist.en_network_workbook_template.json b/workbooks/alz_checklist.en_network_workbook_template.json index 64d2b8237..e06202b31 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\": \"39bf5f38-ecfa-4cd4-8999-0a6b8a58f604\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab0\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"37f0847e-02e3-43d8-9d51-fa5c1f601fdf\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b307eae6-59a6-47e5-b3c6-c279564858b9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b60d81bc-a5e9-4944-8e77-71f0e0b69d6e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab3\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"ccce3323-1ee7-4f02-9af4-10749fb39e7d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5a5e2ab2-cfe4-482a-a744-64483e3a3ffe\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"95e15a0a-4e51-4f7a-b4b4-65e1a69d9ea5\",\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 },\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\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"query10\"\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\": \"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 | 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\": \"query11\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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 },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query19\"\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\": \"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 == '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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"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 = 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\": \"query18\"\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\": \"## Internet\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext12\"\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\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 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\": \"querytext23\"\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\": \"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\": \"## 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\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"87c89a28-e84a-45ab-9add-3cc8e8f6566d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a78cc609-eb83-44aa-8ac7-e93665eb00c9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"48a4285c-00d5-4226-b9f6-257e6dfc586c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab2\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"217e9414-fe7d-4430-ba73-395df6b1dd97\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"05a59fa4-a54d-4e9b-9859-b5e4b4c23cb1\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d7e398c5-f270-48ef-9713-8428ddf28bca\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5c578132-7cc5-4c3e-8d4b-cbc4da235ebc\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query19\"\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\": \"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 == '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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": \"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 = 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\": \"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\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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\": \"query10\"\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\": \"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 | 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\": \"query11\"\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\": \"querytext23\"\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\": \"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\": \"## Internet\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext12\"\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\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you are using a route table in the GatewaySubnet, make sure that gateway routes are propagated. Check [this link](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub) 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,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,subnetName=tostring(subnets.name),routeTableId=tostring(subnets.properties.routeTable.id) | where subnetName == 'GatewaySubnet' | join kind=leftouter (Resources | where type == 'microsoft.network/routetables' | project routeTableName=name,routeTableId=id, disableBgpRoutePropagation=properties.disableBgpRoutePropagation) on routeTableId | project id,compliant = (disableBgpRoutePropagation == False or isnull(disableBgpRoutePropagation)) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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 },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]"