1
0
Эх сурвалжийг харах

Add ILM-specific security privileges (#36493)

* add read_ilm cluster privilege

Although managing ILM policies is best done using the
"manage" cluster privilege, it is useful to have read-only
views.

* adds `read_ilm` cluster privilege for viewing policies and status
* adds Explain API to the `view_index_metadata` index privilege

* add manage_ilm privileges
Tal Levy 6 жил өмнө
parent
commit
e3cf642299

+ 5 - 2
client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/privileges/Role.java

@@ -315,9 +315,11 @@ public final class Role {
         public static final String MANAGE_PIPELINE = "manage_pipeline";
         public static final String MANAGE_PIPELINE = "manage_pipeline";
         public static final String MANAGE_CCR = "manage_ccr";
         public static final String MANAGE_CCR = "manage_ccr";
         public static final String READ_CCR = "read_ccr";
         public static final String READ_CCR = "read_ccr";
+        public static final String MANAGE_ILM = "manage_ilm";
+        public static final String READ_ILM = "read_ilm";
         public static final String[] ALL_ARRAY = new String[] { NONE, ALL, MONITOR, MONITOR_ML, MONITOR_WATCHER, MONITOR_ROLLUP, MANAGE,
         public static final String[] ALL_ARRAY = new String[] { NONE, ALL, MONITOR, MONITOR_ML, MONITOR_WATCHER, MONITOR_ROLLUP, MANAGE,
                 MANAGE_ML, MANAGE_WATCHER, MANAGE_ROLLUP, MANAGE_INDEX_TEMPLATES, MANAGE_INGEST_PIPELINES, TRANSPORT_CLIENT,
                 MANAGE_ML, MANAGE_WATCHER, MANAGE_ROLLUP, MANAGE_INDEX_TEMPLATES, MANAGE_INGEST_PIPELINES, TRANSPORT_CLIENT,
-                MANAGE_SECURITY, MANAGE_SAML, MANAGE_TOKEN, MANAGE_PIPELINE, MANAGE_CCR, READ_CCR };
+                MANAGE_SECURITY, MANAGE_SAML, MANAGE_TOKEN, MANAGE_PIPELINE, MANAGE_CCR, READ_CCR, MANAGE_ILM, READ_ILM };
     }
     }
 
 
     /**
     /**
@@ -338,8 +340,9 @@ public final class Role {
         public static final String CREATE_INDEX = "create_index";
         public static final String CREATE_INDEX = "create_index";
         public static final String VIEW_INDEX_METADATA = "view_index_metadata";
         public static final String VIEW_INDEX_METADATA = "view_index_metadata";
         public static final String MANAGE_FOLLOW_INDEX = "manage_follow_index";
         public static final String MANAGE_FOLLOW_INDEX = "manage_follow_index";
+        public static final String MANAGE_ILM = "manage_ilm";
         public static final String[] ALL_ARRAY = new String[] { NONE, ALL, READ, READ_CROSS, CREATE, INDEX, DELETE, WRITE, MONITOR, MANAGE,
         public static final String[] ALL_ARRAY = new String[] { NONE, ALL, READ, READ_CROSS, CREATE, INDEX, DELETE, WRITE, MONITOR, MANAGE,
-                DELETE_INDEX, CREATE_INDEX, VIEW_INDEX_METADATA, MANAGE_FOLLOW_INDEX };
+                DELETE_INDEX, CREATE_INDEX, VIEW_INDEX_METADATA, MANAGE_FOLLOW_INDEX, MANAGE_ILM };
     }
     }
 
 
 }
 }

+ 8 - 0
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/ClusterPrivilege.java

@@ -9,6 +9,8 @@ import org.apache.lucene.util.automaton.Automaton;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.collect.MapBuilder;
 import org.elasticsearch.common.collect.MapBuilder;
+import org.elasticsearch.xpack.core.indexlifecycle.action.GetLifecycleAction;
+import org.elasticsearch.xpack.core.indexlifecycle.action.GetStatusAction;
 import org.elasticsearch.xpack.core.security.action.token.InvalidateTokenAction;
 import org.elasticsearch.xpack.core.security.action.token.InvalidateTokenAction;
 import org.elasticsearch.xpack.core.security.action.token.RefreshTokenAction;
 import org.elasticsearch.xpack.core.security.action.token.RefreshTokenAction;
 import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesAction;
 import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesAction;
@@ -47,6 +49,8 @@ public final class ClusterPrivilege extends Privilege {
     private static final Automaton MANAGE_CCR_AUTOMATON =
     private static final Automaton MANAGE_CCR_AUTOMATON =
         patterns("cluster:admin/xpack/ccr/*", ClusterStateAction.NAME, HasPrivilegesAction.NAME);
         patterns("cluster:admin/xpack/ccr/*", ClusterStateAction.NAME, HasPrivilegesAction.NAME);
     private static final Automaton READ_CCR_AUTOMATON = patterns(ClusterStateAction.NAME, HasPrivilegesAction.NAME);
     private static final Automaton READ_CCR_AUTOMATON = patterns(ClusterStateAction.NAME, HasPrivilegesAction.NAME);
+    private static final Automaton MANAGE_ILM_AUTOMATON = patterns("cluster:admin/ilm/*");
+    private static final Automaton READ_ILM_AUTOMATON = patterns(GetLifecycleAction.NAME, GetStatusAction.NAME);
 
 
     public static final ClusterPrivilege NONE =                  new ClusterPrivilege("none",                Automatons.EMPTY);
     public static final ClusterPrivilege NONE =                  new ClusterPrivilege("none",                Automatons.EMPTY);
     public static final ClusterPrivilege ALL =                   new ClusterPrivilege("all",                 ALL_CLUSTER_AUTOMATON);
     public static final ClusterPrivilege ALL =                   new ClusterPrivilege("all",                 ALL_CLUSTER_AUTOMATON);
@@ -69,6 +73,8 @@ public final class ClusterPrivilege extends Privilege {
     public static final ClusterPrivilege MANAGE_PIPELINE =       new ClusterPrivilege("manage_pipeline", "cluster:admin/ingest/pipeline/*");
     public static final ClusterPrivilege MANAGE_PIPELINE =       new ClusterPrivilege("manage_pipeline", "cluster:admin/ingest/pipeline/*");
     public static final ClusterPrivilege MANAGE_CCR =            new ClusterPrivilege("manage_ccr", MANAGE_CCR_AUTOMATON);
     public static final ClusterPrivilege MANAGE_CCR =            new ClusterPrivilege("manage_ccr", MANAGE_CCR_AUTOMATON);
     public static final ClusterPrivilege READ_CCR =              new ClusterPrivilege("read_ccr", READ_CCR_AUTOMATON);
     public static final ClusterPrivilege READ_CCR =              new ClusterPrivilege("read_ccr", READ_CCR_AUTOMATON);
+    public static final ClusterPrivilege MANAGE_ILM =            new ClusterPrivilege("manage_ilm", MANAGE_ILM_AUTOMATON);
+    public static final ClusterPrivilege READ_ILM =              new ClusterPrivilege("read_ilm", READ_ILM_AUTOMATON);
 
 
     public static final Predicate<String> ACTION_MATCHER = ClusterPrivilege.ALL.predicate();
     public static final Predicate<String> ACTION_MATCHER = ClusterPrivilege.ALL.predicate();
 
 
@@ -92,6 +98,8 @@ public final class ClusterPrivilege extends Privilege {
             .put("manage_rollup", MANAGE_ROLLUP)
             .put("manage_rollup", MANAGE_ROLLUP)
             .put("manage_ccr", MANAGE_CCR)
             .put("manage_ccr", MANAGE_CCR)
             .put("read_ccr", READ_CCR)
             .put("read_ccr", READ_CCR)
+            .put("manage_ilm", MANAGE_ILM)
+            .put("read_ilm", READ_ILM)
             .immutableMap();
             .immutableMap();
 
 
     private static final ConcurrentHashMap<Set<String>, ClusterPrivilege> CACHE = new ConcurrentHashMap<>();
     private static final ConcurrentHashMap<Set<String>, ClusterPrivilege> CACHE = new ConcurrentHashMap<>();

+ 6 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/IndexPrivilege.java

@@ -24,6 +24,7 @@ import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.collect.MapBuilder;
 import org.elasticsearch.common.collect.MapBuilder;
 import org.elasticsearch.xpack.core.ccr.action.PutFollowAction;
 import org.elasticsearch.xpack.core.ccr.action.PutFollowAction;
 import org.elasticsearch.xpack.core.ccr.action.UnfollowAction;
 import org.elasticsearch.xpack.core.ccr.action.UnfollowAction;
+import org.elasticsearch.xpack.core.indexlifecycle.action.ExplainLifecycleAction;
 import org.elasticsearch.xpack.core.security.support.Automatons;
 import org.elasticsearch.xpack.core.security.support.Automatons;
 
 
 import java.util.Arrays;
 import java.util.Arrays;
@@ -57,9 +58,11 @@ public final class IndexPrivilege extends Privilege {
     private static final Automaton DELETE_INDEX_AUTOMATON = patterns(DeleteIndexAction.NAME);
     private static final Automaton DELETE_INDEX_AUTOMATON = patterns(DeleteIndexAction.NAME);
     private static final Automaton VIEW_METADATA_AUTOMATON = patterns(GetAliasesAction.NAME, AliasesExistAction.NAME,
     private static final Automaton VIEW_METADATA_AUTOMATON = patterns(GetAliasesAction.NAME, AliasesExistAction.NAME,
             GetIndexAction.NAME, IndicesExistsAction.NAME, GetFieldMappingsAction.NAME + "*", GetMappingsAction.NAME,
             GetIndexAction.NAME, IndicesExistsAction.NAME, GetFieldMappingsAction.NAME + "*", GetMappingsAction.NAME,
-            ClusterSearchShardsAction.NAME, TypesExistsAction.NAME, ValidateQueryAction.NAME + "*", GetSettingsAction.NAME);
+            ClusterSearchShardsAction.NAME, TypesExistsAction.NAME, ValidateQueryAction.NAME + "*", GetSettingsAction.NAME,
+            ExplainLifecycleAction.NAME);
     private static final Automaton MANAGE_FOLLOW_INDEX_AUTOMATON = patterns(PutFollowAction.NAME, UnfollowAction.NAME,
     private static final Automaton MANAGE_FOLLOW_INDEX_AUTOMATON = patterns(PutFollowAction.NAME, UnfollowAction.NAME,
         CloseIndexAction.NAME);
         CloseIndexAction.NAME);
+    private static final Automaton MANAGE_ILM_AUTOMATON = patterns("indices:admin/ilm/*");
 
 
     public static final IndexPrivilege NONE =                new IndexPrivilege("none",             Automatons.EMPTY);
     public static final IndexPrivilege NONE =                new IndexPrivilege("none",             Automatons.EMPTY);
     public static final IndexPrivilege ALL =                 new IndexPrivilege("all",              ALL_AUTOMATON);
     public static final IndexPrivilege ALL =                 new IndexPrivilege("all",              ALL_AUTOMATON);
@@ -75,6 +78,7 @@ public final class IndexPrivilege extends Privilege {
     public static final IndexPrivilege CREATE_INDEX =        new IndexPrivilege("create_index",        CREATE_INDEX_AUTOMATON);
     public static final IndexPrivilege CREATE_INDEX =        new IndexPrivilege("create_index",        CREATE_INDEX_AUTOMATON);
     public static final IndexPrivilege VIEW_METADATA =       new IndexPrivilege("view_index_metadata", VIEW_METADATA_AUTOMATON);
     public static final IndexPrivilege VIEW_METADATA =       new IndexPrivilege("view_index_metadata", VIEW_METADATA_AUTOMATON);
     public static final IndexPrivilege MANAGE_FOLLOW_INDEX = new IndexPrivilege("manage_follow_index", MANAGE_FOLLOW_INDEX_AUTOMATON);
     public static final IndexPrivilege MANAGE_FOLLOW_INDEX = new IndexPrivilege("manage_follow_index", MANAGE_FOLLOW_INDEX_AUTOMATON);
+    public static final IndexPrivilege MANAGE_ILM =          new IndexPrivilege("manage_ilm",          MANAGE_ILM_AUTOMATON);
 
 
     private static final Map<String, IndexPrivilege> VALUES = MapBuilder.<String, IndexPrivilege>newMapBuilder()
     private static final Map<String, IndexPrivilege> VALUES = MapBuilder.<String, IndexPrivilege>newMapBuilder()
             .put("none", NONE)
             .put("none", NONE)
@@ -91,6 +95,7 @@ public final class IndexPrivilege extends Privilege {
             .put("view_index_metadata", VIEW_METADATA)
             .put("view_index_metadata", VIEW_METADATA)
             .put("read_cross_cluster", READ_CROSS_CLUSTER)
             .put("read_cross_cluster", READ_CROSS_CLUSTER)
             .put("manage_follow_index", MANAGE_FOLLOW_INDEX)
             .put("manage_follow_index", MANAGE_FOLLOW_INDEX)
+            .put("manage_ilm", MANAGE_ILM)
             .immutableMap();
             .immutableMap();
 
 
     public static final Predicate<String> ACTION_MATCHER = ALL.predicate();
     public static final Predicate<String> ACTION_MATCHER = ALL.predicate();

+ 53 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/PrivilegeTests.java

@@ -138,4 +138,57 @@ public class PrivilegeTests extends ESTestCase {
         assertThat(predicate.test("cluster:admin/xpack/whatever"), is(false));
         assertThat(predicate.test("cluster:admin/xpack/whatever"), is(false));
     }
     }
 
 
+    public void testIlmPrivileges() {
+        {
+            Predicate<String> predicate = ClusterPrivilege.MANAGE_ILM.predicate();
+            // check cluster actions
+            assertThat(predicate.test("cluster:admin/ilm/delete"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/_move/post"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/put"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/start"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/stop"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/brand_new_api"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/get"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/operation_mode/get"), is(true));
+            // check non-ilm action
+            assertThat(predicate.test("cluster:admin/whatever"), is(false));
+        }
+
+        {
+            Predicate<String> predicate = ClusterPrivilege.READ_ILM.predicate();
+            // check cluster actions
+            assertThat(predicate.test("cluster:admin/ilm/delete"), is(false));
+            assertThat(predicate.test("cluster:admin/ilm/_move/post"), is(false));
+            assertThat(predicate.test("cluster:admin/ilm/put"), is(false));
+            assertThat(predicate.test("cluster:admin/ilm/start"), is(false));
+            assertThat(predicate.test("cluster:admin/ilm/stop"), is(false));
+            assertThat(predicate.test("cluster:admin/ilm/brand_new_api"), is(false));
+            assertThat(predicate.test("cluster:admin/ilm/get"), is(true));
+            assertThat(predicate.test("cluster:admin/ilm/operation_mode/get"), is(true));
+            // check non-ilm action
+            assertThat(predicate.test("cluster:admin/whatever"), is(false));
+        }
+
+        {
+            Predicate<String> predicate = IndexPrivilege.MANAGE_ILM.predicate();
+            // check indices actions
+            assertThat(predicate.test("indices:admin/ilm/retry"), is(true));
+            assertThat(predicate.test("indices:admin/ilm/remove_policy"), is(true));
+            assertThat(predicate.test("indices:admin/ilm/brand_new_api"), is(true));
+            assertThat(predicate.test("indices:admin/ilm/explain"), is(true));
+            // check non-ilm action
+            assertThat(predicate.test("indices:admin/whatever"), is(false));
+        }
+
+        {
+            Predicate<String> predicate = IndexPrivilege.VIEW_METADATA.predicate();
+            // check indices actions
+            assertThat(predicate.test("indices:admin/ilm/retry"), is(false));
+            assertThat(predicate.test("indices:admin/ilm/remove_policy"), is(false));
+            assertThat(predicate.test("indices:admin/ilm/brand_new_api"), is(false));
+            assertThat(predicate.test("indices:admin/ilm/explain"), is(true));
+            // check non-ilm action
+            assertThat(predicate.test("indices:admin/whatever"), is(false));
+        }
+    }
 }
 }

+ 4 - 1
x-pack/plugin/ilm/qa/with-security/roles.yml

@@ -1,8 +1,11 @@
 ilm:
 ilm:
   cluster:
   cluster:
     - monitor
     - monitor
-    - manage
+    - manage_ilm
   indices:
   indices:
+    - names: [ 'view-only-*' ]
+      privileges:
+        - view_index_metadata
     - names: [ 'ilm-*' ]
     - names: [ 'ilm-*' ]
       privileges:
       privileges:
         - monitor
         - monitor

+ 7 - 0
x-pack/plugin/ilm/qa/with-security/src/test/java/org/elasticsearch/xpack/security/PermissionsIT.java

@@ -119,6 +119,13 @@ public class PermissionsIT extends ESRestTestCase {
         });
         });
     }
     }
 
 
+    public void testCanViewExplainOnUnmanagedIndex() throws Exception {
+        createIndexAsAdmin("view-only-ilm", indexSettingsWithPolicy, "");
+        Request request = new Request("GET", "/view-only-ilm/_ilm/explain");
+        // test_ilm user has permissions to view
+        assertOK(client().performRequest(request));
+    }
+
     private void createNewSingletonPolicy(String policy, String phaseName, LifecycleAction action) throws IOException {
     private void createNewSingletonPolicy(String policy, String phaseName, LifecycleAction action) throws IOException {
         Phase phase = new Phase(phaseName, TimeValue.ZERO, singletonMap(action.getWriteableName(), action));
         Phase phase = new Phase(phaseName, TimeValue.ZERO, singletonMap(action.getWriteableName(), action));
         LifecyclePolicy lifecyclePolicy = new LifecyclePolicy(policy, singletonMap(phase.getName(), phase));
         LifecyclePolicy lifecyclePolicy = new LifecyclePolicy(policy, singletonMap(phase.getName(), phase));