Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d384351
Added the WithSecure Elements integration for collecting security inc…
fspms Sep 23, 2025
37e3822
Merge branch 'main' into main
fspms Sep 25, 2025
65b5860
Merge branch 'main' into main
fspms Sep 25, 2025
e005f9c
Merge branch 'main' into main
fspms Sep 30, 2025
ebdeeb0
Merge branch 'main' into main
fspms Oct 17, 2025
d5d4d7e
Merge branch 'main' into main
fspms Oct 24, 2025
0fe0636
WithSecure Elements v1.0.2: Fix data collection and add deduplication
fspms Oct 24, 2025
b09c452
fix: JSON field extraction for security_events and incidents data str…
fspms Oct 25, 2025
385ebdb
Merge branch 'main' into main
fspms Oct 25, 2025
f77891c
Merge branch 'main' into main
fspms Oct 27, 2025
73b1c9e
Merge branch 'main' into main
fspms Oct 28, 2025
fad4deb
docs: simplify changelog and set version to 0.1.0
fspms Oct 30, 2025
9429cc3
fix: correct pipeline test files format for all data streams
fspms Oct 30, 2025
94b30b7
fix: improve ingest pipelines with error handling and JSON decoding
fspms Oct 30, 2025
c900260
fix: set version to 0.1.0 and simplify changelog
fspms Oct 30, 2025
d54c033
Merge branch 'main' into main
fspms Oct 30, 2025
04d476c
refactor: change JSON target_field from _temp to json for better clarity
fspms Nov 3, 2025
9a7f3e8
refactor: redesign ingest pipelines to follow Elastic conventions
fspms Nov 3, 2025
24a1da0
Update packages/withsecure_elements/data_stream/incident_detections/e…
fspms Nov 4, 2025
72f75a9
fix: standardize error handling in ingest pipelines and add CODEOWNERS
fspms Nov 4, 2025
0f45c4a
refactor: migrate from httpjson to CEL input type
fspms Nov 4, 2025
227f652
fix: prevent event duplication with fingerprint processor
fspms Nov 4, 2025
1138e44
fix: correct optional anchor handling in incident_detections CEL temp…
fspms Nov 4, 2025
636cd55
Update packages/withsecure_elements/data_stream/incidents/elasticsear…
fspms Nov 5, 2025
60575b7
Update packages/withsecure_elements/data_stream/security_events/elast…
fspms Nov 5, 2025
65d1181
Update packages/withsecure_elements/data_stream/security_events/agent…
fspms Nov 5, 2025
b0b8e2e
Update packages/withsecure_elements/data_stream/incidents/agent/strea…
fspms Nov 5, 2025
9661419
Update packages/withsecure_elements/data_stream/incident_detections/a…
fspms Nov 5, 2025
f0f68f2
refactor: migrate security_events from deprecated GET to POST API
fspms Nov 5, 2025
5c5535d
refactor: remove incident_detections data stream
fspms Nov 5, 2025
978d495
feat: parametrize batch_size for incidents data stream
fspms Nov 5, 2025
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
122 changes: 122 additions & 0 deletions packages/withsecure_elements/changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
- version: "1.0.3"
changes:
- description: "Fixed security_events pipeline to decode JSON from message field or event.original to extract individual fields"
type: bugfix
link: ""
- description: "Fixed incidents pipeline to decode JSON from message field or event.original to extract individual fields"
type: bugfix
link: ""
- description: "Fixed issue where message field contained entire JSON instead of readable event content for both security_events and incidents"
type: bugfix
link: ""
- description: "Added proper field extraction for all security_events fields (id, action, severity, engine, details, device, organization, etc.) from JSON payload"
type: bugfix
link: ""
- description: "Added proper field extraction for all incidents fields (incidentId, status, severity, categories, sources, etc.) from JSON payload"
type: bugfix
link: ""
- description: "Changed initial lookback window for security_events from 30 days to 7 days"
type: enhancement
link: ""
- description: "Changed initial lookback window for incidents from 24 hours to 7 days for consistent historical data collection"
type: enhancement
link: ""
- description: "Added eventTransactionId field mapping to withsecure.security.event.event_transaction_id"
type: enhancement
link: ""
- description: "Added message field mapping to withsecure.security.event.message for events that contain it"
type: enhancement
link: ""
- description: "Added timestamp fields (server_timestamp, persistence_timestamp, client_timestamp) to withsecure.security.event namespace"
type: enhancement
link: ""
- version: "1.0.2"
changes:
- description: "Fixed API request limits to comply with WithSecure API constraints (changed from 200 to 50 for incidents and incident_detections)"
type: bugfix
link: ""
- description: "Fixed security_events data collection by changing from POST to GET method (API accepts both but GET is simpler with httpjson)"
type: bugfix
link: ""
- description: "Added cursor-based data collection for incidents using updatedTimestampStart to prevent duplicate events"
type: enhancement
link: ""
- description: "Added cursor-based data collection for security_events using persistenceTimestampStart to prevent duplicate events"
type: enhancement
link: ""
- description: "Added pagination support with nextAnchor for all data streams to handle large result sets"
type: enhancement
link: ""
- description: "Fixed pagination errors by adding conditional check for nextAnchor existence before using it"
type: bugfix
link: ""
- description: "Added all engine groups (epp, edr, ecp, xm) to security_events data stream for comprehensive event collection"
type: enhancement
link: ""
- description: "Increased initial lookback window for security_events from 24 hours to 30 days to ensure historical data collection"
type: enhancement
link: ""
- description: "Simplified security_events ingest pipeline with proper error handling and conditional field processing"
type: enhancement
link: ""
- description: "Added enable_request_tracer option to all data streams for HTTP request/response debugging"
type: enhancement
link: ""
- description: "Disabled incident_detections data stream by default (requires specific incident_id configuration)"
type: enhancement
link: ""
- description: "Added archived=false filter to incidents data stream to exclude archived incidents"
type: enhancement
link: ""
- version: "1.0.1"
changes:
- description: "Simplified configuration: API credentials (URL, Client ID, Client Secret, Organization ID) are now defined at the input level and shared across all data streams"
type: enhancement
link: ""
- description: "Fixed httpjson template syntax to use correct Handlebars variable notation"
type: bugfix
link: ""
- description: "Added missing document separators (---) to ingest pipeline files"
type: bugfix
link: ""
- description: "Added required object_type property to object fields in field definitions"
type: bugfix
link: ""
- description: "Fixed duplicate field definitions between base-fields.yml and fields.yml"
type: bugfix
link: ""
- description: "Added required ECS fields (@timestamp, data_stream.*) with constant_keyword type"
type: bugfix
link: ""
- description: "Added official WithSecure Elements logo (SVG format)"
type: enhancement
link: ""
- description: "Updated documentation to reflect simplified single-input configuration"
type: enhancement
link: ""
- description: "Improved OAuth2 authentication configuration with proper endpoint_params structure"
type: enhancement
link: ""
- description: "Removed incorrect validation.yml file"
type: bugfix
link: ""
- version: "1.0.0"
changes:
- description: "Initial release of WithSecure Elements integration"
type: enhancement
link: ""
- description: "Add support for collecting incidents (BCDs) from WithSecure Elements API"
type: enhancement
link: ""
- description: "Add support for collecting security events from WithSecure Elements API"
type: enhancement
link: ""
- description: "Add support for collecting incident detections from WithSecure Elements API"
type: enhancement
link: ""
- description: "Add OAuth2 authentication support"
type: enhancement
link: ""
- description: "Add ECS field mapping for incidents, security events, and incident detections"
type: enhancement
link: ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
- name: "Test common configuration"
input:
withsecure.incident.detection:
id: "detection-12345"
incident_id: "2c902c73-e2a6-40fd-9532-257ee102e1c1"
detection_type: "malware"
severity: "high"
status: "active"
created_timestamp: "2023-08-09T12:10:43.537Z"
updated_timestamp: "2023-08-09T12:15:43.537Z"
source: "endpoint"
category: "MALWARE"
description: "Malware detected on endpoint"
device:
id: "device-123"
name: "WORKSTATION-01"
ip_address: "192.168.1.100"
os: "Windows 10"
user:
id: "user-123"
name: "John Doe"
email: "[email protected]"
file:
name: "malware.exe"
path: "C:\\Users\\John\\Downloads\\malware.exe"
hash: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
size: 1024000
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"id": "detection-12345",
"incidentId": "2c902c73-e2a6-40fd-9532-257ee102e1c1",
"detectionType": "malware",
"severity": "high",
"status": "active",
"createdTimestamp": "2023-08-09T12:10:43.537Z",
"updatedTimestamp": "2023-08-09T12:15:43.537Z",
"source": "endpoint",
"category": "MALWARE",
"description": "Malware detected on endpoint",
"device": {
"id": "device-123",
"name": "WORKSTATION-01",
"ipAddress": "192.168.1.100",
"os": "Windows 10"
},
"user": {
"id": "user-123",
"name": "John Doe",
"email": "[email protected]"
},
"file": {
"name": "malware.exe",
"path": "C:\\Users\\John\\Downloads\\malware.exe",
"hash": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"size": 1024000
},
"network": {
"sourceIp": "192.168.1.100",
"destinationIp": "10.0.0.1",
"port": 443,
"protocol": "HTTPS"
},
"details": {
"threatName": "Trojan.Generic.123456",
"confidence": 95,
"behavior": "suspicious_network_activity"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"event": {
"dataset": "withsecure_elements.incident_detections",
"module": "withsecure_elements",
"category": "threat",
"type": "detection",
"kind": "alert",
"provider": "withsecure_elements",
"action": "detected",
"outcome": "success",
"id": "detection-12345",
"created": "2023-08-09T12:10:43.537Z",
"start": "2023-08-09T12:10:43.537Z",
"end": "2023-08-09T12:15:43.537Z",
"severity": "high",
"original": "{{_source}}"
},
"withsecure": {
"incident": {
"detection": {
"id": "detection-12345",
"incident_id": "2c902c73-e2a6-40fd-9532-257ee102e1c1",
"detection_type": "malware",
"severity": "high",
"status": "active",
"created_timestamp": "2023-08-09T12:10:43.537Z",
"updated_timestamp": "2023-08-09T12:15:43.537Z",
"source": "endpoint",
"category": "MALWARE",
"description": "Malware detected on endpoint",
"details": {
"threatName": "Trojan.Generic.123456",
"confidence": 95,
"behavior": "suspicious_network_activity"
},
"device": {
"id": "device-123",
"name": "WORKSTATION-01",
"ip_address": "192.168.1.100",
"os": "Windows 10"
},
"user": {
"id": "user-123",
"name": "John Doe",
"email": "[email protected]"
},
"file": {
"name": "malware.exe",
"path": "C:\\Users\\John\\Downloads\\malware.exe",
"hash": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"size": 1024000
},
"network": {
"source_ip": "192.168.1.100",
"destination_ip": "10.0.0.1",
"port": 443,
"protocol": "HTTPS"
}
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest using the CEL input instead of HTTP JSON.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for the suggestion

You're absolutely right that CEL is the better choice for new integrations. I initially went with httpjson because I was more familiar with it, but I understand that CEL is now the recommended approach and offers several advantages

I suggest doing the initial integration with httpjson and planning a migration to CEL in a future version. It is a significant amount of work.
Would that work for you?

Could you point me to good reference integrations that use CEL with OAuth2 and pagination that I could learn from?

Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest doing the initial integration with httpjson and planning a migration to CEL in a future version. It is a significant amount of work.

Migration from HTTP JSON to CEL cause problems for users, so this is not a preferred path.

As far as CEL configurations go, the OAuth2.0 configuration is the same, depending on how you want to do things. See this for details (the config auth.oauth2.* fields are used to populate the client's authentication components, otherwise you can manually construct auth headers in the CEL program (as is the case in the example I'm linking to below). If you go for config auth, you will need to pass in headers via this config option.

A paginating CEL program with in-CEL authentication that looks pretty similar to what you have here is in the authentik package.

Copy link
Author

Choose a reason for hiding this comment

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

@efd6 Done in commit 0f45c4a!

Migrated all three data streams from httpjson to CEL input type as you recommended.

Implementation:

  • OAuth2 client credentials flow via auth.oauth2 config
  • Custom headers via resource.headers (not in the CEL program itself)
  • Cursor-based pagination with nextAnchor
  • Double optional pattern for state management (state.?cursor.?last_updated)
  • Optional field storage pattern (?"next_anchor": ... ? optional.of(...) : optional.none())
  • Proper error handling with structured error messages

Could you please review the CEL implementation and confirm it follows the expected patterns and best practices? Happy to make any adjustments if needed. Thanks

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
config_version: 2
interval: {{interval}}
{{#if enable_request_tracer}}
request.tracer.filename: "../../logs/httpjson/http-request-trace-*.ndjson"
request.tracer.maxbackups: 5
{{/if}}
request.url: {{url}}/incidents/v1/incidents/{{incident_id}}/detections
request.method: GET
{{#if http_client_timeout}}
request.timeout: {{http_client_timeout}}
{{/if}}
{{#if proxy_url}}
request.proxy_url: {{proxy_url}}
{{/if}}
{{#if ssl}}
request.ssl: {{ssl}}
{{/if}}
auth.oauth2.client.id: {{client_id}}
auth.oauth2.client.secret: {{client_secret}}
auth.oauth2.token_url: {{url}}/as/token.oauth2
auth.oauth2.endpoint_params:
grant_type: client_credentials
scope: connect.api.read
request.transforms:
- set:
target: url.params.limit
value: '50'
- set:
target: url.params.order
value: 'desc'
- set:
target: header.User-Agent
value: "Elastic-WithSecure-Elements-Connector/1.0.1"
- set:
target: header.Accept
value: "application/json"
response.split:
target: body.items
ignore_empty_value: true
response.pagination:
- set:
target: url.params.anchor
value: '[[.last_response.body.nextAnchor]]'
fail_on_template_error: true
tags:
{{#if preserve_original_event}}
- preserve_original_event
{{/if}}
{{#if preserve_duplicate_custom_fields}}
- preserve_duplicate_custom_fields
{{/if}}
{{#each tags as |tag|}}
- {{tag}}
{{/each}}
{{#contains "forwarded" tags}}
publisher_pipeline.disable_host: true
{{/contains}}
{{#if processors}}
processors:
{{processors}}
{{/if}}
Loading