Browse Source

Extend fleet-server service account privileges (#82600)

* Extend fleet-server service account privileges

Allow elastic/fleet-server service account to
additionally read, monitor, and refresh
traces-apm.sampled-* data streams.

These data streams do not contain any sensitive
information. Fleet-server itself does not need
to perform these actions, but it creates API
Keys for APM Server, which does need to.

* Update x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccounts.java

Co-authored-by: Yang Wang <ywangd@gmail.com>

* Apply suggestions from code review

Co-authored-by: Yang Wang <ywangd@gmail.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Andrew Wilkins 3 years ago
parent
commit
ef1f7a5365

+ 11 - 0
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-*"

+ 11 - 0
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-*"

+ 9 - 0
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"

+ 13 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/ElasticServiceAccountsTests.java

@@ -206,6 +206,19 @@ public class ElasticServiceAccountsTests extends ESTestCase {
             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(