Skip to content

Add API Key Management and Enable Index Sync via Scheduled Task#225551

Merged
CAWilson94 merged 40 commits intoelastic:mainfrom
CAWilson94:charlotte-privmon-index-sync-fix
Jul 4, 2025
Merged

Add API Key Management and Enable Index Sync via Scheduled Task#225551
CAWilson94 merged 40 commits intoelastic:mainfrom
CAWilson94:charlotte-privmon-index-sync-fix

Conversation

@CAWilson94
Copy link
Contributor

@CAWilson94 CAWilson94 commented Jun 26, 2025

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.

Further work, Testing and Review

Testing updates upcoming in #225783
Note: Any other further updates @jeramysoucy should be notified for review (same for testing updates above)

⚠️ 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

  • 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.

@CAWilson94 CAWilson94 marked this pull request as ready for review June 27, 2025 11:48
@CAWilson94 CAWilson94 requested review from a team as code owners June 27, 2025 11:48
@CAWilson94 CAWilson94 requested a review from tiansivive June 27, 2025 11:48
@elastic-vault-github-plugin-prod elastic-vault-github-plugin-prod bot requested a review from a team as a code owner June 27, 2025 12:04
Copy link
Contributor

@tiansivive tiansivive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks everyone for the collab! I left some comments

@CAWilson94 CAWilson94 added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Theme: entity_analytics Team:Entity Analytics Security Entity Analytics Team v9.1.0 labels Jun 27, 2025
@elasticmachine
Copy link
Contributor

Pinging @elastic/security-solution (Team: SecuritySolution)

@elasticmachine
Copy link
Contributor

Pinging @elastic/security-entity-analytics (Team:Entity Analytics)

@CAWilson94 CAWilson94 requested a review from machadoum June 27, 2025 14:29
… src/core/server/integration_tests/ci_checks'
@CAWilson94 CAWilson94 requested a review from jeramysoucy July 3, 2025 14:23
@CAWilson94
Copy link
Contributor Author

Thanks for the changes! It's looking good. I just highlighted a few other nits to look at before I approve.

@rudolf Thanks! Updated them now :D

Copy link
Contributor

@jeramysoucy jeramysoucy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the updates and for your patience on this one! Last question for you is if you've considered adding any unit or integration tests for the new functionality/types. I saw the updated authorization api integration tests, but I didn't see any unit or integration tests for the other changes (I may be looking in wrong place).

@CAWilson94
Copy link
Contributor Author

Thanks for all the updates and for your patience on this one! Last question for you is if you've considered adding any unit or integration tests for the new functionality/types. I saw the updated authorization api integration tests, but I didn't see any unit or integration tests for the other changes (I may be looking in wrong place).

Hey, thanks to you too for all the direction and help here! Really appreciate it all 🚀 Yes there is a separate ticket out for this here - #225680. The plan will be pull this down and merge it in and cover it along with this larger refactor and testing. @jeramysoucy

Copy link
Contributor

@jeramysoucy jeramysoucy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with note that test coverage to be implemented in #225680

If further changes are made, please re-request a review before merging.

@CAWilson94 CAWilson94 enabled auto-merge (squash) July 4, 2025 12:35
Copy link
Contributor

@rudolf rudolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving for Core changes related to registering new SO type.

@CAWilson94 CAWilson94 merged commit 441d2a5 into elastic:main Jul 4, 2025
10 checks passed
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
securitySolution 130 131 +1
Unknown metric groups

API count

id before after diff
securitySolution 199 200 +1

References to deprecated APIs

id before after diff
securitySolution 344 345 +1

History

@CAWilson94
Copy link
Contributor Author

#225680

Hey, sorry @jeramysoucy, I told you the wrong ticket earlier - this will be the issue to watch https://github.com/elastic/security-team/issues/12251?issue=elastic%7Csecurity-team%7C12887

adcoelho pushed a commit to adcoelho/kibana that referenced this pull request Jul 7, 2025
…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>
@jaredburgettelastic jaredburgettelastic added backport:version Backport to applied version labels and removed backport:skip This PR does not require backporting labels Jul 7, 2025
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 9.1

https://github.com/elastic/kibana/actions/runs/16119924237

kibanamachine added a commit to kibanamachine/kibana that referenced this pull request Jul 7, 2025
…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)
@kibanamachine
Copy link
Contributor

💚 All backports created successfully

Status Branch Result
9.1

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Jul 7, 2025
…#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>
kertal pushed a commit to kertal/kibana that referenced this pull request Jul 25, 2025
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:version Backport to applied version labels release_note:skip Skip the PR/issue when compiling release notes Team:Entity Analytics Security Entity Analytics Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Theme: entity_analytics v9.1.0 v9.2.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants