Skip to content

Commit 905a3dc

Browse files
authored
refactor!(beyondinsight_password_safe): modernize session data stream (#15010)
Apply improvements from managedsystem refactor to the session data stream including enhanced CEL program with session management, consistent event.original format, enum field conversions, and comprehensive testing infrastructure. Key improvements: - Enhanced CEL program with proper session management and retry logic - Automatic re-authentication when sessions expire (401 responses) - Consistent event.original field containing JSON event data - Enhanced ingest pipeline with enum-to-string conversions for human-readable values - Moved event.dataset and event.module to constant_keyword mappings with static values - Added pipeline test for nullable fields handling API differences from managed{system,account}: - Sessions API returns all sessions at once (no pagination unlike managedaccount/managedsystem) - API has upper limit of 100,000 sessions maximum per response (this could be problematic) Field improvements (breaking): - Convert session_type numeric enum values to human-readable strings (regular, isa, admin) Relates #14985
1 parent e8cf5eb commit 905a3dc

File tree

16 files changed

+636
-274
lines changed

16 files changed

+636
-274
lines changed

packages/beyondinsight_password_safe/changelog.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
- version: "0.9.0"
2+
changes:
3+
- description: For the `session` data stream, enhanced CEL program with proper session management, automatic re-authentication, and improved error handling.
4+
type: enhancement
5+
link: https://github.com/elastic/integrations/pull/15010
6+
- description: For the `session` data stream, converted `session_type` enum field value to human-readable string instead of numeric code. Change `managed_system_id` and `managed_system_id` to a keyword data type.
7+
type: breaking-change
8+
link: https://github.com/elastic/integrations/pull/15010
19
- version: "0.8.0"
210
changes:
311
- description: For the `useraudit` data stream, fixed pagination to avoid duplicate collection.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
services:
2+
beyondinsight-session-cel:
3+
image: docker.elastic.co/observability/stream:v0.20.0
4+
ports:
5+
- 8080
6+
volumes:
7+
- ./files:/files:ro
8+
environment:
9+
PORT: '8080'
10+
command:
11+
- http-server
12+
- --addr=:8080
13+
- --config=/files/config.yml
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# BeyondInsight Password Safe - Sessions Test Mock Configuration
2+
#
3+
# Test Scenario: Simulates session retrieval with authentication and session expiration:
4+
# 1. Initial authentication via SignAppin endpoint (returns 200, sets session cookie)
5+
# 2. First Sessions request (returns 200, all session data - 3 sessions)
6+
# 3. Second Sessions request (returns 401, session expired)
7+
# 4. Re-authentication via SignAppin endpoint (returns 200, new session cookie)
8+
# 5. Retry Sessions request (returns 200, session data again - 1 session)
9+
#
10+
# NOTE: Unlike managedaccount and managedsystem data streams, the Sessions API does NOT support
11+
# pagination with limit/offset parameters. The API returns all sessions at once with an upper
12+
# cap of 100,000 sessions maximum.
13+
14+
rules:
15+
# Auth
16+
- path: "/BeyondTrust/api/public/v3/Auth/SignAppin"
17+
methods: ["POST"]
18+
request_headers:
19+
Authorization: ['PS-Auth key=test_api_key; runas=testuser; pwd=\[password\];']
20+
Content-Type: ['application/json']
21+
responses:
22+
- status_code: 200
23+
headers:
24+
Content-Type: ['application/json']
25+
Set-Cookie: ['ASP.NET_SessionId={{ if eq .req_num 1 }}session_cookie1{{ else }}session_cookie2{{ end }}']
26+
body: |
27+
{{ minify_json `
28+
{
29+
"UserId": 1,
30+
"SID": null,
31+
"EmailAddress": "test.user@example.com",
32+
"UserName": "testuser",
33+
"Name": "Test User"
34+
}
35+
`}}
36+
37+
- path: "/BeyondTrust/api/public/v3/Sessions"
38+
methods: ["GET"]
39+
request_headers:
40+
Content-Type: ['application/json']
41+
Cookie: ['ASP.NET_SessionId=session_cookie1']
42+
as_sequence: true
43+
responses:
44+
# Sessions - first request (successful)
45+
- status_code: 200
46+
headers:
47+
Content-Type: ['application/json']
48+
body: |-
49+
{{ minify_json `
50+
[
51+
{
52+
"SessionID": 1001,
53+
"UserID": 123,
54+
"NodeID": "node-001",
55+
"Status": 1,
56+
"ArchiveStatus": 1,
57+
"Protocol": 0,
58+
"StartTime": "2025-01-15T08:30:00Z",
59+
"EndTime": "2025-01-15T10:45:00Z",
60+
"Duration": 8100,
61+
"AssetName": "web-server-01",
62+
"ManagedSystemID": 456,
63+
"ManagedAccountID": 789,
64+
"ManagedAccountName": "admin_user",
65+
"RecordKey": "rec_key_abc123",
66+
"Token": "token_xyz789",
67+
"ApplicationID": 101,
68+
"RequestID": 201,
69+
"SessionType": 1
70+
},
71+
{
72+
"SessionID": 1002,
73+
"UserID": 124,
74+
"NodeID": "node-002",
75+
"Status": 2,
76+
"ArchiveStatus": 0,
77+
"Protocol": 1,
78+
"StartTime": "2025-01-15T09:00:00Z",
79+
"EndTime": "2025-01-15T11:15:00Z",
80+
"Duration": 8100,
81+
"AssetName": "db-server-01",
82+
"ManagedSystemID": 457,
83+
"ManagedAccountID": 790,
84+
"ManagedAccountName": "database_admin",
85+
"RecordKey": "rec_key_def456",
86+
"Token": "token_abc123",
87+
"ApplicationID": null,
88+
"RequestID": null,
89+
"SessionType": 2
90+
},
91+
{
92+
"SessionID": 1003,
93+
"UserID": 125,
94+
"NodeID": "node-003",
95+
"Status": 8,
96+
"ArchiveStatus": 6,
97+
"Protocol": 0,
98+
"StartTime": "2025-01-15T10:30:00Z",
99+
"EndTime": "2025-01-15T12:00:00Z",
100+
"Duration": 5400,
101+
"AssetName": "app-server-01",
102+
"ManagedSystemID": null,
103+
"ManagedAccountID": 791,
104+
"ManagedAccountName": "service_account",
105+
"RecordKey": "rec_key_ghi789",
106+
"Token": "token_def456",
107+
"ApplicationID": 102,
108+
"RequestID": 202,
109+
"SessionType": 3
110+
}
111+
]
112+
`}}
113+
114+
# Sessions - second request (session expired)
115+
- status_code: 401
116+
headers:
117+
Content-Type: ['application/json']
118+
body: >-
119+
"User not authenticated"
120+
121+
# Sessions - retry after re-authentication
122+
- path: "/BeyondTrust/api/public/v3/Sessions"
123+
methods: ["GET"]
124+
request_headers:
125+
Content-Type: ['application/json']
126+
Cookie: ['ASP.NET_SessionId=session_cookie2']
127+
as_sequence: true
128+
responses:
129+
- status_code: 200
130+
headers:
131+
Content-Type: ['application/json']
132+
body: |-
133+
{{ minify_json `
134+
[
135+
{
136+
"SessionID": 1004,
137+
"UserID": 126,
138+
"NodeID": "node-004",
139+
"Status": 0,
140+
"ArchiveStatus": 2,
141+
"Protocol": 1,
142+
"StartTime": "2025-01-15T11:00:00Z",
143+
"EndTime": null,
144+
"Duration": 0,
145+
"AssetName": "test-server-192.0.2.100",
146+
"ManagedSystemID": 458,
147+
"ManagedAccountID": 792,
148+
"ManagedAccountName": "test_user",
149+
"RecordKey": "rec_key_jkl012",
150+
"Token": "token_ghi789",
151+
"ApplicationID": null,
152+
"RequestID": null,
153+
"SessionType": 1
154+
}
155+
]
156+
`}}

packages/beyondinsight_password_safe/data_stream/session/_dev/test/pipeline/test-common-config.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"events": [
3+
{
4+
"event": {
5+
"original": "{\"SessionID\": 1003, \"UserID\": 125, \"NodeID\": \"node-003\", \"Status\": 8, \"ArchiveStatus\": 6, \"Protocol\": 0, \"StartTime\": \"2025-01-15T10:30:00Z\", \"EndTime\": null, \"Duration\": 0, \"AssetName\": \"app-server-01\", \"ManagedSystemID\": null, \"ManagedAccountID\": 791, \"ManagedAccountName\": \"service_account\", \"RecordKey\": \"rec_key_ghi789\", \"Token\": \"token_def456\", \"ApplicationID\": null, \"RequestID\": null, \"SessionType\": 3}"
6+
}
7+
}
8+
]
9+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"expected": [
3+
{
4+
"beyondinsight_password_safe": {
5+
"session": {
6+
"archive_status": "unknown",
7+
"asset_name": "app-server-01",
8+
"duration": 0,
9+
"managed_account_id": "791",
10+
"managed_account_name": "service_account",
11+
"node_id": "node-003",
12+
"protocol": "rdp",
13+
"record_key": "rec_key_ghi789",
14+
"session_id": "1003",
15+
"session_type": "admin",
16+
"start_time": "2025-01-15T10:30:00Z",
17+
"status": "logged_off",
18+
"token": "token_def456",
19+
"user_id": "125"
20+
}
21+
},
22+
"ecs": {
23+
"version": "8.11.0"
24+
},
25+
"event": {
26+
"category": [
27+
"session"
28+
],
29+
"duration": 0,
30+
"id": "1003",
31+
"kind": "event",
32+
"original": "{\"SessionID\": 1003, \"UserID\": 125, \"NodeID\": \"node-003\", \"Status\": 8, \"ArchiveStatus\": 6, \"Protocol\": 0, \"StartTime\": \"2025-01-15T10:30:00Z\", \"EndTime\": null, \"Duration\": 0, \"AssetName\": \"app-server-01\", \"ManagedSystemID\": null, \"ManagedAccountID\": 791, \"ManagedAccountName\": \"service_account\", \"RecordKey\": \"rec_key_ghi789\", \"Token\": \"token_def456\", \"ApplicationID\": null, \"RequestID\": null, \"SessionType\": 3}",
33+
"start": "2025-01-15T10:30:00.000Z",
34+
"type": [
35+
"info"
36+
]
37+
},
38+
"network": {
39+
"protocol": "rdp"
40+
},
41+
"related": {
42+
"user": [
43+
"125"
44+
]
45+
}
46+
}
47+
]
48+
}

packages/beyondinsight_password_safe/data_stream/session/_dev/test/pipeline/test-session.json

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
{
22
"events": [
33
{
4-
"message": {
5-
"SessionID": 3,
6-
"UserID": 2,
7-
"NodeID": "a5c29153-b351-41f1-a12b-0c4da9408d79",
8-
"Status": 0,
9-
"ArchiveStatus": 0,
10-
"Protocol": 1,
11-
"StartTime": "2021-09-01T12:30:00Z",
12-
"EndTime": "2021-09-01T13:30:00Z",
13-
"Duration": 3600,
14-
"AssetName": "server01",
15-
"ManagedSystemID": 345,
16-
"ManagedAccountID": 678,
17-
"ManagedAccountName": "user01",
18-
"RecordKey": "292837abc123",
19-
"Token": "94872987429837429387"
4+
"event": {
5+
"original": "{\"SessionID\": 1001, \"UserID\": 123, \"NodeID\": \"node-001\", \"Status\": 1, \"ArchiveStatus\": 1, \"Protocol\": 0, \"StartTime\": \"2025-01-15T08:30:00Z\", \"EndTime\": \"2025-01-15T10:45:00Z\", \"Duration\": 8100, \"AssetName\": \"web-server-01\", \"ManagedSystemID\": 456, \"ManagedAccountID\": 789, \"ManagedAccountName\": \"admin_user\", \"RecordKey\": \"rec_key_abc123\", \"Token\": \"token_xyz789\", \"ApplicationID\": 101, \"RequestID\": 201, \"SessionType\": 1}"
206
}
217
}
228
]

packages/beyondinsight_password_safe/data_stream/session/_dev/test/pipeline/test-session.json-expected.json

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
{
44
"beyondinsight_password_safe": {
55
"session": {
6-
"archive_status": "not_archived",
7-
"asset_name": "server01",
8-
"duration": 3600,
9-
"end_time": "2021-09-01T13:30:00Z",
10-
"managed_account_id": 678,
11-
"managed_account_name": "user01",
12-
"managed_system_id": 345,
13-
"node_id": "a5c29153-b351-41f1-a12b-0c4da9408d79",
14-
"protocol": "ssh",
15-
"record_key": "292837abc123",
16-
"session_id": 3,
17-
"start_time": "2021-09-01T12:30:00Z",
18-
"status": "not_started",
19-
"user_id": 2
6+
"application_id": "101",
7+
"archive_status": "archived",
8+
"asset_name": "web-server-01",
9+
"duration": 8100,
10+
"end_time": "2025-01-15T10:45:00Z",
11+
"managed_account_id": "789",
12+
"managed_account_name": "admin_user",
13+
"managed_system_id": "456",
14+
"node_id": "node-001",
15+
"protocol": "rdp",
16+
"record_key": "rec_key_abc123",
17+
"request_id": "201",
18+
"session_id": "1001",
19+
"session_type": "regular",
20+
"start_time": "2025-01-15T08:30:00Z",
21+
"status": "in_progress",
22+
"token": "token_xyz789",
23+
"user_id": "123"
2024
}
2125
},
2226
"ecs": {
@@ -26,25 +30,22 @@
2630
"category": [
2731
"session"
2832
],
29-
"dataset": "beyondinsight_password_safe.session",
30-
"duration": 3600,
31-
"end": "2021-09-01T13:30:00.000Z",
32-
"id": "3",
33+
"duration": 8100000000000,
34+
"end": "2025-01-15T10:45:00.000Z",
35+
"id": "1001",
3336
"kind": "event",
34-
"module": "beyondinsight_password_safe",
35-
"start": "2021-09-01T12:30:00.000Z",
37+
"original": "{\"SessionID\": 1001, \"UserID\": 123, \"NodeID\": \"node-001\", \"Status\": 1, \"ArchiveStatus\": 1, \"Protocol\": 0, \"StartTime\": \"2025-01-15T08:30:00Z\", \"EndTime\": \"2025-01-15T10:45:00Z\", \"Duration\": 8100, \"AssetName\": \"web-server-01\", \"ManagedSystemID\": 456, \"ManagedAccountID\": 789, \"ManagedAccountName\": \"admin_user\", \"RecordKey\": \"rec_key_abc123\", \"Token\": \"token_xyz789\", \"ApplicationID\": 101, \"RequestID\": 201, \"SessionType\": 1}",
38+
"start": "2025-01-15T08:30:00.000Z",
3639
"type": [
3740
"info"
3841
]
3942
},
4043
"network": {
41-
"protocol": [
42-
"ssh"
43-
]
44+
"protocol": "rdp"
4445
},
4546
"related": {
4647
"user": [
47-
"2"
48+
"123"
4849
]
4950
}
5051
}
Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
input: cel
2-
service: beyondinsight
3-
numeric_keyword_fields:
4-
- beyondinsight_password_safe.session.session_id
5-
- beyondinsight_password_safe.session.user_id
2+
service: beyondinsight-session-cel
63
vars:
74
url: http://{{Hostname}}:{{Port}}/BeyondTrust/api/public/v3
8-
apikey: abcd1234byiapitoken
5+
apikey: test_api_key
96
username: testuser
107
password: password
11-
initial_interval: 10s
12-
interval: 10s
13-
limit: 1000
8+
enable_request_tracer: true
9+
data_stream:
10+
vars:
11+
interval: 15s
12+
preserve_original_event: true
1413
assert:
15-
hit_count: 1
14+
hit_count: 4

0 commit comments

Comments
 (0)