Commit fa4b91d
Generalising update detection to work with multiple integrations (elastic#237792)
### Summary
This PR introduces support for multiple integrations by gentrifying the
query for update detection matchers fields, instead of just the okta
'roles'. The changes also include updating constants and bringing in AD
when loading in Saved Objects - monitoring sources.
**Index and Matcher Logic**
* Updated the logic for determining the last full sync markers index to
use the AD users index when the integration is AD, ensuring correct data
source usage.
* Modified the privileged user search query to dynamically include the
relevant matcher field (such as `user.group.name` for AD) in the
`_source` fields, supporting flexible matching across integrations.
[[1]](diffhunk://#diff-dae1d0e0452709a5c2d74497a2c3a2897584faeff73e3ce3f785044cde4673bcR54)
[[2]](diffhunk://#diff-dae1d0e0452709a5c2d74497a2c3a2897584faeff73e3ce3f785044cde4673bcL74-R75)
* Updated the pattern matcher service to pass the matcher field for AD
integrations when building the search body, ensuring correct field
matching for privileged status detection.
## How To Test
If stuck at any point, I posted all the commands I have been using in a
google doc "paste bin" for reference [ --->
here<---](https://docs.google.com/document/d/1SG5NvSqiFx_-u_I9-TXI1JL7mF2s4pTrJaezatzhHFg/edit?tab=t.0#bookmark=id.bh4tzq75v6z)
Some commands are duplicated, but I hope something helps 🤘
### Update Detection
1. Head over to Document Generator and pull the ad-data branch -
https://github.com/CAWilson94/security-documents-generator/tree/ad-data
2.Run Kibana and ES THEN generate a number of users (100 seems good)
from `yarn start privileged-user-monitoring`, choosing the integrations
option only.
3. Open Kibana dev tools - run engine init `POST
kbn:/api/entity_analytics/monitoring/engine/init {}`
4. You will get an error in the console about full sync - no such index
for okta entity-default, because these have not been created. Ignore
this, or create that index. Up to you.
5. Check the monitoring list and make sure there are privileged users
from your sync. Either through minitoring list endpoint or the internal
index itself:
`GET kbn:/api/entity_analytics/monitoring/users/list` OR ` POST
.entity_analytics.monitoring.users-default/_search`
From the index, the output looks like this:
```
"hits": [
{
"_index": ".entity_analytics.monitoring.users-default",
"_id": "4vAjvpkBcs32I8L9OZG9",
"_score": 1,
"_source": {
"entity_analytics_monitoring": {
"labels": [
{
"field": "user.group.name",
"source": "ff1ba7ff-e8cb-47e8-891d-787100ab7c1f",
"value": "Enterprise Admins"
}
]
},
"@timestamp": "2025-10-07T10:06:43.637Z",
"event": {
"ingested": "2025-10-07T10:06:43.639331Z"
},
"user": {
"is_privileged": true,
"name": "Alexandra.Abernathy",
"entity": {
"attributes": {
"Privileged": true
}
}
},
"labels": {
"source_ids": [
"ff1ba7ff-e8cb-47e8-891d-787100ab7c1f"
],
"sources": [
"entity_analytics_integration"
]
}
}
},
```
### Deletion Detection
**Getting Some Data**
1. Head over to Document Generator and pull the ad-data branch -
https://github.com/CAWilson94/security-documents-generator/tree/ad-data
2.Run Kibana and ES THEN generate a number of users (100 seems good)
from yarn start privileged-user-monitoring, choosing the integrations
option only.
**Generating FIRST set of fullSync Markers**
1. Have a look at the ad data added, and get the latest and oldest
timestamps:
```
GET logs-entityanalytics_ad.user-default/_search
{
"size": 1,
"sort": [{ "@timestamp": "desc" }]
}
GET logs-entityanalytics_ad.user-default/_search
{
"size": 1,
"sort": [{ "@timestamp": "asc" }]
}
```
To create the fullSync Marker wrapper documents outside of these times,
make a started event right before the oldest and a completed event right
after the latest:
e.g. something like:
```
POST logs-entityanalytics_ad.user-default/_bulk
{ "create": {} }
{ "@timestamp": "2025-09-28T04:00:19.836Z", // CHANGE THIS
"event": {
"action": "started",
"dataset": "entityanalytics_ad.user",
"kind": "asset",
"category": ["iam"],
"type": ["info"]
}
}
{ "create": {} }
{ "@timestamp": "2025-09-28T05:53:19.836Z", // CHANGE THIS
"event": {
"action": "completed",
"dataset": "entityanalytics_ad.user",
"kind": "asset",
"category": ["iam"],
"type": ["info"]
}
}
```
**Initalize the Engine, Confirm SO Markers:**
1. (optional) shorten the INTERVAL for the engine to something like 3m,
to give time to edit data between syncs:
_...entity_analytics/privilege_monitoring/constants.ts_
2. Initalize engine: `POST
kbn:/api/entity_analytics/monitoring/engine/init{}`
3. On FIRST RUN: the engine will:
* Look for a full sync in SO
* If missing, fallback to the latest complete marker in the index.
VERIFY this by looking at the SO:
```
GET kbn:/api/entity_analytics/monitoring/entity_source/list
```
Expected Shape:
```
"integrations": {
"syncMarkerIndex": "logs-entityanalytics_ad.user-default",
"syncData": {
"lastUpdateProcessed": "…",
"lastFullSync": "2025-09-28T05:53:19.836Z" ...
```
**No full sync - engine should skip**
* Basically, don't add a second set of markers here. It should do
nothing, logs should say _"No new full sync for source.."_
**Full sync with NO users in window - ALL Stale**
1. Add new start and complete markers after all the users timestamps,
that wrap NO user docs.
2. Next engine run will detect a new full sync - find no users between
the markers, and treat all CURRENT privileged (in monitoring index)
users, as stale - soft delete.
Validate:
```
POST .entity_analytics.monitoring.users-default/_search
{
"size": 100,
"_source":
["user.*","labels.*","entity_analytics_monitoring.*","@timestamp","event.ingested"],
"query": {
"term": { "user.is_privileged": true }
}
}
```
Expected: 0 hits
**Full sync with subset - only missing are stale**
1. Create Markers that wrap a time window you will populate
2. Create some new documents in AD within these time windows, ensuring they have the same username as some already in the monitoring index.
3. Check monitoring index after sync, see only missing names are soft deleted.
## Testing Notes and Gotcha's
Because this has been a long testing journey:
* Please make sure when you copy pasta these examples, you are changing timestamps to work with the markers and users created.
And thank you for testing 🧪 🥳
---------
Co-authored-by: Mark Hopkin <[email protected]>1 parent baa2399 commit fa4b91d
File tree
9 files changed
+62
-88
lines changed- x-pack/solutions/security
- plugins/security_solution/server/lib/entity_analytics/privilege_monitoring
- data_sources
- bulk
- sync/integrations
- deletion_detection
- update_detection
- engine
- test/security_solution_api_integration/test_suites/entity_analytics/monitoring/trial_license_complete_tier/privileged_users
9 files changed
+62
-88
lines changedLines changed: 1 addition & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
278 | | - | |
279 | 278 | | |
280 | 279 | | |
281 | 280 | | |
| |||
301 | 300 | | |
302 | 301 | | |
303 | 302 | | |
304 | | - | |
| 303 | + | |
305 | 304 | | |
Lines changed: 12 additions & 45 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
9 | 8 | | |
10 | 9 | | |
11 | 10 | | |
12 | 11 | | |
13 | | - | |
14 | 12 | | |
15 | | - | |
16 | 13 | | |
17 | 14 | | |
18 | 15 | | |
19 | 16 | | |
20 | 17 | | |
21 | 18 | | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | 19 | | |
54 | 20 | | |
55 | 21 | | |
56 | 22 | | |
57 | 23 | | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
64 | 27 | | |
65 | 28 | | |
66 | 29 | | |
| |||
72 | 35 | | |
73 | 36 | | |
74 | 37 | | |
75 | | - | |
76 | | - | |
77 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
78 | 41 | | |
79 | 42 | | |
80 | 43 | | |
81 | 44 | | |
82 | 45 | | |
83 | 46 | | |
84 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
85 | 50 | | |
86 | 51 | | |
87 | 52 | | |
88 | 53 | | |
89 | 54 | | |
90 | 55 | | |
91 | | - | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
92 | 59 | | |
93 | 60 | | |
Lines changed: 4 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| |||
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
44 | | - | |
| 44 | + | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
| 49 | + | |
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
| |||
75 | 76 | | |
76 | 77 | | |
77 | 78 | | |
78 | | - | |
| 79 | + | |
79 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
80 | 86 | | |
81 | 87 | | |
82 | 88 | | |
| |||
115 | 121 | | |
116 | 122 | | |
117 | 123 | | |
118 | | - | |
119 | 124 | | |
120 | 125 | | |
121 | 126 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
105 | | - | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
106 | 112 | | |
107 | 113 | | |
108 | 114 | | |
109 | 115 | | |
110 | 116 | | |
111 | 117 | | |
112 | | - | |
113 | 118 | | |
114 | 119 | | |
115 | 120 | | |
| |||
Lines changed: 10 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| 54 | + | |
54 | 55 | | |
55 | 56 | | |
56 | 57 | | |
| |||
71 | 72 | | |
72 | 73 | | |
73 | 74 | | |
74 | | - | |
| 75 | + | |
75 | 76 | | |
76 | 77 | | |
77 | 78 | | |
| |||
97 | 98 | | |
98 | 99 | | |
99 | 100 | | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
106 | 109 | | |
107 | 110 | | |
108 | 111 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| 69 | + | |
69 | 70 | | |
70 | 71 | | |
71 | 72 | | |
| |||
Lines changed: 4 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
84 | | - | |
| 83 | + | |
85 | 84 | | |
86 | | - | |
| 85 | + | |
87 | 86 | | |
88 | 87 | | |
89 | 88 | | |
| |||
98 | 97 | | |
99 | 98 | | |
100 | 99 | | |
101 | | - | |
| 100 | + | |
102 | 101 | | |
103 | 102 | | |
104 | 103 | | |
105 | 104 | | |
106 | | - | |
| 105 | + | |
107 | 106 | | |
108 | 107 | | |
109 | 108 | | |
| |||
Lines changed: 16 additions & 21 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
68 | 81 | | |
69 | 82 | | |
70 | 83 | | |
| |||
169 | 182 | | |
170 | 183 | | |
171 | 184 | | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
| 185 | + | |
179 | 186 | | |
180 | 187 | | |
181 | 188 | | |
182 | 189 | | |
183 | 190 | | |
184 | 191 | | |
185 | 192 | | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
| 193 | + | |
193 | 194 | | |
194 | 195 | | |
195 | 196 | | |
196 | 197 | | |
197 | 198 | | |
198 | | - | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
| 199 | + | |
205 | 200 | | |
206 | 201 | | |
207 | 202 | | |
| |||
0 commit comments