Skip to content

Commit a1a6de7

Browse files
committed
zscaler_zpa: fix handling of multiple remote IPs, and event categorisation
ZScaler appears to sometimes send events with multiple remote IPs. So split the list an raise client.ip to an array if this is the case. The Zscaler ZPA documentation does not make clear what the semantics of this case are, so we bend the ECS a little here. Also fix handling of event.type and event.category to ensure that they agree with ECS definitions, and add event.outcome mappings.
1 parent f34162d commit a1a6de7

File tree

5 files changed

+153
-19
lines changed

5 files changed

+153
-19
lines changed

packages/zscaler_zpa/changelog.yml

+8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
# newer versions go on top
2+
- version: "1.22.2"
3+
changes:
4+
- description: Fix handling of remote IP lists in audit data stream.
5+
type: bugfix
6+
link: https://github.com/elastic/integrations/pull/
7+
- description: Fix ECS event type, category and outcome mapping of audit events.
8+
type: bugfix
9+
link: https://github.com/elastic/integrations/pull/
210
- version: "1.22.1"
311
changes:
412
- description: Do not set `error.message` for expected behavior related to Zscaler `Host` field.
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
{"ModifiedTime":"2021-11-17T04:29:38.000Z","CreationTime":"2021-11-17T04:29:38.000Z","ModifiedBy":12345678901234567,"RequestID":"11111111-1111-1111-1111-111111111111","SessionID":"1idn23nlfm2q1txa5h3r4mep6","AuditOldValue":"","AuditNewValue":"{\"id\":\"72058340288495701\",\"name\":\"Some-Name\",\"domainOrIpAddress\":\"81.2.69.144\",\"description\":\"This is a description field\",\"enabled\":\"true\"}","AuditOperationType":"Create","ObjectType":"Server","ObjectName":"Some-Name","ObjectID":12345678901234567,"CustomerID":98765432109876543,"User":"[email protected]","ClientAuditUpdate":0}
22
{"ModifiedTime":"","CreationTime":"2021-11-17T04:29:38.000Z","ModifiedBy":12345678901234567,"RequestID":"11111111-1111-1111-1111-111111111111","SessionID":"1idn23nlfm2q1txa5h3r4mep6","AuditOldValue":"","AuditNewValue":"{\"id\":\"72058340288495701\",\"name\":\"Some-Name\",\"domainOrIpAddress\":\"example.com\",\"description\":\"This is a description field\",\"enabled\":\"true\"}","AuditOperationType":"Create","ObjectType":"Server","ObjectName":"Some-Name","ObjectID":12345678901234567,"CustomerID":98765432109876543,"User":"[email protected]","ClientAuditUpdate":0}
3+
{"ModifiedTime":"","CreationTime":"2025-04-30T16:23:40.000Z","ModifiedBy":288263728720249833,"RequestID":"12d6eccc-718c-4657-b267-83cc1c3f35f6","SessionID":"1samau4fwi7xbsf3317mkd5vz","AuditOldValue":"","AuditNewValue":"{\"loginAttempt\":\"2025-04-30 16:23:40 UTC\",\"remoteIP\":\"81.2.69.142, 81.2.69.144\"}","AuditOperationType":"Sign In","ObjectType":"Authentication","ObjectName":"xxxx","ObjectID":"xxxxx","CustomerID":"xxxxx","User":"xxxx","ClientAuditUpdate":1}

packages/zscaler_zpa/data_stream/audit/_dev/test/pipeline/test-audit.log-expected.json

+68
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"id": "11111111-1111-1111-1111-111111111111",
1414
"kind": "event",
1515
"original": "{\"ModifiedTime\":\"2021-11-17T04:29:38.000Z\",\"CreationTime\":\"2021-11-17T04:29:38.000Z\",\"ModifiedBy\":12345678901234567,\"RequestID\":\"11111111-1111-1111-1111-111111111111\",\"SessionID\":\"1idn23nlfm2q1txa5h3r4mep6\",\"AuditOldValue\":\"\",\"AuditNewValue\":\"{\\\"id\\\":\\\"72058340288495701\\\",\\\"name\\\":\\\"Some-Name\\\",\\\"domainOrIpAddress\\\":\\\"81.2.69.144\\\",\\\"description\\\":\\\"This is a description field\\\",\\\"enabled\\\":\\\"true\\\"}\",\"AuditOperationType\":\"Create\",\"ObjectType\":\"Server\",\"ObjectName\":\"Some-Name\",\"ObjectID\":12345678901234567,\"CustomerID\":98765432109876543,\"User\":\"[email protected]\",\"ClientAuditUpdate\":0}",
16+
"outcome": "success",
1617
"type": [
1718
"creation"
1819
]
@@ -77,6 +78,7 @@
7778
"id": "11111111-1111-1111-1111-111111111111",
7879
"kind": "event",
7980
"original": "{\"ModifiedTime\":\"\",\"CreationTime\":\"2021-11-17T04:29:38.000Z\",\"ModifiedBy\":12345678901234567,\"RequestID\":\"11111111-1111-1111-1111-111111111111\",\"SessionID\":\"1idn23nlfm2q1txa5h3r4mep6\",\"AuditOldValue\":\"\",\"AuditNewValue\":\"{\\\"id\\\":\\\"72058340288495701\\\",\\\"name\\\":\\\"Some-Name\\\",\\\"domainOrIpAddress\\\":\\\"example.com\\\",\\\"description\\\":\\\"This is a description field\\\",\\\"enabled\\\":\\\"true\\\"}\",\"AuditOperationType\":\"Create\",\"ObjectType\":\"Server\",\"ObjectName\":\"Some-Name\",\"ObjectID\":12345678901234567,\"CustomerID\":98765432109876543,\"User\":\"[email protected]\",\"ClientAuditUpdate\":0}",
81+
"outcome": "success",
8082
"type": [
8183
"creation"
8284
]
@@ -123,6 +125,72 @@
123125
}
124126
}
125127
}
128+
},
129+
{
130+
"@timestamp": "2025-04-30T16:23:40.000Z",
131+
"client": {
132+
"ip": [
133+
"81.2.69.142",
134+
"81.2.69.144"
135+
]
136+
},
137+
"ecs": {
138+
"version": "8.11.0"
139+
},
140+
"event": {
141+
"category": [
142+
"authentication",
143+
"session"
144+
],
145+
"created": "2025-04-30T16:23:40.000Z",
146+
"id": "12d6eccc-718c-4657-b267-83cc1c3f35f6",
147+
"kind": "event",
148+
"original": "{\"ModifiedTime\":\"\",\"CreationTime\":\"2025-04-30T16:23:40.000Z\",\"ModifiedBy\":288263728720249833,\"RequestID\":\"12d6eccc-718c-4657-b267-83cc1c3f35f6\",\"SessionID\":\"1samau4fwi7xbsf3317mkd5vz\",\"AuditOldValue\":\"\",\"AuditNewValue\":\"{\\\"loginAttempt\\\":\\\"2025-04-30 16:23:40 UTC\\\",\\\"remoteIP\\\":\\\"81.2.69.142, 81.2.69.144\\\"}\",\"AuditOperationType\":\"Sign In\",\"ObjectType\":\"Authentication\",\"ObjectName\":\"xxxx\",\"ObjectID\":\"xxxxx\",\"CustomerID\":\"xxxxx\",\"User\":\"xxxx\",\"ClientAuditUpdate\":1}",
149+
"outcome": "success",
150+
"type": [
151+
"start"
152+
]
153+
},
154+
"organization": {
155+
"id": "xxxxx"
156+
},
157+
"related": {
158+
"ip": [
159+
"81.2.69.142",
160+
"81.2.69.144"
161+
],
162+
"user": [
163+
"288263728720249833",
164+
"xxxx"
165+
]
166+
},
167+
"tags": [
168+
"preserve_original_event"
169+
],
170+
"user": {
171+
"id": "288263728720249833",
172+
"name": "xxxx"
173+
},
174+
"zscaler_zpa": {
175+
"audit": {
176+
"client_audit_update": 1,
177+
"object": {
178+
"id": "xxxxx",
179+
"name": "xxxx",
180+
"type": "Authentication"
181+
},
182+
"operation_type": "Sign In",
183+
"session": {
184+
"id": "1samau4fwi7xbsf3317mkd5vz"
185+
},
186+
"value": {
187+
"new": {
188+
"loginAttempt": "2025-04-30 16:23:40 UTC",
189+
"remoteIP": "81.2.69.142, 81.2.69.144"
190+
}
191+
}
192+
}
193+
}
126194
}
127195
]
128196
}

packages/zscaler_zpa/data_stream/audit/elasticsearch/ingest_pipeline/default.yml

+75-18
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,74 @@ processors:
3939
field: event.created
4040
copy_from: '@timestamp'
4141
ignore_failure: true
42-
- append:
43-
field: event.category
44-
value: iam
4542
- set:
4643
field: event.kind
4744
value: event
4845
- script:
4946
if: ctx.json?.AuditOperationType != null && ctx.json.AuditOperationType != ''
5047
lang: painless
48+
params:
49+
event_classification:
50+
'create':
51+
type:
52+
- creation
53+
category:
54+
- iam
55+
outcome: success
56+
'delete':
57+
type:
58+
- deletion
59+
category:
60+
- iam
61+
outcome: success
62+
'update':
63+
type:
64+
- change
65+
category:
66+
- iam
67+
outcome: success
68+
'sign in':
69+
type:
70+
- start
71+
category:
72+
- authentication
73+
- session
74+
outcome: success
75+
'sign in failure':
76+
type:
77+
- start
78+
- error
79+
category: failure
80+
- session
81+
outcome:
82+
'download':
83+
type:
84+
- info
85+
- access
86+
outcome: success
87+
category:
88+
- file
89+
'sign out':
90+
type:
91+
- end
92+
category:
93+
- session
94+
outcome: success
95+
'client session revoked':
96+
type:
97+
- change
98+
- deletion
99+
category:
100+
- iam
101+
outcome: success
51102
source: |
52-
def eventType = ctx.json.AuditOperationType?.toLowerCase();
53-
ctx.event.type = new ArrayList();
54-
Map referenceTable = [
55-
'create': ['creation'],
56-
'delete': ['deletion'],
57-
'update': ['change'],
58-
'sign in': ['access', 'allowed'],
59-
'sign in failure': ['access', 'error'],
60-
'download': ['info'],
61-
'sign out': ['access'],
62-
'client session revoked': ['end']
63-
];
64-
65-
ctx.event.type = referenceTable[eventType];
103+
def class = params.event_classification[ctx.json.AuditOperationType?.toLowerCase()];
104+
if (class == null) {
105+
return;
106+
}
107+
ctx.event.type = class.type;
108+
ctx.event.category = class.category;
109+
ctx.event.outcome = class.outcome;
66110
- rename:
67111
field: json.RequestID
68112
target_field: event.id
@@ -216,12 +260,25 @@ processors:
216260
ctx.server = new HashMap();
217261
ctx.server.address = valuesMap?.domainOrIpAddress;
218262
}
263+
- split:
264+
field: client.ip
265+
separator: ', *'
266+
if: ctx.client?.ip instanceof String && ctx.client.ip.contains(',')
219267
- append:
220268
field: related.ip
221269
value: '{{{client.ip}}}'
222-
if: ctx.client?.ip != null
270+
if: ctx.client?.ip instanceof String
223271
allow_duplicates: false
224272
ignore_failure: true
273+
- foreach:
274+
field: client.ip
275+
if: ctx.client?.ip instanceof List
276+
processor:
277+
append:
278+
field: related.ip
279+
value: '{{{_ingest._value}}}'
280+
allow_duplicates: false
281+
ignore_failure: true
225282
- convert:
226283
field: server.address
227284
target_field: server.ip

packages/zscaler_zpa/manifest.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
format_version: "3.0.3"
22
name: zscaler_zpa
33
title: Zscaler Private Access
4-
version: "1.22.1"
4+
version: "1.22.2"
55
source:
66
license: Elastic-2.0
77
description: Collect logs from Zscaler Private Access (ZPA) with Elastic Agent.

0 commit comments

Comments
 (0)