Skip to content

Latest commit

 

History

History
3139 lines (3139 loc) · 177 KB

AADSCA.workbook

File metadata and controls

3139 lines (3139 loc) · 177 KB

{ "version": "Notebook/1.0", "items": [ { "type": 11, "content": { "version": "LinkItem/1.0", "style": "tabs", "links": [ { "id": "f27e3cdc-8061-47ad-85da-6aba612b2ccd", "cellValue": "Tab", "linkTarget": "parameter", "linkLabel": "Overview", "subTarget": "Overview", "style": "link" }, { "id": "5f02d1ea-8c88-4be0-a70b-54cf3062dd87", "cellValue": "Tab", "linkTarget": "parameter", "linkLabel": "Configuration Posture", "subTarget": "ConfigurationPosture", "style": "link" }, { "id": "b2c61ea8-f643-4339-a6e3-554954db8515", "cellValue": "Tab", "linkTarget": "parameter", "linkLabel": "Authentication Strength", "subTarget": "AuthenticationStrength", "style": "link" }, { "id": "c9b90a20-5380-41d6-94b0-84975d0ff00e", "cellValue": "Tab", "linkTarget": "parameter", "linkLabel": "Conditional Access Coverage", "subTarget": "ConditionalAccessCoverage", "style": "link" } ] }, "name": "links - 14" }, { "type": 1, "content": { "json": "## Entra ID Security Config Analyzer (EIDSCA)\n---\n\n### Introduction\n\nThis workbook provides insights into Entra ID tenant configurations. The workbook compares current tenant configurations against best practices, and displays the compliance status of each configuration. The best practices are based on community work (see Entra ID Attack and Defense GitHub repo for details). You can also apply your own recommended values by taking a copy of the metadata JSON file, and updating the queries in this workbook to utilize the customized version.\n\nIn addition to providing best practices, each configuration is mapped to MITRE ATT&CK framework, allowing you to to identify potentially vulnerable configurations in terms of tactics and techniques. \n\n### Pre-requisites\nThis workbook requires Entra ID tenant configurations to be imported into a Log Analytics workspace. There are multiple ways of doing this, see Entra ID - Attack and Defense Playbook for more information.\n\n### Notes\nStatus can have the following values:\n- Passed: The configuration is compliant with the recommended value.\n- Failed: The configuration is not compliant with the recommended value. The severity of the finding is High (this is shown in the tooltip).\n- Review: The configuration is not compliant with the recommended value. The severity of the finding is Medium (this is shown in the tooltip).\n- Verify: The configuration needs to be manually verified. The severity of the finding is Medium or High (this is shown in the tooltip).\n- Informational: There are no security implications with this configuration, and therefore is only considered informational in this context.\n" }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "Overview" }, "customWidth": "60", "name": "Introduction" }, { "type": 9, "content": { "version": "KqlParameterItem/1.0", "crossComponentResources": [ "value::selected" ], "parameters": [ { "id": "4666895c-a22c-4fad-be1c-a8d31c4383d9", "version": "KqlParameterItem/1.0", "name": "SelectLogAnalytics", "label": "Select Log Analytics Workspace", "type": 5, "isRequired": true, "query": "resources\r\n| where type == "microsoft.operationalinsights/workspaces"\r\n| project id", "crossComponentResources": [ "value::selected" ], "typeSettings": { "additionalResourceOptions": [] }, "timeContext": { "durationMs": 86400000 }, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", "value": "" }, { "id": "ce036b1b-59f0-4c96-9945-9ceab96e8cd2", "version": "KqlParameterItem/1.0", "name": "SelectControlAreas", "label": "Select Control Areas", "type": 2, "isRequired": true, "multiSelect": true, "quote": "'", "delimiter": ",", "typeSettings": { "additionalResourceOptions": [ "value::all" ], "showDefault": false }, "jsonData": "[\r\n { "value": "AuthorizationPolicy", "label": "Authorization Policy" },\r\n { "value": "AuthMethodMSAuthenticator", "label": "Authentication Methods: Microsoft Authenticator" },\r\n { "value": "AuthMethodFIDO2", "label": "Authentication Methods: FIDO2 security key" },\r\n { "value": "AuthMethodTAP", "label": "Authentication Methods: Temporary Access Pass" },\r\n { "value": "AuthMethod3rdParty", "label": "Authentication Methods: Third-party software OAUTH tokens" },\r\n { "value": "AuthMethodEmailOTP", "label": "Authentication Methods: Email OTP" },\r\n { "value": "AuthMethodVoiceCall", "label": "Authentication Methods: Voice call" },\r\n { "value": "AuthMethodSMS", "label": "Authentication Methods: SMS" },\r\n { "value": "AuthMethodCert", "label": "Authentication Methods: Certificate-based authentication" },\r\n { "value": "DefaultSettings", "label": "Default Settings" },\r\n { "value": "AdminConsentRequest", "label": "Admin Consent Request" }\r\n]", "timeContext": { "durationMs": 86400000 }, "defaultValue": "value::all", "value": [ "value::all" ] }, { "id": "7b852907-8e03-45c7-85df-9438ec4c9b64", "version": "KqlParameterItem/1.0", "name": "ShowAuthorizationPolicy", "label": "Show Authorization Policy", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthorizationPolicy", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 } }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodMSAuthenticator", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodMSAuthenticator", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "2a1be2e6-87ef-47b0-ac1a-0ae5ad670bc8" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodFIDO2", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodFIDO2", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "ee8528ce-1ebc-40cd-96cf-e02c18a57472" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodTAP", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodTAP", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "5564fb57-e110-4179-95ef-8216f43136bb" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethod3rdParty", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethod3rdParty", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "90de6f06-492f-45a8-9a4f-7875a585267c" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodEmailOTP", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodEmailOTP", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "0e09573d-54ef-4538-988b-d3b072431cc5" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodVoiceCall", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodVoiceCall", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "9f91c872-ac0e-444d-a1ab-8c64eca87a34" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodSMS", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodSMS", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "f9da2232-f3cd-4f90-ac46-9a4e1af97d54" }, { "version": "KqlParameterItem/1.0", "name": "ShowAuthMethodCert", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AuthMethodCert", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "4b7d860e-c815-47f0-96a2-20869c017a8e" }, { "id": "aef5f92d-71c5-4457-aee1-ca8886beee4a", "version": "KqlParameterItem/1.0", "name": "JsonMetadataUrl", "label": "Metadata JSON for AADSCA", "type": 1, "isRequired": true, "query": "{"version":"1.0.0","content":"[\r\n { \"value\": \"https://raw.githubusercontent.com/Cloud-Architekt/AzureAD-Attack-Defense/main/config/AadSecConfig.json\" }\r\n]","transformers":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, "queryType": 8 }, { "id": "4541f21f-5521-49ee-8ee9-a878ed4520ed", "version": "KqlParameterItem/1.0", "name": "CustomTableName", "label": "Custom table name for AADSCA", "type": 1, "isRequired": true, "query": "{"version":"1.0.0","content":"[\r\n { \"value\": \"AADSCA_CL\" }\r\n]","transformers":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, "queryType": 8 }, { "id": "d6592b79-69a8-43c8-b5b6-77780f9ed605", "version": "KqlParameterItem/1.0", "name": "ShowAdminConsentRequest", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "AdminConsentRequest", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 } }, { "version": "KqlParameterItem/1.0", "name": "ShowDefaultSettings", "type": 1, "isHiddenWhenLocked": true, "criteriaData": [ { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "contains", "rightValType": "static", "rightVal": "DefaultSettings", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "leftOperand": "SelectControlAreas", "operator": "==", "rightValType": "static", "rightVal": "All", "resultValType": "static", "resultVal": "True" } }, { "criteriaContext": { "operator": "Default", "resultValType": "static", "resultVal": "False" } } ], "timeContext": { "durationMs": 86400000 }, "id": "76e1980f-f577-435d-b2de-190472697176" }, { "id": "1b715564-0367-4fc1-b6d0-594b1200fb59", "version": "KqlParameterItem/1.0", "name": "TimeRange", "label": "Time Range", "type": 4, "isRequired": true, "typeSettings": { "selectableValues": [ { "durationMs": 300000 }, { "durationMs": 900000 }, { "durationMs": 1800000 }, { "durationMs": 3600000 }, { "durationMs": 14400000 }, { "durationMs": 86400000 }, { "durationMs": 604800000 }, { "durationMs": 1209600000 }, { "durationMs": 2592000000 }, { "durationMs": 7776000000 } ], "allowCustom": true }, "value": { "durationMs": 7776000000 } }, { "version": "KqlParameterItem/1.0", "name": "CAPCustomTableName", "type": 1, "isRequired": true, "query": "{"version":"1.0.0","content":"[\r\n { \"value\": \"AADSCA_CAP_CL\" }\r\n]","transformers":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, "queryType": 8, "label": "Custom table name for AADSCA CAP", "id": "a524a8a6-09ad-4b3c-8471-8e197ccc0920" } ], "style": "pills", "queryType": 1, "resourceType": "microsoft.operationalinsights/workspaces" }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isNotEqualTo", "value": "Overview" }, "customWidth": "50", "name": "Parameters" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n| where _odata_context_s == "https://graph.microsoft.com/beta/$metadata#policies/authorizationPolicy"\r\n| summarize arg_max(TimeGenerated, *)\r\n| extend ConfigSet = parse_json(value_s)\r\n| project-away value_s\r\n| mv-expand ConfigTmp = ConfigSet[0]\r\n| mv-expand SubConfig = ConfigTmp["defaultUserRolePermissions"]\r\n| extend ConfigName = case( \r\n SubConfig == "", tostring(bag_keys(ConfigTmp)[0]),\r\n tostring(bag_keys(SubConfig)[0])\r\n)\r\n| extend ConfigValue = case(\r\n SubConfig == "", strcat_array(ConfigTmp[tostring(ConfigName)],","),\r\n tostring((SubConfig[ConfigName]))\r\n)\r\n| where ConfigName !in ("id", "description", "displayName")\r\n| project ConfigName, ConfigValue //, ConfigSet, ConfigTmp, SubConfig\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphEndpoint == "authorizationPolicy"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigName\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ['Configuration'] = ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, Recommendation, RecommendationLink, RecommendationTooltip, ['Default value'] = DefaultValue, Severity, Status, StatusTooltip, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, Description, PortalDeepLink", "size": 2, "showAnalytics": true, "title": "Authorization Policy", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Configuration", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url", "customColumnWidthSetting": "150px" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url", "customColumnWidthSetting": "150px" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Default value", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "150px" } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] }, "tooltipFormat": { "tooltip": "["StatusTooltip"]" } }, { "columnMatch": "StatusTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 } ] } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthorizationPolicy", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConfigurationPosture" } ], "customWidth": "100", "name": "AuthorizationPolicyQuery", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "## Authentication methods\r\nThe tables below show the tenant authentication method configurations. " }, "name": "text - 1" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('MicrosoftAuthenticator')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "Microsoft Authenticator", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" }, "labelSettings": [ { "columnId": "Configuration", "label": "Portal" } ] } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodMSAuthenticator", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsMicrosoftAuthenticator", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.fido2AuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('Fido2')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.fido2AuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "FIDO2 security key", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodFIDO2", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsFIDO2", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.temporaryAccessPassAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('TemporaryAccessPass')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.temporaryAccessPassAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "Temporary Access Pass", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodTAP", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsTemporaryAccessPass", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.softwareOathAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('SoftwareOath')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.softwareOathAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Compliant",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "Third-party software OAUTH tokens", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethod3rdParty", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethods3rdPartyOauthTokens", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.emailAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('Email')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.emailAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Compliant",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "Email OTP", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodEmailOTP", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsEmailOTP", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.voiceAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('Voice')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.voiceAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Compliant",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "Voice call", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodVoiceCall", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsVoiceCall", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.smsAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('Sms')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.smsAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Compliant",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "SMS", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodSMS", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsSMS", "styleSettings": { "showBorder": true } } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "AuthenticationMethodsGroup" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n//| where _odata_context_s has "authenticationMethodConfigurations"\r\n| where _odata_type_s == "#microsoft.graph.x509CertificateAuthenticationMethodConfiguration"\r\n| extend ConfigType = odata_type_s\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}'\r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations('X509Certificate')"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "#microsoft.graph.x509CertificateAuthenticationMethodConfiguration"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend ConfigGroup = case(\r\n ConfigName startswith "numberMatching", "Require number matching for push notifications",\r\n ConfigName startswith "displayAppInformation", "Show application name in push and passwordless notifications",\r\n ConfigName startswith "displayLocationInformation", "Show geographic location in push and passwordless notifications",\r\n "General settings"\r\n)\r\n| extend Pack = pack_all()\r\n| extend ConfigValue = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "_s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_g")])), tostring(Pack[strcat(ConfigMapping, "_g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_b")])), tostring(Pack[strcat(ConfigMapping, "_b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_d")])), tostring(Pack[strcat(ConfigMapping, "_d")]),\r\n tostring(Pack[strcat(ConfigMapping, "_s")])\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink, Configuration = ConfigGroup", "size": 0, "showAnalytics": true, "title": "Certificate-based authentication", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "ConfigName", "formatter": 5 }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Configuration", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "75px" }, "tooltipFormat": { "tooltip": "Used for grouping the controls to reflect the Azure Portal experience" } } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Configuration" ], "expandTopLevel": true, "finalBy": "ConfigName" } } }, "conditionalVisibilities": [ { "parameterName": "ShowAuthMethodCert", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" } ], "name": "AuthMethodsCertificate", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "let Setting0 = {CustomTableName}\r\n| where _odata_context_s == "https://graph.microsoft.com/beta/$metadata#settings"\r\n| summarize arg_max(TimeGenerated, *)\r\n| extend Properties = todynamic(value_s)[0];\r\nlet Setting1 = {CustomTableName}\r\n| where _odata_context_s == "https://graph.microsoft.com/beta/$metadata#settings"\r\n| summarize arg_max(TimeGenerated, *)\r\n| extend Properties = todynamic(value_s)[1];\r\nlet Setting2 = {CustomTableName}\r\n| where odata_context_s == "https://graph.microsoft.com/beta/$metadata#settings"\r\n| summarize arg_max(TimeGenerated, *)\r\n| extend Properties = todynamic(value_s)[2];\r\nunion Setting0, Setting1, Setting2\r\n| extend SettingsNameGraph = Properties.displayName\r\n| mv-expand Config = Properties.values\r\n| extend ConfigName = tostring(Config.name)\r\n| extend ConfigValueGraph = tostring(Config.value)\r\n| where isnotempty(ConfigName)\r\n| project-away Config\r\n| join kind=fullouter (\r\n externaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic)\r\n [ \r\n\th@'{JsonMetadataUrl}'\r\n ]\r\n with(format='multijson')\r\n | where GraphUri == "https://graph.microsoft.com/beta/settings"\r\n // Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n | extend g_MitreTactic = MitreTactic\r\n | extend g_MitreTechnique = MitreTechnique\r\n | extend g_MitreMitigation = MitreMitigation\r\n | project-away MitreTactic, MitreTechnique, MitreMitigation\r\n | mv-expand Control = Controls\r\n | project-away Controls\r\n | evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n | extend ConfigName = tostring(Name)\r\n | extend SettingsNameJson = split(ControlName, " - ")[1]\r\n | extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n // Consolidate control level and control group level Mitre mappings\r\n | extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n | extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n | extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n ) on ConfigName\r\n| extend ConfigValue = case(\r\n isnotempty(ConfigValueGraph), ConfigValueGraph,\r\n DefaultValue\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue =~ RecommendedValue, "Compliant",\r\n ConfigValue !~ RecommendedValue, "NonCompliant",\r\n "Unknown"\r\n )\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n )\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n )\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n )\r\n| extend RecommendationTooltip = Recommendation\r\n| extend Category = case(\r\n isnotempty(SettingsNameGraph), SettingsNameGraph,\r\n SettingsNameJson\r\n)\r\n| extend Configuration = case(\r\n isnotempty(ConfigName), ConfigName,\r\n Name\r\n)\r\n| project\r\n Configuration,\r\n ['Display name'] = DisplayName,\r\n ['Current value'] = ConfigValue,\r\n ['Recommended value'] = RecommendedValue,\r\n ['Default value'] = DefaultValue,\r\n Status,\r\n StatusTooltip,\r\n Severity,\r\n Recommendation,\r\n RecommendationLink,\r\n RecommendationTooltip,\r\n Description,\r\n ['Mitre tactics'] = t_MitreTactic,\r\n ['Mitre techniques'] = t_MitreTechnique,\r\n ['Mitre mitigations'] = t_MitreMitigation,\r\n PortalDeepLink,\r\n Category", "size": 0, "showAnalytics": true, "title": "Default Settings", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Group", "formatter": 1 }, { "columnMatch": "Configuration", "formatter": 5, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url", "customColumnWidthSetting": "150px" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url", "customColumnWidthSetting": "150px" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Default value", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "150px" } }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] }, "tooltipFormat": { "tooltip": "["StatusTooltip"]" } }, { "columnMatch": "StatusTooltip", "formatter": 5 }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 }, { "columnMatch": "Category", "formatter": 1 } ], "hierarchySettings": { "treeType": 1, "groupBy": [ "Category" ], "expandTopLevel": true, "finalBy": "Configuration" } } }, "conditionalVisibilities": [ { "parameterName": "ShowDefaultSettings", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConfigurationPosture" } ], "name": "Default Settings", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CustomTableName}\r\n| where odata_context_s == "https://graph.microsoft.com/beta/$metadata#policies/adminConsentRequestPolicy/$entity"\r\n| extend ConfigType = "adminConsentRequestPolicy"\r\n| summarize arg_max(TimeGenerated, *)\r\n| join kind=leftouter (\r\nexternaldata(ControlName: string, Description: string, GraphEndpoint: string, GraphUri: string, MitreTactic: dynamic, MitreTechnique: dynamic, MitreMitigation: dynamic, Controls: dynamic )\r\n[ \r\n h@'{JsonMetadataUrl}' \r\n]\r\nwith(format='multijson')\r\n| where GraphUri == "https://graph.microsoft.com/beta/policies/adminConsentRequestPolicy"\r\n// Control group level Mitre mappings (will be consolidated with the control level mappings)\r\n| extend g_MitreTactic = MitreTactic\r\n| extend g_MitreTechnique = MitreTechnique\r\n| extend g_MitreMitigation = MitreMitigation\r\n| project-away MitreTactic, MitreTechnique, MitreMitigation\r\n| mv-expand Control = Controls\r\n| extend ConfigType = "adminConsentRequestPolicy"\r\n| project-away Controls\r\n| evaluate bag_unpack(Control, columnsConflict='replace_source')\r\n| extend ConfigMapping = replace_string(CurrentValue, ".", "")\r\n// Consolidate control level and control group level Mitre mappings\r\n| extend t_MitreTactic = array_sort_asc(array_concat(g_MitreTactic, MitreTactic))\r\n| extend t_MitreTechnique = array_sort_asc(array_concat(g_MitreTechnique, MitreTechnique))\r\n| extend t_MitreMitigation = array_sort_asc(array_concat(g_MitreMitigation, MitreMitigation))\r\n| project ConfigName = tostring(Name), ConfigMapping, ConfigType, DisplayName, Description, DefaultValue, RecommendedValue, Recommendation, Severity, t_MitreTactic, t_MitreTechnique, t_MitreMitigation, PortalDeepLink\r\n) on ConfigType\r\n| extend Pack = pack_all()\r\n| extend ConfigValueTmp = case(\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "_s")])), tostring(Pack[strcat(ConfigMapping, "s")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "g")])), tostring(Pack[strcat(ConfigMapping, "g")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "b")])), tostring(Pack[strcat(ConfigMapping, "b")]),\r\n isnotempty(tostring(Pack[strcat(ConfigMapping, "d")])), tostring(Pack[strcat(ConfigMapping, "d")]),\r\n tostring(Pack[strcat(ConfigMapping, "s")])\r\n)\r\n| extend ConfigValue = iff(\r\n ConfigName == "reviewers", iff(\r\n isnotempty(ConfigValueTmp), "Verify from portal",\r\n ConfigValueTmp\r\n ),\r\n ConfigValueTmp\r\n)\r\n| extend ControlCompliance = case(\r\n ConfigValue == "" and RecommendedValue == "", "Unknown",\r\n ConfigValue != "" and RecommendedValue == "", "Unknown",\r\n ConfigValue == RecommendedValue, "Compliant",\r\n ConfigValue == 30, "Compliant",\r\n ConfigValue == "30", "Compliant",\r\n tostring(ConfigValue) =~ tostring(RecommendedValue), "Compliant",\r\n tostring(ConfigValue) != tostring(RecommendedValue), "NonCompliant",\r\n "Unknownn"\r\n)\r\n| extend Status = case(\r\n ControlCompliance == "Compliant", "Passed",\r\n ControlCompliance == "NonCompliant" and Severity == "High", "Failed",\r\n ControlCompliance == "NonCompliant" and Severity == "Medium", "Review",\r\n ControlCompliance == "Unknown" and Severity == "High", "Verify",\r\n ControlCompliance == "Unknown" and Severity == "Medium", "Verify",\r\n Severity == "Informational", "Informational",\r\n "Verify"\r\n)\r\n| extend StatusTooltip = case(\r\n Status == "Passed", "The current configuration is compliant with the recommendation.",\r\n Status == "Failed", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Review", strcat("The current configuration is not compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Verify", strcat("Unable to determine, whether the current configuration is compliant with the recommendation. The severity of this finding is considered '", Severity, "'."),\r\n Status == "Informational", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n Status == "Unknown", "There is no security impliaction with this configuration, and therefore this finding is considered informational.",\r\n "Unknown"\r\n)\r\n| extend RecommendationLink = case(\r\n Recommendation startswith "http", Recommendation,\r\n ""\r\n)\r\n| extend RecommendationTooltip = Recommendation\r\n| project Configuration = ConfigName, ['Display name'] = DisplayName, ['Current value'] = ConfigValue, ['Recommended value'] = RecommendedValue, ['Default value'] = DefaultValue, Status, Severity, Recommendation, RecommendationLink, RecommendationTooltip, Description, ['Mitre tactics'] = t_MitreTactic, ['Mitre techniques'] = t_MitreTechnique, ['Mitre mitigations'] = t_MitreMitigation, PortalDeepLink", "size": 0, "showAnalytics": true, "title": "Admin Consent Request", "timeContext": { "durationMs": 86400000 }, "showExportToExcel": true, "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "formatters": [ { "columnMatch": "Configuration", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Display name", "formatter": 0, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Current value", "formatter": 1, "formatOptions": { "linkColumn": "PortalDeepLink", "linkTarget": "Url", "customColumnWidthSetting": "150px" }, "tooltipFormat": { "tooltip": "["Description"]" } }, { "columnMatch": "Recommended value", "formatter": 1, "formatOptions": { "linkColumn": "RecommendationLink", "linkTarget": "Url", "customColumnWidthSetting": "150px" }, "tooltipFormat": { "tooltip": "["RecommendationTooltip"]" } }, { "columnMatch": "Recommendation", "formatter": 5 }, { "columnMatch": "RecommendationLink", "formatter": 5 }, { "columnMatch": "RecommendationTooltip", "formatter": 5 }, { "columnMatch": "Default value", "formatter": 0, "formatOptions": { "customColumnWidthSetting": "150px" } }, { "columnMatch": "Severity", "formatter": 5 }, { "columnMatch": "Status", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "Passed", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Failed", "representation": "4", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Review", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Verify", "representation": "2", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Informational", "representation": "1", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "unknown", "text": "{0}{1}" } ] }, "tooltipFormat": { "tooltip": "["StatusTooltip"]" } }, { "columnMatch": "StatusTooltip", "formatter": 5 }, { "columnMatch": "Description", "formatter": 5 }, { "columnMatch": "PortalDeepLink", "formatter": 5 } ] } }, "conditionalVisibilities": [ { "parameterName": "ShowAdminConsentRequest", "comparison": "isEqualTo", "value": "True" }, { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConfigurationPosture" } ], "customWidth": "100", "name": "AdminConsentRequest", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "## Conditional Access policies\r\n\r\nThe following table lists the Conditional Access policies configured in the Entra ID tenant." }, "customWidth": "50", "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "text - 36" }, { "type": 9, "content": { "version": "KqlParameterItem/1.0", "parameters": [ { "id": "ff218b87-d982-4bb2-b95d-e196f0590765", "version": "KqlParameterItem/1.0", "name": "CAPDisplayMode", "label": "Display mode", "type": 10, "isRequired": true, "typeSettings": { "additionalResourceOptions": [], "showDefault": false }, "jsonData": "[\r\n { "value": "ExplicitOnly", "label": "Show configured values only" },\r\n { "value": "ExcplicitAndImplicit", "label": "Show implicit (resulting) configurations", "selected": true }\r\n]\r\n", "timeContext": { "durationMs": 86400000 } } ], "style": "pills", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces" }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "ParametersCAP" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "{CAPCustomTableName}\r\n| summarize arg_max(TimeGenerated, *) by id_g\r\n| extend DisplayName = tostring(displayName_s)\r\n| extend PolicyId = tostring(id_g)\r\n//| extend Conditions = Policies.conditions\r\n//| mv-expand Conditions\r\n| extend State = case(\r\n tostring(state_s) == "enabled", "On",\r\n tostring(state_s) == "disabled", "Off",\r\n tostring(state_s) == "enabledForReportingButNotEnforced", "Report-only",\r\n "Unknown"\r\n)\r\n//| extend GrantControls = Policies.grantControls\r\n| extend CreatedTimeDate = createdDateTime_t\r\n| extend ModifiedTimeDate = modifiedDateTime_t\r\n| extend UsersInclude = conditions_users_includeUsers_s\r\n| extend UsersExclude = conditions_users_excludeUsers_s\r\n| extend GroupsInclude = conditions_users_includeGroups_s\r\n| extend GroupsExclude = conditions_users_excludeGroups_s\r\n| extend CloudAppsInclude = conditions_applications_includeApplications_s\r\n| extend CloudAppsExclude = conditions_applications_excludeApplications_s\r\n| extend ClientPlatformsIncludeTmp = column_ifexists("conditions_platforms_includePlatforms_s", "")\r\n| extend ClientPlatformsInclude = case(\r\n '{CAPDisplayMode}' == "ExplicitOnly", ClientPlatformsIncludeTmp,\r\n case(\r\n isnotempty(ClientPlatformsIncludeTmp), ClientPlatformsIncludeTmp, \r\n todynamic("(all)")\r\n )\r\n)\r\n| extend ClientPlatformsIncludeTooltip = case(\r\n ClientPlatformsInclude == "(all)", "This is the implicit configuration. All platforms are included, because the setting has not been configured.",\r\n ""\r\n)\r\n| extend ClientPlatformsExcludeTmp = column_ifexists("conditions_platforms_excludePlatforms_s", "[]")\r\n| extend ClientPlatformsExclude = case(\r\n '{CAPDisplayMode}' == "ExplicitOnly", ClientPlatformsExcludeTmp,\r\n case(\r\n isnotempty(ClientPlatformsExcludeTmp), ClientPlatformsExcludeTmp,\r\n todynamic("[]")\r\n )\r\n)\r\n| extend ClientApps = conditions_clientAppTypes_s\r\n| extend LocationsInclude = case(\r\n '{CAPDisplayMode}' == "ExplicitOnly", conditions_locations_includeLocations_s,\r\n case(\r\n isnotempty(conditions_locations_includeLocations_s), conditions_locations_includeLocations_s,\r\n todynamic("(all)")\r\n )\r\n)\r\n| extend LocationsIncludeTooltip = case(\r\n LocationsInclude == "(all)", "This is the implicit configuration. All locations are included, because the setting has not been configured.",\r\n ""\r\n)\r\n| extend LocationsExclude = case(\r\n '{CAPDisplayMode}' == "ExplicitOnly", conditions_locations_excludeLocations_s,\r\n case(\r\n isnotempty(conditions_locations_excludeLocations_s), conditions_locations_excludeLocations_s,\r\n todynamic("[]")\r\n )\r\n)\r\n| extend UserRiskLevels = case(\r\n '{CAPDisplayMode}' == "ExplicitOnly", conditions_userRiskLevels_s,\r\n case(\r\n array_length(todynamic(conditions_userRiskLevels_s)) != 0, conditions_userRiskLevels_s,\r\n todynamic("(all)")\r\n )\r\n)\r\n| extend UserRiskLevelsTooltip = case(\r\n UserRiskLevels == "(all)", "This is the implicit configuration. All user risk levels are included, because the setting has not been configured.",\r\n ""\r\n)\r\n| extend SigninRiskLevels = case(\r\n '{CAPDisplayMode}' == "ExplicitOnly", conditions_signInRiskLevels_s,\r\n case(\r\n array_length(todynamic(conditions_signInRiskLevels_s)) != 0, conditions_signInRiskLevels_s,\r\n todynamic("(all)")\r\n )\r\n)\r\n| extend SigninRiskLevelsTooltip = case(\r\n UserRiskLevels == "(all)", "This is the implicit configuration. All sign-in risk levels are included, because the setting has not been configured.",\r\n ""\r\n)\r\n| extend GrantControls = grantControls_builtInControls_s\r\n| extend FullPolicyJson = pack_all()\r\n| sort by DisplayName asc\r\n| project ['Policy display name'] = DisplayName, State, ['Cloud apps included'] = CloudAppsInclude, ['Cloud apps excluded'] = CloudAppsExclude, ['Users included'] = UsersInclude, ['Users excluded'] = UsersExclude, ['Groups included'] = GroupsInclude, ['Groups excluded'] = GroupsExclude, ['Client platforms included'] = ClientPlatformsInclude, ['Client platforms excluded'] = ClientPlatformsExclude, ['Client apps'] = ClientApps, ['Locations included'] = LocationsInclude, ['Locations excluded'] = LocationsExclude, ['User risk levels'] = UserRiskLevels, ['Sign-in risk levels'] = SigninRiskLevels, ['Grant controls'] = GrantControls, CreatedTimeDate, ModifiedTimeDate, PolicyId, ['Full policy JSON'] = FullPolicyJson, ClientPlatformsIncludeTooltip, LocationsIncludeTooltip, UserRiskLevelsTooltip, SigninRiskLevelsTooltip\r\n", "size": 0, "timeContext": { "durationMs": 86400000 }, "exportFieldName": "PolicyId", "exportParameterName": "SelectedPolicyId", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "gridSettings": { "formatters": [ { "columnMatch": "State", "formatter": 18, "formatOptions": { "thresholdsOptions": "icons", "thresholdsGrid": [ { "operator": "==", "thresholdValue": "On", "representation": "success", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Off", "representation": "cancelled", "text": "{0}{1}" }, { "operator": "==", "thresholdValue": "Report-only", "representation": "info", "text": "{0}{1}" }, { "operator": "Default", "thresholdValue": null, "representation": "success", "text": "{0}{1}" } ] } }, { "columnMatch": "Client platforms included", "formatter": 0, "tooltipFormat": { "tooltip": "["ClientPlatformsIncludeTooltip"]" } }, { "columnMatch": "Locations included", "formatter": 0, "tooltipFormat": { "tooltip": "["LocationsIncludeTooltip"]" } }, { "columnMatch": "User risk levels", "formatter": 0, "tooltipFormat": { "tooltip": "["UserRiskLevelsTooltip"]" } }, { "columnMatch": "Sign-in risk levels", "formatter": 0, "tooltipFormat": { "tooltip": "["SigninRiskLevelsTooltip"]" } }, { "columnMatch": "PolicyId", "formatter": 5 }, { "columnMatch": "ClientPlatformsIncludeTooltip", "formatter": 5 }, { "columnMatch": "LocationsIncludeTooltip", "formatter": 5 }, { "columnMatch": "UserRiskLevelsTooltip", "formatter": 5 }, { "columnMatch": "SigninRiskLevelsTooltip", "formatter": 5 }, { "columnMatch": "ImplicitOrExplicit", "formatter": 5 } ] } }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "ConditionalAccessPolicies", "styleSettings": { "showBorder": true } }, { "type": 1, "content": { "json": "### Number of sign-ins and the effect of the selected policy\r\nThe following pie chart shows the effect of the selected policy for sign-ins during the selected period.\r\n\r\nNote! You need to select a policy on the list above first." }, "customWidth": "50", "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "text - 37", "styleSettings": { "maxWidth": "50%" } }, { "type": 1, "content": { "json": "### Unusual failure to the selected conditional access policy\r\nThe following table shows the unusual failure of users to selected policy during the selected time period. This requires to enable Microsoft Sentinel UEBA tables.\r\n\r\nNote! You need to select a policy on the list above first." }, "customWidth": "50", "name": "text - 4", "styleSettings": { "maxWidth": "50%" } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "SigninLogs\r\n| mv-expand ConditionalAccessPolicies\r\n| where ConditionalAccessPolicies.id == '{SelectedPolicyId}'\r\n| extend PolicyResult = case(\r\n tostring(ConditionalAccessPolicies.result) == "notApplied", "Not applied",\r\n tostring(ConditionalAccessPolicies.result) == "success", "Success",\r\n tostring(ConditionalAccessPolicies.result) == "failure", "Failure",\r\n tostring(ConditionalAccessPolicies.result) == "notEnabled", "Not enabled",\r\n tostring(ConditionalAccessPolicies.result) == "reportOnlyNotApplied", "Report only",\r\n tostring(ConditionalAccessPolicies.result)\r\n)\r\n| summarize count() by PolicyResult", "size": 2, "showAnalytics": true, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "visualization": "piechart", "chartSettings": { "seriesLabelSettings": [ { "seriesName": "Not applied", "color": "gray" }, { "seriesName": "Report only", "color": "blue" }, { "seriesName": "Success", "color": "green" }, { "seriesName": "Failure", "color": "redBright" }, { "seriesName": "Not enabled", "color": "gray" } ] } }, "customWidth": "50", "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "SigninDetails", "styleSettings": { "maxWidth": "50%" } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": " BehaviorAnalytics\r\n | where ActivityInsights.UnusualNumberOfAADConditionalAccessFailures == "True"\r\n | extend UserPrincipalName = tolower(UserPrincipalName)\r\n | join kind=inner (\r\n union SigninLogs, AADNonInteractiveUserSignInLogs\r\n | where ConditionalAccessStatus == "failure"\r\n | mv-expand ConditionalAccessPolicies_dynamic\r\n | extend ConditionalAccessResult = parse_json(ConditionalAccessPolicies_dynamic.result)\r\n | extend ConditionalAccessName = parse_json(ConditionalAccessPolicies_dynamic.displayName)\r\n | extend ConditionalAccessId = parse_json(ConditionalAccessPolicies_dynamic.id)\r\n | extend ConditionalAccessEnforcedControl = parse_json(tostring(ConditionalAccessPolicies_dynamic.enforcedGrantControls))\r\n | extend SourceIPAddress = IPAddress\r\n | extend UserPrincipalName = tolower(UserPrincipalName)\r\n | where ConditionalAccessResult == "failure"\r\n | project TimeGenerated, UserDisplayName, UserPrincipalName, SourceIPAddress, tostring(ConditionalAccessName), tostring(ConditionalAccessId), tostring(ConditionalAccessResult), tostring(ConditionalAccessEnforcedControl), ResultType, ResultDescription, CorrelationId, IPAddress, AADTenantId\r\n ) on UserPrincipalName, SourceIPAddress\r\n | distinct UserDisplayName, UserPrincipalName, ConditionalAccessName, ConditionalAccessId, ConditionalAccessEnforcedControl, ResultType, ResultDescription, CorrelationId, AADTenantId, IPAddress\r\n | where ConditionalAccessId == '{SelectedPolicyId}'\r\n | summarize count() by UserDisplayName, UserPrincipalName, ConditionalAccessName, ResultType, ResultDescription, IPAddress", "size": 0, "showAnalytics": true, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "customWidth": "50", "name": "query - 5", "styleSettings": { "maxWidth": "50%" } }, { "type": 1, "content": { "json": "### Changes to the selected conditional access policy\r\nThe following table shows the changes made to the selected policy during the selected time period.\r\n\r\nNote! You need to select a policy on the list above first." }, "customWidth": "100", "name": "text - 6", "styleSettings": { "maxWidth": "100%" } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "AuditLogs\r\n| where LoggedByService == "Conditional Access"\r\n| extend InitiatedBy = InitiatedBy.user.userPrincipalName\r\n| extend PolicyId = TargetResources[0].id\r\n| extend PolicyDisplayName = TargetResources[0].displayName\r\n| extend ModifiedProperties = TargetResources[0].modifiedProperties\r\n| where PolicyId == '{SelectedPolicyId}'\r\n| project ActivityDateTime, InitiatedBy, PolicyDisplayName, ModifiedProperties, ActivityDisplayName", "size": 0, "showAnalytics": true, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "customWidth": "100", "name": "query - 7", "styleSettings": { "maxWidth": "100%" } } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "ConditionalAccessGroup" }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "### Percentage of sign ins requiring different authentication strengths\r\n\r\nThe following list shows the count of interactive sign-ins using authentication methods of the {TimeRange}." }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "text - 19" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "SigninLogs\r\n| where ResultType == 0\r\n| where HomeTenantId == ResourceTenantId\r\n| where AppId !in ("29d9ed98-a469-4536-ade2-f981bc1d605e", "38aa3b87-a06d-4817-b275-7a316988d93b", "dd762716-544d-4aeb-a526-687b73838a22") //Exclude Windows Sign-in, Registration Client and Microsoft Authentication Broker\r\n| summarize\r\n ['Total Signin Count']=count(),\r\n ['Total Authentication Strength Count']=countif(AuthenticationRequirementPolicies has 'Authentication Strength(s)' and AuthenticationRequirement == "multiFactorAuthentication"),\r\n ['Total MFA Count']=countif(AuthenticationRequirementPolicies !has 'Authentication Strength(s)' and AuthenticationRequirement == "multiFactorAuthentication"),\r\n ['Total non MFA Count']=countif(AuthenticationRequirement == "singleFactorAuthentication")\r\n by UserId, UserPrincipalName\r\n| project\r\n UserId,\r\n UserPrincipalName,\r\n ['Total Signin Count'],\r\n ['Total Authentication Strength Count'],\r\n ['Authentication Strength Percentage']=(todouble(['Total Authentication Strength Count']) * 100 / todouble(['Total Signin Count'])),\r\n ['Total MFA Count'],\r\n ['MFA Percentage']=(todouble(['Total MFA Count']) * 100 / todouble(['Total Signin Count'])),\r\n ['Total non MFA Count'],\r\n ['Non MFA Percentage']=(todouble(['Total non MFA Count']) * 100 / todouble(['Total Signin Count']))\r\n| sort by ['Total Signin Count'] desc\r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 18" } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "group - 33", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "### Sign-ins using different authentication methods\r\n\r\nThe following pie chart and table describe the different authentication methods used for multi-factor authentication of {TimeRange}." }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "text - 20" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "//Visualize the MFA types used by your users, i.e text message, mobile app notification, verification code\r\n //Data connector required for this query - Azure Active Directory - Signin Logs\r\n// Sentinel-Queries/Azure Active Directory/Identity-VisualizeMFAMethods.kql at main · reprise99/Sentinel-Queries (github.com)\r\nSigninLogs\r\n| where AuthenticationRequirement == "multiFactorAuthentication"\r\n| project AuthenticationDetails\r\n| extend ['MFA Method'] = tostring(parse_json(AuthenticationDetails)[1].authenticationMethod)\r\n| summarize Count=count()by ['MFA Method']\r\n| where ['MFA Method'] != "Previously satisfied" and isnotempty(['MFA Method'])\r\n| sort by Count desc\r\n| render piechart with (title="Types of MFA Methods used")\r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "customWidth": "50", "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 29" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "//Data connector required for this query - Azure Active Directory - Signin Logs\r\n//Sentinel-Queries/Azure Active Directory/Identity-MFAMethodsPivotTable.kql at main · reprise99/Sentinel-Queries (github.com)\r\nlet isGUID = "[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}";\r\nSigninLogs\r\n| mv-expand todynamic(AuthenticationDetails)\r\n| extend ['Authentication Method'] = tostring(AuthenticationDetails.authenticationMethod)\r\n//Exclude previously satisifed, passwords and other data and any UserPrincipalName that comes through as a guid\r\n| where ['Authentication Method'] !in ("Previously satisfied", "Password", "Other")\r\n and isnotempty(['Authentication Method'])\r\n and not(UserPrincipalName matches regex isGUID)\r\n//Create pivot table of each method and the count by user\r\n| evaluate pivot(['Authentication Method'], count(), UserPrincipalName)\r\n| sort by UserPrincipalName asc\r\n", "size": 4, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "customWidth": "50", "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 21", "styleSettings": { "showBorder": true } }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "//Visualize the MFA types used by your users - phone sign in, mobile passcode, push or text message, over time\r\n//Data connector required for this query - Azure Active Directory - Signin Logs\r\n //Sentinel-Queries/Azure Active Directory/Identity-VisualizeMFAMethodsovertime.kql at main · reprise99/Sentinel-Queries (github.com)\r\nSigninLogs\r\n| where TimeGenerated > ago (180d)\r\n| where AuthenticationRequirement == "multiFactorAuthentication"\r\n| project TimeGenerated, AuthenticationDetails\r\n| extend ['MFA Method'] = tostring(parse_json(AuthenticationDetails)[1].authenticationMethod)\r\n| summarize Count=count()by ['MFA Method'], bin(TimeGenerated, 7d)\r\n| where ['MFA Method'] != "Previously satisfied" and isnotempty(['MFA Method']) \r\n| render timechart with (ytitle="Count", xtitle="Day", title="MFA methods per week over time")\r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "ConditionalAccessCoverage" }, "name": "query - 31" } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "group - 36", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "### Percentage of sign-ins using MFA per application\r\n\r\nThe following table shows the percentage of sign-ins that use MFA per application of {TimeRange}, excluding Windows Sign-in, Registration Client and Microsoft Authentication Broker." }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "text - 24" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "//Calculate the percentage of signins to each of your Azure AD applications that used MFA\r\n //Data connector required for this query - Azure Active Directory - Signin Logs\r\n //Sentinel-Queries/Azure Active Directory/Identity-MFAPercentageperapp.kql at main · reprise99/Sentinel-Queries (github.com)\r\nSigninLogs\r\n| where ResultType == 0\r\n| where AppId !in ("29d9ed98-a469-4536-ade2-f981bc1d605e", "38aa3b87-a06d-4817-b275-7a316988d93b", "dd762716-544d-4aeb-a526-687b73838a22")\r\n//Exclude Windows Sign-in, Registration Client and Microsoft Authentication Broker\r\n| summarize\r\n ['Total Signin Count']=count(),\r\n ['Total MFA Count']=countif(AuthenticationRequirement == "multiFactorAuthentication"),\r\n ['Total non MFA Count']=countif(AuthenticationRequirement == "singleFactorAuthentication")\r\n by AppDisplayName\r\n| project\r\n AppDisplayName,\r\n ['Total Signin Count'],\r\n ['Total MFA Count'],\r\n ['Total non MFA Count'],\r\n MFAPercentage=(todouble(['Total MFA Count']) * 100 / todouble(['Total Signin Count']))\r\n| sort by ['Total Signin Count'] desc, MFAPercentage asc \r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 25" } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "group - 30", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "### Percentage of sign-ins using MFA per client\r\n\r\nThe following table shows the percentage of sign-ins using MFA per client {TimeRange},\r\nexcluding Windows Sign-in, Registration Client and Microsoft Authentication Broker." }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "text - 26" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "//Summarize the percentage of signins covered by MFA for your top 20 most popular Azure AD apps\r\n \r\n//Data connector required for this query - Azure Active Directory - Signin Logs\r\n //Microsoft Sentinel query\r\n//First create a list of your top 20 apps by finding distinct user count by application over 30 days\r\n//Sentinel-Queries/Azure Active Directory/Identity-SummarizeMFATop20Apps.kql at main · reprise99/Sentinel-Queries (github.com)\r\nlet top20apps=\r\n SigninLogs\r\n | where TimeGenerated > ago (30d)\r\n | summarize UserCount=dcount(UserPrincipalName)by AppDisplayName\r\n | sort by UserCount desc \r\n | take 20\r\n | project AppDisplayName;\r\n//Use that list to calculate the percentage of signins to those apps that are covered by MFA\r\nSigninLogs\r\n| where AppDisplayName in (top20apps)\r\n| summarize TotalCount=count(),\r\n MFACount=countif(AuthenticationRequirement == "multiFactorAuthentication"),\r\n nonMFACount=countif(AuthenticationRequirement == "singleFactorAuthentication")\r\n by AppDisplayName\r\n| project\r\n AppDisplayName,\r\n TotalCount,\r\n MFACount,\r\n nonMFACount,\r\n MFAPercentage=(todouble(MFACount) * 100 / todouble(TotalCount))\r\n| sort by MFAPercentage asc \r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ], "gridSettings": { "sortBy": [ { "itemKey": "MFAPercentage", "sortOrder": 2 } ] }, "sortBy": [ { "itemKey": "MFAPercentage", "sortOrder": 2 } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 27" } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "group - 29", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "### Failed sign-in reasons\r\n\r\nThe following table lists the main reasons for sign-in failures {TimeRange}." }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "text - 33" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "// Failed Signin reasons \r\n// The query list the main reasons for sign in failures. \r\nSigninLogs\r\n| where ResultType != 0\r\n| project AppDisplayName, ResultDescription, ResultType\r\n| summarize Count=count() by AppDisplayName,ResultDescription, ResultType\r\n| sort by Count desc nulls last\r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 32" } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "group - 28", "styleSettings": { "showBorder": true } }, { "type": 12, "content": { "version": "NotebookGroup/1.0", "groupType": "editable", "items": [ { "type": 1, "content": { "json": "### Authentication method for primary sign-in on Windows devices\r\n\r\nThe table below lists the authentication method for primary sign-in on Windows devices {TimeRange}." }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "text - 34" }, { "type": 3, "content": { "version": "KqlItem/1.0", "query": "// Used Auth Method for primary sign-in on Windows Devices\r\n// Query over all Windows Sign-ins\r\nunion SigninLogs\r\n| where Resource == "Microsoft.aadiam" and AppDisplayName == "Windows Sign In"\r\n| extend authenticationMethod = tostring(parse_json(AuthenticationDetails)[0].authenticationMethod)\r\n| extend succeeded = tostring(parse_json(AuthenticationDetails)[0].succeeded)\r\n| where succeeded == "true"\r\n| extend authenticationStepDateTime = todatetime(tostring(parse_json(AuthenticationDetails)[0].authenticationStepDateTime))\r\n| extend displayName = tostring(DeviceDetail.displayName)\r\n| extend trustType = tostring(DeviceDetail.trustType)\r\n| extend deviceId = tostring(DeviceDetail.deviceId)\r\n| summarize Count=dcount(Identity) by authenticationMethod, UserId\r\n| render piechart\r\n", "size": 0, "timeContextFromParameter": "TimeRange", "queryType": 0, "resourceType": "microsoft.operationalinsights/workspaces", "crossComponentResources": [ "{SelectLogAnalytics}" ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "query - 35" } ] }, "conditionalVisibility": { "parameterName": "Tab", "comparison": "isEqualTo", "value": "AuthenticationStrength" }, "name": "group - 27", "styleSettings": { "showBorder": true } } ], "fallbackResourceIds": [], "fromTemplateId": "sentinel-UserWorkbook", "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json" }