Skip to content

Commit c350d28

Browse files
committed
menlo: handle large numbers in API responses
Some numeric values from the API are outside the range of values that are naturally marshaled as integer numbers. So use string number unmarshaling and special-case the numbers that are needed to send the POST requests. No change is needed in the ingest pipeline since the numeric fields were already being converted to long. The new test case in the pipeline tests was derived from the case above it with the number stringified. Since no large number was present in the system tests, one of the NAs was made to be a large number (obtained frome the issue that this fixes).
1 parent 6d6c332 commit c350d28

File tree

10 files changed

+278
-90
lines changed

10 files changed

+278
-90
lines changed

packages/menlo/_dev/deploy/docker/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ rules:
332332
"is_iframe": "false",
333333
"origin_ip": "192.18.1.4",
334334
"has_password": "false",
335-
"file_size": "NA",
335+
"file_size": 3402270721,
336336
"browser_and_version": "Chrome_119",
337337
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
338338
"egress_ip": "192.18.1.2",

packages/menlo/changelog.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
# newer versions go on top
2+
- version: "1.7.1"
3+
changes:
4+
- description: Fix handling of large numbers.
5+
type: bugfix
6+
link: https://github.com/elastic/integrations/pull/16168
27
- version: "1.7.0"
38
changes:
49
- description: Add parsing for proxy events returned by the Menlo Web API.

packages/menlo/data_stream/dlp/agent/stream/input.yml.hbs

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,36 +30,60 @@ program: |
3030
(string(int(now() - duration(state.initial_interval))))
3131
),
3232
"application/json",
33-
{"token": state.token, "log_type": "dlp", "pagingIdentifiers": (
34-
has(state.cursor) && has(state.cursor.paging) && state.cursor.paging != null ?
35-
state.cursor.paging
36-
:
37-
{}
38-
)
33+
{
34+
"token": state.token,
35+
"log_type": "dlp",
36+
"pagingIdentifiers": (
37+
has(state.?cursor.paging) && state.cursor.paging != null ?
38+
state.cursor.paging.with({
39+
"hashes": state.cursor.paging.hashes.transformMap(_, v, try(int(v), "fail").as(t, has(t.fail) ? v : t))
40+
})
41+
:
42+
{}
43+
)
3944
}.encode_json()
40-
).do_request().as(resp, bytes(resp.Body).decode_json().as(body, {
41-
"events": body[0].result.events.map(e, {
42-
"message": e.encode_json(),
43-
}),
45+
).do_request().as(resp, resp.StatusCode == 200 ?
46+
bytes(resp.Body).decode_json_string_numbers().as(body, {
47+
"events": body[0].result.events.map(e, {
48+
"message": e.encode_json(),
49+
}),
50+
"url": state.url,
51+
"batch_size": state.batch_size,
52+
"token": state.token,
53+
"cursor": {
54+
"last_timestamp": (
55+
has(body[0].timestamp) && body[0].timestamp.size() > 0
56+
?
57+
body[0].timestamp.parse_time(time_layout.RFC3339)
58+
:
59+
null
60+
),
61+
"paging": (
62+
has(body[0].result.pagingIdentifiers) && body[0].result.pagingIdentifiers.size() > 0 ?
63+
body[0].result.pagingIdentifiers
64+
:
65+
null
66+
)
67+
}
68+
})
69+
:
70+
{
71+
"events": {
72+
"error": {
73+
"code": string(resp.StatusCode),
74+
"id": string(resp.Status),
75+
"message": "POST " + state.url.trim_right("/") + (
76+
(size(resp.Body) != 0) ?
77+
string(resp.Body)
78+
:
79+
string(resp.Status) + " (" + string(resp.StatusCode) + ")"
80+
),
81+
},
82+
},
4483
"url": state.url,
4584
"batch_size": state.batch_size,
4685
"token": state.token,
47-
"cursor": {
48-
"last_timestamp": (
49-
has(body[0].timestamp) && body[0].timestamp.size() > 0
50-
?
51-
body[0].timestamp.parse_time(time_layout.RFC3339)
52-
:
53-
null
54-
),
55-
"paging": (
56-
has(body[0].result.pagingIdentifiers) && body[0].result.pagingIdentifiers.size() > 0 ?
57-
body[0].result.pagingIdentifiers
58-
:
59-
null
60-
)
61-
}
62-
})
86+
}
6387
)
6488
tags:
6589
{{#if preserve_original_event}}

packages/menlo/data_stream/dlp/sample_event.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
{
2-
"@timestamp": "2025-06-03T13:29:06.251Z",
2+
"@timestamp": "2025-11-30T23:37:30.347Z",
33
"agent": {
4-
"ephemeral_id": "b46aee26-1420-4f46-8e52-3bec2e7e48f6",
5-
"id": "7af6091c-f1cb-4ddd-accf-48118fcd2a5a",
6-
"name": "elastic-agent-94876",
4+
"ephemeral_id": "9998f9dc-1878-4fdc-a74f-3906648b186c",
5+
"id": "02dc436f-6c46-4084-9ba1-bf15f0b48d5e",
6+
"name": "elastic-agent-90978",
77
"type": "filebeat",
8-
"version": "8.18.1"
8+
"version": "8.19.0"
99
},
1010
"data_stream": {
1111
"dataset": "menlo.dlp",
12-
"namespace": "71436",
12+
"namespace": "57455",
1313
"type": "logs"
1414
},
1515
"ecs": {
1616
"version": "8.11.0"
1717
},
1818
"elastic_agent": {
19-
"id": "7af6091c-f1cb-4ddd-accf-48118fcd2a5a",
19+
"id": "02dc436f-6c46-4084-9ba1-bf15f0b48d5e",
2020
"snapshot": false,
21-
"version": "8.18.1"
21+
"version": "8.19.0"
2222
},
2323
"event": {
2424
"action": "block",
@@ -30,7 +30,7 @@
3030
"created": "2020-03-09T17:17:22.227Z",
3131
"dataset": "menlo.dlp",
3232
"id": "a4c2161b3f81a287ec46d3c993a33f3b97ded5fd854fa184e7f50679303111ce",
33-
"ingested": "2025-06-03T13:29:09Z",
33+
"ingested": "2025-11-30T23:37:33Z",
3434
"kind": "alert",
3535
"original": "{\"event\":{\"action\":\"block\",\"alerted\":\"false\",\"categories\":\"Download Sites\",\"ccl_ids\":\"CreditordebitcardnumbersGlobal\",\"ccl_match_counts\":\"1\",\"ccl_scores\":\"1\",\"domain\":\"tinynewupload.com\",\"dst_url\":\"http://tinynewupload.com/\",\"event_id\":\"a4c2161b3f81a287ec46d3c993a33f3b97ded5fd854fa184e7f50679303111ce\",\"event_time\":\"2020-03-09T17:17:22.227000\",\"file_type\":\"CSV\",\"filename\":\"more_credit_cards.csv\",\"name\":\"file_upload\",\"product\":\"MSIP\",\"protocol\":\"http\",\"request_type\":\"GET\",\"rule_id\":\"1f3ef32c-ec62-42fb-8cad-e1fee3375099\",\"rule_name\":\"Credit card block rule\",\"severity\":\"5\",\"sha256\":\"fd1aee671d92aba0f9f0a8a6d5c6b843e09c8295ced9bb85e16d97360b4d7b3a\",\"src_url\":\"http://tinynewupload.com/\",\"status\":\"dirty\",\"stream_name\":\"/safefile-input/working_file\",\"user_input\":\"false\",\"userid\":\"admin@menlosecurity.com\",\"vendor\":\"Menlo Security\",\"version\":\"2.0\"}}",
3636
"outcome": "success",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{"event":{"top_url":"http://elastic.co/","egress_country":"US","domain":"elastic.co","protocol":"http","risk_tally":"-1","is_iframe":"false","origin_ip":"192.168.1.1","has_password":"false","file_size":"NA","browser_and_version":"Chrome_119","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36","egress_ip":"192.168.4.55","sandboxActivity":"NA","event_time":"2023-11-21T13:12:37.102000","full_session_id":"nLxXe_iU-1","dst":"192.168.1.1","filename":"NA","risk_score":"low","version":"2.0","pe_rulename":"Business and Economy Category","soph_dlp_ref":"NA","numSubfiles":"0","xff_ip":"NA","product":"MSIP","origin_country":"US","vendor":"Menlo Security","rendering_mode":"ACR1","inconsistent_domain":"false","x-client-country":"US","sandboxResult":"NA","request_type":"GET","fullScanResult":"NA","tab_id":"1","pe_reason":"a77757d5-d3be-47ab-9394-cfff5887ade4","categories":"Business and Economy","severity":"5","x-client-ip":"192.168.4.3","name":"page_request","url":"http://elastic.co/","region":"us-east-1c","userid":"example_user","magicName":"NA","pe_action":"isolate","ua_type":"supported_browser","content-type":"text/html; charset=UTF-8","response_code":"308"}}
22
{"event":{"top_url":"https://elastic.co/","egress_country":"US","domain":"elastic.co","protocol":"https","risk_tally":"-1","is_iframe":"false","origin_ip":"192.168.1.1","has_password":"false","file_size":"NA","browser_and_version":"Chrome_119","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36","egress_ip":"192.168.4.55","sandboxActivity":"NA","event_time":"2023-11-21T13:12:37.132000","full_session_id":"nLxXe_iU-1","dst":"192.168.1.1","filename":"NA","risk_score":"low","version":"2.0","pe_rulename":"Business and Economy Category","soph_dlp_ref":"NA","numSubfiles":"0","xff_ip":"NA","product":"MSIP","origin_country":"US","vendor":"Menlo Security","rendering_mode":"ACR1","inconsistent_domain":"false","x-client-country":"US","sandboxResult":"NA","request_type":"GET","referer":"http://elastic.co/","fullScanResult":"NA","tab_id":"1","pe_reason":"a77757d5-d3be-47ab-9394-cfff5887ade4","categories":"Business and Economy","severity":"5","x-client-ip":"192.168.4.3","name":"page_request","url":"https://elastic.co/","region":"us-east-1c","userid":"example_user","magicName":"NA","pe_action":"isolate","ua_type":"supported_browser","response_code":"301"}}
33
{"event":{"top_url":"https://www.elastic.co/","egress_country":"US","domain":"www.elastic.co","protocol":"https","risk_tally":"-1","is_iframe":"false","origin_ip":"192.168.1.2","has_password":"false","file_size":"NA","browser_and_version":"Chrome_119","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36","egress_ip":"192.168.4.55","sandboxActivity":"NA","event_time":"2023-11-21T13:12:37.207000","full_session_id":"nLxXe_iU-1","dst":"192.168.1.2","filename":"NA","risk_score":"low","version":"2.0","pe_rulename":"Business and Economy Category","soph_dlp_ref":"NA","numSubfiles":"0","xff_ip":"NA","product":"MSIP","origin_country":"US","vendor":"Menlo Security","rendering_mode":"ACR1","inconsistent_domain":"false","x-client-country":"US","sandboxResult":"NA","request_type":"GET","referer":"http://elastic.co/","fullScanResult":"NA","tab_id":"1","pe_reason":"a77757d5-d3be-47ab-9394-cfff5887ade4","categories":"Business and Economy","severity":"5","x-client-ip":"192.168.4.3","name":"page_request","url":"https://www.elastic.co/","region":"us-east-1c","userid":"example_user","magicName":"NA","pe_action":"isolate","ua_type":"supported_browser","content-type":"text/html; charset=utf-8","response_code":"200"}}
4+
{"event":{"top_url":"https://www.elastic.co/","egress_country":"US","domain":"www.elastic.co","protocol":"https","risk_tally":"-1","is_iframe":"false","origin_ip":"192.168.1.2","has_password":"false","file_size":"3402270721","browser_and_version":"Chrome_119","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36","egress_ip":"192.168.4.55","sandboxActivity":"NA","event_time":"2023-11-21T13:12:37.207000","full_session_id":"nLxXe_iU-1","dst":"192.168.1.2","filename":"NA","risk_score":"low","version":"2.0","pe_rulename":"Business and Economy Category","soph_dlp_ref":"NA","numSubfiles":"0","xff_ip":"NA","product":"MSIP","origin_country":"US","vendor":"Menlo Security","rendering_mode":"ACR1","inconsistent_domain":"false","x-client-country":"US","sandboxResult":"NA","request_type":"GET","referer":"http://elastic.co/","fullScanResult":"NA","tab_id":"1","pe_reason":"a77757d5-d3be-47ab-9394-cfff5887ade4","categories":"Business and Economy","severity":"5","x-client-ip":"192.168.4.3","name":"page_request","url":"https://www.elastic.co/","region":"us-east-1c","userid":"example_user","magicName":"NA","pe_action":"isolate","ua_type":"supported_browser","content-type":"text/html; charset=utf-8","response_code":"200"}}

packages/menlo/data_stream/web/_dev/test/pipeline/test-web.log-expected.json

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,136 @@
376376
},
377377
"version": "119.0.0.0"
378378
}
379+
},
380+
{
381+
"@timestamp": "2023-11-21T13:12:37.207Z",
382+
"client": {
383+
"geo": {
384+
"country_iso_code": "US"
385+
},
386+
"ip": "192.168.4.3"
387+
},
388+
"cloud": {
389+
"region": "us-east-1c"
390+
},
391+
"destination": {
392+
"geo": {
393+
"country_iso_code": "US"
394+
},
395+
"ip": "192.168.1.2"
396+
},
397+
"dns": {
398+
"answers": {
399+
"data": [
400+
"192.168.1.2"
401+
]
402+
}
403+
},
404+
"ecs": {
405+
"version": "8.11.0"
406+
},
407+
"event": {
408+
"action": "isolate",
409+
"category": [
410+
"web",
411+
"network",
412+
"threat"
413+
],
414+
"id": "nLxXe_iU-1",
415+
"kind": "alert",
416+
"original": "{\"event\":{\"top_url\":\"https://www.elastic.co/\",\"egress_country\":\"US\",\"domain\":\"www.elastic.co\",\"protocol\":\"https\",\"risk_tally\":\"-1\",\"is_iframe\":\"false\",\"origin_ip\":\"192.168.1.2\",\"has_password\":\"false\",\"file_size\":\"3402270721\",\"browser_and_version\":\"Chrome_119\",\"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36\",\"egress_ip\":\"192.168.4.55\",\"sandboxActivity\":\"NA\",\"event_time\":\"2023-11-21T13:12:37.207000\",\"full_session_id\":\"nLxXe_iU-1\",\"dst\":\"192.168.1.2\",\"filename\":\"NA\",\"risk_score\":\"low\",\"version\":\"2.0\",\"pe_rulename\":\"Business and Economy Category\",\"soph_dlp_ref\":\"NA\",\"numSubfiles\":\"0\",\"xff_ip\":\"NA\",\"product\":\"MSIP\",\"origin_country\":\"US\",\"vendor\":\"Menlo Security\",\"rendering_mode\":\"ACR1\",\"inconsistent_domain\":\"false\",\"x-client-country\":\"US\",\"sandboxResult\":\"NA\",\"request_type\":\"GET\",\"referer\":\"http://elastic.co/\",\"fullScanResult\":\"NA\",\"tab_id\":\"1\",\"pe_reason\":\"a77757d5-d3be-47ab-9394-cfff5887ade4\",\"categories\":\"Business and Economy\",\"severity\":\"5\",\"x-client-ip\":\"192.168.4.3\",\"name\":\"page_request\",\"url\":\"https://www.elastic.co/\",\"region\":\"us-east-1c\",\"userid\":\"example_user\",\"magicName\":\"NA\",\"pe_action\":\"isolate\",\"ua_type\":\"supported_browser\",\"content-type\":\"text/html; charset=utf-8\",\"response_code\":\"200\"}}",
417+
"outcome": "failure",
418+
"reason": "a77757d5-d3be-47ab-9394-cfff5887ade4",
419+
"severity": 5
420+
},
421+
"file": {
422+
"size": 3402270721
423+
},
424+
"http": {
425+
"request": {
426+
"method": "GET",
427+
"referrer": "http://elastic.co/"
428+
},
429+
"response": {
430+
"status_code": 200
431+
}
432+
},
433+
"menlo": {
434+
"web": {
435+
"categories": "Business and Economy",
436+
"content_type": "text/html; charset=utf-8",
437+
"has_password": false,
438+
"is_iframe": "false",
439+
"request_type": "page_request",
440+
"risk_score": "low",
441+
"tab_id": "1",
442+
"tally": -1,
443+
"ua_type": "supported_browser"
444+
}
445+
},
446+
"network": {
447+
"protocol": "https"
448+
},
449+
"observer": {
450+
"geo": {
451+
"country_iso_code": "US"
452+
},
453+
"ip": [
454+
"192.168.4.55"
455+
],
456+
"product": "MSIP",
457+
"vendor": "Menlo Security",
458+
"version": "2.0"
459+
},
460+
"related": {
461+
"ip": [
462+
"192.168.4.3",
463+
"192.168.1.2"
464+
],
465+
"user": [
466+
"example_user"
467+
]
468+
},
469+
"server": {
470+
"geo": {
471+
"country_iso_code": "US"
472+
},
473+
"ip": "192.168.1.2"
474+
},
475+
"source": {
476+
"geo": {
477+
"country_iso_code": "US"
478+
},
479+
"ip": "192.168.4.3"
480+
},
481+
"tags": [
482+
"preserve_original_event"
483+
],
484+
"url": {
485+
"domain": "www.elastic.co",
486+
"original": "https://www.elastic.co/",
487+
"path": "/",
488+
"registered_domain": "elastic.co",
489+
"scheme": "https",
490+
"subdomain": "www",
491+
"top_level_domain": "co"
492+
},
493+
"user": {
494+
"name": "example_user"
495+
},
496+
"user_agent": {
497+
"device": {
498+
"name": "Mac"
499+
},
500+
"name": "Chrome",
501+
"original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
502+
"os": {
503+
"full": "Mac OS X 10.15.7",
504+
"name": "Mac OS X",
505+
"version": "10.15.7"
506+
},
507+
"version": "119.0.0.0"
508+
}
379509
}
380510
]
381511
}

packages/menlo/data_stream/web/agent/stream/input.yml.hbs

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,36 +30,60 @@ program: |
3030
(string(int(now() - duration(state.initial_interval))))
3131
),
3232
"application/json",
33-
{"token": state.token, "log_type": "web", "pagingIdentifiers": (
34-
has(state.cursor) && has(state.cursor.paging) && state.cursor.paging != null ?
35-
state.cursor.paging
36-
:
37-
{}
38-
)
33+
{
34+
"token": state.token,
35+
"log_type": "web",
36+
"pagingIdentifiers": (
37+
has(state.?cursor.paging) && state.cursor.paging != null ?
38+
state.cursor.paging.with({
39+
"hashes": state.cursor.paging.hashes.transformMap(_, v, try(int(v), "fail").as(t, has(t.fail) ? v : t))
40+
})
41+
:
42+
{}
43+
)
3944
}.encode_json()
40-
).do_request().as(resp, bytes(resp.Body).decode_json().as(body, {
41-
"events": body[0].result.events.map(e, {
42-
"message": e.encode_json(),
43-
}),
45+
).do_request().as(resp, resp.StatusCode == 200 ?
46+
bytes(resp.Body).decode_json_string_numbers().as(body, {
47+
"events": body[0].result.events.map(e, {
48+
"message": e.encode_json(),
49+
}),
50+
"url": state.url,
51+
"batch_size": state.batch_size,
52+
"token": state.token,
53+
"cursor": {
54+
"last_timestamp": (
55+
has(body[0].timestamp) && body[0].timestamp.size() > 0
56+
?
57+
body[0].timestamp.parse_time(time_layout.RFC3339)
58+
:
59+
null
60+
),
61+
"paging": (
62+
has(body[0].result.pagingIdentifiers) && body[0].result.pagingIdentifiers.size() > 0 ?
63+
body[0].result.pagingIdentifiers
64+
:
65+
null
66+
)
67+
}
68+
})
69+
:
70+
{
71+
"events": {
72+
"error": {
73+
"code": string(resp.StatusCode),
74+
"id": string(resp.Status),
75+
"message": "POST " + state.url.trim_right("/") + (
76+
(size(resp.Body) != 0) ?
77+
string(resp.Body)
78+
:
79+
string(resp.Status) + " (" + string(resp.StatusCode) + ")"
80+
),
81+
},
82+
},
4483
"url": state.url,
4584
"batch_size": state.batch_size,
4685
"token": state.token,
47-
"cursor": {
48-
"last_timestamp": (
49-
has(body[0].timestamp) && body[0].timestamp.size() > 0
50-
?
51-
body[0].timestamp.parse_time(time_layout.RFC3339)
52-
:
53-
null
54-
),
55-
"paging": (
56-
has(body[0].result.pagingIdentifiers) && body[0].result.pagingIdentifiers.size() > 0 ?
57-
body[0].result.pagingIdentifiers
58-
:
59-
null
60-
)
61-
}
62-
})
86+
}
6387
)
6488
tags:
6589
{{#if preserve_original_event}}

0 commit comments

Comments
 (0)