{
  "version": "Notebook/1.0",
  "items": [
    {
      "type": 1,
      "content": {
        "json": "\r\n\r\n# AAD ServicePrincipal SignIn Logs\r\n\r\n## 💡 Introduction\r\n\r\nThis workbook provides insights into AAD Service Principal SignIn Logs collected from Azure AD.\r\n"
      },
      "name": "text - 2"
    },
    {
      "type": 9,
      "content": {
        "version": "KqlParameterItem/1.0",
        "parameters": [
          {
            "id": "eb7146be-1fdd-46b3-9406-02959fe7ce90",
            "version": "KqlParameterItem/1.0",
            "name": "TimeRange",
            "type": 4,
            "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": 43200000
            }
          }
        ],
        "style": "pills",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces"
      },
      "name": "parameters - 3"
    },
    {
      "type": 1,
      "content": {
        "json": "## 🔍 Summary Tiles (Metrics)"
      },
      "name": "text - 4"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\n| summarize Count = count()\n",
        "size": 4,
        "title": "Total ServicePrincipal SignIns",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "visualization": "tiles",
        "tileSettings": {
          "titleContent": {
            "columnMatch": "Count",
            "formatter": 12,
            "formatOptions": {
              "palette": "blue"
            },
            "numberFormat": {
              "unit": 17,
              "options": {
                "style": "decimal"
              }
            }
          },
          "showBorder": false
        }
      },
      "customWidth": "25",
      "name": "query - 2"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\n| summarize Count = dcount(Location)\n",
        "size": 4,
        "title": "Unique Location",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "visualization": "tiles",
        "tileSettings": {
          "titleContent": {
            "columnMatch": "Count",
            "formatter": 12,
            "formatOptions": {
              "palette": "blue"
            },
            "numberFormat": {
              "unit": 17,
              "options": {
                "style": "decimal"
              }
            }
          },
          "showBorder": false
        }
      },
      "customWidth": "25",
      "name": "query - 2 - Copy"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\n| summarize Count = dcount(IPAddress)\n",
        "size": 4,
        "title": " Unique IPs",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "visualization": "tiles",
        "tileSettings": {
          "titleContent": {
            "columnMatch": "Count",
            "formatter": 12,
            "formatOptions": {
              "palette": "blue"
            },
            "numberFormat": {
              "unit": 17,
              "options": {
                "style": "decimal"
              }
            }
          },
          "showBorder": false
        }
      },
      "customWidth": "25",
      "name": "query - 2 - Copy - Copy"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\n| where ResultType != 0 \n| summarize Count = count()\n",
        "size": 4,
        "title": "Failures",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "visualization": "tiles",
        "tileSettings": {
          "titleContent": {
            "columnMatch": "Count",
            "formatter": 12,
            "formatOptions": {
              "palette": "blue"
            },
            "numberFormat": {
              "unit": 17,
              "options": {
                "style": "decimal"
              }
            }
          },
          "showBorder": false
        }
      },
      "customWidth": "25",
      "name": "query - 2 - Copy - Copy - Copy"
    },
    {
      "type": 1,
      "content": {
        "json": "## 📈AAD ServicePrincipal SignIn Trend"
      },
      "name": "text - 10"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\r\n| summarize Count = count() by bin(TimeGenerated, {TimeRange:grain})\r\n| render timechart ",
        "size": 0,
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces"
      },
      "name": "query - 11"
    },
    {
      "type": 1,
      "content": {
        "json": "## 📊 Succeesful and Failed Login Trend"
      },
      "name": "text - 8"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "let Trenddata = (\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),\r\nSuccessfulLogins = countif(ResultType ==0)  \r\nby ServicePrincipalName, bin(TimeGenerated, {TimeRange:grain})\r\n| summarize FailedTrend = makelist(FailedLogins),\r\nSuccessTrend = makelist(SuccessfulLogins) by ServicePrincipalName\r\n);\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),SuccessfulLogins = countif(ResultType ==0)  by ServicePrincipalName\r\n| join kind=inner\r\n(Trenddata) on $left.ServicePrincipalName == $right.ServicePrincipalName\r\n| project ServicePrincipalName, FailedLogins, FailedTrend, SuccessfulLogins, SuccessTrend\r\n| order by FailedLogins desc\r\n",
        "size": 0,
        "title": "Trend on Service Principal Name",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "gridSettings": {
          "formatters": [
            {
              "columnMatch": "FailedLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "FailedTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "SuccessfulLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "blue"
              }
            },
            {
              "columnMatch": "SuccessTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "blue"
              }
            }
          ],
          "rowLimit": 10000,
          "filter": true,
          "sortBy": [
            {
              "itemKey": "ServicePrincipalName",
              "sortOrder": 2
            }
          ]
        },
        "sortBy": [
          {
            "itemKey": "ServicePrincipalName",
            "sortOrder": 2
          }
        ]
      },
      "name": "query - 9"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "let Trenddata = (\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),\r\nSuccessfulLogins = countif(ResultType ==0)  \r\nby Location, bin(TimeGenerated, {TimeRange:grain})\r\n| summarize FailedTrend = makelist(FailedLogins),\r\nSuccessTrend = makelist(SuccessfulLogins) by Location\r\n);\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),SuccessfulLogins = countif(ResultType ==0)  by Location\r\n| join kind=inner\r\n(Trenddata) on $left.Location == $right.Location\r\n| project Location, FailedLogins, FailedTrend, SuccessfulLogins, SuccessTrend\r\n| order by FailedLogins desc\r\n",
        "size": 0,
        "title": "Trend on Location",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "gridSettings": {
          "formatters": [
            {
              "columnMatch": "FailedLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "FailedTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "SuccessfulLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "blue"
              }
            },
            {
              "columnMatch": "SuccessTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "blue"
              }
            }
          ],
          "rowLimit": 10000,
          "filter": true
        }
      },
      "name": "query - 9 - Copy"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "let Trenddata = (\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),\r\nSuccessfulLogins = countif(ResultType ==0)  \r\nby IPAddress, bin(TimeGenerated, {TimeRange:grain})\r\n| summarize FailedTrend = makelist(FailedLogins),\r\nSuccessTrend = makelist(SuccessfulLogins) by IPAddress\r\n);\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),SuccessfulLogins = countif(ResultType ==0)  by IPAddress\r\n| join kind=inner\r\n(Trenddata) on $left.IPAddress == $right.IPAddress\r\n| project IPAddress, FailedLogins, FailedTrend, SuccessfulLogins, SuccessTrend\r\n| order by FailedLogins desc\r\n",
        "size": 0,
        "title": "Trend on IPAddress",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "gridSettings": {
          "formatters": [
            {
              "columnMatch": "FailedLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "FailedTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "SuccessfulLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "blue"
              }
            },
            {
              "columnMatch": "SuccessTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "blue"
              }
            }
          ],
          "rowLimit": 10000,
          "filter": true
        }
      },
      "name": "query - 9 - Copy - Copy"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "let Trenddata = (\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),\r\nSuccessfulLogins = countif(ResultType ==0)  \r\nby IPAddress, bin(TimeGenerated, {TimeRange:grain})\r\n| summarize FailedTrend = makelist(FailedLogins),\r\nSuccessTrend = makelist(SuccessfulLogins) by IPAddress\r\n);\r\nAADServicePrincipalSignInLogs\r\n| summarize FailedLogins = countif(ResultType != 0),SuccessfulLogins = countif(ResultType ==0)  by ServicePrincipalName, Location, IPAddress\r\n| join kind=inner\r\n(Trenddata) on $left.IPAddress == $right.IPAddress\r\n| project ServicePrincipalName,Location, IPAddress, FailedLogins, FailedTrend, SuccessfulLogins, SuccessTrend\r\n| order by FailedLogins desc\r\n",
        "size": 0,
        "title": "Trend on ServicePrincipalName > Location > IPAddress",
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "gridSettings": {
          "formatters": [
            {
              "columnMatch": "FailedLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "FailedTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "red"
              }
            },
            {
              "columnMatch": "SuccessfulLogins",
              "formatter": 8,
              "formatOptions": {
                "palette": "blue"
              }
            },
            {
              "columnMatch": "SuccessTrend",
              "formatter": 10,
              "formatOptions": {
                "palette": "blue"
              }
            }
          ],
          "rowLimit": 10000,
          "filter": true,
          "hierarchySettings": {
            "treeType": 1,
            "groupBy": [
              "ServicePrincipalName",
              "Location"
            ],
            "expandTopLevel": true
          }
        }
      },
      "name": "query - 9 - Copy - Copy - Copy"
    },
    {
      "type": 1,
      "content": {
        "json": "## ❌ Failed AAD ServicePrincipal SignIns"
      },
      "name": "text - 12"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\r\n| where ResultType != 0 \r\n| project TimeGenerated, AppId, IPAddress, Location, ResultDescription\r\n| order by TimeGenerated desc",
        "size": 0,
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "gridSettings": {
          "rowLimit": 10000,
          "filter": true
        }
      },
      "name": "query - 13"
    },
    {
      "type": 1,
      "content": {
        "json": "## 🌍 IP Geolocation Map"
      },
      "name": "text - 14"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\r\n| extend latitude_ = tostring(parse_json(tostring(parse_json(LocationDetails).geoCoordinates)).latitude)\r\n| extend longitude_ = tostring(parse_json(tostring(parse_json(LocationDetails).geoCoordinates)).longitude)\r\n| summarize count() by latitude_, longitude_",
        "size": 0,
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "visualization": "map",
        "mapSettings": {
          "locInfo": "LatLong",
          "locInfoColumn": "Location",
          "latitude": "latitude_",
          "longitude": "longitude_",
          "sizeSettings": "count_",
          "sizeAggregation": "Sum",
          "labelSettings": "latitude_",
          "legendMetric": "count_",
          "legendAggregation": "Sum",
          "itemColorSettings": {
            "nodeColorField": "count_",
            "colorAggregation": "Sum",
            "type": "heatmap",
            "heatmapPalette": "categorical"
          }
        }
      },
      "name": "query - 15"
    },
    {
      "type": 1,
      "content": {
        "json": "##  📌 Suspicious IPs (High failure count)"
      },
      "name": "text - 16"
    },
    {
      "type": 3,
      "content": {
        "version": "KqlItem/1.0",
        "query": "AADServicePrincipalSignInLogs\r\n| where ResultType != 0 \r\n| summarize Failures = count() by IPAddress \r\n| where Failures > 10 \r\n| order by Failures desc",
        "size": 0,
        "timeContextFromParameter": "TimeRange",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces",
        "gridSettings": {
          "formatters": [
            {
              "columnMatch": "Failures",
              "formatter": 8,
              "formatOptions": {
                "palette": "red"
              }
            }
          ],
          "rowLimit": 10000,
          "filter": true
        },
        "mapSettings": {
          "locInfo": "LatLong",
          "locInfoColumn": "Location",
          "latitude": "latitude_",
          "longitude": "longitude_",
          "sizeSettings": "count_",
          "sizeAggregation": "Sum",
          "labelSettings": "latitude_",
          "legendMetric": "count_",
          "legendAggregation": "Sum",
          "itemColorSettings": {
            "nodeColorField": "count_",
            "colorAggregation": "Sum",
            "type": "heatmap",
            "heatmapPalette": "categorical"
          }
        }
      },
      "name": "query - 15 - Copy"
    }
  ],
  "fallbackResourceIds": [],
  "fromTemplateId": "sentinel-AADServicePrincipalSignInLogsWorkbook",
  "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
}
