Skip to content

Commit c0cf478

Browse files
authored
Merge pull request #14256 from gloo-shock/master
Migrate WithSecure connector to codeless solution
2 parents df97deb + 72938b3 commit c0cf478

21 files changed

Lines changed: 1516 additions & 22 deletions
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{
2+
"name": "WithSecureElementsCCF",
3+
"apiVersion": "2022-09-01-preview",
4+
"type": "Microsoft.SecurityInsights/dataConnectorDefinitions",
5+
"location": "{{location}}",
6+
"kind": "Customizable",
7+
"properties": {
8+
"connectorUiConfig": {
9+
"id": "WithSecureElementsCCF",
10+
"title": "WithSecure Elements (CCF)",
11+
"publisher": "WithSecure",
12+
"descriptionMarkdown": "WithSecure Elements security events ingested via Microsoft Sentinel's Codeless Connector Framework (CCF) \u2014 a fully SaaS deployment with no Azure Function, Storage Account or Key Vault to manage.\n\nThe connector polls the [WithSecure Elements security-events API](https://connect.withsecure.com/api-reference/elements#post-/security-events/v1/security-events) and stores normalized events in the `WsSecurityEvents_CL` Log Analytics table.",
13+
"graphQueriesTableName": "WsSecurityEvents_CL",
14+
"graphQueries": [
15+
{
16+
"metricName": "Total events received",
17+
"legend": "WithSecure Elements events",
18+
"baseQuery": "WsSecurityEvents_CL"
19+
}
20+
],
21+
"sampleQueries": [
22+
{
23+
"description": "All WithSecure events (most recent first)",
24+
"query": "WsSecurityEvents_CL\n| sort by TimeGenerated desc"
25+
},
26+
{
27+
"description": "Events grouped by engine",
28+
"query": "WsSecurityEvents_CL\n| summarize Count = count() by DeviceEventClassID\n| sort by Count desc"
29+
}
30+
],
31+
"dataTypes": [
32+
{
33+
"name": "WsSecurityEvents_CL",
34+
"lastDataReceivedQuery": "WsSecurityEvents_CL\n| summarize Time = max(TimeGenerated)\n| where isnotempty(Time)"
35+
}
36+
],
37+
"connectivityCriteria": [
38+
{
39+
"type": "HasDataConnectors"
40+
}
41+
],
42+
"availability": {
43+
"isPreview": false
44+
},
45+
"permissions": {
46+
"resourceProvider": [
47+
{
48+
"provider": "Microsoft.OperationalInsights/workspaces",
49+
"permissionsDisplayText": "read and write permissions on the workspace are required.",
50+
"providerDisplayName": "Workspace",
51+
"scope": "Workspace",
52+
"requiredPermissions": {
53+
"write": true,
54+
"read": true,
55+
"delete": true
56+
}
57+
}
58+
],
59+
"customs": [
60+
{
61+
"name": "WithSecure Elements API client credentials",
62+
"description": "Client credentials are required. See the [user guide](https://connect.withsecure.com/getting-started/elements#getting-client-credentials) for details."
63+
}
64+
]
65+
},
66+
"instructionSteps": [
67+
{
68+
"title": "Create WithSecure Elements API credentials",
69+
"description": "Follow the [user guide](https://connect.withsecure.com/getting-started/elements#getting-client-credentials) to create Elements API credentials. Save the client id and client secret in a safe place."
70+
},
71+
{
72+
"title": "Connect WithSecure Elements to Microsoft Sentinel",
73+
"description": "Provide the Elements API URL together with the client id and client secret you created in the previous step, then click **Connect** to start ingesting events.",
74+
"instructions": [
75+
{
76+
"type": "Textbox",
77+
"parameters": {
78+
"label": "Elements API URL",
79+
"placeholder": "https://api.connect.withsecure.com",
80+
"type": "text",
81+
"name": "elementsApiUrl"
82+
}
83+
},
84+
{
85+
"type": "Textbox",
86+
"parameters": {
87+
"label": "Engine (optional)",
88+
"placeholder": "default",
89+
"type": "text",
90+
"name": "engine"
91+
}
92+
},
93+
{
94+
"type": "Textbox",
95+
"parameters": {
96+
"label": "Engine Group (optional)",
97+
"placeholder": "default",
98+
"type": "text",
99+
"name": "engineGroup"
100+
}
101+
},
102+
{
103+
"type": "OAuthForm",
104+
"parameters": {
105+
"clientIdLabel": "Elements API Client Id",
106+
"clientSecretLabel": "Elements API Client Secret",
107+
"connectButtonLabel": "Connect",
108+
"disconnectButtonLabel": "Disconnect"
109+
}
110+
}
111+
]
112+
}
113+
]
114+
}
115+
}
116+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
[
2+
{
3+
"name": "WsCollectionRule",
4+
"apiVersion": "2022-06-01",
5+
"type": "Microsoft.Insights/dataCollectionRules",
6+
"properties": {
7+
"dataCollectionEndpointId": "{{dataCollectionEndpointId}}",
8+
"streamDeclarations": {
9+
"Custom-WsSecurityEventsRaw_CL": {
10+
"columns": [
11+
{
12+
"name": "engine",
13+
"type": "string"
14+
},
15+
{
16+
"name": "action",
17+
"type": "string"
18+
},
19+
{
20+
"name": "severity",
21+
"type": "string"
22+
},
23+
{
24+
"name": "message",
25+
"type": "string"
26+
},
27+
{
28+
"name": "persistenceTimestamp",
29+
"type": "datetime"
30+
},
31+
{
32+
"name": "serverTimestamp",
33+
"type": "datetime"
34+
},
35+
{
36+
"name": "clientTimestamp",
37+
"type": "datetime"
38+
},
39+
{
40+
"name": "userName",
41+
"type": "string"
42+
},
43+
{
44+
"name": "details",
45+
"type": "dynamic"
46+
},
47+
{
48+
"name": "device",
49+
"type": "dynamic"
50+
},
51+
{
52+
"name": "organization",
53+
"type": "dynamic"
54+
},
55+
{
56+
"name": "target",
57+
"type": "dynamic"
58+
},
59+
{
60+
"name": "id",
61+
"type": "string"
62+
},
63+
{
64+
"name": "eventTransactionId",
65+
"type": "string"
66+
},
67+
{
68+
"name": "acknowledged",
69+
"type": "boolean"
70+
}
71+
]
72+
}
73+
},
74+
"destinations": {
75+
"logAnalytics": [
76+
{
77+
"workspaceResourceId": "{{workspaceResourceId}}",
78+
"name": "WsRuleDest"
79+
}
80+
]
81+
},
82+
"dataFlows": [
83+
{
84+
"streams": [
85+
"Custom-WsSecurityEventsRaw_CL"
86+
],
87+
"destinations": [
88+
"WsRuleDest"
89+
],
90+
"transformKql": "source\n | extend details = todynamic(details)\n | extend device = todynamic(device)\n | extend organization = todynamic(organization)\n | extend engine = tostring(engine)\n | extend action = tostring(action)\n | extend severity = tostring(severity)\n | extend _infectedObject = case(\n engine in (\"fileScanning\", \"manualScanning\"), case(\n isnotempty(tostring(details.filePath)), tostring(details.filePath),\n isnotempty(tostring(details.object)), tostring(details.object),\n tostring(details.path)\n),\n engine == \"deepGuard\" and not(tostring(details.name) matches regex @\"Rarity: (\\d+), Reputation: (\\d+)\" or tostring(details.name) == \"DeepGuard blocks a rare application\"), tostring(details.filePath),\n engine == \"webTrafficScanning\" and isnotempty(tostring(details.alertType)), tostring(details.url),\n engine == \"webTrafficScanning\", tostring(details.websiteUrl),\n engine == \"amsi\", tostring(details.path),\n \"\"\n )\n | extend _malwareName = case(\n engine in (\"fileScanning\", \"manualScanning\"), case(\n isnotempty(tostring(details.name)), tostring(details.name),\n tostring(details.infectionName)\n),\n engine == \"deepGuard\" and not(tostring(details.name) matches regex @\"Rarity: (\\d+), Reputation: (\\d+)\" or tostring(details.name) == \"DeepGuard blocks a rare application\"), tostring(details.name),\n engine == \"webTrafficScanning\" and isnotempty(tostring(details.alertType)), tostring(extract(@\"[^/\\\\]+$\", 0, tostring(details.process))),\n engine == \"webTrafficScanning\", tostring(extract(@\"[^/\\\\]+$\", 0, tostring(details.filePath))),\n engine == \"amsi\", tostring(details.infectionName),\n \"\"\n )\n | extend\n TimeGenerated = now(),\n PersistenceTimestamp = todatetime(persistenceTimestamp),\n Activity = case(\n engine == \"webTrafficScanning\", \"Web Traffic Scanning event\",\n engine == \"webContentControl\", \"Web Content Control event\",\n engine == \"applicationControl\", \"Application Control event\",\n engine == \"fileScanning\", \"File Scanning event\",\n engine == \"manualScanning\", \"Manual Scanning event\",\n engine == \"realtimeScanning\", \"Real - time Scanning event\",\n engine == \"deviceControl\", \"Device Control event\",\n engine == \"deepGuard\", \"DeepGuard event\",\n engine == \"dataGuard\", \"DataGuard event\",\n engine == \"browsingProtection\", \"Browsing Protection event\",\n engine == \"connectionControl\", \"Network connection event\",\n engine == \"reputationBasedBrowsing\", \"Browsing Protection event\",\n engine == \"integrityChecker\", \"Integrity Checker event\",\n engine == \"tamperProtection\", \"Tamper Protection event\",\n engine == \"firewall\", \"Firewall event\",\n engine == \"amsi\", \"Antimalware Scan Interface (AMSI) event\",\n engine == \"connector\", \"Elements Connector event\",\n engine == \"setting\", \"Setting event\",\n engine == \"edr\", \"Endpoint Detection and Response (EDR) event\",\n engine == \"xFence\", \"XFENCE event\",\n engine == \"systemEventsLog\", \"System event\",\n engine == \"activityMonitor\", \"Server Share Protection event\",\n engine == \"emailScan\", \"Email scanning event\",\n engine == \"emailBreach\", \"Email breach event\",\n engine == \"teamsScan\", \"Microsoft Teams scanning event\",\n engine == \"oneDriveScan\", \"Microsoft OneDrive scanning event\",\n engine == \"sharePointScan\", \"Microsoft SharePoint scanning event\",\n engine == \"inboxRuleScan\", \"Suspicious inbox rule event\",\n engine == \"activityMonitorClientProtection\", \"Activity Monitor Client Protection\",\n engine\n ),\n DeviceVendor = \"WithSecure\",\n DeviceEventClassID = strcat(engine, \".\", action),\n DeviceAction = action,\n SimplifiedDeviceAction = action,\n LogSeverity = case(\n severity == \"critical\", int(10),\n severity == \"fatal_error\", int(8),\n severity == \"error\", int(6),\n severity == \"warning\", int(4),\n severity == \"info\", int(1),\n int(null)\n ),\n Message = tostring(message),\n SourceHostName = case(\n isnotempty(tostring(device.name)), tostring(device.name),\n isnotempty(tostring(device.id)), tostring(device.id),\n isnotempty(tostring(device.winsAddress)), tostring(device.winsAddress),\n \"\"\n),\n SourceUserName = tostring(details.userName),\n DeviceCustomString1 = _infectedObject,\n DeviceCustomString1Label = iif(isnotempty(_infectedObject), \"Infected object\", \"\"),\n DeviceCustomString2 = _malwareName,\n DeviceCustomString2Label = iif(isnotempty(_malwareName), \"Malware\", \"\"),\n AdditionalExtensions = strcat('{\"accountName\":\"', tostring(organization.name), '\",','\"details\":', iif(isempty(tostring(details)), \"null\", tostring(details)),'}')\n | project TimeGenerated, PersistenceTimestamp, Activity, DeviceVendor, DeviceEventClassID, DeviceAction, SimplifiedDeviceAction, LogSeverity, Message, SourceHostName, SourceUserName, DeviceCustomString1, DeviceCustomString1Label, DeviceCustomString2, DeviceCustomString2Label, AdditionalExtensions",
91+
"outputStream": "Custom-WsSecurityEvents_CL"
92+
}
93+
]
94+
}
95+
}
96+
]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[
2+
{
3+
"name": "WithSecureElementsConnection",
4+
"apiVersion": "2022-12-01-preview",
5+
"type": "Microsoft.SecurityInsights/dataConnectors",
6+
"location": "{{location}}",
7+
"kind": "RestApiPoller",
8+
"properties": {
9+
"connectorDefinitionName": "WithSecureElementsCCF",
10+
"dataType": "WithSecure Elements security-events",
11+
"auth": {
12+
"type": "OAuth2",
13+
"ClientId": "{{ClientId}}",
14+
"ClientSecret": "{{ClientSecret}}",
15+
"GrantType": "client_credentials",
16+
"TokenEndpoint": "{{elementsApiUrl}}/as/token.oauth2",
17+
"TokenEndpointHeaders": {
18+
"Content-Type": "application/x-www-form-urlencoded",
19+
"Accept": "application/json",
20+
"Authorization": "Basic {{base64(ClientId:ClientSecret)}}"
21+
},
22+
"Scope": "connect.api.read",
23+
"IsClientSecretInHeader": true
24+
},
25+
"request": {
26+
"apiEndpoint": "{{elementsApiUrl}}/security-events/v1/security-events",
27+
"httpMethod": "POST",
28+
"isPostPayloadJson": true,
29+
"queryWindowInMin": 5,
30+
"queryTimeFormat": "yyyy-MM-ddTHH:mm:ss.fffZ",
31+
"rateLimitQPS": 10,
32+
"retryCount": 3,
33+
"timeoutInSeconds": 60,
34+
"headers": {
35+
"Accept": "application/json",
36+
"User-Agent": "ccf-sentinel-connector"
37+
},
38+
"queryParametersTemplate": "{\"limit\":100,\"order\":\"asc\",\"exclusiveStart\":true,\"persistenceTimestampStart\":\"{_QueryWindowStartTime}\",\"persistenceTimestampEnd\":\"{_QueryWindowEndTime}\",\"engineGroup\":[\"epp\",\"edr\",\"ecp\",\"xm\"]}"
39+
},
40+
"response": {
41+
"eventsJsonPaths": ["$.items"],
42+
"format": "json"
43+
},
44+
"paging": {
45+
"pagingType": "NextPageToken",
46+
"nextPageTokenJsonPath": "$.nextAnchor",
47+
"nextPageParaName": "anchor"
48+
},
49+
"dcrConfig": {
50+
"dataCollectionEndpoint": "{{dataCollectionEndpoint}}",
51+
"dataCollectionRuleImmutableId": "{{dataCollectionRuleImmutableId}}",
52+
"streamName": "Custom-WsSecurityEventsRaw_CL"
53+
},
54+
"isActive": true
55+
}
56+
}
57+
]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
[
2+
{
3+
"name": "WsSecurityEvents_CL",
4+
"apiVersion": "2022-10-01",
5+
"type": "Microsoft.OperationalInsights/workspaces/tables",
6+
"properties": {
7+
"schema": {
8+
"name": "WsSecurityEvents_CL",
9+
"columns": [
10+
{
11+
"name": "TimeGenerated",
12+
"type": "datetime"
13+
},
14+
{
15+
"name": "PersistenceTimestamp",
16+
"type": "datetime"
17+
},
18+
{
19+
"name": "Activity",
20+
"type": "string"
21+
},
22+
{
23+
"name": "DeviceVendor",
24+
"type": "string"
25+
},
26+
{
27+
"name": "DeviceEventClassID",
28+
"type": "string"
29+
},
30+
{
31+
"name": "DeviceAction",
32+
"type": "string"
33+
},
34+
{
35+
"name": "SimplifiedDeviceAction",
36+
"type": "string"
37+
},
38+
{
39+
"name": "LogSeverity",
40+
"type": "int"
41+
},
42+
{
43+
"name": "Message",
44+
"type": "string"
45+
},
46+
{
47+
"name": "SourceHostName",
48+
"type": "string"
49+
},
50+
{
51+
"name": "SourceUserName",
52+
"type": "string"
53+
},
54+
{
55+
"name": "DeviceCustomString1",
56+
"type": "string"
57+
},
58+
{
59+
"name": "DeviceCustomString1Label",
60+
"type": "string"
61+
},
62+
{
63+
"name": "DeviceCustomString2",
64+
"type": "string"
65+
},
66+
{
67+
"name": "DeviceCustomString2Label",
68+
"type": "string"
69+
},
70+
{
71+
"name": "AdditionalExtensions",
72+
"type": "string"
73+
}
74+
]
75+
},
76+
"retentionInDays": 30,
77+
"totalRetentionInDays": 30
78+
}
79+
}
80+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"Name": "WithSecureElementsCCF",
3+
"Author": "WithSecure - project-msp-integrations@withsecure.com",
4+
"Logo": "<img src=\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/WithSecure.svg\" width=\"75px\" height=\"75px\">",
5+
"Description": "WithSecure Elements is the unified cloud-based cyber security platform designed to reduce risk, complexity, and inefficiency.\nElevate your security from your endpoints to your cloud applications. Arm yourself against every type of cyber threat, from targeted attacks to zero-day ransomware.\nWithSecure Elements combines powerful predictive, preventive, and responsive security capabilities - all managed and monitored through a single security center. Our modular structure and flexible pricing models give you the freedom to evolve. With our expertise and insight, you'll always be empowered - and you'll never be alone.\nWith Microsoft Sentinel integration, you can correlate [security events](https://connect.withsecure.com/api-reference/security-events#overview) data from the WithSecure Elements solution with data from other sources, enabling a rich overview of your entire environment and faster reaction to threats.\nThis solution uses the Codeless Connector Framework (CCF) to natively poll the WithSecure Elements security-events API — no Azure Function, Storage Account or Key Vault required.\nFor more information visit our website at: [https://www.withsecure.com](https://www.withsecure.com).",
6+
"Workbooks": [
7+
"Solutions/WithSecureElementsCCF/Workbooks/WithSecureTopComputersByInfections.json"
8+
],
9+
"Data Connectors": [
10+
"Solutions/WithSecureElementsCCF/Data Connectors/WithSecureElementsCCP/WithSecureElements_ConnectorDefinition.json"
11+
],
12+
"BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\WithSecureElementsCCF",
13+
"Version": "3.0.0",
14+
"Metadata": "SolutionMetadata.json",
15+
"TemplateSpec": true,
16+
"Is1PConnector": false
17+
}
9.81 KB
Binary file not shown.

0 commit comments

Comments
 (0)