Skip to content

Granting kibana_system reserved role access to "all" privileges to .adhoc.alerts* and .internal.adhoc.alerts* indices #127321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
6 changes: 6 additions & 0 deletions docs/changelog/127321.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 127321
summary: Granting `kibana_system` reserved role access to "all" privileges to `.adhoc.alerts*`
and `.internal.adhoc.alerts*` indices
area: Authorization
type: enhancement
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ static RoleDescriptor kibanaSystem(String name) {
RoleDescriptor.IndicesPrivileges.builder().indices(ReservedRolesStore.ALERTS_INDEX_ALIAS).privileges("all").build(),
// "Alerts as data" public index alias used in Security Solution
// Kibana system user uses them to read / write alerts.
RoleDescriptor.IndicesPrivileges.builder()
.indices(ReservedRolesStore.ADHOC_ALERTS_BACKING_INDEX, ReservedRolesStore.ADHOC_ALERTS_INDEX_ALIAS)

Choose a reason for hiding this comment

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

Are these indices created/owned by Kibana?

Copy link
Author

Choose a reason for hiding this comment

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

Correct

.privileges("create_index", "manage", "read", "write")

Choose a reason for hiding this comment

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

@e40pud Thanks for updating this! The last thing I'd like to ask, is about the manage privilege, which inherently includes all of these privileges:

  • manage_data_stream_lifecycle
  • manage_follow_index
  • manage_ilm
  • manage_leader_index
  • monitor
  • maintenance
  • auto_configure

Aiming for the minimum necessary privileges, could we include just a subset of these? If not, could you provide justification to include them? Sorry to have to ask. We like to be as thorough as we can when changing this role.

Copy link
Author

@e40pud e40pud May 9, 2025

Choose a reason for hiding this comment

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

I went through the ES apis that we use to work with this indices and here is the list of all of them:

  1. Simulate an index (API, Usage in kibana)
  2. Simulate index template (API, Usage in kibana)
  3. Create or update an index template (API, Usage in kibana)
  4. Get data streams (API, Usage in kibana)
  5. Create a data stream (API, Usage in kibana)
  6. Get aliases (API, Usage in kibana)
  7. Get index information (API, Usage in kibana)
  8. Create an index (API, Usage in kibana)
  9. Create or update an alias (API, Usage in kibana)
  10. Get index templates (API, Usage in kibana)
  11. Update field mappings (API, Usage in kibana)
  12. Create or update a lifecycle policy (API, Usage in kibana)
  13. Create or update a component template (API, Usage in kibana)
  14. Update index settings (API, Usage in kibana)
  15. Search (API, Usage in kibana)
  16. Bulk index or delete documents (API, Usage in kibana)

Regarding the manage privilege we need it because when we create the index we also specify the alias for it:

esClient.indices.create({
  index: indexPatterns.name,
  aliases: {
    [indexPatterns.alias]: {
      is_write_index: true,
    },
  },
})

and according to the create_index privilege documentation manage privilege is required.

Privilege to create an index or data stream. A create index request may contain aliases to be added to the index once created. In that case the request requires the manage privilege as well, on both the index and the aliases names.

.build(),
// "Alerts as data" public index alias used in Security Solution
// Kibana system user uses them to read / write alerts.
RoleDescriptor.IndicesPrivileges.builder().indices(ReservedRolesStore.PREVIEW_ALERTS_INDEX_ALIAS).privileges("all").build(),
// "Alerts as data" internal backing indices used in Security Solution
// Kibana system user creates these indices; reads / writes to them via the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public class ReservedRolesStore implements BiConsumer<Set<String>, ActionListene
public static final String PREVIEW_ALERTS_BACKING_INDEX = ".internal.preview.alerts*";
public static final String PREVIEW_ALERTS_BACKING_INDEX_REINDEXED = ".reindexed-v8-internal.preview.alerts*";

/** "Attack Discovery" ad-hoc alerts index */
public static final String ADHOC_ALERTS_INDEX_ALIAS = ".adhoc.alerts*";
public static final String ADHOC_ALERTS_BACKING_INDEX = ".internal.adhoc.alerts*";

/** "Security Solutions" only lists index for value lists for detections */
public static final String LISTS_INDEX = ".lists-*";
public static final String LISTS_INDEX_REINDEXED_V8 = ".reindexed-v8-lists-*";
Expand Down Expand Up @@ -782,7 +786,11 @@ private static RoleDescriptor buildViewerRoleDescriptor() {
.build(),
// Alerts-as-data
RoleDescriptor.IndicesPrivileges.builder()
.indices(ReservedRolesStore.ALERTS_INDEX_ALIAS, ReservedRolesStore.PREVIEW_ALERTS_INDEX_ALIAS)
.indices(
ReservedRolesStore.ALERTS_INDEX_ALIAS,
ReservedRolesStore.PREVIEW_ALERTS_INDEX_ALIAS,
ReservedRolesStore.ADHOC_ALERTS_INDEX_ALIAS
)
.privileges("read", "view_index_metadata")
.build(),
// Universal Profiling
Expand Down Expand Up @@ -846,7 +854,9 @@ private static RoleDescriptor buildEditorRoleDescriptor() {
ReservedRolesStore.ALERTS_INDEX_ALIAS,
ReservedRolesStore.PREVIEW_ALERTS_BACKING_INDEX,
ReservedRolesStore.PREVIEW_ALERTS_BACKING_INDEX_REINDEXED,
ReservedRolesStore.PREVIEW_ALERTS_INDEX_ALIAS
ReservedRolesStore.PREVIEW_ALERTS_INDEX_ALIAS,
ReservedRolesStore.ADHOC_ALERTS_BACKING_INDEX,
ReservedRolesStore.ADHOC_ALERTS_INDEX_ALIAS
)
.privileges("read", "view_index_metadata", "write", "maintenance")
.build(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,17 @@ public void testKibanaSystemRole() {
".slo-observability." + randomAlphaOfLength(randomIntBetween(0, 13))
).forEach(index -> assertAllIndicesAccessAllowed(kibanaRole, index));

Arrays.asList(
ReservedRolesStore.ADHOC_ALERTS_INDEX_ALIAS + randomAlphaOfLength(randomIntBetween(0, 13)),
ReservedRolesStore.ADHOC_ALERTS_BACKING_INDEX + randomAlphaOfLength(randomIntBetween(0, 13))
).forEach(index -> {
final IndexAbstraction indexAbstraction = mockIndexAbstraction(index);
assertThat(kibanaRole.indices().allowedIndicesMatcher(TransportCreateIndexAction.TYPE.name()).test(indexAbstraction), is(true));
assertThat(kibanaRole.indices().allowedIndicesMatcher(TransportSearchAction.TYPE.name()).test(indexAbstraction), is(true));
assertThat(kibanaRole.indices().allowedIndicesMatcher(TransportUpdateAction.TYPE.name()).test(indexAbstraction), is(true));
assertViewIndexMetadata(kibanaRole, index);
});

// read-only index access, including cross cluster
Arrays.asList(".monitoring-" + randomAlphaOfLength(randomIntBetween(0, 13))).forEach((index) -> {
logger.info("index name [{}]", index);
Expand Down
Loading