Skip to content

Abnormal Security: expand CCF Threat Log & Audit Log schemas for MLA parity (v3.2.0)#14712

Open
anoopabsec wants to merge 1 commit into
Azure:masterfrom
anoopabsec:anoop/pr/abnormal-ccf-column-parity
Open

Abnormal Security: expand CCF Threat Log & Audit Log schemas for MLA parity (v3.2.0)#14712
anoopabsec wants to merge 1 commit into
Azure:masterfrom
anoopabsec:anoop/pr/abnormal-ccf-column-parity

Conversation

@anoopabsec

Copy link
Copy Markdown

Summary

Expands the CCF Push connector's Threat Log and Audit Log custom-table schemas to cover the fields the legacy (Azure Functions / MLA) connector produces, so a customer migrating from MLA to CCF has full field parity. Additive and non-breaking.

Changes (v3.1.0 → v3.2.0)

  • AbnormalSecurity_table_ThreatLog.json: +4 columns — message_engagement forwarded/replied counts and abx_body_abx_metadata/abx_metadata datetime timestamps.
  • AbnormalSecurity_table_AuditLog.json: +112 columns — per-field audit details_* and metadata timestamps.
  • AbnormalSecurity_DCR.json: transform lines added to populate the columns with unambiguous source paths (Threat Log's 4 + the audit timestamps). The audit details_* fields are declared for schema parity and remain fully available in abx_body_abx_body_details_s (JSON).
  • DCR input stream names unchanged — no change required on the sender side.
  • Version 3.1.0 → 3.2.0; package regenerated with createSolutionV4.

Test Plan

  • az deployment group validate Succeeded on the regenerated mainTemplate.json.
  • Deployed the tables + DCR to a workspace with pre-existing MLA data: schemas updated additively, data preserved (Threat Log ~7,974 rows intact), types reconciled (guidstring) with no data loss.

Deploy Plan

Content Hub update → re-deploy connector. Existing installations gain the new columns on update; no breaking change.

🤖 Generated with Claude Code

…as for MLA parity (v3.2.0)

Adds the columns the legacy (Azure Functions/MLA) connector produces that the
CCF Push connector's table schemas were missing, so a workspace migrating from
MLA to CCF has full field coverage.

- ThreatLog: +4 columns (message-engagement forwarded/replied counts, abx_body
  metadata + abx_metadata datetime timestamps), populated via DCR transforms.
- AuditLog: +112 columns (per-field audit details_* + metadata timestamps);
  the audit timestamps are populated via transforms, the details_* fields are
  declared for schema parity and remain available in abx_body_abx_body_details_s.
- DCR transforms updated for the populatable columns; input stream names
  unchanged. Additive, non-breaking.
- Version 3.1.0 -> 3.2.0; package regenerated with createSolutionV4.

Validated: az deployment group validate Succeeded.

Co-Authored-By: Claude Opus 4.8 <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.

Expands Abnormal Security’s CCF Push connector table schemas (Threat Log and Audit Log) and updates DCR transforms/versioning to improve field parity with the legacy (MLA) connector while keeping changes additive.

Changes:

  • Bumped solution/package versions to 3.2.0 and updated Release Notes.
  • Added 4 new Threat Log columns (message engagement counts + metadata timestamps) and populated them via DCR transforms.
  • Added ~112 new Audit Log “details_*” parity columns plus metadata timestamps, and populated the audit timestamps via DCR transforms.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Solutions/AbnormalSecurity/ReleaseNotes.md Added 3.2.0 release entry describing schema expansion and transform behavior.
Solutions/AbnormalSecurity/Package/mainTemplate.json Bumped versions, expanded table schemas, and updated DCR transforms for new timestamp/count fields.
Solutions/AbnormalSecurity/Data/Solution_AbnormalSecurity.json Bumped solution version to 3.2.0 for packaging metadata.
Solutions/AbnormalSecurity/Data Connectors/AbnormalSecurity_CCF/AbnormalSecurity_table_ThreatLog.json Added 4 Threat Log columns for parity.
Solutions/AbnormalSecurity/Data Connectors/AbnormalSecurity_CCF/AbnormalSecurity_table_AuditLog.json Added many Audit Log parity columns (details_* + timestamps).
Solutions/AbnormalSecurity/Data Connectors/AbnormalSecurity_CCF/AbnormalSecurity_DCR.json Added transforms to populate new Threat Log fields and Audit/Threat metadata timestamps.

Comment on lines +279 to +287
},
{
"name": "abx_body_abx_body_message_engagement_forwarded_count_d",
"type": "real"
},
{
"name": "abx_body_abx_body_message_engagement_replied_count_d",
"type": "real"
},
"clv2ws1"
],
"transformKql": "source | extend TimeGenerated = todatetime(Time)\n| extend abx_metadata_event_type_s = tostring(abx_metadata.event_type)\n| extend abx_metadata_timestamp_s = tostring(abx_metadata.timestamp)\n| extend abx_metadata_trace_id_g = tostring(abx_metadata.trace_id)\n| extend abx_body_abx_body_abx_message_id_d = toreal(abx_body.abx_body.abx_message_id)\n| extend abx_body_abx_body_abx_message_id_str_s = tostring(abx_body.abx_body.abx_message_id_str)\n| extend abx_body_abx_body_abx_portal_url_s = tostring(abx_body.abx_body.abx_portal_url)\n| extend abx_body_abx_body_threat_id_g = tostring(abx_body.abx_body.threat_id)\n| extend abx_body_abx_body_subject_s = tostring(abx_body.abx_body.subject)\n| extend abx_body_abx_body_from_name_s = tostring(abx_body.abx_body.from_name)\n| extend abx_body_abx_body_from_address_s = tostring(abx_body.abx_body.from_address)\n| extend abx_body_abx_body_to_addresses_s = tostring(abx_body.abx_body.to_addresses)\n| extend abx_body_abx_body_recipient_address_s = tostring(abx_body.abx_body.recipient_address)\n| extend abx_body_abx_body_received_time_t = todatetime(abx_body.abx_body.received_time)\n| extend abx_body_abx_body_sent_time_t = todatetime(abx_body.abx_body.sent_time)\n| extend abx_body_abx_body_internet_message_id_s = tostring(abx_body.abx_body.internet_message_id)\n| extend abx_body_abx_body_auto_remediated_b = tobool(abx_body.abx_body.auto_remediated)\n| extend abx_body_abx_body_post_remediated_b = tobool(abx_body.abx_body.post_remediated)\n| extend abx_body_abx_body_remediation_status_s = tostring(abx_body.abx_body.remediation_status)\n| extend abx_body_abx_body_remediation_timestamp_t = todatetime(abx_body.abx_body.remediation_timestamp)\n| extend abx_body_abx_body_attack_type_s = tostring(abx_body.abx_body.attack_type)\n| extend abx_body_abx_body_attack_strategy_s = tostring(abx_body.abx_body.attack_strategy)\n| extend abx_body_abx_body_attack_vector_s = tostring(abx_body.abx_body.attack_vector)\n| extend abx_body_abx_body_attack_score_d = toreal(abx_body.abx_body.attack_score)\n| extend abx_body_abx_body_attacked_party_s = tostring(abx_body.abx_body.attacked_party)\n| extend abx_body_abx_body_return_path_s = tostring(abx_body.abx_body.return_path)\n| extend abx_body_abx_body_reply_to_emails_s = tostring(abx_body.abx_body.reply_to_emails)\n| extend abx_body_abx_body_cc_emails_s = tostring(abx_body.abx_body.cc_emails)\n| extend abx_body_abx_body_bcc_emails_s = tostring(abx_body.abx_body.bcc_emails)\n| extend abx_body_abx_body_sender_ip_address_s = tostring(abx_body.abx_body.sender_ip_address)\n| extend abx_body_abx_body_sender_domain_s = tostring(abx_body.abx_body.sender_domain)\n| extend abx_body_abx_body_sender_auth_results_spf_s = tostring(abx_body.abx_body.sender_auth_results.spf)\n| extend abx_body_abx_body_sender_auth_results_dkim_s = tostring(abx_body.abx_body.sender_auth_results.dkim)\n| extend abx_body_abx_body_sender_auth_results_dmarc_s = tostring(abx_body.abx_body.sender_auth_results.dmarc)\n| extend abx_body_abx_body_impersonated_party_s = tostring(abx_body.abx_body.impersonated_party)\n| extend abx_body_abx_body_attachment_names_s = tostring(abx_body.abx_body.attachment_names)\n| extend abx_body_abx_body_attachment_count_d = toreal(abx_body.abx_body.attachment_count)\n| extend abx_body_abx_body_attachment_analysis_s = tostring(abx_body.abx_body.attachment_analysis)\n| extend abx_body_abx_body_urls_s = tostring(abx_body.abx_body.urls)\n| extend abx_body_abx_body_url_count_d = toreal(abx_body.abx_body.url_count)\n| extend abx_body_abx_body_summary_insights_s = tostring(abx_body.abx_body.summary_insights)\n| extend abx_body_abx_body_is_read_b = tobool(abx_body.abx_body.is_read)\n| extend abx_body_abx_body_folder_locations_s = tostring(abx_body.abx_body.folder_locations)\n| extend abx_body_abx_body_message_sources_s = tostring(abx_body.abx_body.message_sources)\n| extend abx_body_abx_body_message_engagement_s = tostring(abx_body.abx_body.message_engagement)\n| extend abx_body_abx_body_source_s = tostring(abx_body.abx_body.source)\n| extend abx_body_abx_body_tenant_s = tostring(abx_body.abx_body.tenant)\n| extend abx_body_abx_metadata_event_type_s = tostring(abx_body.abx_metadata.event_type)\n| extend abx_body_abx_metadata_timestamp_s = tostring(abx_body.abx_metadata.timestamp)\n| extend abx_body_abx_metadata_trace_id_g = tostring(abx_body.abx_metadata.trace_id)\n| extend abx_body = tostring(abx_body)\n| extend abx_metadata = tostring(abx_metadata)",
"transformKql": "source | extend TimeGenerated = todatetime(Time)\n| extend abx_body_abx_body_message_engagement_forwarded_count_d = toreal(abx_body.abx_body.message_engagement.forwarded_count)\n| extend abx_body_abx_body_message_engagement_replied_count_d = toreal(abx_body.abx_body.message_engagement.replied_count)\n| extend abx_body_abx_metadata_timestamp_t = todatetime(abx_body.abx_metadata.timestamp)\n| extend abx_metadata_timestamp_t = todatetime(abx_metadata.timestamp)\n| extend abx_metadata_event_type_s = tostring(abx_metadata.event_type)\n| extend abx_metadata_timestamp_s = tostring(abx_metadata.timestamp)\n| extend abx_metadata_trace_id_g = tostring(abx_metadata.trace_id)\n| extend abx_body_abx_body_abx_message_id_d = toreal(abx_body.abx_body.abx_message_id)\n| extend abx_body_abx_body_abx_message_id_str_s = tostring(abx_body.abx_body.abx_message_id_str)\n| extend abx_body_abx_body_abx_portal_url_s = tostring(abx_body.abx_body.abx_portal_url)\n| extend abx_body_abx_body_threat_id_g = tostring(abx_body.abx_body.threat_id)\n| extend abx_body_abx_body_subject_s = tostring(abx_body.abx_body.subject)\n| extend abx_body_abx_body_from_name_s = tostring(abx_body.abx_body.from_name)\n| extend abx_body_abx_body_from_address_s = tostring(abx_body.abx_body.from_address)\n| extend abx_body_abx_body_to_addresses_s = tostring(abx_body.abx_body.to_addresses)\n| extend abx_body_abx_body_recipient_address_s = tostring(abx_body.abx_body.recipient_address)\n| extend abx_body_abx_body_received_time_t = todatetime(abx_body.abx_body.received_time)\n| extend abx_body_abx_body_sent_time_t = todatetime(abx_body.abx_body.sent_time)\n| extend abx_body_abx_body_internet_message_id_s = tostring(abx_body.abx_body.internet_message_id)\n| extend abx_body_abx_body_auto_remediated_b = tobool(abx_body.abx_body.auto_remediated)\n| extend abx_body_abx_body_post_remediated_b = tobool(abx_body.abx_body.post_remediated)\n| extend abx_body_abx_body_remediation_status_s = tostring(abx_body.abx_body.remediation_status)\n| extend abx_body_abx_body_remediation_timestamp_t = todatetime(abx_body.abx_body.remediation_timestamp)\n| extend abx_body_abx_body_attack_type_s = tostring(abx_body.abx_body.attack_type)\n| extend abx_body_abx_body_attack_strategy_s = tostring(abx_body.abx_body.attack_strategy)\n| extend abx_body_abx_body_attack_vector_s = tostring(abx_body.abx_body.attack_vector)\n| extend abx_body_abx_body_attack_score_d = toreal(abx_body.abx_body.attack_score)\n| extend abx_body_abx_body_attacked_party_s = tostring(abx_body.abx_body.attacked_party)\n| extend abx_body_abx_body_return_path_s = tostring(abx_body.abx_body.return_path)\n| extend abx_body_abx_body_reply_to_emails_s = tostring(abx_body.abx_body.reply_to_emails)\n| extend abx_body_abx_body_cc_emails_s = tostring(abx_body.abx_body.cc_emails)\n| extend abx_body_abx_body_bcc_emails_s = tostring(abx_body.abx_body.bcc_emails)\n| extend abx_body_abx_body_sender_ip_address_s = tostring(abx_body.abx_body.sender_ip_address)\n| extend abx_body_abx_body_sender_domain_s = tostring(abx_body.abx_body.sender_domain)\n| extend abx_body_abx_body_sender_auth_results_spf_s = tostring(abx_body.abx_body.sender_auth_results.spf)\n| extend abx_body_abx_body_sender_auth_results_dkim_s = tostring(abx_body.abx_body.sender_auth_results.dkim)\n| extend abx_body_abx_body_sender_auth_results_dmarc_s = tostring(abx_body.abx_body.sender_auth_results.dmarc)\n| extend abx_body_abx_body_impersonated_party_s = tostring(abx_body.abx_body.impersonated_party)\n| extend abx_body_abx_body_attachment_names_s = tostring(abx_body.abx_body.attachment_names)\n| extend abx_body_abx_body_attachment_count_d = toreal(abx_body.abx_body.attachment_count)\n| extend abx_body_abx_body_attachment_analysis_s = tostring(abx_body.abx_body.attachment_analysis)\n| extend abx_body_abx_body_urls_s = tostring(abx_body.abx_body.urls)\n| extend abx_body_abx_body_url_count_d = toreal(abx_body.abx_body.url_count)\n| extend abx_body_abx_body_summary_insights_s = tostring(abx_body.abx_body.summary_insights)\n| extend abx_body_abx_body_is_read_b = tobool(abx_body.abx_body.is_read)\n| extend abx_body_abx_body_folder_locations_s = tostring(abx_body.abx_body.folder_locations)\n| extend abx_body_abx_body_message_sources_s = tostring(abx_body.abx_body.message_sources)\n| extend abx_body_abx_body_message_engagement_s = tostring(abx_body.abx_body.message_engagement)\n| extend abx_body_abx_body_source_s = tostring(abx_body.abx_body.source)\n| extend abx_body_abx_body_tenant_s = tostring(abx_body.abx_body.tenant)\n| extend abx_body_abx_metadata_event_type_s = tostring(abx_body.abx_metadata.event_type)\n| extend abx_body_abx_metadata_timestamp_s = tostring(abx_body.abx_metadata.timestamp)\n| extend abx_body_abx_metadata_trace_id_g = tostring(abx_body.abx_metadata.trace_id)\n| extend abx_body = tostring(abx_body)\n| extend abx_metadata = tostring(abx_metadata)",
Comment on lines +199 to +202
{
"name": "abx_body_abx_body_details_entity_id_g",
"type": "guid"
},
Comment on lines +227 to +230
{
"name": "abx_body_abx_body_details_instanceId_g",
"type": "guid"
},
Comment on lines +239 to +242
{
"name": "abx_body_abx_body_details_levelId_g",
"type": "guid"
},
Comment on lines +399 to +402
{
"name": "abx_body_abx_body_details_rule_uuid_g",
"type": "guid"
},
@v-maheshbh

Copy link
Copy Markdown
Contributor

Hi @anoopabsec

Kindly review the Copilot comments above and mark them as resolved if they have been addressed. and attach a screenshot of the CCF Connector in a connected state for reference.

Thanks!

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.

4 participants