Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"Name": "Fivetran_AuditTrail_CL",
"Properties": [
{ "Name": "TimeGenerated", "Type": "DateTime" },
{ "Name": "id", "Type": "String" },
{ "Name": "captured_at", "Type": "DateTime" },
{ "Name": "user_id", "Type": "String" },
{ "Name": "action", "Type": "String" },
{ "Name": "interaction_method", "Type": "String" },
{ "Name": "primary_resource_type", "Type": "String" },
{ "Name": "primary_resource_id", "Type": "String" },
{ "Name": "secondary_resource_type", "Type": "String" },
{ "Name": "secondary_resource_id", "Type": "String" },
{ "Name": "old_values", "Type": "Dynamic" },
{ "Name": "new_values", "Type": "Dynamic" }
]
}
21 changes: 21 additions & 0 deletions .script/tests/KqlvalidationsTests/CustomTables/Fivetran_CL.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"Name": "Fivetran_CL",
"Properties": [
{
"Name": "TimeGenerated",
"Type": "DateTime"
},
{
"Name": "Level",
"Type": "String"
},
{
"Name": "CreatedAt",
"Type": "DateTime"
},
{
"Name": "Message",
"Type": "String"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Name": "Fivetran_Platform_CL",
"Properties": [
{ "Name": "TimeGenerated", "Type": "DateTime" },
{ "Name": "FivetranTable", "Type": "String" },
{ "Name": "Record", "Type": "Dynamic" }
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -328,5 +328,6 @@
"TailscaleCCF",
"TailscalePremiumCCF",
"WhisperSecurityConnector",
"VaronisSaaSAlertsPush"
"VaronisSaaSAlertsPush",
"Fivetran"
]
12 changes: 12 additions & 0 deletions Logos/Fivetran.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions Solutions/Fivetran/Analytic Rules/FivetranAuthFailures.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
id: bbfbff4e-134d-4e21-a56b-93bc1de7cc2c
name: Fivetran - Repeated authentication failures
description: 'Detects an unusually high number of Fivetran log events referencing authentication, authorization or credential failures within a short window. Repeated failures can indicate brute-force or credential-stuffing attempts against the accounts Fivetran uses, credential theft/misuse, or (more benignly) expired or revoked credentials. The threshold is tuned so routine one-off credential expiry does not alert.'
kind: Scheduled
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Fivetran
dataTypes:
- Fivetran_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: GreaterThan
triggerThreshold: 0
tactics:
- CredentialAccess
relevantTechniques:
- T1110
query: |
let threshold = 10;
Fivetran_CL
| where Level in ("SEVERE", "WARNING")
| where Message has_any (
"authentication failed", "authentication error", "unauthorized",
"invalid credentials", "invalid token", "access denied",
"permission denied", "forbidden", "401", "403",
"token expired", "credential", "auth failure", "login failed")
| summarize FailureCount = count(), SampleMessages = make_set(Message, 5),
FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
by bin(TimeGenerated, 1h)
| where FailureCount > threshold
| sort by FailureCount desc
| extend Application = "Fivetran"
eventGroupingSettings:
aggregationKind: AlertPerResult
customDetails:
FailureCount: FailureCount
FirstSeen: FirstSeen
LastSeen: LastSeen
entityMappings:
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: Application
version: 1.0.0
39 changes: 39 additions & 0 deletions Solutions/Fivetran/Analytic Rules/FivetranIngestionGap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
id: 5f539c60-f2ed-4a22-b779-75a50ea1b919
name: Fivetran - Log ingestion gap (telemetry loss)
description: 'Alerts when no Fivetran logs have been received in Fivetran_CL for more than 2 hours. A gap can indicate a broken Fivetran-to-Sentinel pipeline, disabled logging, expired app credentials, or deliberately impaired security telemetry.'
kind: Scheduled
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: Fivetran
dataTypes:
- Fivetran_CL
queryFrequency: 1h
queryPeriod: 14d
triggerOperator: GreaterThan
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1562
query: |
let lookback = 14d;
let gapThreshold = 2h;
Fivetran_CL
| where TimeGenerated > ago(lookback)
| summarize LastLogReceived = max(TimeGenerated)
| extend GapDuration = now() - LastLogReceived
| where GapDuration > gapThreshold
| extend Reason = strcat("No Fivetran logs received for ", format_timespan(GapDuration, 'dd.hh:mm:ss'))
| extend Application = "Fivetran"
eventGroupingSettings:
aggregationKind: SingleAlert
customDetails:
LastLogReceived: LastLogReceived
Reason: Reason
entityMappings:
- entityType: CloudApplication
fieldMappings:
- identifier: Name
columnName: Application
version: 1.0.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[
{
"name": "fivetranDCR1",
"apiVersion": "2022-06-01",
"type": "Microsoft.Insights/dataCollectionRules",
"location": "{{location}}",
"kind": "Direct",
"properties": {
"streamDeclarations": {
"Custom-Fivetran_CL": {
"columns": [
{ "name": "Level", "type": "string" },
{ "name": "CreatedAt", "type": "datetime" },
{ "name": "Message", "type": "string" }
]
}
},
"destinations": {
"logAnalytics": [
{
"workspaceResourceId": "{{workspaceResourceId}}",
"name": "clv2ws1"
}
]
},
"dataFlows": [
{
"streams": [ "Custom-Fivetran_CL" ],
"destinations": [ "clv2ws1" ],
"outputStream": "Custom-Fivetran_CL",
"transformKql": "source | extend TimeGenerated = CreatedAt"
}
]
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"id": "Fivetran",
"title": "Fivetran Platform Logs",
"publisher": "Michael Woods",
"descriptionMarkdown": "Ingests Fivetran platform and connector logs into Microsoft Sentinel via the Azure Monitor Logs Ingestion API (DCR-based custom table). Fivetran PUSHES its own logs to a Data Collection Rule using an Entra ID app; this tile shows connection status and provides sample queries. It does not itself move data - ingestion is driven by Fivetran plus the DCR.",
"graphQueries": [
{
"metricName": "Total Fivetran log events received",
"legend": "Fivetran_CL",
"baseQuery": "Fivetran_CL"
}
],
"sampleQueries": [
{
"description": "All Fivetran log events (latest first)",
"query": "Fivetran_CL\n| sort by TimeGenerated desc"
},
{
"description": "Errors and warnings only",
"query": "Fivetran_CL\n| where Level in (\"SEVERE\", \"WARNING\")\n| sort by TimeGenerated desc"
},
{
"description": "Event volume by level over time",
"query": "Fivetran_CL\n| summarize count() by Level, bin(TimeGenerated, 1h)"
}
],
"dataTypes": [
{
"name": "Fivetran_CL",
"lastDataReceivedQuery": "Fivetran_CL\n| summarize Time = max(TimeGenerated)\n| where isnotempty(Time)"
}
],
"connectivityCriterias": [
{
"type": "IsConnectedQuery",
"value": [
"Fivetran_CL\n| summarize LastLogReceived = max(TimeGenerated)\n| project IsConnected = LastLogReceived > ago(30d)"
]
}
],
"availability": {
"status": 1,
"isPreview": false
},
Comment thread
woodsonsecurity marked this conversation as resolved.
"permissions": {
"resourceProvider": [
{
"provider": "Microsoft.OperationalInsights/workspaces",
"permissionsDisplayText": "read and write permissions are required.",
"providerDisplayName": "Workspace",
"scope": "Workspace",
"requiredPermissions": {
"write": true,
"read": true,
"delete": true
}
},
{
"provider": "Microsoft.OperationalInsights/workspaces/sharedKeys",
"permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).",
"providerDisplayName": "Keys",
"scope": "Workspace",
"requiredPermissions": {
"action": true
}
}
]
},
"instructionSteps": [
{
"title": "1. Register an Entra ID app for Fivetran",
"description": "In Microsoft Entra ID > App registrations, create an app and a client secret. Record the Application (Client) ID, Directory (Tenant) ID and secret value."
},
{
"title": "2. Create the custom table, DCE and DCR",
"description": "Deploy Fivetran_CL (columns TimeGenerated, Level, CreatedAt, Message) and a Data Collection Rule with stream Custom-Fivetran_CL and transform `source | extend TimeGenerated = CreatedAt`. See the michaelwoods-fivetran skill azure-setup.md."
},
{
"title": "3. Grant the app access to the DCR",
"description": "Assign the Entra app the Monitoring Metrics Publisher role on the DCR."
},
{
"title": "4. Configure Fivetran",
"description": "In Fivetran's external-log (Azure Monitor) setup form, choose the Logs Ingestion API mode and enter the Client ID, Tenant ID, Client secret, Logs Ingestion URI (or DCR logIngestion endpoint), DCR immutableId and stream name Custom-Fivetran_CL. Click Save & Test."
}
],
"metadata": {
"id": "138ff805-42c0-4c6c-b687-df18187a20fe",
"version": "1.0.0",
"kind": "dataConnector",
"source": { "kind": "community" },
"author": { "name": "Michael Woods" },
"support": { "name": "Michael Woods", "tier": "developer" }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"name": "Fivetran_CL",
"type": "Microsoft.OperationalInsights/workspaces/tables",
"apiVersion": "2021-12-01-preview",
"properties": {
"totalRetentionInDays": 365,
"plan": "Analytics",
"schema": {
"name": "Fivetran_CL",
"description": "Fivetran platform and connector logs pushed via the Azure Monitor Logs Ingestion API (DCR-based custom table).",
"columns": [
{
"name": "TimeGenerated",
"type": "DateTime",
"description": "Log Analytics ingestion timestamp, derived from CreatedAt in the DCR transform."
},
{
"name": "Level",
"type": "String",
"description": "Log level reported by Fivetran (INFO, WARNING, SEVERE)."
},
{
"name": "CreatedAt",
"type": "DateTime",
"description": "Timestamp of the log event as sent by Fivetran."
},
{
"name": "Message",
"type": "String",
"description": "Log message body."
}
]
}
}
}
]
31 changes: 31 additions & 0 deletions Solutions/Fivetran/Data/Solution_Fivetran.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"Name": "Fivetran",
"Author": "Michael Woods - michaelwoods@microsoft.com",
"Logo": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/Fivetran.svg\" width=\"75px\" height=\"75px\">",
"Description": "The Fivetran Solution for Microsoft Sentinel ingests Fivetran platform and connector logs into a DCR-based custom table using the Azure Monitor Logs Ingestion API. Fivetran pushes its own logs directly to a Data Collection Rule; this solution ships the custom table, DCR, a data-connector tile, a parser, two analytics rules, a hunting query and a workbook to give SecOps visibility of the Fivetran data pipeline.",
"Data Connectors": [
"Data Connectors/Fivetran_CCF/Fivetran_DataConnector.json"
],
"Parsers": [
"Parsers/Fivetran.yaml",
"Parsers/ASimAuthenticationFivetran.yaml",
"Parsers/vimAuthenticationFivetran.yaml",
"Parsers/ASimAuditEventFivetran.yaml",
"Parsers/vimAuditEventFivetran.yaml"
],
"Analytic Rules": [
"Analytic Rules/FivetranIngestionGap.yaml",
"Analytic Rules/FivetranAuthFailures.yaml"
],
"Hunting Queries": [
"Hunting Queries/FivetranSevereSpike.yaml"
],
"Workbooks": [
"Workbooks/Fivetran.json"
],
"BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Fivetran",
"Version": "3.0.1",
"Metadata": "SolutionMetadata.json",
"TemplateSpec": true,
"Is1PConnector": false
}
18 changes: 18 additions & 0 deletions Solutions/Fivetran/Hunting Queries/FivetranSevereSpike.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
id: 2de1fd60-97f4-4072-b78a-94dc7b047a63
name: Fivetran - Spike in SEVERE log events
description: 'Surfaces hourly windows with an unusually high number of Fivetran SEVERE-level events, which can indicate connector failures, credential problems, or data-pipeline tampering.'
requiredDataConnectors:
- connectorId: Fivetran
dataTypes:
- Fivetran_CL
tactics:
- DefenseEvasion
relevantTechniques:
- T1562
query: |
Fivetran_CL
| where Level == "SEVERE"
| summarize SevereCount = count(), SampleMessages = make_set(Message, 5) by bin(TimeGenerated, 1h)
| where SevereCount > 10
| sort by TimeGenerated desc
version: 1.0.0
Loading