diff --git a/x-pack/docs/en/rest-api/security/get-service-accounts.asciidoc b/x-pack/docs/en/rest-api/security/get-service-accounts.asciidoc index d0ef2b5047ab7..7f1a7c9686e66 100644 --- a/x-pack/docs/en/rest-api/security/get-service-accounts.asciidoc +++ b/x-pack/docs/en/rest-api/security/get-service-accounts.asciidoc @@ -84,6 +84,17 @@ GET /_security/service/elastic/fleet-server ], "allow_restricted_indices": false }, + { + "names" : [ + "traces-apm.sampled-*" + ], + "privileges" : [ + "read", + "monitor", + "maintenance" + ], + "allow_restricted_indices": false + }, { "names": [ ".fleet-*" diff --git a/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java b/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java index 00e3d53616ed7..b08952b78e40f 100644 --- a/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java +++ b/x-pack/plugin/security/qa/service-account/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/service/ServiceAccountIT.java @@ -101,6 +101,17 @@ public class ServiceAccountIT extends ESRestTestCase { ], "allow_restricted_indices": false }, + { + "names": [ + "traces-apm.sampled-*" + ], + "privileges": [ + "read", + "monitor", + "maintenance" + ], + "allow_restricted_indices": false + }, { "names": [ ".fleet-*" diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccounts.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccounts.java index 90e2076603b1f..43cee77e76c26 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccounts.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccounts.java @@ -39,6 +39,15 @@ final class ElasticServiceAccounts { ) .privileges("write", "create_index", "auto_configure") .build(), + RoleDescriptor.IndicesPrivileges.builder() + // APM Server (and hence Fleet Server, which issues its API Keys) needs additional privileges + // for the non-sensitive "sampled traces" data stream: + // - "maintenance" privilege to refresh indices + // - "monitor" privilege to be able to query index stats for the global checkpoint + // - "read" privilege to search the documents + .indices("traces-apm.sampled-*") + .privileges("read", "monitor", "maintenance") + .build(), RoleDescriptor.IndicesPrivileges.builder() .indices(".fleet-*") // Fleet Server needs "maintenance" privilege to be able to perform operations with "refresh" diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccountsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccountsTests.java index e8f4e8281ef33..c93c087b405d4 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccountsTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccountsTests.java @@ -206,6 +206,19 @@ public void testElasticFleetServerPrivileges() { assertThat(role.indices().allowedIndicesMatcher("indices:foo").test(dotFleetIndex), is(false)); }); + final IndexAbstraction apmSampledTracesIndex = mockIndexAbstraction("traces-apm.sampled-" + randomAlphaOfLengthBetween(1, 20)); + assertThat(role.indices().allowedIndicesMatcher(DeleteAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(CreateIndexAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(IndexAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(BulkAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(GetAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(MultiGetAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(SearchAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(IndicesStatsAction.NAME).test(apmSampledTracesIndex), is(true)); + assertThat(role.indices().allowedIndicesMatcher(DeleteIndexAction.NAME).test(apmSampledTracesIndex), is(false)); + assertThat(role.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(apmSampledTracesIndex), is(false)); + final String kibanaApplication = "kibana-" + randomFrom(randomAlphaOfLengthBetween(8, 24), ".kibana"); final String privilegeName = randomAlphaOfLengthBetween(3, 16); assertThat(