Add workbook: Microsoft Security License & Feature Utilization - #14814
Open
d4rk-pri0r wants to merge 1 commit into
Open
Add workbook: Microsoft Security License & Feature Utilization#14814d4rk-pri0r wants to merge 1 commit into
d4rk-pri0r wants to merge 1 commit into
Conversation
New workbook correlating licensed Microsoft security products with the signals actually flowing into Sentinel, surfacing licensed-but-minimally- configured gaps across Defender for Endpoint, Defender for Office 365, Microsoft Entra ID, Defender for Cloud, and Sentinel itself. Adds: - Workbooks/MicrosoftSecurityLicenseUtilization.json - Workbooks/WorkbooksMetadata.json entry - White and Black preview images Drive-by fix: MicrosoftADTierModelWorkbook referenced a logo file (MicrosoftADTierModel.svg) that does not exist in Workbooks/Images/Logos, which fails the Workbooks metadata logo validation; pointed it at the existing azureactivedirectory_logo.svg instead.
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a new Sentinel workbook to visualize whether security-product telemetry is actually flowing (vs. “licensed but minimally configured”), and fixes an existing metadata logo reference that points to a non-existent file.
Changes:
- Added Microsoft Security License & Feature Utilization workbook template with multiple tabbed sections.
- Added a new
WorkbooksMetadata.jsonentry for the workbook (logo + white/black previews). - Fixed
MicrosoftADTierModelWorkbookmetadata to use an existing logo file.
Reviewed changes
Copilot reviewed 2 out of 4 changed files in this pull request and generated 9 comments.
| File | Description |
|---|---|
| Workbooks/WorkbooksMetadata.json | Fixes a broken logo reference and registers the new workbook (logo, previews, dependencies). |
| Workbooks/MicrosoftSecurityLicenseUtilization.json | Introduces the new multi-tab workbook with KQL tiles for identity/endpoint/email/purview/cloud/sentinel coverage. |
Comment on lines
+12
to
+18
| { | ||
| "cellValue": "parameterTab", | ||
| "linkTarget": "parameter", | ||
| "linkLabel": "Overview", | ||
| "subTarget": "overview", | ||
| "style": "link" | ||
| }, |
Comment on lines
+109
to
+113
| "conditionalVisibility": { | ||
| "parameterName": "parameterTab", | ||
| "comparison": "isEqualTo", | ||
| "value": "overview" | ||
| }, |
Comment on lines
+133
to
+134
| "version": "KqlItem/1.0", | ||
| "query": "SigninLogs\n| where TimeGenerated > ago(30d)\n| where ResultType == \"0\"\n| extend Status = case(\n ConditionalAccessStatus =~ \"success\", \"CA Applied\",\n ConditionalAccessStatus =~ \"notApplied\", \"CA Not Applied\",\n ConditionalAccessStatus =~ \"failure\", \"CA Failure\",\n ConditionalAccessStatus =~ \"notEnabled\", \"CA Not Enabled\",\n ConditionalAccessStatus =~ \"reportOnlySuccess\", \"Report Only: Success\",\n ConditionalAccessStatus =~ \"reportOnlyFailure\", \"Report Only: Failure\",\n \"Unknown\")\n| summarize Users = dcount(UserPrincipalName), SignIns = count() by Status\n| order by SignIns desc", |
Comment on lines
+263
to
+264
| "version": "KqlItem/1.0", | ||
| "query": "OfficeActivity\n| where TimeGenerated > ago(30d)\n| where Operation in~ (\"New-InboxRule\", \"Set-Mailbox\", \"Set-MailboxAutoReplyConfiguration\", \"Set-TransportRule\")\n| summarize Operations = count() by Operation, UserId\n| order by Operations desc", |
Comment on lines
+351
to
+352
| "version": "KqlItem/1.0", | ||
| "query": "SecurityNestedRecommendation\n| where TimeGenerated > ago(30d)\n| where RecommendationState == \"UnHealthy\"\n| summarize Findings = count(), Resources = dcount(AssessedResourceId) by RecommendationSeverity\n| order by Findings desc", |
Comment on lines
+416
to
+417
| "version": "KqlItem/1.0", | ||
| "query": "SecurityAlert\n| where TimeGenerated > ago(30d)\n| summarize Alerts = count(), LastAlert = max(TimeGenerated) by ProductName\n| order by Alerts desc", |
Comment on lines
+11074
to
+11086
| "workbookKey": "MicrosoftSecurityLicenseUtilization", | ||
| "logoFileName": "M365securityposturelogo.svg", | ||
| "description": "Correlates the Microsoft security products licensed in your tenant with the signals actually flowing into Microsoft Sentinel, surfacing licensed-but-minimally-configured gaps across Defender for Endpoint, Defender for Office 365, Microsoft Entra ID, Defender for Cloud, and Sentinel itself.", | ||
| "dataTypesDependencies": [ | ||
| "SigninLogs", | ||
| "AuditLogs", | ||
| "OfficeActivity", | ||
| "DeviceInfo", | ||
| "DeviceEvents", | ||
| "DeviceTvmSecureConfigurationAssessment", | ||
| "SecurityNestedRecommendation", | ||
| "InformationProtectionLogs_CL" | ||
| ], |
| { | ||
| "type": 1, | ||
| "content": { | ||
| "json": "## Microsoft Security License & Feature Utilization\n\nThis workbook correlates the Microsoft security products your tenant licenses with the signals that are actually flowing into this Microsoft Sentinel workspace. It is designed to surface **\"licensed but minimally configured\"** gaps: paid capabilities whose data never arrives, or that are enabled yet unmonitored.\n\nEach tab checks one product family. Empty or missing tiles mean the corresponding connector is not collecting data - a candidate to onboard. The workbook reads only the current workspace; no data is modified.", |
Comment on lines
+96
to
+97
| "version": "KqlItem/1.0", | ||
| "query": "let Sources = union isfuzzy=true\n SigninLogs, AuditLogs, OfficeActivity, DeviceInfo, DeviceEvents,\n DeviceTvmSecureConfigurationAssessment, SecurityNestedRecommendation,\n InformationProtectionLogs_CL, SecurityAlert\n| where TimeGenerated > ago(30d)\n| summarize Rows = count() by Source = Type;\nlet Products = datatable(ProductName:string, SignalSource:string)[\n \"Microsoft Entra ID\", \"SigninLogs\",\n \"Microsoft Entra ID\", \"AuditLogs\",\n \"Microsoft 365 Defender - Email (MDO)\", \"OfficeActivity\",\n \"Defender for Endpoint\", \"DeviceInfo\",\n \"Defender for Cloud\", \"SecurityNestedRecommendation\",\n \"Microsoft Purview\", \"InformationProtectionLogs_CL\"\n];\nProducts\n| join kind=leftouter Sources on $left.SignalSource == $right.Source\n| extend HasData = iff(isnotempty(Rows), \"Data Flowing\", \"No Data Collected\")\n| project ProductName, SignalSource, HasData, Rows\n| order by ProductName asc", |
Contributor
|
Hi @d4rk-pri0r, could you please resolve the branch conflicts? I’m also unable to view the images properly they only appear in black and white, as shown in the screenshot below. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Details
New workbook Microsoft Security License & Feature Utilization that correlates licensed Microsoft security products with the signals actually flowing into Microsoft Sentinel, exposing "licensed but minimally configured" gaps across the estate. Seven tabs:
Each tab uses conditional visibility and empty-result guards (
union isfuzzy=trueoverdatatabledefaults) so it renders correctly before a data source is onboarded.Adds the workbook template, its
WorkbooksMetadata.jsonentry (with white/black preview images), and uses the existingM365securityposturelogo.svglogo.Drive-by fix included
Workbooks/WorkbooksMetadata.jsonpreviously referencedMicrosoftADTierModel.svgas the logo forMicrosoftADTierModelWorkbook; that file does not exist inWorkbooks/Images/Logos/(also 404 onmaster), which fails the Workbooks metadata logo validation for any PR touching the file. Repointed the entry to the existingazureactivedirectory_logo.svg.Testing
Notebook/1.0template schema, no user-workbook/resource-info patterns.WorkbooksMetadata.jsonpasses the metadata schema and image/logo/preview validators (CI will re-runworkbook-metadata-validations/workbook-template-validations).kql-validationswhere they reference custom tables.Note to reviewers
Author metadata:
d4rk-pri0r, Community support tier. Preview images are placeholders and will be replaced with captured workbook screenshots in a follow-up commit.