diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2361cec1eda..9cb68625579 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -333,6 +333,7 @@ /packages/mysql_otel @elastic/obs-infraobs-integrations /packages/nagios_xi @elastic/obs-infraobs-integrations /packages/nats @elastic/obs-infraobs-integrations +/packages/neon_cyber @elastic/security-service-integrations /packages/netflow @elastic/integration-experience /packages/netscout @elastic/integration-experience /packages/netskope @elastic/security-service-integrations diff --git a/packages/neon_cyber/_dev/build/build.yml b/packages/neon_cyber/_dev/build/build.yml new file mode 100644 index 00000000000..97fc8aa10cd --- /dev/null +++ b/packages/neon_cyber/_dev/build/build.yml @@ -0,0 +1,3 @@ +dependencies: + ecs: + reference: git@v8.17.0 diff --git a/packages/neon_cyber/_dev/build/docs/README.md b/packages/neon_cyber/_dev/build/docs/README.md new file mode 100644 index 00000000000..576cd62b018 --- /dev/null +++ b/packages/neon_cyber/_dev/build/docs/README.md @@ -0,0 +1,44 @@ +# Neon Cyber Integration for Elastic + +## Overview + +The [Neon Cyber](https://www.neoncyber.com) integration for Elastic enables collection of workforce events and cybersecurity detections from the Neon [API](https://api.neoncyber.io/v1/docs]) + +## What data does this integration collect? + +The Neon Cyber integration collects log messages of the following types: +* Events including geo, navigation, auth, app, extensions, and platform +* Detections including compromised credentials, phishing, malware, and more + +### What do I need to use this integration? + +This integration requires you to generate a developer API key from the account settings of your Neon Cyber instance. + +## How do I deploy this integration? + +### Agent-based deployment + +Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](docs-content://reference/fleet/install-elastic-agents.md). You can install only one Elastic Agent per host. + +Elastic Agent is required to stream data from the syslog or log file receiver and ship the data to Elastic, where the events will then be processed via the integration's ingest pipelines. + +### Agentless Enabled Integration + +Agentless integrations allow you to collect data without having to manage Elastic Agent in your cloud. They make manual agent deployment unnecessary, so you can focus on your data instead of the agent that collects it. For more information, refer to [Agentless integrations](https://www.elastic.co/guide/en/serverless/current/security-agentless-integrations.html) and the [Agentless integrations FAQ](https://www.elastic.co/guide/en/serverless/current/agentless-integration-troubleshooting.html). + +Agentless deployments are only supported in Elastic Serverless and Elastic Cloud environments. This functionality is in beta and is subject to change. Beta features are not subject to the support SLA of official GA features. + + +## Inputs used + +### Event Logs + +{{event "events"}} + +{{fields "events"}} + +### Detection Logs + +{{event "detections"}} + +{{fields "detections"}} diff --git a/packages/neon_cyber/_dev/deploy/docker/docker-compose.yml b/packages/neon_cyber/_dev/deploy/docker/docker-compose.yml new file mode 100644 index 00000000000..6b910f9d077 --- /dev/null +++ b/packages/neon_cyber/_dev/deploy/docker/docker-compose.yml @@ -0,0 +1,14 @@ +services: + neon_cyber: + image: docker.elastic.co/observability/stream:v0.18.0 + hostname: neon_cyber + ports: + - 8080 + volumes: + - ./files:/files:ro + environment: + PORT: 8080 + command: + - http-server + - --addr=:8080 + - --config=/files/config.yml diff --git a/packages/neon_cyber/_dev/deploy/docker/files/config.yml b/packages/neon_cyber/_dev/deploy/docker/files/config.yml new file mode 100644 index 00000000000..48c2bb41f34 --- /dev/null +++ b/packages/neon_cyber/_dev/deploy/docker/files/config.yml @@ -0,0 +1,27 @@ +rules: + - path: /v1/events + methods: ['GET'] + request_headers: + authorization: xxxx + responses: + - status_code: 200 + body: |- + {{ minify_json ` + { + "error": null, + "data": [{"id":"95cf3375-6a70-4366-9a4d-8bb602b0d7c9","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","event_type":"auth","event_timestamp":"2025-10-12T21:39:13.241+00:00","inserted_at":"2025-10-13T18:13:17.312372+00:00","updated_at":"2025-10-13T18:13:17.312372+00:00","agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","description":"User authenticated using userpass for https://www.bluthfamily.biz","url":"https://www.bluthfamily.biz","auth_method":"userpass","email":"barry@bluthfamily.biz","autofill":true}] + } + `}} + - path: /v1/detections + methods: ['GET'] + request_headers: + authorization: xxxx + responses: + - status_code: 200 + body: |- + {{ minify_json ` + { + "error": null, + "data": [{"id":"c24b2526-11e4-48bf-af45-f6837232037f","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","detection_type":"phishing","detection_subtype":null,"detection_timestamp":"2025-10-10T17:09:32.988+00:00","inserted_at":"2025-10-13T18:13:15.88219+00:00","updated_at":"2025-10-13T18:13:15.88219+00:00","source":"Phishing AI","description":null,"tab_id":12345,"url":"https://click.this.link.banckcorp.com","incognito":false,"agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1"}] + } + `}} diff --git a/packages/neon_cyber/changelog.yml b/packages/neon_cyber/changelog.yml new file mode 100644 index 00000000000..a6afa81cfc0 --- /dev/null +++ b/packages/neon_cyber/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "0.1.0" + changes: + - description: Initial version of the package. + type: enhancement + link: https://github.com/elastic/integrations/pull/15725 diff --git a/packages/neon_cyber/data_stream/detections/_dev/test/pipeline/test-detections.log b/packages/neon_cyber/data_stream/detections/_dev/test/pipeline/test-detections.log new file mode 100644 index 00000000000..1eedea6f950 --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/_dev/test/pipeline/test-detections.log @@ -0,0 +1,3 @@ +{"id":"344d53e6-43b4-4cdd-84ad-9421a5f6dc31","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","detection_type":"form","detection_subtype":null,"detection_timestamp":"2025-10-10T17:09:32.988+00:00","inserted_at":"2025-10-13T18:13:16.648002+00:00","updated_at":"2025-10-13T18:13:16.648002+00:00","source":"Compromised Credential","description":null,"tab_id":12345,"url":"https://support.notanapp.com","incognito":false,"agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","action":"/login?","email":"barry@bluthfamily.biz","password":true,"pii":false,"compromised":true,"autofill":null,"catalog_id":null} +{"id":"c24b2526-11e4-48bf-af45-f6837232037f","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","detection_type":"phishing","detection_subtype":null,"detection_timestamp":"2025-10-10T17:09:32.988+00:00","inserted_at":"2025-10-13T18:13:15.88219+00:00","updated_at":"2025-10-13T18:13:15.88219+00:00","source":"Phishing AI","description":null,"tab_id":12345,"url":"https://click.this.link.banckcorp.com","incognito":false,"agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1"} +{"id":"34a32dcf-3e71-4688-8ae6-46376c571bf9","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","detection_type":"download","detection_subtype":null,"detection_timestamp":"2025-10-10T17:09:32.988+00:00","inserted_at":"2025-10-13T18:13:16.149791+00:00","updated_at":"2025-10-13T18:13:16.149791+00:00","source":"Download Incognito","description":null,"tab_id":12345,"url":"https://example.com/docs/support","incognito":true,"agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","filename":"2024_financials.xls","mime":"application/pdf","danger":"SAFE","total_bytes":31337} diff --git a/packages/neon_cyber/data_stream/detections/_dev/test/pipeline/test-detections.log-expected.json b/packages/neon_cyber/data_stream/detections/_dev/test/pipeline/test-detections.log-expected.json new file mode 100644 index 00000000000..0f6c0df4146 --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/_dev/test/pipeline/test-detections.log-expected.json @@ -0,0 +1,242 @@ +{ + "expected": [ + { + "@timestamp": "2025-10-10T17:09:32.988Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "alert", + "original": "{\"id\":\"344d53e6-43b4-4cdd-84ad-9421a5f6dc31\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"detection_type\":\"form\",\"detection_subtype\":null,\"detection_timestamp\":\"2025-10-10T17:09:32.988+00:00\",\"inserted_at\":\"2025-10-13T18:13:16.648002+00:00\",\"updated_at\":\"2025-10-13T18:13:16.648002+00:00\",\"source\":\"Compromised Credential\",\"description\":null,\"tab_id\":12345,\"url\":\"https://support.notanapp.com\",\"incognito\":false,\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\",\"action\":\"/login?\",\"email\":\"barry@bluthfamily.biz\",\"password\":true,\"pii\":false,\"compromised\":true,\"autofill\":null,\"catalog_id\":null}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "detections": { + "action": "/login?", + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "compromised": true, + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "detection_timestamp": "2025-10-10T17:09:32.988Z", + "detection_type": "form", + "display": "Chrome", + "email": "barry@bluthfamily.biz", + "id": "344d53e6-43b4-4cdd-84ad-9421a5f6dc31", + "incognito": false, + "password": true, + "pii": false, + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "source": "Compromised Credential", + "tab_id": 12345, + "url": "https://support.notanapp.com" + } + }, + "url": { + "domain": "support.notanapp.com", + "original": "https://support.notanapp.com", + "scheme": "https" + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + }, + { + "@timestamp": "2025-10-10T17:09:32.988Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "alert", + "original": "{\"id\":\"c24b2526-11e4-48bf-af45-f6837232037f\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"detection_type\":\"phishing\",\"detection_subtype\":null,\"detection_timestamp\":\"2025-10-10T17:09:32.988+00:00\",\"inserted_at\":\"2025-10-13T18:13:15.88219+00:00\",\"updated_at\":\"2025-10-13T18:13:15.88219+00:00\",\"source\":\"Phishing AI\",\"description\":null,\"tab_id\":12345,\"url\":\"https://click.this.link.banckcorp.com\",\"incognito\":false,\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\"}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "detections": { + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "detection_timestamp": "2025-10-10T17:09:32.988Z", + "detection_type": "phishing", + "display": "Chrome", + "id": "c24b2526-11e4-48bf-af45-f6837232037f", + "incognito": false, + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "source": "Phishing AI", + "tab_id": 12345, + "url": "https://click.this.link.banckcorp.com" + } + }, + "url": { + "domain": "click.this.link.banckcorp.com", + "original": "https://click.this.link.banckcorp.com", + "scheme": "https" + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + }, + { + "@timestamp": "2025-10-10T17:09:32.988Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "alert", + "original": "{\"id\":\"34a32dcf-3e71-4688-8ae6-46376c571bf9\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"detection_type\":\"download\",\"detection_subtype\":null,\"detection_timestamp\":\"2025-10-10T17:09:32.988+00:00\",\"inserted_at\":\"2025-10-13T18:13:16.149791+00:00\",\"updated_at\":\"2025-10-13T18:13:16.149791+00:00\",\"source\":\"Download Incognito\",\"description\":null,\"tab_id\":12345,\"url\":\"https://example.com/docs/support\",\"incognito\":true,\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\",\"filename\":\"2024_financials.xls\",\"mime\":\"application/pdf\",\"danger\":\"SAFE\",\"total_bytes\":31337}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "detections": { + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "danger": "SAFE", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "detection_timestamp": "2025-10-10T17:09:32.988Z", + "detection_type": "download", + "display": "Chrome", + "filename": "2024_financials.xls", + "id": "34a32dcf-3e71-4688-8ae6-46376c571bf9", + "incognito": true, + "mime": "application/pdf", + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "source": "Download Incognito", + "tab_id": 12345, + "total_bytes": 31337, + "url": "https://example.com/docs/support" + } + }, + "url": { + "domain": "example.com", + "original": "https://example.com/docs/support", + "path": "/docs/support", + "scheme": "https" + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + } + ] +} diff --git a/packages/neon_cyber/data_stream/detections/_dev/test/policy/test-default.expected b/packages/neon_cyber/data_stream/detections/_dev/test/policy/test-default.expected new file mode 100644 index 00000000000..a627846dcfc --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/_dev/test/policy/test-default.expected @@ -0,0 +1,92 @@ +inputs: + - data_stream: + namespace: ep + meta: + package: + name: neon_cyber + name: test-default-neon_cyber + streams: + - config_version: 2 + data_stream: + dataset: neon_cyber.detections + interval: 1h + program: |- + ( + state.with( + request( + "GET", + state.url.trim_right("/") + "/v1/detections" + ).with( + { + "Header": { + "Authorization": [state.api_token], + } + } + ).do_request().as(resp, (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": dyn( + (has(body.data) && body.data.size() > 0) ? + body.data.map(e, + { + "message": e.encode_json(), + } + ) + : + [] + ) + } + ) + : + { + "events": dyn( + { + "error": { + "code": string(resp.StatusCode), + "id": string(resp.Status), + "message": "GET " + state.url.trim_right("/") + "/v1/detections: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + string(resp.Status) + " (" + string(resp.StatusCode) + ")" + ), + }, + } + ) + } + ) + ) + ) + publisher_pipeline.disable_host: true + redact: + fields: + - api_token + resource.timeout: 30s + resource.tracer: + enabled: false + filename: ../../logs/cel/http-request-trace-*.ndjson + maxbackups: 5 + resource.url: https://api.neoncyber.io + state: + api_token: ${SECRET_0} + tags: + - forwarded + - neon_cyber-detections + type: cel + use_output: default +output_permissions: + default: + _elastic_agent_checks: + cluster: + - monitor + _elastic_agent_monitoring: + indices: [] + uuid-for-permissions-on-related-indices: + indices: + - names: + - logs-neon_cyber.detections-ep + privileges: + - auto_configure + - create_doc +secret_references: + - {} diff --git a/packages/neon_cyber/data_stream/detections/_dev/test/policy/test-default.yml b/packages/neon_cyber/data_stream/detections/_dev/test/policy/test-default.yml new file mode 100644 index 00000000000..07fa3bd166a --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/_dev/test/policy/test-default.yml @@ -0,0 +1,12 @@ +vars: + api_token: test_api_token +data_stream: + vars: + resource_url: http://host.tld + resource_interval: 1m + enable_request_tracer: false + preserve_original_event: false + http_client_timeout: 30s + tags: + - forwarded + - neon_cyber-detections diff --git a/packages/neon_cyber/data_stream/detections/_dev/test/system/test-default-config.yml b/packages/neon_cyber/data_stream/detections/_dev/test/system/test-default-config.yml new file mode 100644 index 00000000000..e333eb01a3c --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/_dev/test/system/test-default-config.yml @@ -0,0 +1,11 @@ +input: cel +service: neon_cyber +vars: + url: http://{{Hostname}}:{{Port}} + api_token: xxxx +data_stream: + vars: + enable_request_tracer: true + preserve_original_event: true +assert: + hit_count: 1 diff --git a/packages/neon_cyber/data_stream/detections/agent/stream/cel.yml.hbs b/packages/neon_cyber/data_stream/detections/agent/stream/cel.yml.hbs new file mode 100644 index 00000000000..efa226430e3 --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/agent/stream/cel.yml.hbs @@ -0,0 +1,85 @@ +config_version: 2 +interval: {{interval}} +resource.tracer: + enabled: {{enable_request_tracer}} + filename: "../../logs/cel/http-request-trace-*.ndjson" + maxbackups: 5 +{{#if ssl}} +resource.ssl: {{ssl}} +{{/if}} +{{#if http_client_timeout}} +resource.timeout: {{http_client_timeout}} +{{/if}} +resource.url: {{url}} +{{#if proxy_url}} +resource.proxy_url: {{proxy_url}} +{{/if}} +state: + api_token: {{api_token}} +redact: + fields: + - api_token +program: |- + ( + state.with( + request( + "GET", + state.url.trim_right("/") + "/v1/detections" + ).with( + { + "Header": { + "Authorization": [state.api_token], + } + } + ).do_request().as(resp, (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": dyn( + (has(body.data) && body.data.size() > 0) ? + body.data.map(e, + { + "message": e.encode_json(), + } + ) + : + [] + ) + } + ) + : + { + "events": dyn( + { + "error": { + "code": string(resp.StatusCode), + "id": string(resp.Status), + "message": "GET " + state.url.trim_right("/") + "/v1/detections: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + string(resp.Status) + " (" + string(resp.StatusCode) + ")" + ), + }, + } + ) + } + ) + ) + ) +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}} diff --git a/packages/neon_cyber/data_stream/detections/elasticsearch/ingest_pipeline/default.yml b/packages/neon_cyber/data_stream/detections/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 00000000000..0879e156126 --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,327 @@ +--- +description: Pipeline for processing Neon detections. +processors: + - set: + field: ecs.version + value: 8.17.0 + tag: set_ecs_version + - terminate: + if: ctx.error?.message != null && ctx.message == null && ctx.event?.original == null + description: error message set and no data to process. + tag: data_collection_error + - set: + field: event.kind + value: alert + tag: set_event_kind + - append: + field: event.category + value: network + tag: append_event_category + - append: + field: event.type + value: info + tag: append_event_type + - rename: + field: message + target_field: event.original + ignore_missing: true + if: ctx.event?.original == null + tag: rename_message_original + - remove: + field: message + ignore_missing: true + if: 'ctx.event?.original != null' + description: 'The `message` field is no longer required if the document has an `event.original` field.' + tag: remove_field_message + - remove: + field: + - organization + - division + - team + ignore_missing: true + if: ctx.organization instanceof String && ctx.division instanceof String && ctx.team instanceof String + description: >- + Removes the fields added by Agentless as metadata, + as they can collide with ECS fields. + tag: remove_agentless_fields + - json: + field: event.original + target_field: json + tag: json_parse_original + - fingerprint: + fields: + - json.inserted_at + - json.updated_at + - json.id + target_field: _id + tag: fingerprint_id_field + - date: + field: json.detection_timestamp + target_field: neon_cyber.detections.detection_timestamp + tag: date_detection_timestamp + formats: + - ISO8601 + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - date: + field: json.detection_timestamp + target_field: '@timestamp' + tag: date_timestamp + formats: + - ISO8601 + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - rename: + field: json.id + target_field: neon_cyber.detections.id + tag: rename_detection_id + - rename: + field: json.deployment_id + target_field: neon_cyber.detections.deployment_id + tag: rename_deployment_id + - rename: + field: json.client_id + target_field: neon_cyber.detections.client_id + tag: rename_client_id + - rename: + field: json.registration_id + target_field: neon_cyber.detections.registration_id + tag: rename_registration_id + - rename: + field: json.detection_type + target_field: neon_cyber.detections.detection_type + tag: rename_detection_type + - rename: + field: json.detection_subtype + target_field: neon_cyber.detections.detection_subtype + ignore_missing: true + tag: rename_detection_subtype + - rename: + field: json.source + target_field: neon_cyber.detections.source + ignore_missing: true + tag: rename_detection_source + - rename: + field: json.agent + target_field: neon_cyber.detections.agent + ignore_missing: true + tag: rename_neon_agent + - rename: + field: json.description + target_field: neon_cyber.detections.description + ignore_missing: true + tag: rename_detection_description + - rename: + field: json.url + target_field: neon_cyber.detections.url + ignore_missing: true + tag: rename_detection_url + - uri_parts: + field: neon_cyber.detections.url + ignore_missing: true + tag: uri_parts_detections_url + - rename: + field: json.filename + target_field: neon_cyber.detections.filename + ignore_missing: true + tag: rename_detection_filename + - rename: + field: json.mime + target_field: neon_cyber.detections.mime + ignore_missing: true + tag: rename_detection_mime + - rename: + field: json.incognito + target_field: neon_cyber.detections.incognito + ignore_missing: true + tag: rename_detection_incognito + - rename: + field: json.referrer + target_field: neon_cyber.detections.referrer + ignore_missing: true + tag: rename_detection_referrer + - rename: + field: json.danger + target_field: neon_cyber.detections.danger + ignore_missing: true + tag: rename_detection_danger + - rename: + field: json.total_bytes + target_field: neon_cyber.detections.total_bytes + ignore_missing: true + tag: rename_detection_total_bytes + - rename: + field: json.action + target_field: neon_cyber.detections.action + ignore_missing: true + tag: rename_detection_action + - rename: + field: json.email + target_field: neon_cyber.detections.email + ignore_missing: true + tag: rename_detection_email + - rename: + field: json.password + target_field: neon_cyber.detections.password + ignore_missing: true + tag: rename_detection_password + - rename: + field: json.pii + target_field: neon_cyber.detections.pii + ignore_missing: true + tag: rename_detection_pii + - rename: + field: json.compromised + target_field: neon_cyber.detections.compromised + ignore_missing: true + tag: rename_detection_compromised + - rename: + field: json.tab_id + target_field: neon_cyber.detections.tab_id + ignore_missing: true + tag: rename_detection_tab_id + - rename: + field: json.autofill + target_field: neon_cyber.detections.autofill + ignore_missing: true + tag: rename_detection_autofill + - rename: + field: json.catalog_id + target_field: neon_cyber.detections.catalog_id + ignore_missing: true + tag: rename_detection_catalog_id + - rename: + field: json.arch + target_field: host.architecture + ignore_missing: true + tag: rename_host_architecture + - rename: + field: json.os + target_field: host.os.platform + ignore_missing: true + tag: rename_host_os_platform + - rename: + field: json.latitude + target_field: host.geo.location.lat + ignore_missing: true + tag: rename_host_geo_lat + - rename: + field: json.longitude + target_field: host.geo.location.lon + ignore_missing: true + tag: rename_host_geo_lon + - rename: + field: json.ip + target_field: client.nat.ip + ignore_missing: true + tag: rename_client_nat_ip + - rename: + field: json.ip_latitude + target_field: client.geo.location.lat + ignore_missing: true + tag: rename_client_geo_lat + - rename: + field: json.ip_longitude + target_field: client.geo.location.lon + ignore_missing: true + tag: rename_client_geo_lon + - rename: + field: json.city + target_field: client.geo.city_name + ignore_missing: true + tag: rename_client_city_name + - rename: + field: json.country + target_field: client.geo.country_name + ignore_missing: true + tag: rename_client_country + - rename: + field: json.postal_code + target_field: client.geo.postal_code + ignore_missing: true + tag: rename_client_postal_code + - rename: + field: json.region_code + target_field: client.geo.region_iso_code + ignore_missing: true + tag: rename_client_iso_code + - rename: + field: json.region_name + target_field: client.geo.region_name + ignore_missing: true + tag: rename_client_region_name + - rename: + field: json.asn + target_field: client.as.number + ignore_missing: true + tag: rename_client_as_number + - rename: + field: json.asn_isp + target_field: client.as.organization.name + ignore_missing: true + tag: rename_client_as_organization + - rename: + field: json.name + target_field: user_agent.name + ignore_missing: true + tag: rename_user_agent_name + - rename: + field: json.version + target_field: user_agent.version + ignore_missing: true + tag: rename_user_agent_version + - rename: + field: json.ua + target_field: user_agent.original + ignore_missing: true + tag: rename_user_agent_original + - rename: + field: json.display + target_field: neon_cyber.detections.display + ignore_missing: true + tag: rename_detections_display + - remove: + field: json.detection_timestamp + tag: remove_detection_timestamp + - remove: + field: json.inserted_at + tag: remove_inserted_at + - remove: + field: json.updated_at + tag: remove_updated_at + - script: + tag: drop_nulls + description: Drops null/empty values recursively. + lang: painless + source: | + boolean dropEmptyFields(Object object) { + if (object == null || object == '') { + return true; + } else if (object instanceof Map) { + ((Map) object).values().removeIf(value -> dropEmptyFields(value)); + return (((Map) object).size() == 0); + } else if (object instanceof List) { + ((List) object).removeIf(value -> dropEmptyFields(value)); + return (((List) object).length == 0); + } + return false; + } + dropEmptyFields(ctx); +on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + tag: append_error_message + - set: + field: event.kind + value: pipeline_error + tag: set_pipeline_error_to_event_kind + - append: + field: tags + value: preserve_original_event + allow_duplicates: false + tag: append_tags diff --git a/packages/neon_cyber/data_stream/detections/fields/base-fields.yml b/packages/neon_cyber/data_stream/detections/fields/base-fields.yml new file mode 100644 index 00000000000..89cf0e4691a --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/fields/base-fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + external: ecs +- name: data_stream.dataset + external: ecs +- name: data_stream.namespace + external: ecs +- name: event.module + type: constant_keyword + external: ecs + value: neon_cyber +- name: event.dataset + type: constant_keyword + external: ecs + value: neon_cyber.detections +- name: '@timestamp' + external: ecs diff --git a/packages/neon_cyber/data_stream/detections/fields/beats.yml b/packages/neon_cyber/data_stream/detections/fields/beats.yml new file mode 100644 index 00000000000..4084f1dc7f5 --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/fields/beats.yml @@ -0,0 +1,6 @@ +- name: input.type + type: keyword + description: Type of filebeat input. +- name: log.offset + type: long + description: Log offset. diff --git a/packages/neon_cyber/data_stream/detections/fields/ecs.yml b/packages/neon_cyber/data_stream/detections/fields/ecs.yml new file mode 100644 index 00000000000..32b642ce16c --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/fields/ecs.yml @@ -0,0 +1,2 @@ +- external: ecs + name: ecs.version diff --git a/packages/neon_cyber/data_stream/detections/fields/fields.yml b/packages/neon_cyber/data_stream/detections/fields/fields.yml new file mode 100644 index 00000000000..f6eceb8d191 --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/fields/fields.yml @@ -0,0 +1,135 @@ +- name: neon_cyber + type: group + fields: + - name: detections + type: group + fields: + - name: id + type: keyword + description: Unique id of the event. + - name: deployment_id + type: keyword + description: The deployment id of the user. + - name: client_id + type: keyword + description: The clients unique id. + - name: registration_id + type: keyword + description: The browsers unique registration id. + - name: detection_type + type: keyword + description: The Neon specific detection type. + - name: detection_subtype + type: keyword + description: The Neon specific detection subtype. + - name: detection_timestamp + type: date + description: The timestamp of the detection. + - name: source + type: keyword + description: The detection source. + - name: description + type: keyword + description: The description of the detection. + - name: url + type: keyword + description: The page url of the tab that triggered the detection. + - name: filename + type: keyword + description: The filename of the file that triggered the detection. + - name: mime + type: keyword + description: The mime type of the file that triggered the detection. + - name: incognito + type: boolean + description: Was the browser in incognito mode when the detection triggered. + - name: referrer + type: keyword + description: The referrer of the url that triggered the detection. + - name: danger + type: keyword + description: The safe-browsing danger level of the downloaded file. + - name: total_bytes + type: long + description: The size of the downloaded file. + - name: action + type: keyword + description: The action of the form. + - name: email + type: keyword + description: The email address used in the form. + - name: password + type: boolean + description: A password was entered into the form. + - name: pii + type: boolean + description: PII was detected in the submitted form. + - name: compromised + type: boolean + description: Is the password compromised. + - name: tab_id + type: long + description: The tab id that triggered the detection. + - name: autofill + type: boolean + description: Was the password autofilled into the form. + - name: catalog_id + type: keyword + description: The catalog id of the target SaaS app. + - name: agent + type: keyword + description: The neon agent version. + - name: arch + type: keyword + description: The device architecture. + - name: display + type: keyword + description: The display name of the browser vendor. + - name: name + type: keyword + description: The short name of the browser vendor. + - name: os + type: keyword + description: The operating system of the device. + - name: ua + type: keyword + description: The User-Agent of the browser. + - name: version + type: keyword + description: The version of the browser. + - name: latitude + type: float + description: The browser-reported latitude of the device. + - name: longitude + type: float + description: The browser-reported longitude of the device. + - name: ip + type: ip + description: The egress ip address of the device. + - name: ip_latitude + type: float + description: The geo-ip latitude of the egress ip. + - name: ip_longitude + type: float + description: The geo-ip longitude of the egress ip. + - name: asn + type: long + description: The ASN of the egress ip. + - name: asn_isp + type: keyword + description: The ISP owner of the ASN. + - name: city + type: keyword + description: The geo-ip city of the egress ip. + - name: country + type: keyword + description: The geo-ip country code of the egress ip. + - name: postal_code + type: keyword + description: The geo-ip postal code of the egress ip. + - name: region_code + type: keyword + description: The geo-ip region or state code of the egress ip. + - name: region_name + type: keyword + description: The geo-ip region or state of the egress ip. diff --git a/packages/neon_cyber/data_stream/detections/manifest.yml b/packages/neon_cyber/data_stream/detections/manifest.yml new file mode 100644 index 00000000000..a7ab0d8de2e --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/manifest.yml @@ -0,0 +1,46 @@ +title: 'Neon Cyber Detections' +type: logs +streams: + - input: cel + title: 'Collect Neon Cyber Detections' + description: |- + Collect workforce detections from the Neon Cyber Platform + template_path: cel.yml.hbs + vars: + - name: interval + type: text + title: 'Detection Endpoint Interval' + description: |- + How often the API is polled, supports seconds, minutes and hours. + required: true + show_user: true + default: 1h + - name: enable_request_tracer + type: bool + title: Enable request tracing + default: false + multi: false + required: false + show_user: false + description: The request tracer logs requests and responses to the agent's local file-system for debugging configurations. Enabling this request tracing compromises security and should only be used for debugging. See [documentation](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-cel.html#_resource_tracer_filename) for details. + - name: tags + type: text + title: 'Tags' + multi: true + show_user: false + default: + - forwarded + - neon_cyber-detections + - name: preserve_original_event + required: true + show_user: true + title: Preserve original event + description: Preserves a raw copy of the original event, added to the field `event.original`. + type: bool + multi: false + default: false + - name: processors + type: yaml + title: 'Processors' + description: |- + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. diff --git a/packages/neon_cyber/data_stream/detections/sample_event.json b/packages/neon_cyber/data_stream/detections/sample_event.json new file mode 100644 index 00000000000..f2ef475e1dd --- /dev/null +++ b/packages/neon_cyber/data_stream/detections/sample_event.json @@ -0,0 +1,104 @@ +{ + "@timestamp": "2025-10-10T17:09:32.988Z", + "agent": { + "ephemeral_id": "0ea008fb-25c6-4e96-a0cb-580156905c33", + "id": "b328b57b-9887-4a4a-a714-81cc1c317559", + "name": "elastic-agent-75127", + "type": "filebeat", + "version": "8.17.0" + }, + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "data_stream": { + "dataset": "neon_cyber.detections", + "namespace": "11517", + "type": "logs" + }, + "ecs": { + "version": "8.17.0" + }, + "elastic_agent": { + "id": "b328b57b-9887-4a4a-a714-81cc1c317559", + "snapshot": false, + "version": "8.17.0" + }, + "event": { + "agent_id_status": "verified", + "category": [ + "network" + ], + "dataset": "neon_cyber.detections", + "ingested": "2025-11-06T04:11:02Z", + "kind": "alert", + "original": "{\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"country\":\"GB\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"description\":null,\"detection_subtype\":null,\"detection_timestamp\":\"2025-10-10T17:09:32.988+00:00\",\"detection_type\":\"phishing\",\"display\":\"Chrome\",\"id\":\"c24b2526-11e4-48bf-af45-f6837232037f\",\"incognito\":false,\"inserted_at\":\"2025-10-13T18:13:15.88219+00:00\",\"ip\":\"192.0.2.1\",\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"latitude\":11.1111,\"longitude\":-0.111,\"name\":\"chrome\",\"os\":\"linux\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"source\":\"Phishing AI\",\"tab_id\":12345,\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"updated_at\":\"2025-10-13T18:13:15.88219+00:00\",\"url\":\"https://click.this.link.banckcorp.com\",\"version\":\"134.0.0.0\"}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "input": { + "type": "cel" + }, + "neon_cyber": { + "detections": { + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "detection_timestamp": "2025-10-10T17:09:32.988Z", + "detection_type": "phishing", + "display": "Chrome", + "id": "c24b2526-11e4-48bf-af45-f6837232037f", + "incognito": false, + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "source": "Phishing AI", + "tab_id": 12345, + "url": "https://click.this.link.banckcorp.com" + } + }, + "tags": [ + "preserve_original_event", + "forwarded", + "neon_cyber-detections" + ], + "url": { + "domain": "click.this.link.banckcorp.com", + "original": "https://click.this.link.banckcorp.com", + "scheme": "https" + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } +} diff --git a/packages/neon_cyber/data_stream/events/_dev/test/pipeline/test-events.log b/packages/neon_cyber/data_stream/events/_dev/test/pipeline/test-events.log new file mode 100644 index 00000000000..ef5e9bc9b2e --- /dev/null +++ b/packages/neon_cyber/data_stream/events/_dev/test/pipeline/test-events.log @@ -0,0 +1,6 @@ +{"id":"67739497-055a-4ead-ac18-6af8482b93ff","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"3fcbb274-4dbb-4d77-b1e7-7336fcd3a609","registration_id":"25249c89-542d-4c59-b3f5-e455aeba0a54","event_type":"geo","event_timestamp":"2025-09-30T19:24:27.909+00:00","inserted_at":"2025-09-30T19:24:29.837364+00:00","updated_at":"2025-09-30T19:24:29.837364+00:00","agent":"1.2.25","arch":"x86-64","display":"Chrome","name":"chrome","os":"win","ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","version":"140.0.0.0","latitude":11.1111,"longitude":-0.111,"ip":"192.0.2.1","ip_latitude":11.1111,"ip_longitude":-0.111,"asn":7922,"asn_isp":"COMCAST-7922","city":"Portland","country":"US","postal_code":"97214","region_code":"OR","region_name":"Oregon","tab_id":null,"url":null,"frame_id":null,"download_id":null,"filename":null,"mime":null,"incognito":null,"referrer":null,"danger":null,"total_bytes":null} +{"id":"5e5bf010-8ef5-4908-b888-7f63dcb3eb27","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"3c52367d-f07f-437d-b0c6-32185f1b5a9a","registration_id":"e8b92afe-b218-4041-bdd5-7835d92c768b","event_type":"platform","event_timestamp":"2025-10-22T01:33:59.106+00:00","inserted_at":"2025-10-22T01:33:59.245716+00:00","updated_at":"2025-10-22T01:33:59.245716+00:00","agent":"1.2.25","arch":"arm64","display":"Chrome","name":"chrome","os":"mac","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36","version":"141.0.0.0","latitude":0,"longitude":0,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":7018,"asn_isp":"ATT-INTERNET4","city":"North Richland Hills","country":"US","postal_code":"76182","region_code":"TX","region_name":"Texas","ip":"192.0.2.1","description":"User browser is Chrome version 141.0.0.0 on mac","extensions":[{"id":"ghbmnnjooekpmoecnnnilnnbdlolhkhi","name":"Google Docs Offline","enabled":true,"description":"Edit, create, and view your documents, spreadsheets, and presentations — all without internet access.","homepageUrl":"https://chromewebstore.google.com/detail/ghbmnnjooekpmoecnnnilnnbdlolhkhi","installType":"sideload","permissions":["alarms","offscreen","storage","unlimitedStorage"],"hostPermissions":["https://docs.google.com/*","https://drive.google.com/*"]}]} +{"id":"95cf3375-6a70-4366-9a4d-8bb602b0d7c9","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","event_type":"auth","event_timestamp":"2025-10-12T21:39:13.241+00:00","inserted_at":"2025-10-13T18:13:17.312372+00:00","updated_at":"2025-10-13T18:13:17.312372+00:00","agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","description":"User authenticated using userpass for https://www.bluthfamily.biz","url":"https://www.bluthfamily.biz","auth_method":"userpass","email":"barry@bluthfamily.biz","autofill":true} +{"id":"166754fd-3bd8-4327-8aff-c0df354fce19","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","event_type":"app","event_timestamp":"2025-10-12T19:21:29.802+00:00","inserted_at":"2025-10-13T18:13:17.312372+00:00","updated_at":"2025-10-13T18:13:17.312372+00:00","agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","description":"User used Qualtrics for 5939 seconds between Sun Oct 12 2025 and Sun Oct 12 2025","catalog_id":"e47cd523-1f40-47c7-8e9d-0ed82d0bb4a3","catalog_name":"Qualtrics","domains":"qualtrics.com","start_timestamp":"2025-10-12T23:15:08.713+00:00","end_timestamp":"2025-10-13T00:15:08.713+00:00","cumulative":5939,"login":true,"mfa":false} +{"id":"1451b06b-3623-4421-baab-c7769a13947e","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","event_type":"upload","event_timestamp":"2025-10-12T19:49:24.693+00:00","inserted_at":"2025-10-13T18:13:17.312372+00:00","updated_at":"2025-10-13T18:13:17.312372+00:00","agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","description":"User uploaded hr_instructions.pdf to https://example.com","url":"https://example.com","tab_id":null,"filename":"hr_instructions.pdf","mime":"application/pdf","incognito":null,"filehash":"9801739daae44ec5293d4e1f53d3f4d2d426d91c","referrer":null,"total_bytes":31337} +{"id":"d63da2a5-fec8-41fc-8da1-11d8e7fa072e","deployment_id":"ec080215-913c-490c-bb81-a1baa311ee45","client_id":"d19143bd-3a34-4c7e-886b-87f643df4835","registration_id":"a00db187-ad55-4074-8a84-d085555abe29","event_type":"download","event_timestamp":"2025-10-12T15:09:39.669+00:00","inserted_at":"2025-10-13T18:13:17.312372+00:00","updated_at":"2025-10-13T18:13:17.312372+00:00","agent":"1.2.4","arch":"arm64","display":"Chrome","name":"chrome","os":"linux","ua":"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","version":"134.0.0.0","latitude":11.1111,"longitude":-0.111,"ip_latitude":11.1111,"ip_longitude":-0.111,"asn":9105,"asn_isp":"TalkTalk","city":"Brighton","country":"GB","postal_code":"BN3","region_code":"BNH","region_name":"Brighton and Hove","ip":"192.0.2.1","description":"User downloaded 2024_financials.xls from https://example.com","url":"https://example.com","tab_id":null,"download_id":31337,"filename":"2024_financials.xls","mime":"application/pdf","incognito":false,"referrer":"https://mail.google.com/open","danger":"SAFE","total_bytes":31337} diff --git a/packages/neon_cyber/data_stream/events/_dev/test/pipeline/test-events.log-expected.json b/packages/neon_cyber/data_stream/events/_dev/test/pipeline/test-events.log-expected.json new file mode 100644 index 00000000000..b3efcd11ffc --- /dev/null +++ b/packages/neon_cyber/data_stream/events/_dev/test/pipeline/test-events.log-expected.json @@ -0,0 +1,456 @@ +{ + "expected": [ + { + "@timestamp": "2025-09-30T19:24:27.909Z", + "client": { + "as": { + "number": 7922, + "organization": { + "name": "COMCAST-7922" + } + }, + "geo": { + "city_name": "Portland", + "country_name": "US", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "97214", + "region_iso_code": "OR", + "region_name": "Oregon" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "event", + "original": "{\"id\":\"67739497-055a-4ead-ac18-6af8482b93ff\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"3fcbb274-4dbb-4d77-b1e7-7336fcd3a609\",\"registration_id\":\"25249c89-542d-4c59-b3f5-e455aeba0a54\",\"event_type\":\"geo\",\"event_timestamp\":\"2025-09-30T19:24:27.909+00:00\",\"inserted_at\":\"2025-09-30T19:24:29.837364+00:00\",\"updated_at\":\"2025-09-30T19:24:29.837364+00:00\",\"agent\":\"1.2.25\",\"arch\":\"x86-64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"win\",\"ua\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36\",\"version\":\"140.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip\":\"192.0.2.1\",\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":7922,\"asn_isp\":\"COMCAST-7922\",\"city\":\"Portland\",\"country\":\"US\",\"postal_code\":\"97214\",\"region_code\":\"OR\",\"region_name\":\"Oregon\",\"tab_id\":null,\"url\":null,\"frame_id\":null,\"download_id\":null,\"filename\":null,\"mime\":null,\"incognito\":null,\"referrer\":null,\"danger\":null,\"total_bytes\":null}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "x86-64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "win" + } + }, + "neon_cyber": { + "events": { + "agent": "1.2.25", + "client_id": "3fcbb274-4dbb-4d77-b1e7-7336fcd3a609", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "display": "Chrome", + "event_timestamp": "2025-09-30T19:24:27.909Z", + "event_type": "geo", + "id": "67739497-055a-4ead-ac18-6af8482b93ff", + "registration_id": "25249c89-542d-4c59-b3f5-e455aeba0a54" + } + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36", + "version": "140.0.0.0" + } + }, + { + "@timestamp": "2025-10-22T01:33:59.106Z", + "client": { + "as": { + "number": 7018, + "organization": { + "name": "ATT-INTERNET4" + } + }, + "geo": { + "city_name": "North Richland Hills", + "country_name": "US", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "76182", + "region_iso_code": "TX", + "region_name": "Texas" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "event", + "original": "{\"id\":\"5e5bf010-8ef5-4908-b888-7f63dcb3eb27\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"3c52367d-f07f-437d-b0c6-32185f1b5a9a\",\"registration_id\":\"e8b92afe-b218-4041-bdd5-7835d92c768b\",\"event_type\":\"platform\",\"event_timestamp\":\"2025-10-22T01:33:59.106+00:00\",\"inserted_at\":\"2025-10-22T01:33:59.245716+00:00\",\"updated_at\":\"2025-10-22T01:33:59.245716+00:00\",\"agent\":\"1.2.25\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"mac\",\"ua\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36\",\"version\":\"141.0.0.0\",\"latitude\":0,\"longitude\":0,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":7018,\"asn_isp\":\"ATT-INTERNET4\",\"city\":\"North Richland Hills\",\"country\":\"US\",\"postal_code\":\"76182\",\"region_code\":\"TX\",\"region_name\":\"Texas\",\"ip\":\"192.0.2.1\",\"description\":\"User browser is Chrome version 141.0.0.0 on mac\",\"extensions\":[{\"id\":\"ghbmnnjooekpmoecnnnilnnbdlolhkhi\",\"name\":\"Google Docs Offline\",\"enabled\":true,\"description\":\"Edit, create, and view your documents, spreadsheets, and presentations — all without internet access.\",\"homepageUrl\":\"https://chromewebstore.google.com/detail/ghbmnnjooekpmoecnnnilnnbdlolhkhi\",\"installType\":\"sideload\",\"permissions\":[\"alarms\",\"offscreen\",\"storage\",\"unlimitedStorage\"],\"hostPermissions\":[\"https://docs.google.com/*\",\"https://drive.google.com/*\"]}]}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 0, + "lon": 0 + } + }, + "os": { + "platform": "mac" + } + }, + "neon_cyber": { + "events": { + "agent": "1.2.25", + "client_id": "3c52367d-f07f-437d-b0c6-32185f1b5a9a", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User browser is Chrome version 141.0.0.0 on mac", + "display": "Chrome", + "event_timestamp": "2025-10-22T01:33:59.106Z", + "event_type": "platform", + "extensions": [ + { + "description": "Edit, create, and view your documents, spreadsheets, and presentations — all without internet access.", + "enabled": true, + "homepageUrl": "https://chromewebstore.google.com/detail/ghbmnnjooekpmoecnnnilnnbdlolhkhi", + "hostPermissions": [ + "https://docs.google.com/*", + "https://drive.google.com/*" + ], + "id": "ghbmnnjooekpmoecnnnilnnbdlolhkhi", + "installType": "sideload", + "name": "Google Docs Offline", + "permissions": [ + "alarms", + "offscreen", + "storage", + "unlimitedStorage" + ] + } + ], + "id": "5e5bf010-8ef5-4908-b888-7f63dcb3eb27", + "registration_id": "e8b92afe-b218-4041-bdd5-7835d92c768b" + } + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", + "version": "141.0.0.0" + } + }, + { + "@timestamp": "2025-10-12T21:39:13.241Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "event", + "original": "{\"id\":\"95cf3375-6a70-4366-9a4d-8bb602b0d7c9\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"event_type\":\"auth\",\"event_timestamp\":\"2025-10-12T21:39:13.241+00:00\",\"inserted_at\":\"2025-10-13T18:13:17.312372+00:00\",\"updated_at\":\"2025-10-13T18:13:17.312372+00:00\",\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\",\"description\":\"User authenticated using userpass for https://www.bluthfamily.biz\",\"url\":\"https://www.bluthfamily.biz\",\"auth_method\":\"userpass\",\"email\":\"barry@bluthfamily.biz\",\"autofill\":true}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "events": { + "agent": "1.2.4", + "auth_method": "userpass", + "autofill": true, + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User authenticated using userpass for https://www.bluthfamily.biz", + "display": "Chrome", + "email": "barry@bluthfamily.biz", + "event_timestamp": "2025-10-12T21:39:13.241Z", + "event_type": "auth", + "id": "95cf3375-6a70-4366-9a4d-8bb602b0d7c9", + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "url": "https://www.bluthfamily.biz" + } + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + }, + { + "@timestamp": "2025-10-12T19:21:29.802Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "event", + "original": "{\"id\":\"166754fd-3bd8-4327-8aff-c0df354fce19\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"event_type\":\"app\",\"event_timestamp\":\"2025-10-12T19:21:29.802+00:00\",\"inserted_at\":\"2025-10-13T18:13:17.312372+00:00\",\"updated_at\":\"2025-10-13T18:13:17.312372+00:00\",\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\",\"description\":\"User used Qualtrics for 5939 seconds between Sun Oct 12 2025 and Sun Oct 12 2025\",\"catalog_id\":\"e47cd523-1f40-47c7-8e9d-0ed82d0bb4a3\",\"catalog_name\":\"Qualtrics\",\"domains\":\"qualtrics.com\",\"start_timestamp\":\"2025-10-12T23:15:08.713+00:00\",\"end_timestamp\":\"2025-10-13T00:15:08.713+00:00\",\"cumulative\":5939,\"login\":true,\"mfa\":false}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "events": { + "agent": "1.2.4", + "catalog_id": "e47cd523-1f40-47c7-8e9d-0ed82d0bb4a3", + "catalog_name": "Qualtrics", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "cumulative": 5939, + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User used Qualtrics for 5939 seconds between Sun Oct 12 2025 and Sun Oct 12 2025", + "display": "Chrome", + "domains": "qualtrics.com", + "end_timestamp": "2025-10-13T00:15:08.713Z", + "event_timestamp": "2025-10-12T19:21:29.802Z", + "event_type": "app", + "id": "166754fd-3bd8-4327-8aff-c0df354fce19", + "login": true, + "mfa": false, + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "start_timestamp": "2025-10-12T23:15:08.713Z" + } + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + }, + { + "@timestamp": "2025-10-12T19:49:24.693Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "event", + "original": "{\"id\":\"1451b06b-3623-4421-baab-c7769a13947e\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"event_type\":\"upload\",\"event_timestamp\":\"2025-10-12T19:49:24.693+00:00\",\"inserted_at\":\"2025-10-13T18:13:17.312372+00:00\",\"updated_at\":\"2025-10-13T18:13:17.312372+00:00\",\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\",\"description\":\"User uploaded hr_instructions.pdf to https://example.com\",\"url\":\"https://example.com\",\"tab_id\":null,\"filename\":\"hr_instructions.pdf\",\"mime\":\"application/pdf\",\"incognito\":null,\"filehash\":\"9801739daae44ec5293d4e1f53d3f4d2d426d91c\",\"referrer\":null,\"total_bytes\":31337}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "events": { + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User uploaded hr_instructions.pdf to https://example.com", + "display": "Chrome", + "event_timestamp": "2025-10-12T19:49:24.693Z", + "event_type": "upload", + "filehash": "9801739daae44ec5293d4e1f53d3f4d2d426d91c", + "filename": "hr_instructions.pdf", + "id": "1451b06b-3623-4421-baab-c7769a13947e", + "mime": "application/pdf", + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "total_bytes": 31337, + "url": "https://example.com" + } + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + }, + { + "@timestamp": "2025-10-12T15:09:39.669Z", + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "ecs": { + "version": "8.17.0" + }, + "event": { + "category": [ + "network" + ], + "kind": "event", + "original": "{\"id\":\"d63da2a5-fec8-41fc-8da1-11d8e7fa072e\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"event_type\":\"download\",\"event_timestamp\":\"2025-10-12T15:09:39.669+00:00\",\"inserted_at\":\"2025-10-13T18:13:17.312372+00:00\",\"updated_at\":\"2025-10-13T18:13:17.312372+00:00\",\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"display\":\"Chrome\",\"name\":\"chrome\",\"os\":\"linux\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"version\":\"134.0.0.0\",\"latitude\":11.1111,\"longitude\":-0.111,\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"country\":\"GB\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"ip\":\"192.0.2.1\",\"description\":\"User downloaded 2024_financials.xls from https://example.com\",\"url\":\"https://example.com\",\"tab_id\":null,\"download_id\":31337,\"filename\":\"2024_financials.xls\",\"mime\":\"application/pdf\",\"incognito\":false,\"referrer\":\"https://mail.google.com/open\",\"danger\":\"SAFE\",\"total_bytes\":31337}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "neon_cyber": { + "events": { + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "danger": "SAFE", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User downloaded 2024_financials.xls from https://example.com", + "display": "Chrome", + "download_id": 31337, + "event_timestamp": "2025-10-12T15:09:39.669Z", + "event_type": "download", + "filename": "2024_financials.xls", + "id": "d63da2a5-fec8-41fc-8da1-11d8e7fa072e", + "incognito": false, + "mime": "application/pdf", + "referrer": "https://mail.google.com/open", + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "total_bytes": 31337, + "url": "https://example.com" + } + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } + } + ] +} diff --git a/packages/neon_cyber/data_stream/events/_dev/test/policy/test-default.expected b/packages/neon_cyber/data_stream/events/_dev/test/policy/test-default.expected new file mode 100644 index 00000000000..a01327d93f4 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/_dev/test/policy/test-default.expected @@ -0,0 +1,92 @@ +inputs: + - data_stream: + namespace: ep + meta: + package: + name: neon_cyber + name: test-default-neon_cyber + streams: + - config_version: 2 + data_stream: + dataset: neon_cyber.events + interval: 1h + program: |- + ( + state.with( + request( + "GET", + state.url.trim_right("/") + "/v1/events" + ).with( + { + "Header": { + "Authorization": [state.api_token], + } + } + ).do_request().as(resp, (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": dyn( + (has(body.data) && body.data.size() > 0) ? + body.data.map(e, + { + "message": e.encode_json(), + } + ) + : + [] + ) + } + ) + : + { + "events": dyn( + { + "error": { + "code": string(resp.StatusCode), + "id": string(resp.Status), + "message": "GET " + state.url.trim_right("/") + "/v1/events: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + string(resp.Status) + " (" + string(resp.StatusCode) + ")" + ), + }, + } + ) + } + ) + ) + ) + publisher_pipeline.disable_host: true + redact: + fields: + - api_token + resource.timeout: 30s + resource.tracer: + enabled: false + filename: ../../logs/cel/http-request-trace-*.ndjson + maxbackups: 5 + resource.url: https://api.neoncyber.io + state: + api_token: ${SECRET_0} + tags: + - forwarded + - neon_cyber-events + type: cel + use_output: default +output_permissions: + default: + _elastic_agent_checks: + cluster: + - monitor + _elastic_agent_monitoring: + indices: [] + uuid-for-permissions-on-related-indices: + indices: + - names: + - logs-neon_cyber.events-ep + privileges: + - auto_configure + - create_doc +secret_references: + - {} diff --git a/packages/neon_cyber/data_stream/events/_dev/test/policy/test-default.yml b/packages/neon_cyber/data_stream/events/_dev/test/policy/test-default.yml new file mode 100644 index 00000000000..1ef84cf6f17 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/_dev/test/policy/test-default.yml @@ -0,0 +1,12 @@ +vars: + api_token: test_api_token +data_stream: + vars: + resource_url: http://host.tld + resource_interval: 1m + enable_request_tracer: false + preserve_original_event: false + http_client_timeout: 30s + tags: + - forwarded + - neon_cyber-events diff --git a/packages/neon_cyber/data_stream/events/_dev/test/system/test-default-config.yml b/packages/neon_cyber/data_stream/events/_dev/test/system/test-default-config.yml new file mode 100644 index 00000000000..e333eb01a3c --- /dev/null +++ b/packages/neon_cyber/data_stream/events/_dev/test/system/test-default-config.yml @@ -0,0 +1,11 @@ +input: cel +service: neon_cyber +vars: + url: http://{{Hostname}}:{{Port}} + api_token: xxxx +data_stream: + vars: + enable_request_tracer: true + preserve_original_event: true +assert: + hit_count: 1 diff --git a/packages/neon_cyber/data_stream/events/agent/stream/cel.yml.hbs b/packages/neon_cyber/data_stream/events/agent/stream/cel.yml.hbs new file mode 100644 index 00000000000..54cb70b0ac2 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/agent/stream/cel.yml.hbs @@ -0,0 +1,85 @@ +config_version: 2 +interval: {{interval}} +resource.tracer: + enabled: {{enable_request_tracer}} + filename: "../../logs/cel/http-request-trace-*.ndjson" + maxbackups: 5 +{{#if ssl}} +resource.ssl: {{ssl}} +{{/if}} +{{#if http_client_timeout}} +resource.timeout: {{http_client_timeout}} +{{/if}} +resource.url: {{url}} +{{#if proxy_url}} +resource.proxy_url: {{proxy_url}} +{{/if}} +state: + api_token: {{api_token}} +redact: + fields: + - api_token +program: |- + ( + state.with( + request( + "GET", + state.url.trim_right("/") + "/v1/events" + ).with( + { + "Header": { + "Authorization": [state.api_token], + } + } + ).do_request().as(resp, (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + { + "events": dyn( + (has(body.data) && body.data.size() > 0) ? + body.data.map(e, + { + "message": e.encode_json(), + } + ) + : + [] + ) + } + ) + : + { + "events": dyn( + { + "error": { + "code": string(resp.StatusCode), + "id": string(resp.Status), + "message": "GET " + state.url.trim_right("/") + "/v1/events: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + string(resp.Status) + " (" + string(resp.StatusCode) + ")" + ), + }, + } + ) + } + ) + ) + ) +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}} diff --git a/packages/neon_cyber/data_stream/events/elasticsearch/ingest_pipeline/default.yml b/packages/neon_cyber/data_stream/events/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 00000000000..38d6d60e6b2 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,410 @@ +--- +description: Pipeline for processing Neon events. +processors: + - set: + field: ecs.version + value: 8.17.0 + tag: set_ecs_version + - terminate: + if: ctx.error?.message != null && ctx.message == null && ctx.event?.original == null + description: error message set and no data to process. + tag: data_collection_error + - set: + field: event.kind + value: event + tag: set_event_kind + - append: + field: event.category + value: network + tag: append_event_category + - append: + field: event.type + value: info + tag: append_event_type + - rename: + field: message + target_field: event.original + ignore_missing: true + if: ctx.event?.original == null + tag: rename_message_original + - remove: + field: message + ignore_missing: true + if: 'ctx.event?.original != null' + description: 'The `message` field is no longer required if the document has an `event.original` field.' + tag: remove_field_message + - remove: + field: + - organization + - division + - team + ignore_missing: true + if: ctx.organization instanceof String && ctx.division instanceof String && ctx.team instanceof String + description: >- + Removes the fields added by Agentless as metadata, + as they can collide with ECS fields. + tag: remove_agentless_fields + - json: + field: event.original + target_field: json + tag: json_parse_original + - fingerprint: + fields: + - json.inserted_at + - json.updated_at + - json.id + target_field: _id + tag: fingerprint_id_field + - date: + field: json.event_timestamp + target_field: neon_cyber.events.event_timestamp + tag: date_event_timestamp + formats: + - ISO8601 + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - date: + field: json.event_timestamp + target_field: '@timestamp' + tag: date_event_timestamp + formats: + - ISO8601 + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - rename: + field: json.id + target_field: neon_cyber.events.id + tag: rename_events_id + - rename: + field: json.deployment_id + target_field: neon_cyber.events.deployment_id + tag: rename_deployment_id + - rename: + field: json.client_id + target_field: neon_cyber.events.client_id + tag: rename_client_id + - rename: + field: json.registration_id + target_field: neon_cyber.events.registration_id + tag: rename_registration_id + - rename: + field: json.event_type + target_field: neon_cyber.events.event_type + tag: rename_event_type + - rename: + field: json.arch + target_field: host.architecture + ignore_missing: true + tag: rename_host_architecture + - rename: + field: json.os + target_field: host.os.platform + ignore_missing: true + tag: rename_host_os_platform + - rename: + field: json.latitude + target_field: host.geo.location.lat + ignore_missing: true + tag: rename_host_geo_lat + - rename: + field: json.longitude + target_field: host.geo.location.lon + ignore_missing: true + tag: rename_host_geo_lon + - rename: + field: json.ip + target_field: client.nat.ip + ignore_missing: true + tag: rename_client_nat_ip + - rename: + field: json.ip_latitude + target_field: client.geo.location.lat + ignore_missing: true + tag: rename_client_geo_lat + - rename: + field: json.ip_longitude + target_field: client.geo.location.lon + ignore_missing: true + tag: rename_client_geo_lon + - rename: + field: json.city + target_field: client.geo.city_name + ignore_missing: true + tag: rename_client_city_name + - rename: + field: json.country + target_field: client.geo.country_name + ignore_missing: true + tag: rename_client_country + - rename: + field: json.postal_code + target_field: client.geo.postal_code + ignore_missing: true + tag: rename_client_postal_code + - rename: + field: json.region_code + target_field: client.geo.region_iso_code + ignore_missing: true + tag: rename_client_iso_code + - rename: + field: json.region_name + target_field: client.geo.region_name + ignore_missing: true + tag: rename_client_region_name + - rename: + field: json.asn + target_field: client.as.number + ignore_missing: true + tag: rename_client_as_number + - rename: + field: json.asn_isp + target_field: client.as.organization.name + ignore_missing: true + tag: rename_client_as_organization + - rename: + field: json.name + target_field: user_agent.name + ignore_missing: true + tag: rename_user_agent_name + - rename: + field: json.version + target_field: user_agent.version + ignore_missing: true + tag: rename_user_agent_version + - rename: + field: json.ua + target_field: user_agent.original + ignore_missing: true + tag: rename_user_agent_original + - rename: + field: json.url + target_field: neon_cyber.events.url + ignore_missing: true + tag: rename_events_url + - uri_parts: + field: neon_cyber.detections.url + ignore_missing: true + tag: uri_parts_detections_url + - rename: + field: json.agent + target_field: neon_cyber.events.agent + ignore_missing: true + tag: rename_neon_agent + - rename: + field: json.display + target_field: neon_cyber.events.display + ignore_missing: true + tag: rename_events_display + - rename: + field: json.tab_id + target_field: neon_cyber.events.tab_id + ignore_missing: true + tag: rename_events_tab_id + - rename: + field: json.frame_id + target_field: neon_cyber.events.frame_id + ignore_missing: true + tag: rename_events_frame_id + - rename: + field: json.parent_frame_id + target_field: neon_cyber.events.parent_frame_id + ignore_missing: true + tag: rename_events_parent_frame_id + - rename: + field: json.download_id + target_field: neon_cyber.events.download_id + ignore_missing: true + tag: rename_events_download_id + - rename: + field: json.filename + target_field: neon_cyber.events.filename + ignore_missing: true + tag: rename_events_filename + - rename: + field: json.mime + target_field: neon_cyber.events.mime + ignore_missing: true + tag: rename_events_mime + - rename: + field: json.incognito + target_field: neon_cyber.events.incognito + ignore_missing: true + tag: rename_events_incognito + - rename: + field: json.referrer + target_field: neon_cyber.events.referrer + ignore_missing: true + tag: rename_events_referrer + - rename: + field: json.danger + target_field: neon_cyber.events.danger + ignore_missing: true + tag: rename_events_danger + - rename: + field: json.total_bytes + target_field: neon_cyber.events.total_bytes + ignore_missing: true + tag: rename_events_total_bytes + - rename: + field: json.description + target_field: neon_cyber.events.description + ignore_missing: true + tag: rename_events_description + - rename: + field: json.catalog_id + target_field: neon_cyber.events.catalog_id + ignore_missing: true + tag: rename_events_catalog_id + - rename: + field: json.catalog_name + target_field: neon_cyber.events.catalog_name + ignore_missing: true + tag: rename_events_catalog_name + - rename: + field: json.domains + target_field: neon_cyber.events.domains + ignore_missing: true + tag: rename_events_domains + - date: + field: json.start_timestamp + target_field: neon_cyber.events.start_timestamp + formats: + - ISO8601 + if: ctx.json?.start_timestamp != null + tag: date_events_start_timestamp + - date: + field: json.end_timestamp + target_field: neon_cyber.events.end_timestamp + formats: + - ISO8601 + if: ctx.json?.end_timestamp != null + tag: date_events_end_timestamp + - rename: + field: json.cumulative + target_field: neon_cyber.events.cumulative + ignore_missing: true + tag: rename_events_cumulative + - rename: + field: json.auth_method + target_field: neon_cyber.events.auth_method + ignore_missing: true + tag: rename_events_auth_method + - rename: + field: json.login + target_field: neon_cyber.events.login + ignore_missing: true + tag: rename_events_login + - rename: + field: json.mfa + target_field: neon_cyber.events.mfa + ignore_missing: true + tag: rename_events_mfa + - rename: + field: json.email + target_field: neon_cyber.events.email + ignore_missing: true + tag: rename_events_email + - rename: + field: json.autofill + target_field: neon_cyber.events.autofill + ignore_missing: true + tag: rename_events_autofill + - rename: + field: json.filehash + target_field: neon_cyber.events.filehash + ignore_missing: true + tag: rename_events_filehash + - rename: + field: json.extensions + target_field: neon_cyber.events.extensions + if: ctx.json.extensions != null + ignore_failure: true + tag: rename_events_extensions + - rename: + field: json.ext_id + target_field: neon_cyber.events.ext_id + ignore_missing: true + tag: rename_events_ext_id + - rename: + field: json.ext_name + target_field: neon_cyber.events.ext_name + ignore_missing: true + tag: rename_events_ext_name + - rename: + field: json.ext_enabled + target_field: neon_cyber.events.ext_enabled + ignore_missing: true + tag: rename_events_ext_enabled + - rename: + field: json.ext_description + target_field: neon_cyber.events.ext_description + ignore_missing: true + tag: rename_events_ext_description + - rename: + field: json.ext_install_type + target_field: neon_cyber.events.ext_install_type + ignore_missing: true + tag: rename_events_ext_install_type + - rename: + field: json.ext_host_permissions + target_field: neon_cyber.events.ext_host_permissions + ignore_missing: true + tag: rename_events_ext_host_permissions + - rename: + field: json.ext_permissions + target_field: neon_cyber.events.ext_permissions + ignore_missing: true + tag: rename_events_ext_permissions + - remove: + field: json.event_timestamp + tag: remove_event_timestamp + - remove: + field: json.inserted_at + tag: remove_inserted_at + - remove: + field: json.updated_at + tag: remove_updated_at + - remove: + field: json.start_timestamp + if: ctx.json?.start_timestamp != null + tag: remove_start_timestamp + - remove: + field: json.end_timestamp + if: ctx.json?.end_timestamp != null + tag: remove_ent_timestamp + - script: + tag: drop_nulls + description: Drops null/empty values recursively. + lang: painless + source: | + boolean dropEmptyFields(Object object) { + if (object == null || object == '') { + return true; + } else if (object instanceof Map) { + ((Map) object).values().removeIf(value -> dropEmptyFields(value)); + return (((Map) object).size() == 0); + } else if (object instanceof List) { + ((List) object).removeIf(value -> dropEmptyFields(value)); + return (((List) object).length == 0); + } + return false; + } + dropEmptyFields(ctx); +on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + tag: append_error_message + - set: + field: event.kind + value: pipeline_error + tag: set_pipeline_error_to_event_kind + - append: + field: tags + value: preserve_original_event + allow_duplicates: false + tag: append_tags diff --git a/packages/neon_cyber/data_stream/events/fields/base-fields.yml b/packages/neon_cyber/data_stream/events/fields/base-fields.yml new file mode 100644 index 00000000000..466ebecd28f --- /dev/null +++ b/packages/neon_cyber/data_stream/events/fields/base-fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + external: ecs +- name: data_stream.dataset + external: ecs +- name: data_stream.namespace + external: ecs +- name: event.module + type: constant_keyword + external: ecs + value: neon_cyber +- name: event.dataset + type: constant_keyword + external: ecs + value: neon_cyber.events +- name: '@timestamp' + external: ecs diff --git a/packages/neon_cyber/data_stream/events/fields/beats.yml b/packages/neon_cyber/data_stream/events/fields/beats.yml new file mode 100644 index 00000000000..4084f1dc7f5 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/fields/beats.yml @@ -0,0 +1,6 @@ +- name: input.type + type: keyword + description: Type of filebeat input. +- name: log.offset + type: long + description: Log offset. diff --git a/packages/neon_cyber/data_stream/events/fields/ecs.yml b/packages/neon_cyber/data_stream/events/fields/ecs.yml new file mode 100644 index 00000000000..32b642ce16c --- /dev/null +++ b/packages/neon_cyber/data_stream/events/fields/ecs.yml @@ -0,0 +1,2 @@ +- external: ecs + name: ecs.version diff --git a/packages/neon_cyber/data_stream/events/fields/fields.yml b/packages/neon_cyber/data_stream/events/fields/fields.yml new file mode 100644 index 00000000000..7e578f0d442 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/fields/fields.yml @@ -0,0 +1,201 @@ +- name: neon_cyber + type: group + fields: + - name: events + type: group + fields: + - name: id + type: keyword + description: Unique id of the event. + - name: deployment_id + type: keyword + description: The deployment id of the user. + - name: client_id + type: keyword + description: The clients unique id. + - name: registration_id + type: keyword + description: The browsers unique registration id. + - name: event_type + type: keyword + description: The Neon specific event type. + - name: event_timestamp + type: date + description: The timestamp of the event. + - name: agent + type: keyword + description: The version of the Neon agent. + - name: arch + type: keyword + description: The device architecture. + - name: display + type: keyword + description: The display name of the browser vendor. + - name: name + type: keyword + description: The short name of the browser vendor. + - name: os + type: keyword + description: The operating system of the device. + - name: ua + type: keyword + description: The User-Agent of the browser. + - name: version + type: keyword + description: The version of the browser. + - name: latitude + type: float + description: The browser-reported latitude of the device. + - name: longitude + type: float + description: The browser-reported longitude of the device. + - name: ip + type: ip + description: The egress ip address of the device. + - name: ip_latitude + type: float + description: The geo-ip latitude of the egress ip. + - name: ip_longitude + type: float + description: The geo-ip longitude of the egress ip. + - name: asn + type: long + description: The ASN of the egress ip. + - name: asn_isp + type: keyword + description: The ISP owner of the ASN. + - name: city + type: keyword + description: The geo-ip city of the egress ip. + - name: country + type: keyword + description: The geo-ip country code of the egress ip. + - name: postal_code + type: keyword + description: The geo-ip postal code of the egress ip. + - name: region_code + type: keyword + description: The geo-ip region or state code of the egress ip. + - name: region_name + type: keyword + description: The geo-ip region or state of the egress ip. + - name: tab_id + type: long + description: The tab id of the browser tab that triggered the event. + - name: url + type: keyword + description: The page url of the tab that triggered the event. + - name: frame_id + type: long + description: The frame id of the browser tab that triggered the event. + - name: parent_frame_id + type: long + description: The parent frame id that triggered the event. + - name: download_id + type: long + description: The download id of the browser tab that triggered the download event. + - name: filename + type: keyword + description: The file name of the download event. + - name: mime + type: keyword + description: The file mime type of the download event. + - name: incognito + type: boolean + description: Was the browser in incognito mode when the event triggered. + - name: referrer + type: keyword + description: The referrer of the page that triggered the event. + - name: danger + type: keyword + description: The safe browsing classification of the download event. + - name: total_bytes + type: long + description: The file size of the downloaded file. + - name: description + type: keyword + description: The description of the event. + - name: catalog_id + type: keyword + description: The SaaS app catalog id when the event triggered if applicable. + - name: catalog_name + type: keyword + description: The SaaS app name when the event triggered if applicable. + - name: domains + type: keyword + description: The domains associated with the event. + - name: start_timestamp + type: date + description: The start timestamp of the application usage. + - name: end_timestamp + type: date + description: The end timestamp of the application usage. + - name: cumulative + type: long + description: The total time spent using the application in seconds. + - name: auth_method + type: keyword + description: The method of authentication. + - name: login + type: boolean + description: Was an account login present during the authentication event. + - name: mfa + type: boolean + description: Was mfa used during the authentication event. + - name: email + type: keyword + description: The email associated with the authentication event. + - name: autofill + type: boolean + description: Was autofill used to authenticate. + - name: filehash + type: keyword + description: The file has of the uploaded file. + - name: extensions + type: nested + fields: + - name: id + type: keyword + description: The id of the installed extension. + - name: name + type: keyword + description: The name of the installed extension. + - name: enabled + type: boolean + description: Is the installed extension enabled. + - name: description + type: keyword + description: The description of the installed extension. + - name: homepageUrl + type: keyword + description: The homepage of the installed extension. + - name: installType + type: keyword + description: The install type of the installed extension. + - name: hostPermissions + type: keyword + description: The install type of the installed extension. + - name: permissions + type: keyword + description: The install type of the installed extension. + - name: ext_id + type: keyword + description: The extension id of the installed extension. + - name: ext_name + type: keyword + description: The extension name of the installed extension. + - name: ext_enabled + type: boolean + description: Is the extensions enabled in the browser. + - name: ext_description + type: keyword + description: The description of the installed extension. + - name: ext_install_type + type: keyword + description: The way the extension was installed. + - name: ext_host_permissions + type: keyword + description: The extensions requested host permissions. + - name: ext_permissions + type: keyword + description: The extensions requested permissions. diff --git a/packages/neon_cyber/data_stream/events/manifest.yml b/packages/neon_cyber/data_stream/events/manifest.yml new file mode 100644 index 00000000000..0f6c8c22a29 --- /dev/null +++ b/packages/neon_cyber/data_stream/events/manifest.yml @@ -0,0 +1,46 @@ +title: 'Neon Cyber Events' +type: logs +streams: + - input: cel + title: 'Collect Neon Cyber Events' + description: |- + Collect workforce events from the Neon Cyber Platform + template_path: cel.yml.hbs + vars: + - name: interval + type: text + title: 'Events Endpoint Interval' + description: |- + How often the API is polled, supports seconds, minutes and hours. + required: true + show_user: true + default: 1h + - name: enable_request_tracer + type: bool + title: Enable request tracing + default: false + multi: false + required: false + show_user: false + description: The request tracer logs requests and responses to the agent's local file-system for debugging configurations. Enabling this request tracing compromises security and should only be used for debugging. See [documentation](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-cel.html#_resource_tracer_filename) for details. + - name: tags + type: text + title: 'Tags' + multi: true + show_user: false + default: + - forwarded + - neon_cyber-events + - name: preserve_original_event + required: true + show_user: true + title: Preserve original event + description: Preserves a raw copy of the original event, added to the field `event.original`. + type: bool + multi: false + default: false + - name: processors + type: yaml + title: 'Processors' + description: |- + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. diff --git a/packages/neon_cyber/data_stream/events/sample_event.json b/packages/neon_cyber/data_stream/events/sample_event.json new file mode 100644 index 00000000000..a8a12ac901f --- /dev/null +++ b/packages/neon_cyber/data_stream/events/sample_event.json @@ -0,0 +1,100 @@ +{ + "@timestamp": "2025-10-12T21:39:13.241Z", + "agent": { + "ephemeral_id": "4557466d-fe9d-488d-a8e8-2598d68ac9e8", + "id": "9ccd0f38-920a-4eb6-ab60-4eb6163b537c", + "name": "elastic-agent-78481", + "type": "filebeat", + "version": "8.17.0" + }, + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "data_stream": { + "dataset": "neon_cyber.events", + "namespace": "67591", + "type": "logs" + }, + "ecs": { + "version": "8.17.0" + }, + "elastic_agent": { + "id": "9ccd0f38-920a-4eb6-ab60-4eb6163b537c", + "snapshot": false, + "version": "8.17.0" + }, + "event": { + "agent_id_status": "verified", + "category": [ + "network" + ], + "dataset": "neon_cyber.events", + "ingested": "2025-11-06T04:12:07Z", + "kind": "event", + "original": "{\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"auth_method\":\"userpass\",\"autofill\":true,\"city\":\"Brighton\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"country\":\"GB\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"description\":\"User authenticated using userpass for https://www.bluthfamily.biz\",\"display\":\"Chrome\",\"email\":\"barry@bluthfamily.biz\",\"event_timestamp\":\"2025-10-12T21:39:13.241+00:00\",\"event_type\":\"auth\",\"id\":\"95cf3375-6a70-4366-9a4d-8bb602b0d7c9\",\"inserted_at\":\"2025-10-13T18:13:17.312372+00:00\",\"ip\":\"192.0.2.1\",\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"latitude\":11.1111,\"longitude\":-0.111,\"name\":\"chrome\",\"os\":\"linux\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"updated_at\":\"2025-10-13T18:13:17.312372+00:00\",\"url\":\"https://www.bluthfamily.biz\",\"version\":\"134.0.0.0\"}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "input": { + "type": "cel" + }, + "neon_cyber": { + "events": { + "agent": "1.2.4", + "auth_method": "userpass", + "autofill": true, + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User authenticated using userpass for https://www.bluthfamily.biz", + "display": "Chrome", + "email": "barry@bluthfamily.biz", + "event_timestamp": "2025-10-12T21:39:13.241Z", + "event_type": "auth", + "id": "95cf3375-6a70-4366-9a4d-8bb602b0d7c9", + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "url": "https://www.bluthfamily.biz" + } + }, + "tags": [ + "preserve_original_event", + "forwarded", + "neon_cyber-events" + ], + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } +} diff --git a/packages/neon_cyber/docs/README.md b/packages/neon_cyber/docs/README.md new file mode 100644 index 00000000000..0ae9939898d --- /dev/null +++ b/packages/neon_cyber/docs/README.md @@ -0,0 +1,387 @@ +# Neon Cyber Integration for Elastic + +## Overview + +The [Neon Cyber](https://www.neoncyber.com) integration for Elastic enables collection of workforce events and cybersecurity detections from the Neon [API](https://api.neoncyber.io/v1/docs]) + +## What data does this integration collect? + +The Neon Cyber integration collects log messages of the following types: +* Events including geo, navigation, auth, app, extensions, and platform +* Detections including compromised credentials, phishing, malware, and more + +### What do I need to use this integration? + +This integration requires you to generate a developer API key from the account settings of your Neon Cyber instance. + +## How do I deploy this integration? + +### Agent-based deployment + +Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](docs-content://reference/fleet/install-elastic-agents.md). You can install only one Elastic Agent per host. + +Elastic Agent is required to stream data from the syslog or log file receiver and ship the data to Elastic, where the events will then be processed via the integration's ingest pipelines. + +### Agentless Enabled Integration + +Agentless integrations allow you to collect data without having to manage Elastic Agent in your cloud. They make manual agent deployment unnecessary, so you can focus on your data instead of the agent that collects it. For more information, refer to [Agentless integrations](https://www.elastic.co/guide/en/serverless/current/security-agentless-integrations.html) and the [Agentless integrations FAQ](https://www.elastic.co/guide/en/serverless/current/agentless-integration-troubleshooting.html). + +Agentless deployments are only supported in Elastic Serverless and Elastic Cloud environments. This functionality is in beta and is subject to change. Beta features are not subject to the support SLA of official GA features. + + +## Inputs used + +### Event Logs + +An example event for `events` looks as following: + +```json +{ + "@timestamp": "2025-10-12T21:39:13.241Z", + "agent": { + "ephemeral_id": "4557466d-fe9d-488d-a8e8-2598d68ac9e8", + "id": "9ccd0f38-920a-4eb6-ab60-4eb6163b537c", + "name": "elastic-agent-78481", + "type": "filebeat", + "version": "8.17.0" + }, + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "data_stream": { + "dataset": "neon_cyber.events", + "namespace": "67591", + "type": "logs" + }, + "ecs": { + "version": "8.17.0" + }, + "elastic_agent": { + "id": "9ccd0f38-920a-4eb6-ab60-4eb6163b537c", + "snapshot": false, + "version": "8.17.0" + }, + "event": { + "agent_id_status": "verified", + "category": [ + "network" + ], + "dataset": "neon_cyber.events", + "ingested": "2025-11-06T04:12:07Z", + "kind": "event", + "original": "{\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"auth_method\":\"userpass\",\"autofill\":true,\"city\":\"Brighton\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"country\":\"GB\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"description\":\"User authenticated using userpass for https://www.bluthfamily.biz\",\"display\":\"Chrome\",\"email\":\"barry@bluthfamily.biz\",\"event_timestamp\":\"2025-10-12T21:39:13.241+00:00\",\"event_type\":\"auth\",\"id\":\"95cf3375-6a70-4366-9a4d-8bb602b0d7c9\",\"inserted_at\":\"2025-10-13T18:13:17.312372+00:00\",\"ip\":\"192.0.2.1\",\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"latitude\":11.1111,\"longitude\":-0.111,\"name\":\"chrome\",\"os\":\"linux\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"updated_at\":\"2025-10-13T18:13:17.312372+00:00\",\"url\":\"https://www.bluthfamily.biz\",\"version\":\"134.0.0.0\"}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "input": { + "type": "cel" + }, + "neon_cyber": { + "events": { + "agent": "1.2.4", + "auth_method": "userpass", + "autofill": true, + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "description": "User authenticated using userpass for https://www.bluthfamily.biz", + "display": "Chrome", + "email": "barry@bluthfamily.biz", + "event_timestamp": "2025-10-12T21:39:13.241Z", + "event_type": "auth", + "id": "95cf3375-6a70-4366-9a4d-8bb602b0d7c9", + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "url": "https://www.bluthfamily.biz" + } + }, + "tags": [ + "preserve_original_event", + "forwarded", + "neon_cyber-events" + ], + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } +} +``` + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| input.type | Type of filebeat input. | keyword | +| log.offset | Log offset. | long | +| neon_cyber.events.agent | The version of the Neon agent. | keyword | +| neon_cyber.events.arch | The device architecture. | keyword | +| neon_cyber.events.asn | The ASN of the egress ip. | long | +| neon_cyber.events.asn_isp | The ISP owner of the ASN. | keyword | +| neon_cyber.events.auth_method | The method of authentication. | keyword | +| neon_cyber.events.autofill | Was autofill used to authenticate. | boolean | +| neon_cyber.events.catalog_id | The SaaS app catalog id when the event triggered if applicable. | keyword | +| neon_cyber.events.catalog_name | The SaaS app name when the event triggered if applicable. | keyword | +| neon_cyber.events.city | The geo-ip city of the egress ip. | keyword | +| neon_cyber.events.client_id | The clients unique id. | keyword | +| neon_cyber.events.country | The geo-ip country code of the egress ip. | keyword | +| neon_cyber.events.cumulative | The total time spent using the application in seconds. | long | +| neon_cyber.events.danger | The safe browsing classification of the download event. | keyword | +| neon_cyber.events.deployment_id | The deployment id of the user. | keyword | +| neon_cyber.events.description | The description of the event. | keyword | +| neon_cyber.events.display | The display name of the browser vendor. | keyword | +| neon_cyber.events.domains | The domains associated with the event. | keyword | +| neon_cyber.events.download_id | The download id of the browser tab that triggered the download event. | long | +| neon_cyber.events.email | The email associated with the authentication event. | keyword | +| neon_cyber.events.end_timestamp | The end timestamp of the application usage. | date | +| neon_cyber.events.event_timestamp | The timestamp of the event. | date | +| neon_cyber.events.event_type | The Neon specific event type. | keyword | +| neon_cyber.events.ext_description | The description of the installed extension. | keyword | +| neon_cyber.events.ext_enabled | Is the extensions enabled in the browser. | boolean | +| neon_cyber.events.ext_host_permissions | The extensions requested host permissions. | keyword | +| neon_cyber.events.ext_id | The extension id of the installed extension. | keyword | +| neon_cyber.events.ext_install_type | The way the extension was installed. | keyword | +| neon_cyber.events.ext_name | The extension name of the installed extension. | keyword | +| neon_cyber.events.ext_permissions | The extensions requested permissions. | keyword | +| neon_cyber.events.extensions.description | The description of the installed extension. | keyword | +| neon_cyber.events.extensions.enabled | Is the installed extension enabled. | boolean | +| neon_cyber.events.extensions.homepageUrl | The homepage of the installed extension. | keyword | +| neon_cyber.events.extensions.hostPermissions | The install type of the installed extension. | keyword | +| neon_cyber.events.extensions.id | The id of the installed extension. | keyword | +| neon_cyber.events.extensions.installType | The install type of the installed extension. | keyword | +| neon_cyber.events.extensions.name | The name of the installed extension. | keyword | +| neon_cyber.events.extensions.permissions | The install type of the installed extension. | keyword | +| neon_cyber.events.filehash | The file has of the uploaded file. | keyword | +| neon_cyber.events.filename | The file name of the download event. | keyword | +| neon_cyber.events.frame_id | The frame id of the browser tab that triggered the event. | long | +| neon_cyber.events.id | Unique id of the event. | keyword | +| neon_cyber.events.incognito | Was the browser in incognito mode when the event triggered. | boolean | +| neon_cyber.events.ip | The egress ip address of the device. | ip | +| neon_cyber.events.ip_latitude | The geo-ip latitude of the egress ip. | float | +| neon_cyber.events.ip_longitude | The geo-ip longitude of the egress ip. | float | +| neon_cyber.events.latitude | The browser-reported latitude of the device. | float | +| neon_cyber.events.login | Was an account login present during the authentication event. | boolean | +| neon_cyber.events.longitude | The browser-reported longitude of the device. | float | +| neon_cyber.events.mfa | Was mfa used during the authentication event. | boolean | +| neon_cyber.events.mime | The file mime type of the download event. | keyword | +| neon_cyber.events.name | The short name of the browser vendor. | keyword | +| neon_cyber.events.os | The operating system of the device. | keyword | +| neon_cyber.events.parent_frame_id | The parent frame id that triggered the event. | long | +| neon_cyber.events.postal_code | The geo-ip postal code of the egress ip. | keyword | +| neon_cyber.events.referrer | The referrer of the page that triggered the event. | keyword | +| neon_cyber.events.region_code | The geo-ip region or state code of the egress ip. | keyword | +| neon_cyber.events.region_name | The geo-ip region or state of the egress ip. | keyword | +| neon_cyber.events.registration_id | The browsers unique registration id. | keyword | +| neon_cyber.events.start_timestamp | The start timestamp of the application usage. | date | +| neon_cyber.events.tab_id | The tab id of the browser tab that triggered the event. | long | +| neon_cyber.events.total_bytes | The file size of the downloaded file. | long | +| neon_cyber.events.ua | The User-Agent of the browser. | keyword | +| neon_cyber.events.url | The page url of the tab that triggered the event. | keyword | +| neon_cyber.events.version | The version of the browser. | keyword | + + +### Detection Logs + +An example event for `detections` looks as following: + +```json +{ + "@timestamp": "2025-10-10T17:09:32.988Z", + "agent": { + "ephemeral_id": "0ea008fb-25c6-4e96-a0cb-580156905c33", + "id": "b328b57b-9887-4a4a-a714-81cc1c317559", + "name": "elastic-agent-75127", + "type": "filebeat", + "version": "8.17.0" + }, + "client": { + "as": { + "number": 9105, + "organization": { + "name": "TalkTalk" + } + }, + "geo": { + "city_name": "Brighton", + "country_name": "GB", + "location": { + "lat": 11.1111, + "lon": -0.111 + }, + "postal_code": "BN3", + "region_iso_code": "BNH", + "region_name": "Brighton and Hove" + }, + "nat": { + "ip": "192.0.2.1" + } + }, + "data_stream": { + "dataset": "neon_cyber.detections", + "namespace": "11517", + "type": "logs" + }, + "ecs": { + "version": "8.17.0" + }, + "elastic_agent": { + "id": "b328b57b-9887-4a4a-a714-81cc1c317559", + "snapshot": false, + "version": "8.17.0" + }, + "event": { + "agent_id_status": "verified", + "category": [ + "network" + ], + "dataset": "neon_cyber.detections", + "ingested": "2025-11-06T04:11:02Z", + "kind": "alert", + "original": "{\"agent\":\"1.2.4\",\"arch\":\"arm64\",\"asn\":9105,\"asn_isp\":\"TalkTalk\",\"city\":\"Brighton\",\"client_id\":\"d19143bd-3a34-4c7e-886b-87f643df4835\",\"country\":\"GB\",\"deployment_id\":\"ec080215-913c-490c-bb81-a1baa311ee45\",\"description\":null,\"detection_subtype\":null,\"detection_timestamp\":\"2025-10-10T17:09:32.988+00:00\",\"detection_type\":\"phishing\",\"display\":\"Chrome\",\"id\":\"c24b2526-11e4-48bf-af45-f6837232037f\",\"incognito\":false,\"inserted_at\":\"2025-10-13T18:13:15.88219+00:00\",\"ip\":\"192.0.2.1\",\"ip_latitude\":11.1111,\"ip_longitude\":-0.111,\"latitude\":11.1111,\"longitude\":-0.111,\"name\":\"chrome\",\"os\":\"linux\",\"postal_code\":\"BN3\",\"region_code\":\"BNH\",\"region_name\":\"Brighton and Hove\",\"registration_id\":\"a00db187-ad55-4074-8a84-d085555abe29\",\"source\":\"Phishing AI\",\"tab_id\":12345,\"ua\":\"Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\",\"updated_at\":\"2025-10-13T18:13:15.88219+00:00\",\"url\":\"https://click.this.link.banckcorp.com\",\"version\":\"134.0.0.0\"}", + "type": [ + "info" + ] + }, + "host": { + "architecture": "arm64", + "geo": { + "location": { + "lat": 11.1111, + "lon": -0.111 + } + }, + "os": { + "platform": "linux" + } + }, + "input": { + "type": "cel" + }, + "neon_cyber": { + "detections": { + "agent": "1.2.4", + "client_id": "d19143bd-3a34-4c7e-886b-87f643df4835", + "deployment_id": "ec080215-913c-490c-bb81-a1baa311ee45", + "detection_timestamp": "2025-10-10T17:09:32.988Z", + "detection_type": "phishing", + "display": "Chrome", + "id": "c24b2526-11e4-48bf-af45-f6837232037f", + "incognito": false, + "registration_id": "a00db187-ad55-4074-8a84-d085555abe29", + "source": "Phishing AI", + "tab_id": 12345, + "url": "https://click.this.link.banckcorp.com" + } + }, + "tags": [ + "preserve_original_event", + "forwarded", + "neon_cyber-detections" + ], + "url": { + "domain": "click.this.link.banckcorp.com", + "original": "https://click.this.link.banckcorp.com", + "scheme": "https" + }, + "user_agent": { + "name": "chrome", + "original": "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", + "version": "134.0.0.0" + } +} +``` + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| input.type | Type of filebeat input. | keyword | +| log.offset | Log offset. | long | +| neon_cyber.detections.action | The action of the form. | keyword | +| neon_cyber.detections.agent | The neon agent version. | keyword | +| neon_cyber.detections.arch | The device architecture. | keyword | +| neon_cyber.detections.asn | The ASN of the egress ip. | long | +| neon_cyber.detections.asn_isp | The ISP owner of the ASN. | keyword | +| neon_cyber.detections.autofill | Was the password autofilled into the form. | boolean | +| neon_cyber.detections.catalog_id | The catalog id of the target SaaS app. | keyword | +| neon_cyber.detections.city | The geo-ip city of the egress ip. | keyword | +| neon_cyber.detections.client_id | The clients unique id. | keyword | +| neon_cyber.detections.compromised | Is the password compromised. | boolean | +| neon_cyber.detections.country | The geo-ip country code of the egress ip. | keyword | +| neon_cyber.detections.danger | The safe-browsing danger level of the downloaded file. | keyword | +| neon_cyber.detections.deployment_id | The deployment id of the user. | keyword | +| neon_cyber.detections.description | The description of the detection. | keyword | +| neon_cyber.detections.detection_subtype | The Neon specific detection subtype. | keyword | +| neon_cyber.detections.detection_timestamp | The timestamp of the detection. | date | +| neon_cyber.detections.detection_type | The Neon specific detection type. | keyword | +| neon_cyber.detections.display | The display name of the browser vendor. | keyword | +| neon_cyber.detections.email | The email address used in the form. | keyword | +| neon_cyber.detections.filename | The filename of the file that triggered the detection. | keyword | +| neon_cyber.detections.id | Unique id of the event. | keyword | +| neon_cyber.detections.incognito | Was the browser in incognito mode when the detection triggered. | boolean | +| neon_cyber.detections.ip | The egress ip address of the device. | ip | +| neon_cyber.detections.ip_latitude | The geo-ip latitude of the egress ip. | float | +| neon_cyber.detections.ip_longitude | The geo-ip longitude of the egress ip. | float | +| neon_cyber.detections.latitude | The browser-reported latitude of the device. | float | +| neon_cyber.detections.longitude | The browser-reported longitude of the device. | float | +| neon_cyber.detections.mime | The mime type of the file that triggered the detection. | keyword | +| neon_cyber.detections.name | The short name of the browser vendor. | keyword | +| neon_cyber.detections.os | The operating system of the device. | keyword | +| neon_cyber.detections.password | A password was entered into the form. | boolean | +| neon_cyber.detections.pii | PII was detected in the submitted form. | boolean | +| neon_cyber.detections.postal_code | The geo-ip postal code of the egress ip. | keyword | +| neon_cyber.detections.referrer | The referrer of the url that triggered the detection. | keyword | +| neon_cyber.detections.region_code | The geo-ip region or state code of the egress ip. | keyword | +| neon_cyber.detections.region_name | The geo-ip region or state of the egress ip. | keyword | +| neon_cyber.detections.registration_id | The browsers unique registration id. | keyword | +| neon_cyber.detections.source | The detection source. | keyword | +| neon_cyber.detections.tab_id | The tab id that triggered the detection. | long | +| neon_cyber.detections.total_bytes | The size of the downloaded file. | long | +| neon_cyber.detections.ua | The User-Agent of the browser. | keyword | +| neon_cyber.detections.url | The page url of the tab that triggered the detection. | keyword | +| neon_cyber.detections.version | The version of the browser. | keyword | + diff --git a/packages/neon_cyber/img/neoncyber-logo.svg b/packages/neon_cyber/img/neoncyber-logo.svg new file mode 100644 index 00000000000..2d8cd4aba06 --- /dev/null +++ b/packages/neon_cyber/img/neoncyber-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/neon_cyber/img/neoncyber-screenshot.png b/packages/neon_cyber/img/neoncyber-screenshot.png new file mode 100644 index 00000000000..5c7457827dd Binary files /dev/null and b/packages/neon_cyber/img/neoncyber-screenshot.png differ diff --git a/packages/neon_cyber/manifest.yml b/packages/neon_cyber/manifest.yml new file mode 100644 index 00000000000..a2553e950d6 --- /dev/null +++ b/packages/neon_cyber/manifest.yml @@ -0,0 +1,84 @@ +format_version: 3.5.0 +name: neon_cyber +title: 'Neon Cyber' +version: 0.1.0 +source: + license: 'Elastic-2.0' +description: 'The Neon Cyber integration for the Elastic Stack' +type: integration +categories: + - security + - edr_xdr +conditions: + kibana: + version: '^8.17.0 || ^9.0.0' + elastic: + subscription: 'basic' +screenshots: + - src: /img/neoncyber-screenshot.png + title: Neon events screenshot + size: 600x600 + type: image/png +icons: + - src: /img/neoncyber-logo.svg + title: Neon Cyber logo + size: 32x32 + type: image/svg+xml +policy_templates: + - name: neon_cyber + title: Neon Cyber + description: Collect workforce logs from the Neon Cyber API + deployment_modes: + default: + enabled: true + agentless: + enabled: true + organization: security + division: engineering + team: security-service-integrations + inputs: + - type: cel + title: Collect Neon Cyber Data + description: Collecting Neon Cyber events and detections via API + vars: + - name: url + type: text + title: Neon Cyber API URL + description: Neon Cyber developer API URL + multi: false + required: true + show_user: true + default: 'https://api.neoncyber.io' + - name: api_token + type: password + title: API Token + description: Neon Cyber developer API token + multi: false + required: true + show_user: true + secret: true + - name: http_client_timeout + type: text + title: HTTP Client Timeout + description: Duration before declaring that the HTTP client connection has timed out. Valid time units are ns, us, ms, s, m, h. + multi: false + required: false + show_user: true + default: 30s + - name: proxy_url + type: text + title: Proxy URL + description: URL to proxy connections in the form of http\[s\]://:@: + multi: false + required: false + show_user: false + - name: ssl + type: yaml + title: SSL Configuration + description: SSL configuration options. See [documentation](https://www.elastic.co/guide/en/beats/filebeat/current/configuration-ssl.html#ssl-common-config) for details. + multi: false + required: false + show_user: false +owner: + github: elastic/security-service-integrations + type: partner