Skip to content

[Egress Defend] Add KnowBe4 Defend Logs Ingestion API (DCR) connector… - #14973

Open
olliespires wants to merge 4 commits into
Azure:masterfrom
olliespires:egress-defend-4.0
Open

[Egress Defend] Add KnowBe4 Defend Logs Ingestion API (DCR) connector…#14973
olliespires wants to merge 4 commits into
Azure:masterfrom
olliespires:egress-defend-4.0

Conversation

@olliespires

@olliespires olliespires commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Migrate the Egress Defend Microsoft Sentinel connector off the retiring HTTP Data Collector API to the Logs Ingestion API (DCR/DCE, CCF RestApiPoller).

  • Add CCF data connector "KnowBe4 Defend (via Logs Ingestion API)" (EgressDefendAudit): connector definition, RestApiPoller poller config, DCR, DCE and the EgressDefend_v4_CL table. Pulls from the Defend V1/events API and lands events in EgressDefend_v4_CL.
  • Add DefendAuditData_v4 parser, unioning classic EgressDefend_CL with the new EgressDefend_v4_CL for upgrade continuity.
  • Repoint the Dangerous Attachment Received / Dangerous Link Click analytic rules and the Dangerous Links Clicked hunting query to DefendAuditData_v4; add EgressDefend_v4_CL as a data type; bump rule versions to 1.1.0.
  • Bump the solution to 3.1.0 and regenerate the package.
  • Add KqlValidations CustomTables entries for EgressDefend_v4_CL and DefendAuditData_v4.

The new connector's user-facing display text uses the "KnowBe4 Defend" brand (matching the marketplace listing); publisher, technical identifiers, the legacy connector, analytic-rule names and solution metadata are unchanged.

Why _v4 (in place): all changes stay within the existing Egress Defend solution - same rule ids, solution id and offerId - so the migration lands as an in-place upgrade for existing installs rather than a duplicate detection. It deliberately leaves the separate KnowBe4 Defend Sentinel solution (merged to this repo but not yet published) untouched.

Change(s):

  • Add CCF RestApiPoller connector "Egress Defend v2" (EgressDefendAudit): connector definition, poller config, DCR, DCE and the new EgressDefend_v4_CL table.
  • Add DefendAuditData_v4 parser, unioning EgressDefend_CL with EgressDefend_v4_CL for upgrade continuity.
  • Repoint the two analytic rules and the Dangerous Links Clicked hunting query to DefendAuditData_v4; add EgressDefend_v4_CL data type.
  • Bump solution to 3.1.0 and regenerate the package.
  • Add KqlValidations CustomTables entries for the new table and parser.

Reason for Change(s):

Version Updated:

  • Yes. Analytic rules bumped 1.0.0 → 1.1.0; solution 3.0.0 → 3.1.0.

Testing Completed:

Checked that the validations are passing and have addressed any issues that are present:

  • Yes, validations run locally

…; solution v4.0.0

Migrate the Egress Defend Microsoft Sentinel connector off the retiring
HTTP Data Collector API to the Logs Ingestion API (DCR/DCE, CCF RestApiPoller).

- Add CCF data connector "KnowBe4 Defend (via Logs Ingestion API)"
  (EgressDefendAudit): connector definition, RestApiPoller poller config,
  DCR, DCE and the EgressDefend_v4_CL table. Pulls from the Defend
  V1/events API and lands events in EgressDefend_v4_CL.
- Add DefendAuditData_v4 parser, unioning classic EgressDefend_CL with the
  new EgressDefend_v4_CL for upgrade continuity.
- Repoint the Dangerous Attachment Received / Dangerous Link Click analytic
  rules and the Dangerous Links Clicked hunting query to DefendAuditData_v4;
  add EgressDefend_v4_CL as a data type; bump rule versions to 1.1.0.
- Bump the solution to 4.0.0 and regenerate the package.
- Add KqlValidations CustomTables entries for EgressDefend_v4_CL and
  DefendAuditData_v4.

The new connector's user-facing display text uses the "KnowBe4 Defend" brand
(matching the marketplace listing); publisher, technical identifiers, the
legacy connector, analytic-rule names and solution metadata are unchanged.

Why _v4 (in place): all changes stay within the existing Egress Defend
solution - same rule ids, solution id and offerId - so the migration lands
as an in-place upgrade for existing installs rather than a duplicate
detection. It deliberately leaves the separate KnowBe4 Defend Sentinel
solution (merged to this repo but not yet published) untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Migrates the Egress Defend Microsoft Sentinel solution from the retiring HTTP Data Collector API to the Logs Ingestion API (DCR/DCE + CCF RestApiPoller), introducing a new v4 custom table + parser and repointing workbook/rules/queries for seamless upgrade continuity.

Changes:

  • Added the “KnowBe4 Defend (via Logs Ingestion API)” RestApiPoller connector assets (connector definition, poller config, DCR, custom table).
  • Added DefendAuditData_v4 parser to union classic and v4 tables; updated workbook, analytic rules, and hunting query to use it.
  • Bumped solution/workbook/rules versions and updated KQL validations entries for the new table/parser.

Reviewed changes

Copilot reviewed 17 out of 19 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
Workbooks/WorkbooksMetadata.json Adds v4 table dependency + workbook version bump.
Solutions/Egress Defend/Workbooks/DefendMetrics.json Repoints workbook queries to DefendAuditData_v4.
Solutions/Egress Defend/ReleaseNotes.md Adds 4.0.0 release notes entry describing the migration.
Solutions/Egress Defend/Parsers/DefendAuditData_v4.yaml Introduces new parser unioning EgressDefend_CL + EgressDefend_v4_CL.
Solutions/Egress Defend/Package/testParameters.json Adds ARM test parameters used by packaging/deployment tests.
Solutions/Egress Defend/Package/mainTemplate.json Updates packaged ARM template: versions, metadata, adds v4 parser + new CCP connector artifacts.
Solutions/Egress Defend/Package/createUiDefinition.json Updates install UX text to reflect connector/parser counts and new connector messaging.
Solutions/Egress Defend/Hunting Queries/DangerousLinksClicked.yaml Repoints hunting query to DefendAuditData_v4 + adds v4 datatype dependency.
Solutions/Egress Defend/Data/Solution_EgressDefend.json Updates solution manifest to include new parser + connector definition and version bump.
Solutions/Egress Defend/Data Connectors/EgressDefendAuditLogs_ccp/* Adds CCP assets: table schema, poller config, DCR, connector definition.
Solutions/Egress Defend/Analytic Rules/*.yaml Repoints rules to DefendAuditData_v4, adds v4 datatype, bumps versions.
.script/tests/KqlvalidationsTests/CustomTables/*.json Adds KQL validation schemas for the new custom table and parser output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

"contentVersion": "[variables('dataConnectorCCPVersion')]",
"parameters": {
"guidValue": {
"defaultValue": "[[newGuid()]",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

}
},
{
"name": "[[concat(parameters('innerWorkspace'),'/Microsoft.SecurityInsights/', 'EgressDefendAudit', parameters('guidValue'))]",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

Comment on lines +1747 to +1748
"dataCollectionEndpoint": "[[parameters('dcrConfig').dataCollectionEndpoint]",
"dataCollectionRuleImmutableId": "[[parameters('dcrConfig').dataCollectionRuleImmutableId]"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

},
"auth": {
"type": "APIKey",
"ApiKey": "[[parameters('apiKey')]",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

"IsApiKeyInPostPayload": false
},
"request": {
"apiEndpoint": "[[concat('https://',parameters('apiUrl'),'/V1/events/?pagingMode=offset&domain=',parameters('domain'))]",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

ThreatLevel=email_threat_s,
TrustLevel=email_trust_s,
FirstTimeSender=email_firstTimeSender_b,
PayLoad=columnifexists('email_payload_Type_s', ""),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks good catch, but did it the other way around as that is what the others do

FunctionAlias: DefendAuditData_v4
FunctionQuery: |
union isfuzzy=true EgressDefend_CL, EgressDefend_v4_CL
| summarize arg_max(TimeGenerated, *) by email_messageId_s, time_t

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to dedupe these as data will need to be displayed from the old table and new as customers migrate. Both of these fields should always be populated, we think this is sensible but suggestions welcome if not

{
"name": "EgressDefend_v4_CL",
"type": "Microsoft.OperationalInsights/workspaces/tables",
"apiVersion": "2021-03-01-privatepreview",
"type": "Microsoft.Common.TextBlock",
"options": {
"text": "This will check for emails that Defend has identified as dangerous and a user has clicked a link. This hunting query depends on EgressDefend data connector (EgressDefend_CL Parser or Table)"
"text": "This will check for emails that Defend has identified as dangerous and a user has clicked a link. This hunting query depends on EgressDefend data connector (EgressDefend_CL EgressDefend_v4_CL Parser or Table)"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

},
"support": {
"name": "Egress",
"name": "egress1589289169584",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is package generated as far as I can see

@olliespires
olliespires marked this pull request as ready for review August 26, 2026 07:17
@olliespires
olliespires requested review from a team as code owners August 26, 2026 07:17
@v-maheshbh

v-maheshbh (v-maheshbh) commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Hi olliespires

image

Kindly ensure the existing ZIP file remains unchanged and is included correctly with the current changes.

Kindly repackage the solution with version 3.0.1 or 3.1.0 as the last released version was 3.0.0. Additionally, please update the release notes to reflect the changes included in this version.

Please provide a screenshot showing the CCF connector in a connected state

Thanks!

@olliespires

Copy link
Copy Markdown
Contributor Author

Hi olliespires

image Kindly ensure the existing ZIP file remains unchanged and is included correctly with the current changes.

Kindly repackage the solution with version 3.0.1 or 3.1.0 as the last released version was 3.0.0. Additionally, please update the release notes to reflect the changes included in this version.

Please provide a screenshot showing the CCF connector in a connected state

Thanks!

Hi v-maheshbh (@v-maheshbh)

Thanks, I have restored that old package, changed the version to 3.1.0 and updated the release notes.

Here is the V2 connector in the list

Pasted Graphic

Then we checked the data, this unioned view contains data from the old and new connectors:

Pasted Graphic 1

We then sent another record and you can see we have gone from 47 to 48:

Pasted Graphic 2

We had both the connectors enabled, here is the row in the old table:

Pasted Graphic 3

And here it is in the new table. There is only one in the view because of the data union. Let me know if we have missed anything here in the testing, thanks!

Pasted Graphic 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants