From 2ebec5942b1139fb115be00fbd11891e873d421d Mon Sep 17 00:00:00 2001 From: Michael Epping Date: Wed, 13 Nov 2024 08:29:05 -0800 Subject: [PATCH 1/2] Phishing-Resistant Passwordless Workbook (#2832) * Phishing-Resistant Passwordless Workbook Added a new workbook, in preview mode, to facilitate customer deployments of phishing-resistant passwordless * Fixed path to workbook folder * Update Phishing-Resistant Passwordless.workbook Fixed column labels and added an option to suppress the explanation text * Update Phishing-Resistant Passwordless.workbook * Update microsoft.aadiam-tenant.json * Fixed some parameter and table names and formats * Added a preview tag to the workbook * Moved the passwordless workbook out of its own section and into Usage * Fixed minor issues with labels and UX filters * Clarified enforcement instructions --- .../Phishing-Resistant Passwordless.workbook | 3217 +++++++++++++++++ gallery/workbook/microsoft.aadiam-tenant.json | 5 + 2 files changed, 3222 insertions(+) create mode 100644 Workbooks/Azure Active Directory/Passwordless/Phishing-Resistant Passwordless Deployment/Phishing-Resistant Passwordless.workbook diff --git a/Workbooks/Azure Active Directory/Passwordless/Phishing-Resistant Passwordless Deployment/Phishing-Resistant Passwordless.workbook b/Workbooks/Azure Active Directory/Passwordless/Phishing-Resistant Passwordless Deployment/Phishing-Resistant Passwordless.workbook new file mode 100644 index 0000000000..c3423951b7 --- /dev/null +++ b/Workbooks/Azure Active Directory/Passwordless/Phishing-Resistant Passwordless Deployment/Phishing-Resistant Passwordless.workbook @@ -0,0 +1,3217 @@ +{ + "version": "Notebook/1.0", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "# Phishing-Resistant Passwordless Workbook (Preview)" + }, + "name": "text - 0" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "13bcc373-4bc2-4004-b0e0-753afe1aa7d3", + "version": "KqlParameterItem/1.0", + "name": "Explanation", + "label": "Explanation Text", + "type": 2, + "description": "Choose whether or not to hide some explanation text found within this workbook", + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [] + }, + "jsonData": "[{ \"value\": \"Show\", \"label\": \"Show Explanation Text\" }, { \"value\": \"Hide\", \"label\": \"Hide Explanation Text\" }]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "Show" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "Text Hide/Show Parameter" + }, + { + "type": 1, + "content": { + "json": "This workbook is designed to assist you in two phases of your phishing-resistant passwordless deployment. The data used in the report comes from the sign-in logs exported from your Microsoft Entra ID tenant to Azure Monitor. Refer to [aka.ms/PasswordlessGuide](https://aka.ms/PasswordlessGuide) for in depth deployment guidance.\n\nBelow you will find two main tabs:\n- The Enrollment Readiness Phase tab will help you identify users and devices that are ready to register for phishing-resistant passwordless credentials\n- The Enforcement Readiness Phase tab will help you identify user/device pairs that are ready to have phishing-resistant passwordless requirements enforced using conditional access\n\nRefer to each tab for further details on how to interpret and use the data presented.", + "style": "info" + }, + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "text - 1" + } + ], + "exportParameters": true + }, + "name": "Group - Help" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "d4eaea92-091c-4dce-8c70-212d64584d26", + "version": "KqlParameterItem/1.0", + "name": "Workbook", + "label": "Workspace", + "type": 5, + "isRequired": true, + "isGlobal": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "typeSettings": { + "resourceTypeFilter": { + "microsoft.operationalinsights/workspaces": true + }, + "additionalResourceOptions": [ + "value::all" + ] + }, + "timeContext": { + "durationMs": 86400000 + }, + "defaultValue": "value::all", + "value": [ + "value::all" + ] + }, + { + "id": "a557cf80-5122-422c-9241-51cf3c3e7d7a", + "version": "KqlParameterItem/1.0", + "name": "Subscription", + "type": 6, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "includeAll": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": [ + "value::all" + ] + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "crossComponentResources": [ + "{Workbook}" + ], + "parameters": [ + { + "id": "b8b331d7-d189-4d90-8936-ebb1a67f9368", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "label": "Time Range", + "type": 4, + "isRequired": true, + "isGlobal": true, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 300000 + }, + { + "durationMs": 900000 + }, + { + "durationMs": 1800000 + }, + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2419200000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": { + "durationMs": 2592000000 + } + }, + { + "id": "b9ed272b-069a-47ac-8968-09167e223e13", + "version": "KqlParameterItem/1.0", + "name": "Apps", + "type": 2, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "SigninLogs\n| summarize Count = count() by AppDisplayName\n| order by Count desc, AppDisplayName asc\n| project Value = AppDisplayName, Label = strcat(AppDisplayName), Selected = false\n", + "crossComponentResources": [ + "{Workbook}" + ], + "isHiddenWhenLocked": true, + "typeSettings": { + "limitSelectTo": 20, + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + { + "id": "9697a10d-0107-4504-a96c-cb1aefe93c7f", + "version": "KqlParameterItem/1.0", + "name": "Users", + "type": 2, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "SigninLogs\n|where AppDisplayName in ({Apps}) or '*' in ({Apps})\n| summarize Count = count() by UserDisplayName\n| order by Count desc, UserDisplayName asc\n| project Value = UserDisplayName, Label = strcat(UserDisplayName), Selected = false\n", + "crossComponentResources": [ + "{Workbook}" + ], + "isHiddenWhenLocked": true, + "typeSettings": { + "limitSelectTo": 20, + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + { + "id": "9bba8082-8af0-4dd7-9256-d3b6b4024843", + "version": "KqlParameterItem/1.0", + "name": "deviceReadiness", + "label": "Device Readiness", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "isHiddenWhenLocked": true, + "typeSettings": { + "limitSelectTo": 1, + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "jsonData": "[{ \"value\": \"Ready\", \"label\": \"Ready\" }, { \"value\": \"NotReady\", \"label\": \"NotReady\" }, { \"value\": \"Unknown\", \"label\": \"Unknown\" }]", + "timeContext": { + "durationMs": 86400000 + }, + "defaultValue": "value::all", + "value": [ + "value::all" + ] + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 0" + } + ], + "exportParameters": true + }, + "name": "Group - Parameters" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "tabStyle": "bigger", + "links": [ + { + "id": "f920cec9-e8ff-400b-b86c-d300af1ae6e0", + "cellValue": "Phase", + "linkTarget": "parameter", + "linkLabel": "Enrollment Readiness Phase", + "subTarget": "enrollment", + "style": "link" + }, + { + "id": "202d2b0b-c081-4b85-a43c-02e6ab86df19", + "cellValue": "Phase", + "linkTarget": "parameter", + "linkLabel": "Enforcement Readiness Phase", + "subTarget": "enforcement", + "style": "link" + } + ] + }, + "name": "links - 5" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "# Enrollment Readiness Phase Instructions\n\nBelow you will find tabs for Windows, macOS, iOS, and Android. Within each tab you will find a subsection for the commonly recommended credentials on those operating systems. Each tab will help you evaluate your readiness for that particular credential on the chosen operating system based on data from your sign-in logs.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "text - 1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [] + }, + "name": "Group - Charts" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "b8dcc882-0003-48bb-8f49-ba803942b8ad", + "cellValue": "OSSelection", + "linkTarget": "parameter", + "linkLabel": "Windows", + "subTarget": "Windows", + "preText": "Windows", + "style": "link" + }, + { + "id": "32d0ca1a-56aa-410b-a09a-2fb82270cc32", + "cellValue": "OSSelection", + "linkTarget": "parameter", + "linkLabel": "macOS", + "subTarget": "macOS", + "preText": "macOS", + "style": "link" + }, + { + "id": "06bd095e-89db-4bb5-999e-66d620661e43", + "cellValue": "OSSelection", + "linkTarget": "parameter", + "linkLabel": "iOS", + "subTarget": "iOS", + "preText": "iOS", + "style": "link" + }, + { + "id": "11e43e72-21cc-40bd-82db-4b887cc5519e", + "cellValue": "OSSelection", + "linkTarget": "parameter", + "linkLabel": "Android", + "subTarget": "Android", + "preText": "Android", + "style": "link" + } + ] + }, + "name": "links - 4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "490a0ca6-ef9a-4247-853c-808877b92e5b", + "version": "KqlParameterItem/1.0", + "name": "windowsReadinessSelected", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "label": "Windows Readiness Selected" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 2" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "01aea2b0-a5d0-4b39-8836-cff87e6e35f2", + "cellValue": "WindowsCredential", + "linkTarget": "parameter", + "linkLabel": "Windows Hello for Business", + "subTarget": "whfb", + "style": "link" + }, + { + "id": "e8ce92e0-d0bf-4db8-86ce-a1eef5c1f795", + "cellValue": "WindowsCredential", + "linkTarget": "parameter", + "linkLabel": "FIDO2 Security Key", + "subTarget": "fido", + "style": "link" + }, + { + "id": "6f19945c-c7ed-4b46-a7bb-ac5b71ab5a2b", + "cellValue": "WindowsCredential", + "linkTarget": "parameter", + "linkLabel": "Authenticator App Passkey", + "subTarget": "authapppasskey", + "style": "link" + }, + { + "id": "6e00b9c6-08b1-4c10-9302-1688e1560737", + "cellValue": "WindowsCredential", + "linkTarget": "parameter", + "linkLabel": "Certificate-Based Authentication / Smart Card", + "subTarget": "cba", + "style": "link" + } + ] + }, + "name": "OS Tabs" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 10, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "windowsReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "group": "readinessCheck", + "createOtherGroup": null, + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Windows", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Windows", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "Windows Hello for Business Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Windows Hello for Business Query Explanation\n\nWindows Hello for Business readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Windows 10 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "WHFB Description" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 10, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{windowsReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "Windows Hello for Business Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "WindowsCredential", + "comparison": "isEqualTo", + "value": "whfb" + }, + "name": "Windows Hello for Business" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 10, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "windowsReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "group": "readinessCheck", + "createOtherGroup": null, + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Windows", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Windows", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "FIDO2 on Windows Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Windows FIDO2 Query Explanation\n\nFIDO2 Security Key on Windows readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Windows 10 or higher\n\nWindows 10 or higher supports logging into Windows with FIDO2 security keys on Hybrid or Entra Joined devices.\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "FIDO2 on Windows Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 10, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{windowsReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "FIDO2 on Windows Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "WindowsCredential", + "comparison": "isEqualTo", + "value": "fido" + }, + "name": "FIDO2 Security Key" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 11, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "windowsReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "group": "readinessCheck", + "createOtherGroup": null, + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Windows", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Windows", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "Auth App Passkey on Windows Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Windows Auth App Passkey Query Explanation\n\nAuth App Passkey on Windows readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Windows 11 or higher\n\nWindows 11 is recommended because it supports web sign-in on **Entra Joined devices**, which allows for logging into Windows with passkeys in Microsoft Authenticator.\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "Auth App Passkey on Windows Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 11, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{windowsReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "Auth App Passkey on Windows Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "WindowsCredential", + "comparison": "isEqualTo", + "value": "authapppasskey" + }, + "name": "Authenticator App Passkey" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 10, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "windowsReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "group": "readinessCheck", + "createOtherGroup": null, + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Windows", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Windows", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "CBA on Windows Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Certificate-Based Authentication / Smart Card Query Explanation\n\nCertificate-Based Authentication / Smart Card auth on Windows readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Windows 10 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "CBA on Windows Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Windows\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 10, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{windowsReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "CBA on Windows Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "WindowsCredential", + "comparison": "isEqualTo", + "value": "cba" + }, + "name": "CBA" + } + ] + }, + "conditionalVisibility": { + "parameterName": "OSSelection", + "comparison": "isEqualTo", + "value": "Windows" + }, + "name": "Windows Readiness" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "12abf1ed-d951-4b9d-9cf6-59e719766f1f", + "version": "KqlParameterItem/1.0", + "name": "macosReadinessSelected", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + } + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 2" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "9fd455ac-3cc6-4e2a-a2c5-a5ae9aae4ba3", + "cellValue": "macOSCredential", + "linkTarget": "parameter", + "linkLabel": "Platform SSO Secure Enclave Key", + "subTarget": "sekey", + "style": "link" + }, + { + "id": "3e606137-b9d2-4b70-a2ba-36a015eb274d", + "cellValue": "macOSCredential", + "linkTarget": "parameter", + "linkLabel": "FIDO2 Security Key", + "subTarget": "fido", + "style": "link" + }, + { + "id": "486329eb-fa97-4a78-935c-b8119cd0a0ff", + "cellValue": "macOSCredential", + "linkTarget": "parameter", + "linkLabel": "Authenticator App Passkey", + "subTarget": "authapppasskey", + "style": "link" + }, + { + "id": "5461370d-af48-4373-a732-1c2b70a3f5b1", + "cellValue": "macOSCredential", + "linkTarget": "parameter", + "linkLabel": "Certificate-Based Authentication / Smart Card", + "subTarget": "cba", + "style": "link" + } + ] + }, + "name": "links - 3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff((browserFamily == \"Safari\" and browserVersion >= 17.1), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "macosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on macOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on macOS", + "color": "redBright" + }, + { + "seriesName": "Unknown", + "color": "orange" + } + ] + } + }, + "customWidth": "50", + "name": "PSSO on macOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# macOS Secure Enclave Key Query Explanation\n\nSecure Enclave Key on macOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- macOS 13 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.\n\n_*Note: Macs do not accurately report their version via user agent string, so many Macs are in an unknown state. Entra ID can only affirmatively determine the Mac's version if it is also MDM enrolled. Additional investigation may be required in your MDM._", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "PSSO on macOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff((browserFamily == \"Safari\" and browserVersion >= 17.1), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{macosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "browserFamily", + "label": "Browser Family" + }, + { + "columnId": "browserVersion", + "label": "Browser Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "PSSO on macOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "macOSCredential", + "comparison": "isEqualTo", + "value": "sekey" + }, + "name": "Platform SSO Secure Enclave Key" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff(((browserFamily == \"Safari\" and browserVersion >= 13) or (browserFamily == \"Edge\") or (browserFamily == \"Chrome\")), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "macosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on macOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on macOS", + "color": "redBright" + }, + { + "seriesName": "Unknown", + "color": "orange" + } + ] + } + }, + "customWidth": "50", + "name": "FIDO2 Key on macOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# macOS FIDO2 Key Query Explanation\n\nFIDO2 Security Key on macOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Safari 13 or higher\n- Microsoft Edge\n- Google Chrome\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.\n\n_*Note: FIDO2 security keys can only be used post-login on macOS. They cannot be used to sign into the operating system itself._", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "FIDO2 Key on macOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff(((browserFamily == \"Safari\" and browserVersion >= 13) or (browserFamily == \"Edge\") or (browserFamily == \"Chrome\")), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{macosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "browserFamily", + "label": "Browser Family" + }, + { + "columnId": "browserVersion", + "label": "Browser Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "FIDO2 Key on macOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "macOSCredential", + "comparison": "isEqualTo", + "value": "fido" + }, + "name": "macOS FIDO 2 Key" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff(((browserFamily == \"Safari\" and browserVersion >= 17.1) or (browserFamily == \"Edge\") or (browserFamily == \"Chrome\")), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "macosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on macOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on macOS", + "color": "redBright" + }, + { + "seriesName": "Unknown", + "color": "orange" + } + ] + } + }, + "customWidth": "50", + "name": "Auth App Passkey on macOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# macOS Auth App Passkey Query Explanation\n\nAuth App Passkey on macOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Safari 13 or higher\n- Microsoft Edge\n- Google Chrome\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.\n\n_*Note: Auth App Passkeys can only be used post-login on macOS. They cannot be used to sign into the operating system itself._", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "Auth App Passkey on macOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff(((browserFamily == \"Safari\" and browserVersion >= 17.1) or (browserFamily == \"Edge\") or (browserFamily == \"Chrome\")), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{macosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "browserFamily", + "label": "Browser Family" + }, + { + "columnId": "browserVersion", + "label": "Browser Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "Auth App Passkey on macOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "macOSCredential", + "comparison": "isEqualTo", + "value": "authapppasskey" + }, + "name": "macOS Auth App Passkey" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff((browserFamily == \"Safari\" and browserVersion >= 17.1), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "macosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on macOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on macOS", + "color": "redBright" + }, + { + "seriesName": "Unknown", + "color": "orange" + } + ] + } + }, + "customWidth": "50", + "name": "CBA on macOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# macOS Certificate-Based Authentication / Smart Card Query Explanation\n\nCertificate-Based Authentication / Smart Card on macOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- macOS 14 or higher\n\nMicrosoft recommends implementing Certificate Based Authentication on macOS with Platform SSO rather than on-premises Active Directory. Platform SSO CBA requires macOS 14 or later.\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.\n\n_*Note: Macs do not accurately report their version via user agent string, so many Macs are in an unknown state. Entra ID can only affirmatively determine the Mac's version if it is also MDM enrolled. Additional investigation may be required in your MDM._", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "CBA on macOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend y = parse_user_agent(UserAgent, \"browser\")\n| extend browserFamily = tostring(y.Browser.Family)\n| extend browserVersion = todecimal(strcat(tostring(y.Browser.MajorVersion), \".\", tostring(y.Browser.MinorVersion)))\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| where OSFamily == \"Mac OS X\"\n| extend readinessCheck = iff((browserFamily == \"Safari\" and browserVersion >= 17.1), \"Ready\", \"Unknown\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{macosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, browserFamily, browserVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "browserFamily", + "label": "Browser Family" + }, + { + "columnId": "browserVersion", + "label": "Browser Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "Indicates the device is running Windows 10 or later" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "CBA on macOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "macOSCredential", + "comparison": "isEqualTo", + "value": "cba" + }, + "name": "Certificate-Based Authentication / Smart Card" + } + ] + }, + "conditionalVisibility": { + "parameterName": "OSSelection", + "comparison": "isEqualTo", + "value": "macOS" + }, + "name": "Group - macOS" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "5522daf9-a727-4a1d-9ffd-2146e72f159d", + "version": "KqlParameterItem/1.0", + "name": "iosReadinessSelected", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + } + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 2" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "5afc3cb4-863a-4031-a556-fc4ee5483bc0", + "cellValue": "iOSCredential", + "linkTarget": "parameter", + "linkLabel": "Authenticator App Passkey", + "subTarget": "authapppasskey", + "style": "link" + }, + { + "id": "e25f6b76-f200-45b8-a8ca-e003aa5c928f", + "cellValue": "iOSCredential", + "linkTarget": "parameter", + "linkLabel": "FIDO2 Security Key", + "subTarget": "fido", + "style": "link" + }, + { + "id": "60330329-d0ae-4154-b256-45fe84625042", + "cellValue": "iOSCredential", + "linkTarget": "parameter", + "linkLabel": "Certificate-Based Authentication / Smart Card", + "subTarget": "cba", + "style": "link" + } + ] + }, + "name": "links - 3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"iOS\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 17, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "iosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on iOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on iOS", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "Auth App Passkey on iOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# iOS Auth App Passkey Query Explanation\n\nAuth App Passkey on iOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- iOS 17 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "Auth App Passkey on iOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"iOS\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 17, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{iosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "OSMinorVersion", + "label": "OS Minor Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "Auth App Passkey on iOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "iOSCredential", + "comparison": "isEqualTo", + "value": "authapppasskey" + }, + "name": "Auth App Passkey" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"iOS\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 16, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "iosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on iOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on iOS", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "FIDO Key on iOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# iOS FIDO2 Key Query Explanation\n\nFIDO2 Security Key on iOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- iOS 16 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "FIDO Key on iOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"iOS\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 16, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{iosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "OSMinorVersion", + "label": "OS Minor Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "FIDO Key on iOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "iOSCredential", + "comparison": "isEqualTo", + "value": "fido" + }, + "name": "FIDO2 Security Key" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"iOS\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 9, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportParameterName": "iosReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on iOS", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on iOS", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "CBA on iOS Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# iOS Certificate-Based Authentication / Smart Card Query Explanation\n\nCertificate-Based Authentication / Smart Card on iOS readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- iOS 9 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "CBA on iOS Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"iOS\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 9, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{iosReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "OSMinorVersion", + "label": "OS Minor Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "CBA on iOS Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "iOSCredential", + "comparison": "isEqualTo", + "value": "cba" + }, + "name": "Certificate-Based Authentication / Smart Card" + } + ] + }, + "conditionalVisibility": { + "parameterName": "OSSelection", + "comparison": "isEqualTo", + "value": "iOS" + }, + "name": "Group - iOS" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "f9ad3be4-263b-49a5-8e91-2e1cefc4072f", + "version": "KqlParameterItem/1.0", + "name": "androidReadinessSelected", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + } + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 2" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "65ac1bd6-0c25-4797-af5d-2f37b9f87531", + "cellValue": "AndroidCredential", + "linkTarget": "parameter", + "linkLabel": "Authenticator App Passkey", + "subTarget": "authapppasskey", + "style": "link" + }, + { + "id": "8374f190-04bc-4914-b872-0e96ea1ed0bf", + "cellValue": "AndroidCredential", + "linkTarget": "parameter", + "linkLabel": "FIDO2 Security Key", + "subTarget": "fido", + "style": "link" + }, + { + "id": "8ef30859-d3cf-4a36-b143-a0818c5181ec", + "cellValue": "AndroidCredential", + "linkTarget": "parameter", + "linkLabel": "Certificate-Based Authentication / Smart Card", + "subTarget": "cba", + "style": "link" + } + ] + }, + "name": "links - 3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Android\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 14, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "androidReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Android", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Android", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "Auth App Passkey on Android Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Android Auth App Passkey Query Explanation\n\nAuth App Passkey on Android readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Android 14 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "Auth App Passkey on Android Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Android\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 14, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{androidReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "OSMinorVersion", + "label": "OS Minor Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "Auth App Passkey on Android Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "AndroidCredential", + "comparison": "isEqualTo", + "value": "authapppasskey" + }, + "name": "Android Auth App Passkey" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Android\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 13, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "androidReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Android", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Android", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "FIDO Key on Android Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Android FIDO2 Key Query Explanation\n\nFIDO2 Security Key on Android readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Android 13 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "FIDO Key on Android Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Android\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 13, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{androidReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "OSMinorVersion", + "label": "OS Minor Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "FIDO Key on Android Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "AndroidCredential", + "comparison": "isEqualTo", + "value": "fido" + }, + "name": "Android Auth App FIDO2 Key" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Android\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 9, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_\n| summarize count(UserDisplayName) by readinessCheck", + "size": 3, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "androidReadinessSelected", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "showMetrics": false, + "showLegend": true, + "seriesLabelSettings": [ + { + "seriesName": "Ready", + "label": "User/Device Pairs Ready for Enrollment on Android", + "color": "blue" + }, + { + "seriesName": "NotReady", + "label": "User/Device Pairs Not Ready for Enrollment on Android", + "color": "redBright" + } + ] + } + }, + "customWidth": "50", + "name": "CBA on Android Readiness Visualization" + }, + { + "type": 1, + "content": { + "json": "# Android Certificate-Based Authentication / Smart Card Query Explanation\n\nCertificate-Based Authentication / Smart Card on Android readiness is assessed by looking for the following criteria, based on your sign-in log data:\n\n- Android 9 or higher\n\nClick on the diagram to the left to filter the list of users. You can export a list of Ready users below and use that list of users to begin your deployment. Evaluate the list of users who are NotReady and determine which steps are required to prepare those users for deployment.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "CBA on Android Readiness Explanation" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n//| where UserType == \"Member\"\n//| where ResultType == \"0\"\n| where ResultType == \"0\"\n| where CrossTenantAccessType == \"none\"\n| project UserDisplayName, UserPrincipalName, DeviceDetail, UserAgent, CorrelationId\n| extend deviceId_ = tostring(DeviceDetail.deviceId)\n| extend deviceName_ = tostring(DeviceDetail.displayName)\n| extend operatingSystem_ = tostring(DeviceDetail.operatingSystem)\n| extend x = parse_user_agent(UserAgent, \"os\")\n| extend OSFamily = tostring(x.OperatingSystem.Family)\n| extend OSMajorVersion = tostring(x.OperatingSystem.MajorVersion)\n| extend OSMinorVersion = tostring(x.OperatingSystem.MinorVersion)\n| where OSFamily == \"Android\"\n| extend OSVersionForDisplay = strcat(tostring(OSMajorVersion))\n| extend readinessCheck = iff(x.OperatingSystem.MajorVersion >= 9, \"Ready\", \"NotReady\")\n| where readinessCheck in ({deviceReadiness}) or '*' in ({deviceReadiness})\n| mv-expand ParsedReadiness = parse_json(tostring('{androidReadinessSelected}'))\n | extend SelectedReadiness = ParsedReadiness.series\n | where SelectedReadiness == 'All' or (readinessCheck == SelectedReadiness)\n| project UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, readinessCheck, deviceId_, deviceName_\n| summarize count(deviceId_) by UserDisplayName, UserPrincipalName, OSFamily, OSMajorVersion, OSMinorVersion, deviceName_, readinessCheck, deviceId_", + "size": 0, + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "labelSettings": [ + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "OSFamily", + "label": "Operating System" + }, + { + "columnId": "OSMajorVersion", + "label": "OS Version" + }, + { + "columnId": "OSMinorVersion", + "label": "OS Minor Version" + }, + { + "columnId": "deviceName_", + "label": "Entra ID Device Name" + }, + { + "columnId": "readinessCheck", + "label": "Device Ready for Enrollment?", + "comment": "" + }, + { + "columnId": "deviceId_", + "label": "Entra ID Device ID" + }, + { + "columnId": "count_deviceId_", + "label": "Sign-In Count by User/Device Pair" + } + ] + } + }, + "name": "CBA on Android Readiness Table" + } + ] + }, + "conditionalVisibility": { + "parameterName": "AndroidCredential", + "comparison": "isEqualTo", + "value": "cba" + }, + "name": "Certificate-Based Authentication / Smart Card" + } + ], + "exportParameters": true + }, + "conditionalVisibility": { + "parameterName": "OSSelection", + "comparison": "isEqualTo", + "value": "Android" + }, + "name": "Group - Android" + } + ] + }, + "name": "Group - OS Selection" + } + ] + }, + "name": "Group - Display" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Phase", + "comparison": "isEqualTo", + "value": "enrollment" + }, + "name": "Enrollment Readiness Phase" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "# Enforcement Readiness Phase Instructions\n\nEnforcement requires several individual steps. First you must evaluate your readiness for enforcement using a report-only mode conditional access policy. Then you must put users in scope for enforcement.\n\n## Report Only Mode Instructions\n\n1. Create one Microsoft Entra ID conditional access policies in report-only mode. This policy should use the following controls:\n\t- User/Group Assignment: All users, excluding break glass accounts\n\t- App Assignment: All cloud apps\n\t- Grant Controls: Require Authentication Strength - Phishing-resistant MFA\n\t- Policy in Report-Only Mode\n3. Use this policy in your environment for a period of time to gather data on whether your users are using phishing-resistant passwordless credentials or not.\n4. In the workbook below, select the conditional access policy you created from the policy dropdown selector\n5. Use each of the tabs below to aid you in beginning your enforcement or evaluating where you have users who are not yet ready for enforcement.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "Enforcement Readiness Phase Instructions" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"MsGraphEndpoint/1.0\",\"data\":null,\"headers\":[],\"method\":\"GETARRAY\",\"path\":\"/beta/identity/conditionalAccess/policies?$filter=state eq 'enabled'\",\"urlParams\":[],\"transformers\":[{\"type\":\"jsonpath\",\"settings\":{\"columns\":[{\"path\":\"$.id\",\"columnid\":\"id\"},{\"path\":\"$.displayName\",\"columnid\":\"name\"},{\"path\":\"$.id\",\"columnid\":\"group\",\"columnType\":\"string\",\"substringRegexMatch\":\".*\",\"substringReplace\":\"Select individual enabled policy\"}]}}]}", + "size": 4, + "queryType": 14 + }, + "conditionalVisibility": { + "parameterName": "1", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "Graph call enabled" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"MsGraphEndpoint/1.0\",\"data\":null,\"headers\":[],\"method\":\"GETARRAY\",\"path\":\"/beta/identity/conditionalAccess/policies?$filter=state eq 'enabledForReportingButNotEnforced'\",\"urlParams\":[],\"transformers\":[{\"type\":\"jsonpath\",\"settings\":{\"columns\":[{\"path\":\"$.id\",\"columnid\":\"id\"},{\"path\":\"$.displayName\",\"columnid\":\"name\"},{\"path\":\"$.id\",\"columnid\":\"group\",\"columnType\":\"string\",\"substringRegexMatch\":\".*\",\"substringReplace\":\"Select individual report-only policy\"}]}}]}", + "size": 4, + "queryType": 14 + }, + "conditionalVisibility": { + "parameterName": "1", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "Graph call report-only" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "7872e5bd-19a2-476e-b87e-64a4f9436dda", + "version": "KqlParameterItem/1.0", + "name": "policy", + "label": "Phishing-Resistant Passwordless Read-Only Conditional Access Policy", + "type": 2, + "isRequired": true, + "query": "{\"version\":\"Merge/1.0\",\"merges\":[{\"id\":\"5550361f-24c8-4874-9984-366e29434072\",\"mergeType\":\"union\",\"leftTable\":\"Graph call report-only\",\"rightTable\":\"Graph call enabled\"}],\"projectRename\":[{\"originalName\":\"id\",\"mergedName\":\"id\",\"fromId\":\"unknown\"},{\"originalName\":\"name\",\"mergedName\":\"name\",\"fromId\":\"unknown\"},{\"originalName\":\"group\",\"mergedName\":\"group\",\"fromId\":\"unknown\"},{\"originalName\":\"[Graph call report-only].id\",\"mergedName\":\"id1\",\"fromId\":\"5550361f-24c8-4874-9984-366e29434072\"},{\"originalName\":\"[Graph call report-only].name\",\"mergedName\":\"name1\",\"fromId\":\"5550361f-24c8-4874-9984-366e29434072\"},{\"originalName\":\"[Graph call report-only].group\",\"mergedName\":\"group1\",\"fromId\":\"5550361f-24c8-4874-9984-366e29434072\"}]}", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "queryType": 7, + "value": "379964bb-731d-413c-872a-0198a87c2e8d" + }, + { + "id": "71ac70b1-3378-46a0-8266-3eb50a061044", + "version": "KqlParameterItem/1.0", + "name": "unit", + "label": "Data view", + "type": 2, + "isRequired": true, + "query": "let unit = datatable(label:string,units:string)\n[\"users\", \"|\"];\nunit \n| project Value = units, Label = label", + "isHiddenWhenLocked": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "value": "|" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 0" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "a66413e0-cfa3-4457-a169-ec2de2da59ce", + "cellValue": "View", + "linkTarget": "parameter", + "linkLabel": "Users Ready for Enforcement", + "subTarget": "Enforce", + "style": "link" + }, + { + "id": "6332c03a-f221-4ea3-82f4-14105aa3a376", + "cellValue": "View", + "linkTarget": "parameter", + "linkLabel": "Further Data Analysis", + "subTarget": "Analyze", + "style": "link" + } + ] + }, + "name": "links - 3" + } + ], + "exportParameters": true + }, + "name": "Top Level Enforcement Parameters" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// Total\r\nSigninLogs\r\n| where TimeGenerated {TimeRange:value}\r\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, UserDisplayName\r\n| where ConditionalAccessPolicies != \"[]\"\r\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\r\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\r\n| project-away AppDisplayName\r\n| mv-expand ConditionalAccessPolicies\r\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\r\n| project-away ConditionalAccessPolicies\r\n{unit} summarize count() by UserPrincipalName\r\n| summarize count()\r\n| extend resultName = \"Total\", unit = case(\"{unit}\" == \"//\", \"sign-ins\",\"users\"), statusCode = 1\r\n//\r\n//\r\n// Number of success/failure/user action required/not applied\r\n| union (\r\nSigninLogs\r\n| where TimeGenerated {TimeRange:value}\r\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, UserDisplayName\r\n| where ConditionalAccessPolicies != \"[]\"\r\n| where AppDisplayName in ({Apps}) or '*' in ({Apps})\r\n| where UserDisplayName in ({Users}) or '*' in ({Users})\r\n| project-away AppDisplayName\r\n| mv-expand ConditionalAccessPolicies\r\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\r\n| extend result = ConditionalAccessPolicies[\"result\"]\r\n| project-away ConditionalAccessPolicies\r\n| extend resultName = case(result == \"success\", \"Success\", result == \"reportOnlySuccess\", \"Report Only Success\", result == \"failure\", \"Failure\", result == \"reportOnlyFailure\", \"Report Only Failure\", result == \"interrupt\", \"User action required\", result == \"reportOnlyInterrupted\", \"Policy Not Satisfied\", \"Not applied\")\r\n| extend statusCode = case(resultName == \"Success\", 2, resultName == \"Report Only Success\", 3, resultName == \"Failure\", 4, resultName == \"Report Only Failure\", 5, resultName == \"User action required\", 6, resultName == \"Policy Not Satisfied\", 7, 8)\r\n{unit} summarize count() by resultName, UserPrincipalName, statusCode\r\n| summarize count() by resultName, statusCode\r\n| extend unit = case(\"{unit}\" == \"//\", \"sign-ins\",\"users\")\r\n)\r\n//\r\n// Case if result count is 0\r\n| join kind = fullouter (\r\n datatable (resultName:string,statusCode1:string)\r\n [\"Total\", 1,\r\n \"Report Only Success\", 3,\r\n \"Policy Not Satisfied\", 7,\r\n \"Not applied\", 8]\r\n) on resultName\r\n| extend resultName = iff(resultName == '', resultName1, resultName), count_ = iff(resultName == '', 0, count_), unit = \"{unit:label}\", statusCode1\r\n| project-away resultName1\r\n| sort by statusCode1 asc", + "size": 4, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "resultName", + "exportParameterName": "resultName", + "exportDefaultValue": "Total", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "resultName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "count_", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 2, + "maximumSignificantDigits": 3 + } + } + }, + "secondaryContent": { + "columnMatch": "unit", + "formatter": 1 + }, + "showBorder": true + } + }, + "name": "All Policies Summary" + } + ], + "exportParameters": true + }, + "name": "Parameters" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, DeviceDetail, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n// filter by the result type selected\n// Total = any result type (the result type will contain the empty string \"\")\n// Success = result types containing \"uccess\" (includes \"success\" and \"reportOnlySuccess\")\n// Failure = result types containing \"ailure\" (includes \"failure\" and \"reportOnlyFailure\")\n// User action required = result types containing \"nterrupt\" (includes \"interrupt\" and \"reportOnlyInterrupted\")\n// Not applied = result types containing \"ot\" (includes \"notApplied\", \"reportOnlyNotApplied\", and \"notEnabled\")\n| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Success\", \"uccess\", \"{resultName}\" == \"Failure\", \"ailure\", \"{resultName}\" == \"User action required\", \"nterrupted\",\"ot\")\n| where result contains filterResult\n| extend deviceState = case(DeviceDetail[\"trustType\"] == \"\", \"Unmanaged\", DeviceDetail[\"trustType\"])\n{unit} summarize count() by UserPrincipalName, deviceState\n| summarize count() by deviceState", + "size": 3, + "title": "Device State - Total (Each user may be counted more than once)", + "timeContextFromParameter": "TimeRange", + "exportFieldName": "", + "exportParameterName": "registeredState", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Azure AD registered", + "label": "Entra Registered" + }, + { + "seriesName": "Azure AD joined", + "label": "Entra Joined" + }, + { + "seriesName": "Hybrid Azure AD joined", + "label": "Entra Hybrid Joined" + }, + { + "seriesName": "Unmanaged", + "label": "Unmanaged" + } + ] + } + }, + "customWidth": "33", + "name": "Device State - Total" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, DeviceDetail, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n// filter by the result type selected\n// Total = any result type (the result type will contain the empty string \"\")\n// Success = result types containing \"uccess\" (includes \"success\" and \"reportOnlySuccess\")\n// Failure = result types containing \"ailure\" (includes \"failure\" and \"reportOnlyFailure\")\n// User action required = result types containing \"nterrupt\" (includes \"interrupt\" and \"reportOnlyInterrupted\")\n// Not applied = result types containing \"ot\" (includes \"notApplied\", \"reportOnlyNotApplied\", and \"notEnabled\")\n| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Success\", \"uccess\", \"{resultName}\" == \"Failure\", \"ailure\", \"{resultName}\" == \"User action required\", \"nterrupted\",\"ot\")\n| where result contains filterResult\n| extend device = tostring(DeviceDetail[\"operatingSystem\"])\n{unit} summarize count() by UserPrincipalName, device\n| summarize count() by device", + "size": 3, + "title": "Device Platform - Total (Each user may be counted more than once)", + "timeContextFromParameter": "TimeRange", + "exportParameterName": "osType", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Windows10", + "label": "Windows 10" + }, + { + "seriesName": "MacOs", + "label": "macOS" + }, + { + "seriesName": "Other", + "label": "Other" + }, + { + "seriesName": "Android", + "label": "Android" + }, + { + "seriesName": "Ios", + "label": "iOS" + } + ] + } + }, + "customWidth": "33", + "name": "Device Platform - Total" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, ClientAppUsed, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n// filter by the result type selected\n// Total = any result type (the result type will contain the empty string \"\")\n// Success = result types containing \"uccess\" (includes \"success\" and \"reportOnlySuccess\")\n// Failure = result types containing \"ailure\" (includes \"failure\" and \"reportOnlyFailure\")\n// User action required = result types containing \"nterrupt\" (includes \"interrupt\" and \"reportOnlyInterrupted\")\n// Not applied = result types containing \"ot\" (includes \"notApplied\", \"reportOnlyNotApplied\", and \"notEnabled\")\n| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Success\", \"uccess\", \"{resultName}\" == \"Failure\", \"ailure\", \"{resultName}\" == \"User action required\", \"nterrupted\",\"ot\")\n| where result contains filterResult\n{unit} summarize count() by UserPrincipalName, ClientAppUsed\n| summarize count() by ClientAppUsed", + "size": 3, + "title": "Client App - Total (Each user may be counted more than once)", + "timeContextFromParameter": "TimeRange", + "exportParameterName": "clientType", + "exportDefaultValue": "{\"series\":\"All\"}", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "piechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Browser", + "label": "Browser" + }, + { + "seriesName": "Mobile Apps and Desktop clients", + "label": "Mobile Apps and Desktop clients" + }, + { + "seriesName": "", + "label": "Other" + } + ] + } + }, + "customWidth": "33", + "name": "Client App - Total" + } + ], + "exportParameters": true + }, + "name": "Pie Charts" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, UserDisplayName, DeviceDetail, ClientAppUsed\n| extend deviceState = case(DeviceDetail[\"trustType\"] == \"\", \"Unmanaged\", DeviceDetail[\"trustType\"])\n| mv-expand ParsedRegisteredState = parse_json(tostring('{registeredState}'))\n | extend SelectedRegisteredState = ParsedRegisteredState.series\n | where SelectedRegisteredState == 'All' or (deviceState == SelectedRegisteredState)\n| extend deviceOS = tostring(DeviceDetail[\"operatingSystem\"])\n| mv-expand ParsedOS = parse_json(tostring('{osType}'))\n | extend SelectedOS = ParsedOS.series\n | where SelectedOS == 'All' or (deviceOS == SelectedOS)\n| mv-expand ParsedClientApp = parse_json(tostring('{clientType}'))\n | extend SelectedClientApp = ParsedClientApp.series\n | where SelectedClientApp == 'All' or (ClientAppUsed == SelectedClientApp)\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies, DeviceDetail, ClientAppUsed\n// filter by the result type selected\n// Total = any result type (the result type will contain the empty string \"\")\n// Success = result types containing \"uccess\" (includes \"success\" and \"reportOnlySuccess\")\n// Failure = result types containing \"ailure\" (includes \"failure\" and \"reportOnlyFailure\")\n// User action required = result types containing \"nterrupt\" (includes \"interrupt\" and \"reportOnlyInterrupted\")\n// Not applied = result types containing \"ot\" (includes \"notApplied\", \"reportOnlyNotApplied\", and \"notEnabled\")\n//| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Success\", \"uccess\", \"{resultName}\" == \"Failure\", \"ailure\", \"{resultName}\" == \"User action required\", \"nterrupted\",\"ot\")\n| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Report Only Success\", \"OnlySuccess\", \"{resultName}\" == \"Policy Not Satisfied\", \"OnlyInterrupted\",\"ot\")\n| where result endswith filterResult\n{unit} summarize count() by UserPrincipalName, AppDisplayName\n| summarize Count = count() by AppDisplayName\n| sort by Count desc", + "size": 0, + "showAnalytics": true, + "title": "Sign-In Count Per App", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 8, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "location", + "formatter": 8, + "formatOptions": { + "palette": "green" + } + }, + { + "columnMatch": "-- Group By --", + "formatter": 8, + "formatOptions": { + "palette": "green" + } + } + ], + "labelSettings": [ + { + "columnId": "AppDisplayName", + "label": "App Display Name" + }, + { + "columnId": "Count", + "label": "Sign-In Count" + } + ] + } + }, + "customWidth": "50", + "name": "Sign-In Count Per App" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, UserDisplayName, DeviceDetail, ClientAppUsed\n| extend deviceState = case(DeviceDetail[\"trustType\"] == \"\", \"Unmanaged\", DeviceDetail[\"trustType\"])\n| mv-expand ParsedRegisteredState = parse_json(tostring('{registeredState}'))\n | extend SelectedRegisteredState = ParsedRegisteredState.series\n | where SelectedRegisteredState == 'All' or (deviceState == SelectedRegisteredState)\n| extend deviceOS = tostring(DeviceDetail[\"operatingSystem\"])\n| mv-expand ParsedOS = parse_json(tostring('{osType}'))\n | extend SelectedOS = ParsedOS.series\n | where SelectedOS == 'All' or (deviceOS == SelectedOS)\n| mv-expand ParsedClientApp = parse_json(tostring('{clientType}'))\n | extend SelectedClientApp = ParsedClientApp.series\n | where SelectedClientApp == 'All' or (ClientAppUsed == SelectedClientApp)\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies, DeviceDetail, ClientAppUsed\n// filter by the result type selected\n// Total = any result type (the result type will contain the empty string \"\")\n// Success = result types containing \"uccess\" (includes \"success\" and \"reportOnlySuccess\")\n// Failure = result types containing \"ailure\" (includes \"failure\" and \"reportOnlyFailure\")\n// User action required = result types containing \"nterrupt\" (includes \"interrupt\" and \"reportOnlyInterrupted\")\n// Not applied = result types containing \"ot\" (includes \"notApplied\", \"reportOnlyNotApplied\", and \"notEnabled\")\n| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Report Only Success\", \"OnlySuccess\", \"{resultName}\" == \"Policy Not Satisfied\", \"OnlyInterrupted\",\"ot\")\n| where result endswith filterResult\n| summarize Count = count() by UserPrincipalName, UserDisplayName\n| sort by Count desc", + "size": 0, + "showAnalytics": true, + "title": "Sign-In Count Per User", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 8, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "Signins", + "formatter": 8, + "formatOptions": { + "palette": "blue" + } + } + ], + "labelSettings": [ + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "Count", + "label": "Sign-In Count" + } + ] + } + }, + "customWidth": "50", + "name": "Sign-In Count Per User" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, TimeGenerated, UserPrincipalName, AppDisplayName, CorrelationId, Status, UserDisplayName, MfaDetail, DeviceDetail, ClientAppUsed\n| extend deviceState = case(DeviceDetail[\"trustType\"] == \"\", \"Unmanaged\", DeviceDetail[\"trustType\"])\n| mv-expand ParsedRegisteredState = parse_json(tostring('{registeredState}'))\n | extend SelectedRegisteredState = ParsedRegisteredState.series\n | where SelectedRegisteredState == 'All' or (deviceState == SelectedRegisteredState)\n| extend deviceOS = tostring(DeviceDetail[\"operatingSystem\"])\n| mv-expand ParsedOS = parse_json(tostring('{osType}'))\n | extend SelectedOS = ParsedOS.series\n | where SelectedOS == 'All' or (deviceOS == SelectedOS)\n| mv-expand ParsedClientApp = parse_json(tostring('{clientType}'))\n | extend SelectedClientApp = ParsedClientApp.series\n | where SelectedClientApp == 'All' or (ClientAppUsed == SelectedClientApp)\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"], failureReason = tostring(Status[\"failureReason\"])\n| extend mfaMethod = tostring(MfaDetail.authMethod)\n| project-away ConditionalAccessPolicies, DeviceDetail, ClientAppUsed\n// filter by the result type selected\n// Total = any result type (the result type will contain the empty string \"\")\n// Success = result types containing \"uccess\" (includes \"success\" and \"reportOnlySuccess\")\n// Failure = result types containing \"ailure\" (includes \"failure\" and \"reportOnlyFailure\")\n// User action required = result types containing \"nterrupt\" (includes \"interrupt\" and \"reportOnlyInterrupted\")\n// Not applied = result types containing \"ot\" (includes \"notApplied\", \"reportOnlyNotApplied\", and \"notEnabled\")\n//| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Success\", \"uccess\", \"{resultName}\" == \"Failure\", \"ailure\", \"{resultName}\" == \"User action required\", \"nterrupted\",\"ot\")\n| extend filterResult = case(\"{resultName}\" == \"Total\",\"\", \"{resultName}\" == \"Report Only Success\", \"OnlySuccess\", \"{resultName}\" == \"Policy Not Satisfied\", \"OnlyInterrupted\",\"ot\")\n| where result endswith filterResult\n| project TimeGenerated, UserPrincipalName, UserDisplayName, AppDisplayName, result, CorrelationId, mfaMethod\n| sort by TimeGenerated desc", + "size": 0, + "showAnalytics": true, + "title": "Sign-Ins", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "Signins", + "formatter": 0, + "formatOptions": { + "aggregation": "Count" + } + }, + { + "columnMatch": "combinedResult", + "formatter": 0, + "formatOptions": { + "aggregation": "Count" + } + } + ], + "labelSettings": [ + { + "columnId": "TimeGenerated", + "label": "Time Generated" + }, + { + "columnId": "UserPrincipalName", + "label": "User Principal Name" + }, + { + "columnId": "UserDisplayName", + "label": "User Display Name" + }, + { + "columnId": "AppDisplayName", + "label": "App Display Name" + }, + { + "columnId": "result", + "label": "Result" + }, + { + "columnId": "CorrelationId", + "label": "Correlation ID" + }, + { + "columnId": "mfaMethod", + "label": "MFA Method" + } + ] + } + }, + "name": "Sign-Ins" + } + ] + }, + "name": "Tables" + } + ] + }, + "conditionalVisibility": { + "parameterName": "View", + "comparison": "isEqualTo", + "value": "Analyze" + }, + "name": "Analyze Tab" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "# Enforcement Guidance\n\nIt is recommended that you follow these steps for enforcement:\n\n1. First, create 4 Microsoft Entra ID security groups for enforcement, each aligned with a particular OS platform. Its recommended that these be cloud-native Microsoft Entra ID security groups rather than groups synced from on-premises Active Directory. These security groups will be used to enforce phishing-resistant authentication for each user by OS:\n\t- Windows Enforcement Group\n\t- macOS Enforcement Group\n\t- iOS Enforcement Group\n\t- Android Enforcement Group\n2. Create 4 conditional access policies, each aligned to enforcing on a particular OS platform:\n\t- Policy 1 - Windows Enforcement\n\t\t- User/Group Assignment: Windows Enforcement Group\n\t\t- App Assignment: All cloud apps\n\t\t- Grant Controls: Require Authentication Strength - Phishing-resistant MFA\n\t- Policy 2 - macOS Enforcement\n\t\t- User/Group Assignment: macOS Enforcement Group\n\t\t- App Assignment: All cloud apps\n\t\t- Grant Controls: Require Authentication Strength - Phishing-resistant MFA\n\t- Policy 3 - iOS Enforcement\n\t\t- User/Group Assignment: iOS Enforcement Group\n\t\t- App Assignment: All cloud apps\n\t\t- Grant Controls: Require Authentication Strength - Phishing-resistant MFA\n\t- Policy 4 - Android Enforcement\n\t\t- User/Group Assignment: Android Enforcement Group\n\t\t- App Assignment: All cloud apps\n\t\t- Grant Controls: Require Authentication Strength - Phishing-resistant MFA\n3. Download the list of users who are ready for enforcement from each of the lists below\n4. Place the appropriate users in each of the correct enforcement groups for that particular user. For example, some users may be placed into the Windows enforcement group, but not the other enforcement groups.\n5. Re-run this process of downloading users and adding them to enforcement groups periodically, until all your users are represented in every group.\n6. Use the \"Further Data Analysis\" tab to investigate user/device pairs that are not ready for enforcement yet and may require further end-user communication or other remediations.", + "style": "info" + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Explanation", + "comparison": "isNotEqualTo", + "value": "Hide" + }, + "name": "text - 4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "dff72d6b-62c6-4e53-b68c-8dd62b8b0fd5", + "version": "KqlParameterItem/1.0", + "name": "resultName", + "type": 1, + "isRequired": true, + "query": "let unit = datatable(label:string,units:string)\n[\"users\", \"|\"];\nunit \n| project Value = units, Label = label", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "name": "parameters - 0" + } + ], + "exportParameters": true + }, + "name": "Parameters" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Windows Users Ready for Enforcement" + }, + "customWidth": "25", + "name": "text - 0" + }, + { + "type": 1, + "content": { + "json": "### macOS Users Ready for Enforcement" + }, + "customWidth": "25", + "name": "text - 0 - Copy" + }, + { + "type": 1, + "content": { + "json": "### iOS Users Ready for Enforcement" + }, + "customWidth": "25", + "name": "text - 0 - Copy - Copy" + }, + { + "type": 1, + "content": { + "json": "### Android Users Ready for Enforcement" + }, + "customWidth": "25", + "name": "text - 0 - Copy - Copy - Copy" + } + ] + }, + "name": "Text Descriptions" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, DeviceDetail, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n| where result == \"reportOnlySuccess\"\n| extend device = tostring(DeviceDetail[\"operatingSystem\"])\n| where device contains \"Windows\"\n| summarize count() by UserPrincipalName\n| sort by UserPrincipalName asc", + "size": 0, + "title": "Windows", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "count_", + "formatter": 5 + } + ] + } + }, + "customWidth": "25", + "name": "Windows" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, DeviceDetail, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n| where result == \"reportOnlySuccess\"\n| extend device = tostring(DeviceDetail[\"operatingSystem\"])\n| where device contains \"Mac\" or device contains \"osx\"\n| summarize count() by UserPrincipalName\n| sort by UserPrincipalName asc", + "size": 0, + "title": "macOS", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "count_", + "formatter": 5 + } + ] + } + }, + "customWidth": "25", + "name": "macOS" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, DeviceDetail, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n| where result == \"reportOnlySuccess\"\n| extend device = tostring(DeviceDetail[\"operatingSystem\"])\n| where device contains \"iOS\"\n| summarize count() by UserPrincipalName\n| sort by UserPrincipalName asc", + "size": 0, + "title": "iOS", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "count_", + "formatter": 5 + } + ] + } + }, + "customWidth": "25", + "name": "iOS" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SigninLogs\n| where TimeGenerated {TimeRange:value}\n| project ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, DeviceDetail, UserDisplayName\n| where ConditionalAccessPolicies != \"[]\"\n//| where AppDisplayName in ({Apps}) or '*' in ({Apps})\n//| where UserDisplayName in ({Users}) or '*' in ({Users})\n| project-away AppDisplayName\n| mv-expand ConditionalAccessPolicies\n| where ConditionalAccessPolicies[\"id\"] == \"{policy:escape}\"\n| extend result = ConditionalAccessPolicies[\"result\"]\n| project-away ConditionalAccessPolicies\n| where result == \"reportOnlySuccess\"\n| extend device = tostring(DeviceDetail[\"operatingSystem\"])\n| where device contains \"Android\"\n| summarize count() by UserPrincipalName\n| sort by UserPrincipalName asc", + "size": 0, + "title": "Android", + "timeContextFromParameter": "TimeRange", + "showExportToExcel": true, + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "crossComponentResources": [ + "{Workbook}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "count_", + "formatter": 5 + } + ] + } + }, + "customWidth": "25", + "name": "Android" + } + ] + }, + "name": "Enforcement User Lists" + } + ] + }, + "name": "Enforcement Tables" + } + ] + }, + "conditionalVisibility": { + "parameterName": "View", + "comparison": "isEqualTo", + "value": "Enforce" + }, + "name": "Enforce Tab" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Phase", + "comparison": "isEqualTo", + "value": "enforcement" + }, + "name": "Enforcement Readiness Phase" + } + ], + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json" +} \ No newline at end of file diff --git a/gallery/workbook/microsoft.aadiam-tenant.json b/gallery/workbook/microsoft.aadiam-tenant.json index f65c1babe8..5cfe2c543a 100644 --- a/gallery/workbook/microsoft.aadiam-tenant.json +++ b/gallery/workbook/microsoft.aadiam-tenant.json @@ -68,6 +68,11 @@ "id": "Workbooks/Azure Active Directory/CrossTenantAccessActivity", "author": "Microsoft", "name": "Cross-tenant access activity" + }, + { + "id": "Workbooks/Azure Active Directory/Passwordless/Phishing-Resistant Passwordless Deployment", + "author": "Microsoft", + "name": "Phishing-Resistant Passwordless Deployment (Preview)" } ] }, From 2e6e2eaadfc9e105a6ed8686641fe4489232039f Mon Sep 17 00:00:00 2001 From: asaiedCorp <147104835+asaiedCorp@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:39:16 -0800 Subject: [PATCH 2/2] have users type track userchCategory if exists (#2837) Co-authored-by: Ahmed Saied Co-authored-by: MSKaiLian <48222200+MSKaiLian@users.noreply.github.com> --- .../UsageMetrics/Usage - Users/Usage - Users.workbook | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Workbooks/UsageMetrics/Usage - Users/Usage - Users.workbook b/Workbooks/UsageMetrics/Usage - Users/Usage - Users.workbook index 70ce9ab4a3..3b7c0c73d4 100644 --- a/Workbooks/UsageMetrics/Usage - Users/Usage - Users.workbook +++ b/Workbooks/UsageMetrics/Usage - Users/Usage - Users.workbook @@ -492,6 +492,16 @@ "resultVal": "user_AuthenticatedId" } }, + { + "criteriaContext": { + "leftOperand": "userschCategory", + "operator": "==", + "rightValType": "static", + "rightVal": "user_AuthenticatedId", + "resultValType": "static", + "resultVal": "user_AuthenticatedId" + } + }, { "criteriaContext": { "operator": "Default",