Browse Source

[Failure Store] Access for internal users (#125660) (#125780)

This PR grants `manage_failure_store` to the internal user
`_data_stream_lifecycle` to enable life-cycle management for the failure
indices of data stream, which includes rollovers using the failures
selector.

I'm only unit testing this but we also need to add DLM tests for the
failure store with security enabled. 

Relates: ES-11355

Co-authored-by: Slobodan Adamović <slobodanadamovic@users.noreply.github.com>
Nikolaj Volgushev 7 months ago
parent
commit
34c24dfae2

+ 42 - 35
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/InternalUsers.java

@@ -36,9 +36,11 @@ import org.elasticsearch.xpack.core.ilm.action.ILMActions;
 import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
 import org.elasticsearch.xpack.core.security.support.MetadataUtils;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -158,14 +160,18 @@ public class InternalUsers {
                 RoleDescriptor.IndicesPrivileges.builder()
                     .indices("*")
                     .privileges(
-                        "delete_index",
-                        RolloverAction.NAME,
-                        ForceMergeAction.NAME + "*",
-                        // indices stats is used by rollover, so we need to grant it here
-                        IndicesStatsAction.NAME + "*",
-                        TransportUpdateSettingsAction.TYPE.name(),
-                        DownsampleAction.NAME,
-                        TransportAddIndexBlockAction.TYPE.name()
+                        filterNonNull(
+                            // needed to rollover failure store
+                            DataStream.isFailureStoreFeatureFlagEnabled() ? "manage_failure_store" : null,
+                            "delete_index",
+                            RolloverAction.NAME,
+                            ForceMergeAction.NAME + "*",
+                            // indices stats is used by rollover, so we need to grant it here
+                            IndicesStatsAction.NAME + "*",
+                            TransportUpdateSettingsAction.TYPE.name(),
+                            DownsampleAction.NAME,
+                            TransportAddIndexBlockAction.TYPE.name()
+                        )
                     )
                     .allowRestrictedIndices(false)
                     .build(),
@@ -177,14 +183,18 @@ public class InternalUsers {
                         ".fleet-fileds*"
                     )
                     .privileges(
-                        "delete_index",
-                        RolloverAction.NAME,
-                        ForceMergeAction.NAME + "*",
-                        // indices stats is used by rollover, so we need to grant it here
-                        IndicesStatsAction.NAME + "*",
-                        TransportUpdateSettingsAction.TYPE.name(),
-                        DownsampleAction.NAME,
-                        TransportAddIndexBlockAction.TYPE.name()
+                        filterNonNull(
+                            // needed to rollover failure store
+                            DataStream.isFailureStoreFeatureFlagEnabled() ? "manage_failure_store" : null,
+                            "delete_index",
+                            RolloverAction.NAME,
+                            ForceMergeAction.NAME + "*",
+                            // indices stats is used by rollover, so we need to grant it here
+                            IndicesStatsAction.NAME + "*",
+                            TransportUpdateSettingsAction.TYPE.name(),
+                            DownsampleAction.NAME,
+                            TransportAddIndexBlockAction.TYPE.name()
+                        )
                     )
                     .allowRestrictedIndices(true)
                     .build() },
@@ -248,25 +258,18 @@ public class InternalUsers {
         new RoleDescriptor(
             UsernamesField.LAZY_ROLLOVER_ROLE,
             new String[] {},
-            DataStream.isFailureStoreFeatureFlagEnabled()
-                ? new RoleDescriptor.IndicesPrivileges[] {
-                    RoleDescriptor.IndicesPrivileges.builder()
-                        .indices("*")
-                        .privileges(LazyRolloverAction.NAME)
-                        .allowRestrictedIndices(true)
-                        .build(),
-                    RoleDescriptor.IndicesPrivileges.builder()
-                        .indices("*")
-                        // needed to rollover failure store
-                        .privileges("manage_failure_store")
-                        .allowRestrictedIndices(true)
-                        .build() }
-                : new RoleDescriptor.IndicesPrivileges[] {
-                    RoleDescriptor.IndicesPrivileges.builder()
-                        .indices("*")
-                        .privileges(LazyRolloverAction.NAME)
-                        .allowRestrictedIndices(true)
-                        .build(), },
+            new RoleDescriptor.IndicesPrivileges[] {
+                RoleDescriptor.IndicesPrivileges.builder()
+                    .indices("*")
+                    .privileges(
+                        filterNonNull(
+                            // needed to rollover failure store
+                            DataStream.isFailureStoreFeatureFlagEnabled() ? "manage_failure_store" : null,
+                            LazyRolloverAction.NAME
+                        )
+                    )
+                    .allowRestrictedIndices(true)
+                    .build() },
             null,
             null,
             new String[] {},
@@ -324,4 +327,8 @@ public class InternalUsers {
         }
         return instance;
     }
+
+    private static String[] filterNonNull(String... privileges) {
+        return Arrays.stream(privileges).filter(Objects::nonNull).toArray(String[]::new);
+    }
 }

+ 18 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/user/InternalUsersTests.java

@@ -271,6 +271,7 @@ public class InternalUsersTests extends ESTestCase {
             TransportAddIndexBlockAction.TYPE.name()
         );
         final String dataStream = randomAlphaOfLengthBetween(3, 12);
+
         checkIndexAccess(role, randomFrom(sampleIndexActions), dataStream, true);
         // Also check backing index access
         checkIndexAccess(
@@ -280,6 +281,15 @@ public class InternalUsersTests extends ESTestCase {
             true
         );
 
+        checkIndexAccess(role, randomFrom(sampleIndexActions), dataStream + "::failures", true);
+        // Also check failure index access
+        checkIndexAccess(
+            role,
+            randomFrom(sampleIndexActions),
+            DataStream.FAILURE_STORE_PREFIX + dataStream + randomAlphaOfLengthBetween(4, 8),
+            true
+        );
+
         allowedSystemDataStreams.forEach(allowedSystemDataStream -> {
             checkIndexAccess(role, randomFrom(sampleSystemDataStreamActions), allowedSystemDataStream, true);
             checkIndexAccess(
@@ -288,6 +298,14 @@ public class InternalUsersTests extends ESTestCase {
                 DataStream.BACKING_INDEX_PREFIX + allowedSystemDataStream + randomAlphaOfLengthBetween(4, 8),
                 true
             );
+
+            checkIndexAccess(role, randomFrom(sampleSystemDataStreamActions), allowedSystemDataStream + "::failures", true);
+            checkIndexAccess(
+                role,
+                randomFrom(sampleSystemDataStreamActions),
+                DataStream.FAILURE_STORE_PREFIX + allowedSystemDataStream + randomAlphaOfLengthBetween(4, 8),
+                true
+            );
         });
 
         checkIndexAccess(role, randomFrom(sampleSystemDataStreamActions), randomFrom(TestRestrictedIndices.SAMPLE_RESTRICTED_NAMES), false);