{
    "version": "Notebook/1.0",
    "items": [
        {
            "type": 11,
            "content": {
                "version": "LinkItem/1.0",
                "style": "tabs",
                "links": [
                    {
                        "id": "5fcea91d-a1e3-4f09-b39e-0fb2798357a5",
                        "cellValue": "setTab",
                        "linkTarget": "parameter",
                        "linkLabel": "Overview",
                        "subTarget": "Overview",
                        "style": "link"
                    },
                    {
                        "id": "76a8c413-8eda-4332-a363-8ab214a3ed01",
                        "cellValue": "setTab",
                        "linkTarget": "parameter",
                        "linkLabel": "Identity Management",
                        "subTarget": "Identity",
                        "style": "link"
                    },
                    {
                        "id": "e3a7b5c1-9d2f-4a8e-b6c3-7f1d0e4a2b9c",
                        "cellValue": "setTab",
                        "linkTarget": "parameter",
                        "linkLabel": "Custom App Audit Coverage",
                        "subTarget": "AuditCoverage",
                        "style": "link"
                    }
                ]
            },
            "name": "links - 2"
        },
        {
            "type": 12,
            "content": {
                "version": "NotebookGroup/1.0",
                "groupType": "editable",
                "items": [
                    {
                        "type": 1,
                        "content": {
                            "json": "# BTP Overview Dashboard\r\n\r\nThis dashboard provides a birds-eye view of audit log activity across BTP accounts. This is intended to show the most active accounts and event sources, and general trends in activity.\r\n\r\nModify the Time Range selector to alter the lookback period and select the Identity Management tab to see more."
                        },
                        "name": "text - 4"
                    },
                    {
                        "type": 9,
                        "content": {
                            "version": "KqlParameterItem/1.0",
                            "parameters": [
                                {
                                    "id": "065c5ee8-c358-49aa-b839-47da6759d71d",
                                    "version": "KqlParameterItem/1.0",
                                    "name": "TimeRange",
                                    "label": "Time Range",
                                    "type": 4,
                                    "typeSettings": {
                                        "selectableValues": [
                                            {
                                                "durationMs": 86400000
                                            },
                                            {
                                                "durationMs": 172800000
                                            },
                                            {
                                                "durationMs": 259200000
                                            },
                                            {
                                                "durationMs": 604800000
                                            },
                                            {
                                                "durationMs": 1209600000
                                            },
                                            {
                                                "durationMs": 2419200000
                                            },
                                            {
                                                "durationMs": 2592000000
                                            },
                                            {
                                                "durationMs": 5184000000
                                            },
                                            {
                                                "durationMs": 7776000000
                                            }
                                        ]
                                    },
                                    "timeContext": {
                                        "durationMs": 86400000
                                    },
                                    "value": {
                                        "durationMs": 2592000000
                                    }
                                }
                            ],
                            "style": "pills",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces"
                        },
                        "name": "parameters - 2"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| make-series Trend = count() default = 0 on UpdatedOn from {TimeRange:start} to now() step 1d by Tenant\r\n| project-away UpdatedOn\r\n| join kind = inner (SAPBTPAuditLog_CL\r\n    | summarize Requests = count() by Tenant\r\n    ) on Tenant\r\n| project Tenant, Requests, Trend\r\n| order by Requests desc",
                            "size": 1,
                            "title": "Most active accounts by events generated",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "table",
                            "gridSettings": {
                                "formatters": [
                                    {
                                        "columnMatch": "Requests",
                                        "formatter": 4,
                                        "formatOptions": {
                                            "palette": "blue"
                                        }
                                    },
                                    {
                                        "columnMatch": "Trend",
                                        "formatter": 10,
                                        "formatOptions": {
                                            "palette": "blue",
                                            "compositeBarSettings": {
                                                "labelText": "",
                                                "columnSettings": []
                                            }
                                        }
                                    }
                                ]
                            },
                            "graphSettings": {
                                "type": 0,
                                "topContent": {
                                    "columnMatch": "Tenant",
                                    "formatter": 1
                                },
                                "centerContent": {
                                    "columnMatch": "count_",
                                    "formatter": 1,
                                    "numberFormat": {
                                        "unit": 17,
                                        "options": {
                                            "maximumSignificantDigits": 3,
                                            "maximumFractionDigits": 2
                                        }
                                    }
                                }
                            }
                        },
                        "customWidth": "50",
                        "name": "query - 2"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where TimeGenerated >= {TimeRange:start}\r\n| summarize count() by Category",
                            "size": 1,
                            "title": "Ingested events by audit category",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "piechart",
                            "tileSettings": {
                                "showBorder": false,
                                "titleContent": {
                                    "columnMatch": "Category",
                                    "formatter": 1
                                },
                                "leftContent": {
                                    "columnMatch": "count_",
                                    "formatter": 12,
                                    "formatOptions": {
                                        "palette": "auto"
                                    },
                                    "numberFormat": {
                                        "unit": 17,
                                        "options": {
                                            "maximumSignificantDigits": 3,
                                            "maximumFractionDigits": 2
                                        }
                                    }
                                }
                            }
                        },
                        "customWidth": "50",
                        "name": "query - 1"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where Category == \"audit.security-events\"\r\n| where Message has \"UserAuthenticationSuccess\"\r\n| make-series Events = count() default = 0 on UpdatedOn from {TimeRange:start} to now() step 1d by Tenant",
                            "size": 0,
                            "title": "Successful user sign-in activity over time",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "areachart"
                        },
                        "name": "query - 3"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where Category == \"audit.security-events\"\r\n| where Message has \"Unauthorized access attempt\"\r\n| make-series Events = count() default = 0 on UpdatedOn from {TimeRange:start} to now() step 1d by Tenant\r\n| extend (baseline) = series_decompose(Events)\r\n| extend (anomalies, baseline) = series_decompose_anomalies(Events, 3, -1, 'linefit')",
                            "size": 0,
                            "title": "Business Application Studio sign-in: unauthorized access anomalies",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "linechart"
                        },
                        "customWidth": "50",
                        "name": "query - 5",
                        "styleSettings": {
                            "margin": "10px",
                            "padding": "10px"
                        }
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SecurityAlert\r\n| where Entities has \"SAP BTP\"\r\n| make-series Events = count() default = 0 on TimeGenerated from {TimeRange:start} to now() step 1d",
                            "size": 0,
                            "title": "BTP Security alerts over time",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "barchart"
                        },
                        "customWidth": "50",
                        "name": "query - 6",
                        "styleSettings": {
                            "margin": "10px",
                            "padding": "10px"
                        }
                    }
                ]
            },
            "conditionalVisibility": {
                "parameterName": "setTab",
                "comparison": "isEqualTo",
                "value": "Overview"
            },
            "name": "group - 1"
        },
        {
            "type": 12,
            "content": {
                "version": "NotebookGroup/1.0",
                "groupType": "editable",
                "items": [
                    {
                        "type": 1,
                        "content": {
                            "json": "# BTP Identity Management"
                        },
                        "name": "text - 2"
                    },
                    {
                        "type": 9,
                        "content": {
                            "version": "KqlParameterItem/1.0",
                            "parameters": [
                                {
                                    "id": "04187a88-ee78-4ddf-bab3-5ce201d0c3c1",
                                    "version": "KqlParameterItem/1.0",
                                    "name": "TimeRange",
                                    "label": "Time Range",
                                    "type": 4,
                                    "typeSettings": {
                                        "selectableValues": [
                                            {
                                                "durationMs": 900000
                                            },
                                            {
                                                "durationMs": 1800000
                                            },
                                            {
                                                "durationMs": 3600000
                                            },
                                            {
                                                "durationMs": 14400000
                                            },
                                            {
                                                "durationMs": 43200000
                                            },
                                            {
                                                "durationMs": 86400000
                                            },
                                            {
                                                "durationMs": 172800000
                                            },
                                            {
                                                "durationMs": 259200000
                                            },
                                            {
                                                "durationMs": 604800000
                                            },
                                            {
                                                "durationMs": 1209600000
                                            },
                                            {
                                                "durationMs": 2592000000
                                            },
                                            {
                                                "durationMs": 5184000000
                                            },
                                            {
                                                "durationMs": 7776000000
                                            }
                                        ],
                                        "allowCustom": true
                                    },
                                    "timeContext": {
                                        "durationMs": 86400000
                                    },
                                    "value": {
                                        "durationMs": 2592000000
                                    }
                                }
                            ],
                            "style": "pills",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces"
                        },
                        "name": "parameters - 3"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where UpdatedOn >= {TimeRange:start}\r\n| where Message has \"scim user\"\r\n| extend Action = tostring(parse_json(tostring(parse_json(tostring(Message.object)).id)).crudType)\r\n| summarize Events = count() by UserName, Action\r\n| evaluate pivot(Action, sum(Events)) : (UserName:string, CREATE:int, UPDATE:int, DELETE:int)\r\n| extend Total = CREATE + UPDATE + DELETE\r\n| order by Total desc",
                            "size": 1,
                            "title": "Top user account management events by user",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "table",
                            "gridSettings": {
                                "formatters": [
                                    {
                                        "columnMatch": "CREATE",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "DELETE",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "UPDATE",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "Total",
                                        "formatter": 22,
                                        "formatOptions": {
                                            "compositeBarSettings": {
                                                "labelText": "",
                                                "columnSettings": [
                                                    {
                                                        "columnName": "CREATE",
                                                        "color": "green"
                                                    },
                                                    {
                                                        "columnName": "UPDATE",
                                                        "color": "blue"
                                                    },
                                                    {
                                                        "columnName": "DELETE",
                                                        "color": "orange"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                ]
                            },
                            "sortBy": []
                        },
                        "customWidth": "33.3",
                        "name": "query - 4"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where UpdatedOn >= {TimeRange:start}\r\n| where Message has \"scim user\"\r\n| extend Action = tostring(parse_json(tostring(parse_json(tostring(Message.object)).id)).crudType)\r\n| summarize count() by Tenant",
                            "size": 1,
                            "title": "User account management events by subaccount",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "piechart"
                        },
                        "customWidth": "33.3",
                        "name": "query - 6"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where UpdatedOn between ({TimeRange:start} .. {TimeRange:end})\r\n| where Message has \"scim user\"\r\n| extend Action = tostring(parse_json(tostring(parse_json(tostring(Message.object)).id)).crudType)\r\n| summarize Events = count() by UserName, Action\r\n| evaluate pivot(Action, sum(Events)) : (UserName:string, CREATE:int, UPDATE:int, DELETE:int)\r\n| extend Events = CREATE + UPDATE + DELETE\r\n| order by Events asc",
                            "size": 1,
                            "title": "Most rare user account management events by user",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "gridSettings": {
                                "formatters": [
                                    {
                                        "columnMatch": "CREATE",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "UPDATE",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "DELETE",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "Events",
                                        "formatter": 22,
                                        "formatOptions": {
                                            "compositeBarSettings": {
                                                "labelText": "",
                                                "columnSettings": [
                                                    {
                                                        "columnName": "CREATE",
                                                        "color": "green"
                                                    },
                                                    {
                                                        "columnName": "UPDATE",
                                                        "color": "blue"
                                                    },
                                                    {
                                                        "columnName": "DELETE",
                                                        "color": "orange"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                ],
                                "sortBy": [
                                    {
                                        "itemKey": "$gen_compositeBar_Events_4",
                                        "sortOrder": 1
                                    }
                                ]
                            },
                            "sortBy": [
                                {
                                    "itemKey": "$gen_compositeBar_Events_4",
                                    "sortOrder": 1
                                }
                            ]
                        },
                        "customWidth": "33.3",
                        "name": "query - 5"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "let user_account_changes = materialize(SAPBTPAuditLog_CL\r\n    | where UpdatedOn between ({TimeRange:start} .. {TimeRange:end})\r\n    | where isnotempty(Message.object)\r\n    | where Message has \"scim user\"\r\n    | extend Attributes = parse_json(Message.attributes)\r\n    | mv-expand Attributes\r\n    | where isnotempty(Attributes.new)\r\n    | extend New = replace_regex(tostring(Attributes.new), \"\\\\r\", \"\")\r\n    | extend Old = replace_regex(tostring(Attributes.old), \"\\\\r\", \"\")\r\n    | extend Action = tostring(parse_json(tostring(parse_json(tostring(Message.object)).id)).crudType)\r\n    | project UpdatedOn, UserName, Action, Tenant, New, Old);\r\nlet unpack_object = (Changes: (UpdatedOn: datetime, UserName: string, Tenant:string, Action: string, Column: string, Value: string)) {\r\n    Changes\r\n    | extend Column = parse_json(Column)\r\n    | evaluate bag_unpack(Column): (\r\n        UpdatedOn: datetime\r\n        , UserName: string\r\n        , Tenant: string\r\n        , Action: string\r\n        , Value: string\r\n        , userName: string\r\n        , active: string\r\n        , emails: string\r\n        , externalId: string\r\n        , id: string\r\n        , meta: string\r\n        , name: string\r\n        , origin: string\r\n        , passwordLastModified: datetime\r\n        , verified: string\r\n        , zoneid: string)\r\n};\r\nlet old_user = user_account_changes\r\n    | project-away New\r\n    | project-rename Column = Old\r\n    | extend Value = \"Old\"\r\n    | where not (Action == \"CREATE\" and Value == \"Old\");\r\nlet new_user = user_account_changes\r\n    | project-away Old\r\n    | project-rename Column = New\r\n    | extend Value = \"New\";\r\nunion (unpack_object(old_user)), (unpack_object(new_user))\r\n| where UserName !startswith \"sb-\"\r\n| order by UpdatedOn desc, Value asc ",
                            "size": 0,
                            "title": "User account management activity",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "table",
                            "gridSettings": {
                                "filter": true,
                                "labelSettings": [
                                    {
                                        "columnId": "Action",
                                        "label": "Activity"
                                    },
                                    {
                                        "columnId": "userName",
                                        "label": "Target User"
                                    },
                                    {
                                        "columnId": "active",
                                        "label": "Active"
                                    },
                                    {
                                        "columnId": "emails",
                                        "label": "Email"
                                    },
                                    {
                                        "columnId": "externalId",
                                        "label": "ExternalId"
                                    },
                                    {
                                        "columnId": "id",
                                        "label": "Id"
                                    },
                                    {
                                        "columnId": "meta",
                                        "label": "Meta"
                                    },
                                    {
                                        "columnId": "name",
                                        "label": "Name"
                                    },
                                    {
                                        "columnId": "origin",
                                        "label": "Origin"
                                    },
                                    {
                                        "columnId": "passwordLastModified",
                                        "label": "Password Last Modified"
                                    },
                                    {
                                        "columnId": "verified",
                                        "label": "Verified"
                                    },
                                    {
                                        "columnId": "zoneid",
                                        "label": "Zone Id"
                                    }
                                ]
                            }
                        },
                        "name": "query - 1"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "SAPBTPAuditLog_CL\r\n| where UpdatedOn between ({TimeRange:start} .. {TimeRange:end})\r\n| where Message has_any (\"xs_rolecollection2user\", \"xsrolecollection2role\", \"xsrolecollections\")\r\n| where UserName != \"client/hcp_onboarding\"\r\n| extend ChangeId = parse_json(tostring(parse_json(Message.object).id))\r\n| evaluate bag_unpack(ChangeId)\r\n| project-away TimeGenerated, Message, MessageUuid, OrgId, SpaceId, AlsServiceId, Category, Type, TenantId, _ResourceId\r\n| project-reorder UpdatedOn, UserName",
                            "size": 0,
                            "title": "Security role collection management events",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "gridSettings": {
                                "formatters": [
                                    {
                                        "columnMatch": "creationTimestamp",
                                        "formatter": 5
                                    },
                                    {
                                        "columnMatch": "onBehalfOf",
                                        "formatter": 5
                                    }
                                ],
                                "filter": true,
                                "labelSettings": [
                                    {
                                        "columnId": "crudType",
                                        "label": "Activity"
                                    },
                                    {
                                        "columnId": "origin",
                                        "label": "Origin"
                                    },
                                    {
                                        "columnId": "rolecollection_identity_zone_id",
                                        "label": "Identity Zone"
                                    },
                                    {
                                        "columnId": "rolecollection_name",
                                        "label": "Role Collection Name"
                                    },
                                    {
                                        "columnId": "tableName",
                                        "label": "Activity"
                                    },
                                    {
                                        "columnId": "user_id",
                                        "label": "Target User"
                                    }
                                ]
                            }
                        },
                        "name": "query - 2"
                    }
                ]
            },
            "conditionalVisibility": {
                "parameterName": "setTab",
                "comparison": "isEqualTo",
                "value": "Identity"
            },
            "name": "group - identity"
        },
        {
            "type": 12,
            "content": {
                "version": "NotebookGroup/1.0",
                "groupType": "editable",
                "items": [
                    {
                        "type": 1,
                        "content": {
                            "json": "# BTP Audit Coverage\r\n\r\nThis view identifies custom BTP applications that have user logins but no business audit trail. These applications may be missing audit log service bindings or `@AuditLog` annotations, creating security blind spots where user actions are invisible to monitoring."
                        },
                        "name": "text - audit-coverage"
                    },
                    {
                        "type": 9,
                        "content": {
                            "version": "KqlParameterItem/1.0",
                            "parameters": [
                                {
                                    "id": "b7e2a1c4-3d5f-48e9-a0b6-c1d2e3f4a5b7",
                                    "version": "KqlParameterItem/1.0",
                                    "name": "TimeRange",
                                    "label": "Time Range",
                                    "type": 4,
                                    "typeSettings": {
                                        "selectableValues": [
                                            {
                                                "durationMs": 3600000
                                            },
                                            {
                                                "durationMs": 14400000
                                            },
                                            {
                                                "durationMs": 43200000
                                            },
                                            {
                                                "durationMs": 86400000
                                            },
                                            {
                                                "durationMs": 259200000
                                            },
                                            {
                                                "durationMs": 604800000
                                            },
                                            {
                                                "durationMs": 1209600000
                                            },
                                            {
                                                "durationMs": 2592000000
                                            }
                                        ]
                                    },
                                    "timeContext": {
                                        "durationMs": 86400000
                                    },
                                    "value": {
                                        "durationMs": 604800000
                                    }
                                }
                            ],
                            "style": "pills",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces"
                        },
                        "name": "parameters - audit-coverage"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "let platform_service_patterns = dynamic([\r\n    \"app-studio\", \"auditlog\", \"cis-local\", \"service-manager\",\r\n    \"destination-xsappname\", \"connectivity-proxy\", \"feature-flags\"\r\n]);\r\nlet base = materialize(SAPBTPAuditLog_CL | where TimeGenerated >= {TimeRange:start});\r\nlet app_logins = base\r\n    | where Category == \"audit.security-events\"\r\n    | extend data_s = tostring(Message.data)\r\n    | where data_s has \"TokenIssuedEvent\"\r\n    | extend ParsedData = parse_json(data_s)\r\n    | extend ClientId = tostring(ParsedData.origin)\r\n    | where ClientId startswith \"sb-\"\r\n    | extend EventMessage = tostring(ParsedData.message)\r\n    | extend GrantType = extract(@'\"grant_type\"\\s*:\\s*\"([^\"]+)\"', 1, EventMessage)\r\n    | where GrantType == \"authorization_code\"\r\n    | extend XsAppName = extract(@\"^sb-(.+?)!\\w+$\", 1, ClientId)\r\n    | where isnotempty(XsAppName)\r\n    | where not(XsAppName has_any (platform_service_patterns))\r\n    | extend AppName = extract(@\"^([A-Za-z][A-Za-z0-9_]*)\", 1, XsAppName)\r\n    | extend HumanUser = extract(@'\"user_name\"\\s*:\\s*\"([^\"]+)\"', 1, EventMessage);\r\nlet audited_by_sb = base\r\n    | where Category !in (\"audit.security-events\")\r\n    | where UserName startswith \"sb-\"\r\n    | extend AuditedAppName = extract(@\"^sb-(.+?)!\\w+\", 1, UserName)\r\n    | where isnotempty(AuditedAppName)\r\n    | distinct AuditedAppName, Tenant;\r\nlet audited_by_binding = base\r\n    | where Category == \"audit.security-events\"\r\n    | where UserName contains \"customer-auditlog\"\r\n    | where isnotempty(AlsServiceId)\r\n    | distinct AlsServiceId, Tenant;\r\nlet all_apps_summary = app_logins\r\n    | summarize\r\n        LoginCount = count(),\r\n        FirstLogin = min(TimeGenerated),\r\n        LastLogin = max(TimeGenerated),\r\n        Users = make_set(HumanUser, 100)\r\n        by AppName, XsAppName, AlsServiceId, SubaccountName, Tenant;\r\nlet audited_xsappnames = union\r\n    (audited_by_sb | project XsAppName = AuditedAppName, Tenant),\r\n    (audited_by_binding\r\n        | join kind=inner (all_apps_summary | distinct XsAppName, AlsServiceId, Tenant) on AlsServiceId, Tenant\r\n        | project XsAppName, Tenant)\r\n    | distinct XsAppName, Tenant;\r\nall_apps_summary\r\n| join kind=leftouter (audited_xsappnames | extend IsAudited = true) on XsAppName, Tenant\r\n| extend AuditStatus = iff(IsAudited == true, \"Audited\", \"Unaudited\")\r\n| project AppName, XsAppName, SubaccountName, Tenant, AuditStatus, LoginCount, FirstLogin, LastLogin, Users\r\n| order by AuditStatus asc, LoginCount desc",
                            "size": 0,
                            "title": "Custom app audit coverage",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "table",
                            "gridSettings": {
                                "formatters": [
                                    {
                                        "columnMatch": "AuditStatus",
                                        "formatter": 18,
                                        "formatOptions": {
                                            "thresholdsOptions": "icons",
                                            "thresholdsGrid": [
                                                {
                                                    "operator": "==",
                                                    "thresholdValue": "Unaudited",
                                                    "representation": "warning",
                                                    "text": "{0}{1}"
                                                },
                                                {
                                                    "operator": "==",
                                                    "thresholdValue": "Audited",
                                                    "representation": "success",
                                                    "text": "{0}{1}"
                                                },
                                                {
                                                    "operator": "Default",
                                                    "representation": "unknown",
                                                    "text": "{0}{1}"
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        "columnMatch": "LoginCount",
                                        "formatter": 4,
                                        "formatOptions": {
                                            "palette": "blue"
                                        }
                                    }
                                ],
                                "filter": true,
                                "sortBy": [
                                    {
                                        "itemKey": "AuditStatus",
                                        "sortOrder": 1
                                    }
                                ],
                                "labelSettings": [
                                    {
                                        "columnId": "AppName",
                                        "label": "Application"
                                    },
                                    {
                                        "columnId": "XsAppName",
                                        "label": "XSUAA App Name"
                                    },
                                    {
                                        "columnId": "SubaccountName",
                                        "label": "Subaccount"
                                    },
                                    {
                                        "columnId": "Tenant",
                                        "label": "Tenant"
                                    },
                                    {
                                        "columnId": "AuditStatus",
                                        "label": "Audit Status"
                                    },
                                    {
                                        "columnId": "LoginCount",
                                        "label": "Logins"
                                    },
                                    {
                                        "columnId": "FirstLogin",
                                        "label": "First Login"
                                    },
                                    {
                                        "columnId": "LastLogin",
                                        "label": "Last Login"
                                    },
                                    {
                                        "columnId": "Users",
                                        "label": "Users"
                                    }
                                ]
                            }
                        },
                        "name": "query - app-audit-coverage"
                    },
                    {
                        "type": 3,
                        "content": {
                            "version": "KqlItem/1.0",
                            "query": "let platform_service_patterns = dynamic([\r\n    \"app-studio\", \"auditlog\", \"cis-local\", \"service-manager\",\r\n    \"destination-xsappname\", \"connectivity-proxy\", \"feature-flags\"\r\n]);\r\nlet base = materialize(SAPBTPAuditLog_CL | where TimeGenerated >= {TimeRange:start});\r\nlet app_logins = base\r\n    | where Category == \"audit.security-events\"\r\n    | extend data_s = tostring(Message.data)\r\n    | where data_s has \"TokenIssuedEvent\"\r\n    | extend ParsedData = parse_json(data_s)\r\n    | extend ClientId = tostring(ParsedData.origin)\r\n    | where ClientId startswith \"sb-\"\r\n    | extend EventMessage = tostring(ParsedData.message)\r\n    | extend GrantType = extract(@'\"grant_type\"\\s*:\\s*\"([^\"]+)\"', 1, EventMessage)\r\n    | where GrantType == \"authorization_code\"\r\n    | extend XsAppName = extract(@\"^sb-(.+?)!\\w+$\", 1, ClientId)\r\n    | where isnotempty(XsAppName)\r\n    | where not(XsAppName has_any (platform_service_patterns))\r\n    | distinct XsAppName, AlsServiceId, Tenant;\r\nlet audited_by_sb = base\r\n    | where Category !in (\"audit.security-events\")\r\n    | where UserName startswith \"sb-\"\r\n    | extend AuditedAppName = extract(@\"^sb-(.+?)!\\w+\", 1, UserName)\r\n    | where isnotempty(AuditedAppName)\r\n    | distinct AuditedAppName, Tenant;\r\nlet audited_by_binding = base\r\n    | where Category == \"audit.security-events\"\r\n    | where UserName contains \"customer-auditlog\"\r\n    | where isnotempty(AlsServiceId)\r\n    | distinct AlsServiceId, Tenant;\r\nlet audited_xsappnames = union\r\n    (audited_by_sb | project XsAppName = AuditedAppName, Tenant),\r\n    (audited_by_binding\r\n        | join kind=inner (app_logins) on AlsServiceId, Tenant\r\n        | project XsAppName, Tenant)\r\n    | distinct XsAppName, Tenant;\r\nlet total_apps = app_logins | summarize Total = dcount(XsAppName);\r\nlet audited_count = audited_xsappnames\r\n| join kind=inner (app_logins | distinct XsAppName, Tenant) on XsAppName, Tenant\r\n| summarize Audited = dcount(XsAppName);\r\ntotal_apps\r\n| extend placeholder = 1\r\n| join kind=leftouter (audited_count | extend placeholder = 1) on placeholder\r\n| extend Audited = coalesce(Audited, 0)\r\n| extend Unaudited = Total - Audited\r\n| extend AuditedPct = iff(Total == 0, 0.0, round(100.0 * Audited / Total, 1))\r\n| project Score = iff(Total == 0, \"No custom app logins in range\", strcat(Audited, \" / \", Total, \" apps audited (\", AuditedPct, \"%)\")), AuditedPct",
                            "size": 4,
                            "title": "Audit coverage score",
                            "timeContextFromParameter": "TimeRange",
                            "queryType": 0,
                            "resourceType": "microsoft.operationalinsights/workspaces",
                            "visualization": "tiles",
                            "tileSettings": {
                                "titleContent": {
                                    "columnMatch": "Score",
                                    "formatter": 1
                                },
                                "leftContent": {
                                    "columnMatch": "AuditedPct",
                                    "formatter": 12,
                                    "formatOptions": {
                                        "palette": "redGreen",
                                        "min": 0,
                                        "max": 100
                                    },
                                    "numberFormat": {
                                        "unit": 1,
                                        "options": {
                                            "style": "decimal",
                                            "maximumFractionDigits": 1
                                        }
                                    }
                                },
                                "showBorder": true,
                                "size": "auto"
                            }
                        },
                        "customWidth": "50",
                        "name": "query - unaudited-score"
                    }
                ]
            },
            "conditionalVisibility": {
                "parameterName": "setTab",
                "comparison": "isEqualTo",
                "value": "AuditCoverage"
            },
            "name": "group - audit-coverage"
        }
    ],
    "isLocked": true,
    "fallbackResourceIds": [],
    "fromTemplateId": "sentinel-SAPBTPActivity"
}