SecOps - 41203 - Custom data connectors are configured in Microsoft Sentinel for in-scope sources without a built-in connector - #1495
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new SecOps assessment (Test ID 41203) to evaluate whether Microsoft Sentinel workspaces have at least one customer-/partner-authored codeless (custom) data connector configured, and provides the accompanying markdown description for reporting/remediation context.
Changes:
- Introduces
Test-Assessment-41203PowerShell test to enumerate Sentinel workspaces, query data connectors/definitions, classify “custom” connectors by publisher, and emit a summarized markdown table. - Adds
Test-Assessment.41203.mdnarrative/remediation content for the new assessment.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/powershell/tests/Test-Assessment.41203.ps1 | New assessment implementation that queries Sentinel workspaces and evaluates presence of custom codeless connectors. |
| src/powershell/tests/Test-Assessment.41203.md | New assessment documentation/remediation text and results placeholder. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Aleksandar Nikolić (alexandair)
left a comment
There was a problem hiding this comment.
Manoj Kesana (@Manoj-Kesana) Please, address my feedback.
Suggestion: Include inaccessible or unresolved workspace rows in the report. The current table is built only from confirmed onboarded workspaces, so an Investigate result does not show every workspace that caused it.
|
|
||
| # Codeless / custom-builder connector kinds per KnownDataConnectorKind. | ||
| $codelessKinds = @('GenericUI', 'APIPolling') | ||
| # Publishers that identify a first-party connector rather than a customer-authored one. |
There was a problem hiding this comment.
Any non-Microsoft publisher is incorrectly classified as customer-authored
Code: Test-Assessment.41203.ps1#L138-L179
Specification: /ztspecs/specs/secops/41203.md#L94-L101
$builtInPublishers = @('Microsoft', 'Microsoft Corporation')
...
IsCustom = -not [string]::IsNullOrWhiteSpace($publisher) -and
$builtInPublishers -notcontains $publisherThe specification requires a non-Microsoft publisher to also be absent from a known commercial-vendor list. The implementation has no such list and no customer-organization identity to compare against. It therefore marks any partner-authored CCF connector, such as one published by an ISV or MSSP, as custom and can return Pass when the tenant has no customer-authored connector.
This is not a theoretical distinction: Microsoft documents Microsoft-supported, partner-supported, and community-supported connector authors. A publisher other than Microsoft does not establish customer authorship.
Required change: classify a connector as customer-authored only from affirmative evidence. Implement the specification's maintained commercial-vendor exclusion and customer publisher matching, or return Investigate when authorship cannot be established. Apply the same rule to $customDefinitions; it currently has the same false-positive behavior.
| $passedItems = @($workspaceResults | Where-Object { $_.RowStatus -eq 'Pass' }) | ||
| $investigateItems = @($workspaceResults | Where-Object { $_.RowStatus -eq 'Investigate' }) | ||
|
|
||
| $passed = $passedItems.Count -gt 0 |
There was a problem hiding this comment.
A successful workspace masks failed API calls and inaccessible workspaces
Code: Test-Assessment.41203.ps1#L208-L224
Error capture: Test-Assessment.41203.ps1#L112-L130
Specification: /ztspecs/specs/secops/41203.md#L103
$passed = $passedItems.Count -gt 0
...
if (-not $passed -and ($investigateItems.Count -gt 0 -or
$forbiddenWorkspaces.Count -gt 0 -or
$unresolvedWorkspaces.Count -gt 0)) {
$customStatus = 'Investigate'
}Once any workspace has a connector classified as custom, $passed is true and the Investigate branch is disabled. The final result is therefore Pass even when:
- Q1 or Q2 failed for another Sentinel workspace;
- Sentinel onboarding could not be checked for another workspace; or
- another workspace was inaccessible due to permissions.
That contradicts the explicit specification rule that a Q1 or Q2 error returns Investigate, and it hides incomplete tenant coverage behind one successful workspace.
Required change: unresolved connector/onboarding results must take precedence over Pass. Compute Investigate first whenever any relevant workspace or query is unresolved. Add focused tests for mixed states, especially one Pass plus one Q1 failure, one Q2 failure, and one inaccessible workspace.
| Category = 'Security information and event management', | ||
| ImplementationCost = 'High', | ||
| MinimumLicense = ('Consumption-based: Microsoft Sentinel'), | ||
| Pillar = 'SecOps', |
There was a problem hiding this comment.
The code declares Pillar = 'SecOps', while the specification declares Data. Because the specification resides under specs/secops and the workshop task is SecOps, the code value is likely intentional and the specification likely needs correction.
| @@ -0,0 +1,10 @@ | |||
| Every enterprise has security-relevant log sources that no Microsoft- or partner-authored connector covers: bespoke line-of-business applications, internal authentication services, custom proxies, internally developed APIs, mainframe security exits, and homegrown SaaS. When these sources have no detection coverage, threat actor activity that touches them — credential reuse against an internal application, exploitation of a custom API, data staging from a homegrown SaaS prior to exfiltration — is silently absent from Sentinel's incident graph. Sentinel exposes three documented mechanisms for shipping these logs into the workspace and registering them as connectors: the Codeless Connector Framework (GenericUI / APIPolling / RestApiPoller kinds) for REST API sources, the Logs Ingestion API plus Data Collection Rules for arbitrary HTTP-shipped logs, and Logstash/Function App connectors. Building at least one custom connector is the documented best practice when an in-scope source has no existing connector — without it, the only alternative is to drop the source entirely (no detection) or run a parallel logging pipeline that bypasses the SIEM (no correlation). This check confirms that the Sentinel workspace contains at least one codeless connector whose publisher is not Microsoft, which indicates a customer- or partner-authored custom connector. | |||
There was a problem hiding this comment.
Companion documentation overstates what the check proves
Documentation: Test-Assessment.41203.md#L1
Specification: /ztspecs/specs/secops/41203.md#L54-L56
The implementation documentation says the check confirms a "customer- or partner-authored custom connector." The specification says the check confirms a customer-authored connector and explicitly excludes known commercial vendors. Align the documentation after fixing classification so users are not told that a partner connector satisfies the control.
No description provided.