[Privmon] Synchronize Privileged User index based on configured Entity Sources#221610
[Privmon] Synchronize Privileged User index based on configured Entity Sources#221610CAWilson94 merged 35 commits intoelastic:mainfrom
Conversation
… and updated registering SO imports; creating sourceindex from privmon init
… and updated registering SO imports; creating sourceindex from privmon init
…ine with SO documentation recommendations.
…ndexPattern, matchers, and filters
…t for testing and retrieve username from indexPatterns in SO's.
…testing with temp arrays.
…rk required on data client for get and delete methods
default indexpattern rename for spec
...ion/server/lib/entity_analytics/privilege_monitoring/monitoring_entity_source_data_client.ts
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
…ring sync sources. WIP: To change to using helper bulk wrapper; bulk ops for soft delete too; code splitting
Depends on #221610 This PR adds the import index workflow to privileged user monitoring and API changes required to support it. ### API Enhancements * **New API for privilege monitoring index creation**: Added a new API endpoint (`PUT /api/entity_analytics/monitoring/privileges/indices`) to create indices for privilege monitoring with support for `standard` and `lookup` modes. This includes the implementation of request and response schemas (`create_indidex.gen.ts`, `create_indidex.schema.yaml`). [[1]](diffhunk://#diff-68329bb90dea945f343e1637990d5d05bc159e0aa2511ef1e45d37ed1a6cda51R1-R41) [[2]](diffhunk://#diff-e979499654a27b3c1930d63c5b1002113c1c3f53f84ce27a4d75a5c492717a96R1-R42) * **Updated privilege monitoring health response**: Modified the health response schema to include a `status` field and an optional `error` object for detailed error handling (`privilege_monitoring/health.gen.ts`, `privilege_monitoring/health.schema.yaml`). [[1]](diffhunk://#diff-00f39a3e65a336eaddf7d3203d1370d910f5ecd2062b6cc21d9c06922c12884eR19-R28) [[2]](diffhunk://#diff-83afa72b7a1fc48f3cc063e9fb855190d3525228bc0488fb8b871e112b90e961L22-R33) ### Frontend Integration * **Introduce the create index modal that opens when the create index button is clicked. * **Onboarding modal improvements**: Updated the `AddDataSourcePanel` component to handle index creation more robustly by passing callbacks to the modal (`add_data_source.tsx`). * **Error handling in UI**: Enhanced the `PrivilegedUserMonitoring` component to display error callouts when privilege monitoring data fails to load (`privileged_user_monitoring/index.tsx`). [[1]](diffhunk://#diff-273ad32c97dcf15c6c6054fd7c5516d587132674578d25986b235cd174c75789R22-R26) [[2]](diffhunk://#diff-273ad32c97dcf15c6c6054fd7c5516d587132674578d25986b235cd174c75789R38-R51) ### How to test it? * Go to the priv mon page with an empty cluster * Click on the data source by the index button * Search for available indices, it should return indices with `user.name.keyword` fields * Click 'create index' and create a new index * Choose the created index and click 'Add privileged users' * You should be redirected to the dashboard (The API is currently not working) ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) ### Identify risks Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss. Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging. - [ ] [See some risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) - [ ] ... --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
...security/plugins/security_solution/common/entity_analytics/privilege_monitoring/constants.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Outdated
Show resolved
Hide resolved
...olution/server/lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client.ts
Show resolved
Hide resolved
| } | ||
| } | ||
|
|
||
| public async getAllUsernamesFromIndex({ |
There was a problem hiding this comment.
getAllUsernamesFromIndex does much more than its name suggests. A ' get `function should only retrieve data. This one adds data to an index.
There was a problem hiding this comment.
I would suggest splitting it into 2 functions
There was a problem hiding this comment.
Added a comment onto this for now - will split into two after merge
...n/server/lib/entity_analytics/privilege_monitoring/saved_objects/monitoring_entity_source.ts
Show resolved
Hide resolved
tiansivive
left a comment
There was a problem hiding this comment.
🚢
Thanks for all the work! This was quite the epic
| export const defaultMonitoringUsersIndex = 'entity_analytics.privileged_monitoring'; // TODO: update in accordance to spec. Why does this not work when you do this. Investigate. | ||
| // should be entity-analytics.privileged-users |
There was a problem hiding this comment.
???
Have you gone back and checked? looks like a really puzzling issue
There was a problem hiding this comment.
ty for nudge, lost it somewhere. BUT classically I don't know why it didn't work and I don't know why it does work now - probably some typo somewhere down the line. All good now 🎉
There was a problem hiding this comment.
Actually, previous index makes more sense. Struggling to find reference for this in the spec, will bring up with @hop-dev when back, its easy to change after which is ok.
machadoum
left a comment
There was a problem hiding this comment.
The code looks ok, we can do the improvement in a follow-up PR due to the time constraintsThe code seems acceptable; improvements can be made in a follow-up PR due to time constraints.
I haven't tested it locally.
Thank you for handling this complex feature! 👏 👏 👏
Added a ticket here: https://github.com/elastic/security-team/issues/12887 thanks @machadoum and @tiansivive for having a look and giving feedback 🚀 |
💚 Build Succeeded
Metrics [docs]Unknown metric groupsESLint disabled line counts
Total ESLint disabled count
History
cc @CAWilson94 |
Depends on elastic#221610 This PR adds the import index workflow to privileged user monitoring and API changes required to support it. ### API Enhancements * **New API for privilege monitoring index creation**: Added a new API endpoint (`PUT /api/entity_analytics/monitoring/privileges/indices`) to create indices for privilege monitoring with support for `standard` and `lookup` modes. This includes the implementation of request and response schemas (`create_indidex.gen.ts`, `create_indidex.schema.yaml`). [[1]](diffhunk://#diff-68329bb90dea945f343e1637990d5d05bc159e0aa2511ef1e45d37ed1a6cda51R1-R41) [[2]](diffhunk://#diff-e979499654a27b3c1930d63c5b1002113c1c3f53f84ce27a4d75a5c492717a96R1-R42) * **Updated privilege monitoring health response**: Modified the health response schema to include a `status` field and an optional `error` object for detailed error handling (`privilege_monitoring/health.gen.ts`, `privilege_monitoring/health.schema.yaml`). [[1]](diffhunk://#diff-00f39a3e65a336eaddf7d3203d1370d910f5ecd2062b6cc21d9c06922c12884eR19-R28) [[2]](diffhunk://#diff-83afa72b7a1fc48f3cc063e9fb855190d3525228bc0488fb8b871e112b90e961L22-R33) ### Frontend Integration * **Introduce the create index modal that opens when the create index button is clicked. * **Onboarding modal improvements**: Updated the `AddDataSourcePanel` component to handle index creation more robustly by passing callbacks to the modal (`add_data_source.tsx`). * **Error handling in UI**: Enhanced the `PrivilegedUserMonitoring` component to display error callouts when privilege monitoring data fails to load (`privileged_user_monitoring/index.tsx`). [[1]](diffhunk://#diff-273ad32c97dcf15c6c6054fd7c5516d587132674578d25986b235cd174c75789R22-R26) [[2]](diffhunk://#diff-273ad32c97dcf15c6c6054fd7c5516d587132674578d25986b235cd174c75789R38-R51) ### How to test it? * Go to the priv mon page with an empty cluster * Click on the data source by the index button * Search for available indices, it should return indices with `user.name.keyword` fields * Click 'create index' and create a new index * Choose the created index and click 'Add privileged users' * You should be redirected to the dashboard (The API is currently not working) ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) ### Identify risks Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss. Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging. - [ ] [See some risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) - [ ] ... --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
…y Sources (elastic#221610) # Summary This PR introduces support for populating the Privileged Users index from custom data sources (Elasticsearch indices) by querying Privileged User Monitoring Saved Objects from a Kibana task. [Related Issue](elastic/security-team#12289) [Figma Breakdown](https://www.figma.com/board/yBr1pBDGu4JqNxb5ZrULtk/MonEntitySourceSyncTask?node-id=0-1&p=f&t=q52ABMD5MLX0uGj1-0) Working from the _"Synchronize Privileged User index based on configured Entity Sources"_ section, to the right. ### ✅ Implemented • Registered the temporary type and mappings • Created a Descriptor Client that saves it via soClient.create() • Called Descriptor Client create method from PrivMon initialisation. * Testing above default Saved Object creation within PrivMon Initialisation * Update the entity_analytics:monitoring:privileges:engine task to: * Read all Saved objects of index type * query user.name values from given indexPattern * Apply any filters or matchers defined in the Saved Object * Insert matched user.names into .entity_analytics.monitoring.users-<space> with source type index. * Cleanup logic: * Target pattern does not exist, log warning and continue task * Failures will be caught and do not interrupt task loop * Remove previously stored user.names with source type index, that are no longer present. * Component Testing ### 🚧 Wish List * Pull out sync functions from privilege monitoring data client into their own sync service class / similar * * Currently in the data client, they should not be on this layer. * Update GET and DELETE methods with dynamic id's for monitoring data client as per [this ticket](elastic/security-team#12851) # How to Test - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name.keyword": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
) ## Summary This PR adds in API key management and runs plain index sync on task execution. Thanks to @jaredburgettelastic for the below changes 🚀 : ### Key Changes Tasks now call plainIndexSync to sync index users at specified intervals — this is the main functionality change. The following updates support it: - Added support for scoped API key usage via getClientfromApiKey in the getApiKeyManager - Using createInternalRepository for API key generation, to allow for internal kibana user to create saved object client. - API keys now store a snapshot of the user’s privileges by passing {} to role_descriptors. - Updated the find method in MonitoringEntitySourceDescriptorClient to use a namespace-scoped saved objects client. ##⚠️ Important Note You must fully restart Elasticsearch and Kibana after pulling these changes to regenerate the API key with the updated privileges. While taking a privilege snapshot is known to be problematic (e.g., privileges can get out of sync if updated later), it’s a known issue and consistent with the current behavior in the Entity Store. @tiansivive raised 🚀 # How to Test: Steps Taken from [#221610](#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` ## Recurring Sync Current interval is 10m, change this interval to 30s / shorter interval for testing - ` x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts` under 'INTERVAL'. Should be able to add some more indicies/ delete some users from current indicies and see results from the same users list above, on index sync as well as this log "[Privilege Monitoring] Running privilege monitoring task" running every x chosen INTERVAL occurrence. --------- Co-authored-by: jaredburgettelastic <jared.burgett@elastic.co> Co-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>
…tic#225551) ## Summary This PR adds in API key management and runs plain index sync on task execution. Thanks to @jaredburgettelastic for the below changes 🚀 : ### Key Changes Tasks now call plainIndexSync to sync index users at specified intervals — this is the main functionality change. The following updates support it: - Added support for scoped API key usage via getClientfromApiKey in the getApiKeyManager - Using createInternalRepository for API key generation, to allow for internal kibana user to create saved object client. - API keys now store a snapshot of the user’s privileges by passing {} to role_descriptors. - Updated the find method in MonitoringEntitySourceDescriptorClient to use a namespace-scoped saved objects client. ##⚠️ Important Note You must fully restart Elasticsearch and Kibana after pulling these changes to regenerate the API key with the updated privileges. While taking a privilege snapshot is known to be problematic (e.g., privileges can get out of sync if updated later), it’s a known issue and consistent with the current behavior in the Entity Store. @tiansivive raised 🚀 # How to Test: Steps Taken from [elastic#221610](elastic#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` ## Recurring Sync Current interval is 10m, change this interval to 30s / shorter interval for testing - ` x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts` under 'INTERVAL'. Should be able to add some more indicies/ delete some users from current indicies and see results from the same users list above, on index sync as well as this log "[Privilege Monitoring] Running privilege monitoring task" running every x chosen INTERVAL occurrence. --------- Co-authored-by: jaredburgettelastic <jared.burgett@elastic.co> Co-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>
…tic#225551) ## Summary This PR adds in API key management and runs plain index sync on task execution. Thanks to @jaredburgettelastic for the below changes 🚀 : ### Key Changes Tasks now call plainIndexSync to sync index users at specified intervals — this is the main functionality change. The following updates support it: - Added support for scoped API key usage via getClientfromApiKey in the getApiKeyManager - Using createInternalRepository for API key generation, to allow for internal kibana user to create saved object client. - API keys now store a snapshot of the user’s privileges by passing {} to role_descriptors. - Updated the find method in MonitoringEntitySourceDescriptorClient to use a namespace-scoped saved objects client. ##⚠️ Important Note You must fully restart Elasticsearch and Kibana after pulling these changes to regenerate the API key with the updated privileges. While taking a privilege snapshot is known to be problematic (e.g., privileges can get out of sync if updated later), it’s a known issue and consistent with the current behavior in the Entity Store. @tiansivive raised 🚀 # How to Test: Steps Taken from [elastic#221610](elastic#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` ## Recurring Sync Current interval is 10m, change this interval to 30s / shorter interval for testing - ` x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts` under 'INTERVAL'. Should be able to add some more indicies/ delete some users from current indicies and see results from the same users list above, on index sync as well as this log "[Privilege Monitoring] Running privilege monitoring task" running every x chosen INTERVAL occurrence. --------- Co-authored-by: jaredburgettelastic <jared.burgett@elastic.co> Co-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co> (cherry picked from commit 441d2a5)
…#225551) (#226834) # Backport This will backport the following commits from `main` to `9.1`: - [Add API Key Management and Enable Index Sync via Scheduled Task (#225551)](#225551) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Charlotte Alexandra Wilson","email":"CAWilson94@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-07-04T14:10:24Z","message":"Add API Key Management and Enable Index Sync via Scheduled Task (#225551)\n\n## Summary \nThis PR adds in API key management and runs plain index sync on task\nexecution. Thanks to @jaredburgettelastic for the below changes 🚀 :\n### Key Changes \nTasks now call plainIndexSync to sync index users at specified intervals\n— this is the main functionality change. The following updates support\nit:\n- Added support for scoped API key usage via getClientfromApiKey in the\ngetApiKeyManager\n- Using createInternalRepository for API key generation, to allow for\ninternal kibana user to create saved object client.\n- API keys now store a snapshot of the user’s privileges by passing {}\nto role_descriptors.\n- Updated the find method in MonitoringEntitySourceDescriptorClient to\nuse a namespace-scoped saved objects client.\n\n##⚠️ Important Note \nYou must fully restart Elasticsearch and Kibana after pulling these\nchanges to regenerate the API key with the updated privileges.\n\nWhile taking a privilege snapshot is known to be problematic (e.g.,\nprivileges can get out of sync if updated later), it’s a known issue and\nconsistent with the current behavior in the Entity Store. @tiansivive\nraised 🚀\n\n# How to Test:\nSteps Taken from\n[#221610](https://github.com/elastic/kibana/pull/221610)\n- Pull branch into local machine\n- Security experimental flag enable: 'privilegeMonitoringEnabled'\n- Start up ElasticSearch and Kibana\n\n**1. Optional - create the default index, this should just skip if you\ndon't make it.**\n\n```\nPOST entity_analytics.privileged_monitoring/_doc\n{\n \"user\": {\n \"name\": \"default name\"\n }\n}\n```\n\n**2. Create test index/ indicies**\n\n```\nPUT /tatooine-\n{\n \"mappings\": {\n \"properties\": {\n \"user\": {\n \"properties\": {\n \"name\": {\n \"type\": \"keyword\",\n \"fields\": {\n \"text\": {\n \"type\": \"text\"\n }\n }\n }\n }\n }\n }\n }\n}\n\n```\n```\nPOST tatooine-/_bulk\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Luke Skywalker\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Leia Organa\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Han Solo\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Chewbacca\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Obi-Wan Kenobi\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Yoda\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"R2-D2\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"C-3PO\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Darth Vader\" } }\n\n``` \n**3. Register Monitoring Entity Source Saved Objects**\n```\nPOST kbn:/api/entity_analytics/monitoring/entity_source\n{\n \"type\": \"index\",\n \"name\": \"StarWars\",\n \"managed\": true,\n \"indexPattern\": \"tatooine-\",\n \"enabled\": true,\n \"matchers\": [\n {\n \"fields\": [\"user.role\"],\n \"values\": [\"admin\"]\n }\n ],\n \"filter\": {}\n}\n\n``` \n**- OPTIONAL: You can check what is in the monitoring entity_source\nSO:**\n\n``` \nGET kbn:/api/entity_analytics/monitoring/entity_source/list\n``` \n**4. Initialise monitoring engine:** \n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init {}\n``` \n\n**5. Verify Users in Monitoring Index**\n- Check the list of synced user, should include: \n- - The created users\n- - The default user (if you created it)\n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n``` \n\n**e.g. output:**\n\n```\n[\n {\n \"id\": \"FkMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"C-3PO\",\n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ],\n }\n },\n {\n \"id\": \"F0MJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Chewbacca\", \n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ], \n }\n },\n// ... more here \n\n```\n\n## Testing: Removing Stale Users\nThe engine should soft delete users from the internal index if they no\nlonger appear in the synced sources - e.g. label as\nmonitoring.privileged_users: \"not_monitored\"\n**Example:**\n\n- Delete users in index: \n```\nPOST tatooine-/_delete_by_query\n{\n \"query\": {\n \"terms\": {\n \"user.name\": [\"Chewbacca\", \"Han Solo\"]\n }\n }\n}\n\n```\n- re-run engine init\n\n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init\n{}\n```\n-Fetch the updated user list: \n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n```\nYou should now only see both Chewbacca and Han Solo are no longer\nprivileged:\n```\n// ..\n{\n \"id\": \"GUMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Han Solo\"\n \"is_privileged\": false \n },\n \"labels\": {\n \"sources\": [],\n \"source_indices\": [],\n }\n }\n]\n```\n\n## Recurring Sync \nCurrent interval is 10m, change this interval to 30s / shorter interval\nfor testing -\n`\nx-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts`\nunder 'INTERVAL'.\n\nShould be able to add some more indicies/ delete some users from current\nindicies and see results from the same users list above, on index sync\nas well as this log \"[Privilege Monitoring] Running privilege monitoring\ntask\" running every x chosen INTERVAL occurrence.\n\n---------\n\nCo-authored-by: jaredburgettelastic <jared.burgett@elastic.co>\nCo-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co>\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>","sha":"441d2a51a4c249706794e2bffa5ed8f64a14b6b9","branchLabelMapping":{"^v9.2.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team: SecuritySolution","Theme: entity_analytics","Team:Entity Analytics","backport:version","v9.1.0","v9.2.0"],"title":"Add API Key Management and Enable Index Sync via Scheduled Task","number":225551,"url":"https://github.com/elastic/kibana/pull/225551","mergeCommit":{"message":"Add API Key Management and Enable Index Sync via Scheduled Task (#225551)\n\n## Summary \nThis PR adds in API key management and runs plain index sync on task\nexecution. Thanks to @jaredburgettelastic for the below changes 🚀 :\n### Key Changes \nTasks now call plainIndexSync to sync index users at specified intervals\n— this is the main functionality change. The following updates support\nit:\n- Added support for scoped API key usage via getClientfromApiKey in the\ngetApiKeyManager\n- Using createInternalRepository for API key generation, to allow for\ninternal kibana user to create saved object client.\n- API keys now store a snapshot of the user’s privileges by passing {}\nto role_descriptors.\n- Updated the find method in MonitoringEntitySourceDescriptorClient to\nuse a namespace-scoped saved objects client.\n\n##⚠️ Important Note \nYou must fully restart Elasticsearch and Kibana after pulling these\nchanges to regenerate the API key with the updated privileges.\n\nWhile taking a privilege snapshot is known to be problematic (e.g.,\nprivileges can get out of sync if updated later), it’s a known issue and\nconsistent with the current behavior in the Entity Store. @tiansivive\nraised 🚀\n\n# How to Test:\nSteps Taken from\n[#221610](https://github.com/elastic/kibana/pull/221610)\n- Pull branch into local machine\n- Security experimental flag enable: 'privilegeMonitoringEnabled'\n- Start up ElasticSearch and Kibana\n\n**1. Optional - create the default index, this should just skip if you\ndon't make it.**\n\n```\nPOST entity_analytics.privileged_monitoring/_doc\n{\n \"user\": {\n \"name\": \"default name\"\n }\n}\n```\n\n**2. Create test index/ indicies**\n\n```\nPUT /tatooine-\n{\n \"mappings\": {\n \"properties\": {\n \"user\": {\n \"properties\": {\n \"name\": {\n \"type\": \"keyword\",\n \"fields\": {\n \"text\": {\n \"type\": \"text\"\n }\n }\n }\n }\n }\n }\n }\n}\n\n```\n```\nPOST tatooine-/_bulk\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Luke Skywalker\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Leia Organa\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Han Solo\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Chewbacca\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Obi-Wan Kenobi\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Yoda\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"R2-D2\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"C-3PO\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Darth Vader\" } }\n\n``` \n**3. Register Monitoring Entity Source Saved Objects**\n```\nPOST kbn:/api/entity_analytics/monitoring/entity_source\n{\n \"type\": \"index\",\n \"name\": \"StarWars\",\n \"managed\": true,\n \"indexPattern\": \"tatooine-\",\n \"enabled\": true,\n \"matchers\": [\n {\n \"fields\": [\"user.role\"],\n \"values\": [\"admin\"]\n }\n ],\n \"filter\": {}\n}\n\n``` \n**- OPTIONAL: You can check what is in the monitoring entity_source\nSO:**\n\n``` \nGET kbn:/api/entity_analytics/monitoring/entity_source/list\n``` \n**4. Initialise monitoring engine:** \n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init {}\n``` \n\n**5. Verify Users in Monitoring Index**\n- Check the list of synced user, should include: \n- - The created users\n- - The default user (if you created it)\n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n``` \n\n**e.g. output:**\n\n```\n[\n {\n \"id\": \"FkMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"C-3PO\",\n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ],\n }\n },\n {\n \"id\": \"F0MJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Chewbacca\", \n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ], \n }\n },\n// ... more here \n\n```\n\n## Testing: Removing Stale Users\nThe engine should soft delete users from the internal index if they no\nlonger appear in the synced sources - e.g. label as\nmonitoring.privileged_users: \"not_monitored\"\n**Example:**\n\n- Delete users in index: \n```\nPOST tatooine-/_delete_by_query\n{\n \"query\": {\n \"terms\": {\n \"user.name\": [\"Chewbacca\", \"Han Solo\"]\n }\n }\n}\n\n```\n- re-run engine init\n\n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init\n{}\n```\n-Fetch the updated user list: \n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n```\nYou should now only see both Chewbacca and Han Solo are no longer\nprivileged:\n```\n// ..\n{\n \"id\": \"GUMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Han Solo\"\n \"is_privileged\": false \n },\n \"labels\": {\n \"sources\": [],\n \"source_indices\": [],\n }\n }\n]\n```\n\n## Recurring Sync \nCurrent interval is 10m, change this interval to 30s / shorter interval\nfor testing -\n`\nx-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts`\nunder 'INTERVAL'.\n\nShould be able to add some more indicies/ delete some users from current\nindicies and see results from the same users list above, on index sync\nas well as this log \"[Privilege Monitoring] Running privilege monitoring\ntask\" running every x chosen INTERVAL occurrence.\n\n---------\n\nCo-authored-by: jaredburgettelastic <jared.burgett@elastic.co>\nCo-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co>\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>","sha":"441d2a51a4c249706794e2bffa5ed8f64a14b6b9"}},"sourceBranch":"main","suggestedTargetBranches":["9.1"],"targetPullRequestStates":[{"branch":"9.1","label":"v9.1.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.2.0","branchLabelMappingKey":"^v9.2.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/225551","number":225551,"mergeCommit":{"message":"Add API Key Management and Enable Index Sync via Scheduled Task (#225551)\n\n## Summary \nThis PR adds in API key management and runs plain index sync on task\nexecution. Thanks to @jaredburgettelastic for the below changes 🚀 :\n### Key Changes \nTasks now call plainIndexSync to sync index users at specified intervals\n— this is the main functionality change. The following updates support\nit:\n- Added support for scoped API key usage via getClientfromApiKey in the\ngetApiKeyManager\n- Using createInternalRepository for API key generation, to allow for\ninternal kibana user to create saved object client.\n- API keys now store a snapshot of the user’s privileges by passing {}\nto role_descriptors.\n- Updated the find method in MonitoringEntitySourceDescriptorClient to\nuse a namespace-scoped saved objects client.\n\n##⚠️ Important Note \nYou must fully restart Elasticsearch and Kibana after pulling these\nchanges to regenerate the API key with the updated privileges.\n\nWhile taking a privilege snapshot is known to be problematic (e.g.,\nprivileges can get out of sync if updated later), it’s a known issue and\nconsistent with the current behavior in the Entity Store. @tiansivive\nraised 🚀\n\n# How to Test:\nSteps Taken from\n[#221610](https://github.com/elastic/kibana/pull/221610)\n- Pull branch into local machine\n- Security experimental flag enable: 'privilegeMonitoringEnabled'\n- Start up ElasticSearch and Kibana\n\n**1. Optional - create the default index, this should just skip if you\ndon't make it.**\n\n```\nPOST entity_analytics.privileged_monitoring/_doc\n{\n \"user\": {\n \"name\": \"default name\"\n }\n}\n```\n\n**2. Create test index/ indicies**\n\n```\nPUT /tatooine-\n{\n \"mappings\": {\n \"properties\": {\n \"user\": {\n \"properties\": {\n \"name\": {\n \"type\": \"keyword\",\n \"fields\": {\n \"text\": {\n \"type\": \"text\"\n }\n }\n }\n }\n }\n }\n }\n}\n\n```\n```\nPOST tatooine-/_bulk\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Luke Skywalker\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Leia Organa\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Han Solo\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Chewbacca\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Obi-Wan Kenobi\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Yoda\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"R2-D2\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"C-3PO\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Darth Vader\" } }\n\n``` \n**3. Register Monitoring Entity Source Saved Objects**\n```\nPOST kbn:/api/entity_analytics/monitoring/entity_source\n{\n \"type\": \"index\",\n \"name\": \"StarWars\",\n \"managed\": true,\n \"indexPattern\": \"tatooine-\",\n \"enabled\": true,\n \"matchers\": [\n {\n \"fields\": [\"user.role\"],\n \"values\": [\"admin\"]\n }\n ],\n \"filter\": {}\n}\n\n``` \n**- OPTIONAL: You can check what is in the monitoring entity_source\nSO:**\n\n``` \nGET kbn:/api/entity_analytics/monitoring/entity_source/list\n``` \n**4. Initialise monitoring engine:** \n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init {}\n``` \n\n**5. Verify Users in Monitoring Index**\n- Check the list of synced user, should include: \n- - The created users\n- - The default user (if you created it)\n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n``` \n\n**e.g. output:**\n\n```\n[\n {\n \"id\": \"FkMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"C-3PO\",\n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ],\n }\n },\n {\n \"id\": \"F0MJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Chewbacca\", \n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ], \n }\n },\n// ... more here \n\n```\n\n## Testing: Removing Stale Users\nThe engine should soft delete users from the internal index if they no\nlonger appear in the synced sources - e.g. label as\nmonitoring.privileged_users: \"not_monitored\"\n**Example:**\n\n- Delete users in index: \n```\nPOST tatooine-/_delete_by_query\n{\n \"query\": {\n \"terms\": {\n \"user.name\": [\"Chewbacca\", \"Han Solo\"]\n }\n }\n}\n\n```\n- re-run engine init\n\n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init\n{}\n```\n-Fetch the updated user list: \n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n```\nYou should now only see both Chewbacca and Han Solo are no longer\nprivileged:\n```\n// ..\n{\n \"id\": \"GUMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Han Solo\"\n \"is_privileged\": false \n },\n \"labels\": {\n \"sources\": [],\n \"source_indices\": [],\n }\n }\n]\n```\n\n## Recurring Sync \nCurrent interval is 10m, change this interval to 30s / shorter interval\nfor testing -\n`\nx-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts`\nunder 'INTERVAL'.\n\nShould be able to add some more indicies/ delete some users from current\nindicies and see results from the same users list above, on index sync\nas well as this log \"[Privilege Monitoring] Running privilege monitoring\ntask\" running every x chosen INTERVAL occurrence.\n\n---------\n\nCo-authored-by: jaredburgettelastic <jared.burgett@elastic.co>\nCo-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co>\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>","sha":"441d2a51a4c249706794e2bffa5ed8f64a14b6b9"}}]}] BACKPORT--> Co-authored-by: Charlotte Alexandra Wilson <CAWilson94@users.noreply.github.com> Co-authored-by: jaredburgettelastic <jared.burgett@elastic.co> Co-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co> Co-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>
…aved objects (#227420) ## Summary revert to using the default UUID generation for monitoring data source saved objects and remove any reference to temp-id. Previously we were generating the ID using the integration name or index name and the namespace, and also overriding this with temp-id. - remove temp-id refs - add ID param to the get and update routes URL - Remove the behaviour where the create API will update if the source already exists ## Testing Steps Taken from [#221610](#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
…aved objects (elastic#227420) ## Summary revert to using the default UUID generation for monitoring data source saved objects and remove any reference to temp-id. Previously we were generating the ID using the integration name or index name and the namespace, and also overriding this with temp-id. - remove temp-id refs - add ID param to the get and update routes URL - Remove the behaviour where the create API will update if the source already exists ## Testing Steps Taken from [elastic#221610](elastic#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> (cherry picked from commit e26d309)
…urce saved objects (#227420) (#227702) # Backport This will backport the following commits from `main` to `9.1`: - [[Entity Analytics][Privmon] Use default UUIDs for monitoring source saved objects (#227420)](#227420) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Mark Hopkin","email":"mark.hopkin@elastic.co"},"sourceCommit":{"committedDate":"2025-07-11T17:04:53Z","message":"[Entity Analytics][Privmon] Use default UUIDs for monitoring source saved objects (#227420)\n\n## Summary\n\nrevert to using the default UUID generation for monitoring data source\nsaved objects and remove any reference to temp-id. Previously we were\ngenerating the ID using the integration name or index name and the\nnamespace, and also overriding this with temp-id.\n\n- remove temp-id refs\n- add ID param to the get and update routes URL\n- Remove the behaviour where the create API will update if the source\nalready exists\n\n## Testing\n\nSteps Taken from\n[#221610](https://github.com/elastic/kibana/pull/221610)\n- Pull branch into local machine\n- Security experimental flag enable: 'privilegeMonitoringEnabled'\n- Start up ElasticSearch and Kibana\n\n**1. Optional - create the default index, this should just skip if you\ndon't make it.**\n\n```\nPOST entity_analytics.privileged_monitoring/_doc\n{\n \"user\": {\n \"name\": \"default name\"\n }\n}\n```\n\n**2. Create test index/ indicies**\n\n```\nPUT /tatooine-\n{\n \"mappings\": {\n \"properties\": {\n \"user\": {\n \"properties\": {\n \"name\": {\n \"type\": \"keyword\",\n \"fields\": {\n \"text\": {\n \"type\": \"text\"\n }\n }\n }\n }\n }\n }\n }\n}\n\n```\n```\nPOST tatooine-/_bulk\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Luke Skywalker\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Leia Organa\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Han Solo\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Chewbacca\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Obi-Wan Kenobi\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Yoda\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"R2-D2\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"C-3PO\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Darth Vader\" } }\n\n``` \n**3. Register Monitoring Entity Source Saved Objects**\n```\nPOST kbn:/api/entity_analytics/monitoring/entity_source\n{\n \"type\": \"index\",\n \"name\": \"StarWars\",\n \"managed\": true,\n \"indexPattern\": \"tatooine-\",\n \"enabled\": true,\n \"matchers\": [\n {\n \"fields\": [\"user.role\"],\n \"values\": [\"admin\"]\n }\n ],\n \"filter\": {}\n}\n\n``` \n**- OPTIONAL: You can check what is in the monitoring entity_source\nSO:**\n\n``` \nGET kbn:/api/entity_analytics/monitoring/entity_source/list\n``` \n**4. Initialise monitoring engine:** \n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init {}\n``` \n\n**5. Verify Users in Monitoring Index**\n- Check the list of synced user, should include: \n- - The created users\n- - The default user (if you created it)\n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n``` \n\n**e.g. output:**\n\n```\n[\n {\n \"id\": \"FkMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"C-3PO\",\n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ],\n }\n },\n {\n \"id\": \"F0MJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Chewbacca\", \n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ], \n }\n },\n// ... more here \n\n```\n\n## Testing: Removing Stale Users\nThe engine should soft delete users from the internal index if they no\nlonger appear in the synced sources - e.g. label as\nmonitoring.privileged_users: \"not_monitored\"\n**Example:**\n\n- Delete users in index: \n```\nPOST tatooine-/_delete_by_query\n{\n \"query\": {\n \"terms\": {\n \"user.name\": [\"Chewbacca\", \"Han Solo\"]\n }\n }\n}\n\n```\n- re-run engine init\n\n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init\n{}\n```\n-Fetch the updated user list: \n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n```\nYou should now only see both Chewbacca and Han Solo are no longer\nprivileged:\n```\n// ..\n{\n \"id\": \"GUMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Han Solo\"\n \"is_privileged\": false \n },\n \"labels\": {\n \"sources\": [],\n \"source_indices\": [],\n }\n }\n]\n```\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"e26d309535c1c5c1ebe1b6111e4438e08b065a7f","branchLabelMapping":{"^v9.2.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Entity Analytics","backport:version","v9.1.0","v9.2.0"],"title":"[Entity Analytics][Privmon] Use default UUIDs for monitoring source saved objects","number":227420,"url":"https://github.com/elastic/kibana/pull/227420","mergeCommit":{"message":"[Entity Analytics][Privmon] Use default UUIDs for monitoring source saved objects (#227420)\n\n## Summary\n\nrevert to using the default UUID generation for monitoring data source\nsaved objects and remove any reference to temp-id. Previously we were\ngenerating the ID using the integration name or index name and the\nnamespace, and also overriding this with temp-id.\n\n- remove temp-id refs\n- add ID param to the get and update routes URL\n- Remove the behaviour where the create API will update if the source\nalready exists\n\n## Testing\n\nSteps Taken from\n[#221610](https://github.com/elastic/kibana/pull/221610)\n- Pull branch into local machine\n- Security experimental flag enable: 'privilegeMonitoringEnabled'\n- Start up ElasticSearch and Kibana\n\n**1. Optional - create the default index, this should just skip if you\ndon't make it.**\n\n```\nPOST entity_analytics.privileged_monitoring/_doc\n{\n \"user\": {\n \"name\": \"default name\"\n }\n}\n```\n\n**2. Create test index/ indicies**\n\n```\nPUT /tatooine-\n{\n \"mappings\": {\n \"properties\": {\n \"user\": {\n \"properties\": {\n \"name\": {\n \"type\": \"keyword\",\n \"fields\": {\n \"text\": {\n \"type\": \"text\"\n }\n }\n }\n }\n }\n }\n }\n}\n\n```\n```\nPOST tatooine-/_bulk\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Luke Skywalker\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Leia Organa\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Han Solo\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Chewbacca\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Obi-Wan Kenobi\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Yoda\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"R2-D2\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"C-3PO\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Darth Vader\" } }\n\n``` \n**3. Register Monitoring Entity Source Saved Objects**\n```\nPOST kbn:/api/entity_analytics/monitoring/entity_source\n{\n \"type\": \"index\",\n \"name\": \"StarWars\",\n \"managed\": true,\n \"indexPattern\": \"tatooine-\",\n \"enabled\": true,\n \"matchers\": [\n {\n \"fields\": [\"user.role\"],\n \"values\": [\"admin\"]\n }\n ],\n \"filter\": {}\n}\n\n``` \n**- OPTIONAL: You can check what is in the monitoring entity_source\nSO:**\n\n``` \nGET kbn:/api/entity_analytics/monitoring/entity_source/list\n``` \n**4. Initialise monitoring engine:** \n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init {}\n``` \n\n**5. Verify Users in Monitoring Index**\n- Check the list of synced user, should include: \n- - The created users\n- - The default user (if you created it)\n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n``` \n\n**e.g. output:**\n\n```\n[\n {\n \"id\": \"FkMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"C-3PO\",\n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ],\n }\n },\n {\n \"id\": \"F0MJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Chewbacca\", \n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ], \n }\n },\n// ... more here \n\n```\n\n## Testing: Removing Stale Users\nThe engine should soft delete users from the internal index if they no\nlonger appear in the synced sources - e.g. label as\nmonitoring.privileged_users: \"not_monitored\"\n**Example:**\n\n- Delete users in index: \n```\nPOST tatooine-/_delete_by_query\n{\n \"query\": {\n \"terms\": {\n \"user.name\": [\"Chewbacca\", \"Han Solo\"]\n }\n }\n}\n\n```\n- re-run engine init\n\n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init\n{}\n```\n-Fetch the updated user list: \n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n```\nYou should now only see both Chewbacca and Han Solo are no longer\nprivileged:\n```\n// ..\n{\n \"id\": \"GUMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Han Solo\"\n \"is_privileged\": false \n },\n \"labels\": {\n \"sources\": [],\n \"source_indices\": [],\n }\n }\n]\n```\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"e26d309535c1c5c1ebe1b6111e4438e08b065a7f"}},"sourceBranch":"main","suggestedTargetBranches":["9.1"],"targetPullRequestStates":[{"branch":"9.1","label":"v9.1.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.2.0","branchLabelMappingKey":"^v9.2.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/227420","number":227420,"mergeCommit":{"message":"[Entity Analytics][Privmon] Use default UUIDs for monitoring source saved objects (#227420)\n\n## Summary\n\nrevert to using the default UUID generation for monitoring data source\nsaved objects and remove any reference to temp-id. Previously we were\ngenerating the ID using the integration name or index name and the\nnamespace, and also overriding this with temp-id.\n\n- remove temp-id refs\n- add ID param to the get and update routes URL\n- Remove the behaviour where the create API will update if the source\nalready exists\n\n## Testing\n\nSteps Taken from\n[#221610](https://github.com/elastic/kibana/pull/221610)\n- Pull branch into local machine\n- Security experimental flag enable: 'privilegeMonitoringEnabled'\n- Start up ElasticSearch and Kibana\n\n**1. Optional - create the default index, this should just skip if you\ndon't make it.**\n\n```\nPOST entity_analytics.privileged_monitoring/_doc\n{\n \"user\": {\n \"name\": \"default name\"\n }\n}\n```\n\n**2. Create test index/ indicies**\n\n```\nPUT /tatooine-\n{\n \"mappings\": {\n \"properties\": {\n \"user\": {\n \"properties\": {\n \"name\": {\n \"type\": \"keyword\",\n \"fields\": {\n \"text\": {\n \"type\": \"text\"\n }\n }\n }\n }\n }\n }\n }\n}\n\n```\n```\nPOST tatooine-/_bulk\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Luke Skywalker\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Leia Organa\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Han Solo\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Chewbacca\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Obi-Wan Kenobi\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Yoda\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"R2-D2\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"C-3PO\" } }\n{ \"index\": {} }\n{ \"user\": { \"name\": \"Darth Vader\" } }\n\n``` \n**3. Register Monitoring Entity Source Saved Objects**\n```\nPOST kbn:/api/entity_analytics/monitoring/entity_source\n{\n \"type\": \"index\",\n \"name\": \"StarWars\",\n \"managed\": true,\n \"indexPattern\": \"tatooine-\",\n \"enabled\": true,\n \"matchers\": [\n {\n \"fields\": [\"user.role\"],\n \"values\": [\"admin\"]\n }\n ],\n \"filter\": {}\n}\n\n``` \n**- OPTIONAL: You can check what is in the monitoring entity_source\nSO:**\n\n``` \nGET kbn:/api/entity_analytics/monitoring/entity_source/list\n``` \n**4. Initialise monitoring engine:** \n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init {}\n``` \n\n**5. Verify Users in Monitoring Index**\n- Check the list of synced user, should include: \n- - The created users\n- - The default user (if you created it)\n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n``` \n\n**e.g. output:**\n\n```\n[\n {\n \"id\": \"FkMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"C-3PO\",\n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ],\n }\n },\n {\n \"id\": \"F0MJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Chewbacca\", \n \"is_privileged\": true\n },\n \"labels\": {\n \"sources\": [\n \"index\"\n ],\n \"source_indices\": [\n \"tatooine-\"\n ], \n }\n },\n// ... more here \n\n```\n\n## Testing: Removing Stale Users\nThe engine should soft delete users from the internal index if they no\nlonger appear in the synced sources - e.g. label as\nmonitoring.privileged_users: \"not_monitored\"\n**Example:**\n\n- Delete users in index: \n```\nPOST tatooine-/_delete_by_query\n{\n \"query\": {\n \"terms\": {\n \"user.name\": [\"Chewbacca\", \"Han Solo\"]\n }\n }\n}\n\n```\n- re-run engine init\n\n```\nPOST kbn:/api/entity_analytics/monitoring/engine/init\n{}\n```\n-Fetch the updated user list: \n\n```\nGET kbn:/api/entity_analytics/monitoring/users/list\n```\nYou should now only see both Chewbacca and Han Solo are no longer\nprivileged:\n```\n// ..\n{\n \"id\": \"GUMJoZcB7muj1aiwb_eQ\",\n \"user\": {\n \"name\": \"Han Solo\"\n \"is_privileged\": false \n },\n \"labels\": {\n \"sources\": [],\n \"source_indices\": [],\n }\n }\n]\n```\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"e26d309535c1c5c1ebe1b6111e4438e08b065a7f"}}]}] BACKPORT--> Co-authored-by: Mark Hopkin <mark.hopkin@elastic.co>
…tic#225551) ## Summary This PR adds in API key management and runs plain index sync on task execution. Thanks to @jaredburgettelastic for the below changes 🚀 : ### Key Changes Tasks now call plainIndexSync to sync index users at specified intervals — this is the main functionality change. The following updates support it: - Added support for scoped API key usage via getClientfromApiKey in the getApiKeyManager - Using createInternalRepository for API key generation, to allow for internal kibana user to create saved object client. - API keys now store a snapshot of the user’s privileges by passing {} to role_descriptors. - Updated the find method in MonitoringEntitySourceDescriptorClient to use a namespace-scoped saved objects client. ##⚠️ Important Note You must fully restart Elasticsearch and Kibana after pulling these changes to regenerate the API key with the updated privileges. While taking a privilege snapshot is known to be problematic (e.g., privileges can get out of sync if updated later), it’s a known issue and consistent with the current behavior in the Entity Store. @tiansivive raised 🚀 # How to Test: Steps Taken from [elastic#221610](elastic#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` ## Recurring Sync Current interval is 10m, change this interval to 30s / shorter interval for testing - ` x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/privilege_monitoring/constants.ts` under 'INTERVAL'. Should be able to add some more indicies/ delete some users from current indicies and see results from the same users list above, on index sync as well as this log "[Privilege Monitoring] Running privilege monitoring task" running every x chosen INTERVAL occurrence. --------- Co-authored-by: jaredburgettelastic <jared.burgett@elastic.co> Co-authored-by: Tiago Vila Verde <tiago.vilaverde@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jeramy Soucy <jeramy.soucy@elastic.co>
…aved objects (elastic#227420) ## Summary revert to using the default UUID generation for monitoring data source saved objects and remove any reference to temp-id. Previously we were generating the ID using the integration name or index name and the namespace, and also overriding this with temp-id. - remove temp-id refs - add ID param to the get and update routes URL - Remove the behaviour where the create API will update if the source already exists ## Testing Steps Taken from [elastic#221610](elastic#221610) - Pull branch into local machine - Security experimental flag enable: 'privilegeMonitoringEnabled' - Start up ElasticSearch and Kibana **1. Optional - create the default index, this should just skip if you don't make it.** ``` POST entity_analytics.privileged_monitoring/_doc { "user": { "name": "default name" } } ``` **2. Create test index/ indicies** ``` PUT /tatooine- { "mappings": { "properties": { "user": { "properties": { "name": { "type": "keyword", "fields": { "text": { "type": "text" } } } } } } } } ``` ``` POST tatooine-/_bulk { "index": {} } { "user": { "name": "Luke Skywalker" } } { "index": {} } { "user": { "name": "Leia Organa" } } { "index": {} } { "user": { "name": "Han Solo" } } { "index": {} } { "user": { "name": "Chewbacca" } } { "index": {} } { "user": { "name": "Obi-Wan Kenobi" } } { "index": {} } { "user": { "name": "Yoda" } } { "index": {} } { "user": { "name": "R2-D2" } } { "index": {} } { "user": { "name": "C-3PO" } } { "index": {} } { "user": { "name": "Darth Vader" } } ``` **3. Register Monitoring Entity Source Saved Objects** ``` POST kbn:/api/entity_analytics/monitoring/entity_source { "type": "index", "name": "StarWars", "managed": true, "indexPattern": "tatooine-", "enabled": true, "matchers": [ { "fields": ["user.role"], "values": ["admin"] } ], "filter": {} } ``` **- OPTIONAL: You can check what is in the monitoring entity_source SO:** ``` GET kbn:/api/entity_analytics/monitoring/entity_source/list ``` **4. Initialise monitoring engine:** ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` **5. Verify Users in Monitoring Index** - Check the list of synced user, should include: - - The created users - - The default user (if you created it) ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` **e.g. output:** ``` [ { "id": "FkMJoZcB7muj1aiwb_eQ", "user": { "name": "C-3PO", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, { "id": "F0MJoZcB7muj1aiwb_eQ", "user": { "name": "Chewbacca", "is_privileged": true }, "labels": { "sources": [ "index" ], "source_indices": [ "tatooine-" ], } }, // ... more here ``` ## Testing: Removing Stale Users The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored" **Example:** - Delete users in index: ``` POST tatooine-/_delete_by_query { "query": { "terms": { "user.name": ["Chewbacca", "Han Solo"] } } } ``` - re-run engine init ``` POST kbn:/api/entity_analytics/monitoring/engine/init {} ``` -Fetch the updated user list: ``` GET kbn:/api/entity_analytics/monitoring/users/list ``` You should now only see both Chewbacca and Han Solo are no longer privileged: ``` // .. { "id": "GUMJoZcB7muj1aiwb_eQ", "user": { "name": "Han Solo" "is_privileged": false }, "labels": { "sources": [], "source_indices": [], } } ] ``` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Summary
This PR introduces support for populating the Privileged Users index from custom data sources (Elasticsearch indices) by querying Privileged User Monitoring Saved Objects from a Kibana task.
Related Issue
Figma Breakdown Working from the "Synchronize Privileged User index based on configured Entity Sources" section, to the right.
✅ Implemented
• Registered the temporary type and mappings
• Created a Descriptor Client that saves it via soClient.create()
• Called Descriptor Client create method from PrivMon initialisation.
🚧 Wish List
Follow-up Issues:
How to Test
1. Optional - create the default index, this should just skip if you don't make it.
2. Create test index/ indicies
3. Register Monitoring Entity Source Saved Objects
- OPTIONAL: You can check what is in the monitoring entity_source SO:
4. Initialise monitoring engine:
5. Verify Users in Monitoring Index
e.g. output:
Testing: Removing Stale Users
The engine should soft delete users from the internal index if they no longer appear in the synced sources - e.g. label as monitoring.privileged_users: "not_monitored"
Example:
-Fetch the updated user list:
You should now only see both Chewbacca and Han Solo are no longer privileged: