diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/privileges/Role.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/privileges/Role.java index 3ef0d6dd33252..738f41e38b2b5 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/privileges/Role.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/privileges/Role.java @@ -350,8 +350,9 @@ public static class IndexPrivilegeName { public static final String MANAGE_FOLLOW_INDEX = "manage_follow_index"; public static final String MANAGE_ILM = "manage_ilm"; public static final String CREATE_DOC = "create_doc"; + public static final String MAINTENANCE = "maintenance"; 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, MANAGE_ILM, CREATE_DOC }; + DELETE_INDEX, CREATE_INDEX, VIEW_INDEX_METADATA, MANAGE_FOLLOW_INDEX, MANAGE_ILM, CREATE_DOC, MAINTENANCE }; } } diff --git a/x-pack/docs/en/rest-api/security/get-builtin-privileges.asciidoc b/x-pack/docs/en/rest-api/security/get-builtin-privileges.asciidoc index e5af329b63843..72a419c0bbb87 100644 --- a/x-pack/docs/en/rest-api/security/get-builtin-privileges.asciidoc +++ b/x-pack/docs/en/rest-api/security/get-builtin-privileges.asciidoc @@ -12,7 +12,7 @@ available in this version of {es}. [[security-api-get-builtin-privileges-request]] ==== {api-request-title} -`GET /_security/privilege/_builtin` +`GET /_security/privilege/_builtin` [[security-api-get-builtin-privileges-prereqs]] @@ -104,6 +104,7 @@ A successful call returns an object with "cluster" and "index" fields. "delete", "delete_index", "index", + "maintenance", "manage", "manage_follow_index", "manage_ilm", diff --git a/x-pack/docs/en/security/authorization/privileges.asciidoc b/x-pack/docs/en/security/authorization/privileges.asciidoc index 1d53c7b20aa6a..0db5300b66bc5 100644 --- a/x-pack/docs/en/security/authorization/privileges.asciidoc +++ b/x-pack/docs/en/security/authorization/privileges.asciidoc @@ -21,12 +21,12 @@ Privileges to list and view details on existing repositories and snapshots. `manage`:: Builds on `monitor` and adds cluster operations that change values in the cluster. -This includes snapshotting, updating settings, and rerouting. It also includes -obtaining snapshot and restore status. This privilege does not include the +This includes snapshotting, updating settings, and rerouting. It also includes +obtaining snapshot and restore status. This privilege does not include the ability to manage security. `manage_api_key`:: -All security-related operations on {es} API keys including +All security-related operations on {es} API keys including <>, <>, and <>. @@ -45,10 +45,10 @@ owned by other users. -- `manage_ccr`:: -All {ccr} operations related to managing follower indices and auto-follow -patterns. It also includes the authority to grant the privileges necessary to -manage follower indices and auto-follow patterns. This privilege is necessary -only on clusters that contain follower indices. +All {ccr} operations related to managing follower indices and auto-follow +patterns. It also includes the authority to grant the privileges necessary to +manage follower indices and auto-follow patterns. This privilege is necessary +only on clusters that contain follower indices. `manage_transform`:: All operations related to managing {transforms}. @@ -83,7 +83,7 @@ to initiate and manage OpenID Connect authentication on behalf of other users. `manage_own_api_key`:: All security-related operations on {es} API keys that are owned by the current -authenticated user. The operations include +authenticated user. The operations include <>, <>, and <>. @@ -119,7 +119,7 @@ security roles of the user who created or updated them. -- `monitor`:: -All cluster read-only operations, like cluster health and state, hot threads, +All cluster read-only operations, like cluster health and state, hot threads, node info, node and cluster stats, and pending cluster tasks. `monitor_transform`:: @@ -131,16 +131,16 @@ model snapshots, or results. `monitor_rollup`:: All read-only rollup operations, such as viewing the list of historical and -currently running rollup jobs and their capabilities. +currently running rollup jobs and their capabilities. `monitor_watcher`:: All read-only watcher operations, such as getting a watch and watcher stats. `read_ccr`:: -All read-only {ccr} operations, such as getting information about indices and -metadata for leader indices in the cluster. It also includes the authority to -check whether users have the appropriate privileges to follow leader indices. -This privilege is necessary only on clusters that contain leader indices. +All read-only {ccr} operations, such as getting information about indices and +metadata for leader indices in the cluster. It also includes the authority to +check whether users have the appropriate privileges to follow leader indices. +This privilege is necessary only on clusters that contain leader indices. `read_ilm`:: All read-only {Ilm} operations, such as getting policies and checking the @@ -204,6 +204,10 @@ Privilege to delete an index. Privilege to index and update documents. Also grants access to the update mapping action. +`maintenance`:: +Permits refresh, flush, synced flush and force merge index administration operations. +No privilege to read or write index data or otherwise manage the index. + `manage`:: All `monitor` privileges plus index administration (aliases, analyze, cache clear, close, delete, exists, flush, mapping, open, force merge, refresh, settings, @@ -211,8 +215,8 @@ search shards, templates, validate). `manage_follow_index`:: All actions that are required to manage the lifecycle of a follower index, which -includes creating a follower index, closing it, and converting it to a regular -index. This privilege is necessary only on clusters that contain follower indices. +includes creating a follower index, closing it, and converting it to a regular +index. This privilege is necessary only on clusters that contain follower indices. `manage_ilm`:: All {Ilm} operations relating to managing the execution of policies of an index @@ -225,7 +229,7 @@ includes <>. This privilege is necessary only on clusters that contain leader indices. `monitor`:: -All actions that are required for monitoring (recovery, segments info, index +All actions that are required for monitoring (recovery, segments info, index stats and status). `read`:: @@ -258,14 +262,14 @@ sequence.) For more information, see [[application-privileges]] ==== Application privileges -Application privileges are managed within {es} and can be retrieved with the -<> and the -<>. They do -not, however, grant access to any actions or resources within {es}. Their -purpose is to enable applications to represent and store their own privilege -models within {es} roles. - -To create application privileges, use the -<>. You can -then associate these application privileges with roles, as described in -<>. +Application privileges are managed within {es} and can be retrieved with the +<> and the +<>. They do +not, however, grant access to any actions or resources within {es}. Their +purpose is to enable applications to represent and store their own privilege +models within {es} roles. + +To create application privileges, use the +<>. You can +then associate these application privileges with roles, as described in +<>. diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/IndexPrivilege.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/IndexPrivilege.java index 8ae7337ba195f..47dad67ee1af9 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/IndexPrivilege.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/privilege/IndexPrivilege.java @@ -66,6 +66,8 @@ public final class IndexPrivilege extends Privilege { CloseIndexAction.NAME + "*"); private static final Automaton MANAGE_LEADER_INDEX_AUTOMATON = patterns(ForgetFollowerAction.NAME + "*"); private static final Automaton MANAGE_ILM_AUTOMATON = patterns("indices:admin/ilm/*"); + private static final Automaton MAINTENANCE_AUTOMATON = patterns("indices:admin/refresh*", "indices:admin/flush*", + "indices:admin/synced_flush", "indices:admin/forcemerge*"); public static final IndexPrivilege NONE = new IndexPrivilege("none", Automatons.EMPTY); public static final IndexPrivilege ALL = new IndexPrivilege("all", ALL_AUTOMATON); @@ -83,7 +85,8 @@ public final class IndexPrivilege extends Privilege { 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_LEADER_INDEX = new IndexPrivilege("manage_leader_index", MANAGE_LEADER_INDEX_AUTOMATON); - public static final IndexPrivilege MANAGE_ILM = new IndexPrivilege("manage_ilm", MANAGE_ILM_AUTOMATON); + public static final IndexPrivilege MANAGE_ILM = new IndexPrivilege("manage_ilm", MANAGE_ILM_AUTOMATON); + public static final IndexPrivilege MAINTENANCE = new IndexPrivilege("maintenance", MAINTENANCE_AUTOMATON); private static final Map VALUES = Map.ofEntries( entry("none", NONE), @@ -102,7 +105,8 @@ public final class IndexPrivilege extends Privilege { entry("read_cross_cluster", READ_CROSS_CLUSTER), entry("manage_follow_index", MANAGE_FOLLOW_INDEX), entry("manage_leader_index", MANAGE_LEADER_INDEX), - entry("manage_ilm", MANAGE_ILM)); + entry("manage_ilm", MANAGE_ILM), + entry("maintenance", MAINTENANCE)); public static final Predicate ACTION_MATCHER = ALL.predicate(); public static final Predicate CREATE_INDEX_MATCHER = CREATE_INDEX.predicate(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java index f0d2b3ad14a67..880186f0dbb03 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java @@ -69,6 +69,10 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase { " indices:\n" + " - names: 'b'\n" + " privileges: [ monitor ]\n" + + "maintenance_a_role:\n" + + " indices:\n" + + " - names: 'a'\n" + + " privileges: [ maintenance ]\n" + "read_write_a_role:\n" + " indices:\n" + " - names: 'a'\n" + @@ -96,6 +100,7 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase { "read_write_all_role:u12\n" + "create_c_role:u11\n" + "monitor_b_role:u14\n" + + "maintenance_a_role:u15\n" + "read_write_a_role:u12\n" + "delete_b_role:u11\n" + "index_a_role:u13\n"; @@ -129,7 +134,8 @@ protected String configUsers() { "u11:" + usersPasswdHashed + "\n" + "u12:" + usersPasswdHashed + "\n" + "u13:" + usersPasswdHashed + "\n" + - "u14:" + usersPasswdHashed + "\n"; + "u14:" + usersPasswdHashed + "\n" + + "u15:" + usersPasswdHashed + "\n" ; } @Override @@ -308,12 +314,14 @@ public void testUserU11() throws Exception { assertUserIsDenied("u11", "manage", "b"); assertUserIsDenied("u11", "index", "b"); assertUserIsDenied("u11", "search", "b"); + assertUserIsDenied("u11", "maintenance", "b"); assertUserIsAllowed("u11", "delete", "b"); assertAccessIsAllowed("admin", "DELETE", "/c"); assertUserIsAllowed("u11", "create_index", "c"); assertUserIsDenied("u11", "data_access", "c"); assertUserIsDenied("u11", "monitor", "c"); + assertUserIsDenied("u11", "maintenance", "c"); assertAccessIsDenied("u11", "GET", "/" + randomIndex() + "/_msearch", "{}\n{ \"query\" : { \"match_all\" : {} } }\n"); @@ -385,6 +393,11 @@ public void testUserU14() throws Exception { "GET", "/" + randomIndex() + "/_mtermvectors", "{ \"docs\" : [ { \"_id\": \"1\" }, { \"_id\": \"2\" } ] }"); } + public void testUserU15() throws Exception { + assertUserIsAllowed("u15", "maintenance", "a"); + assertUserIsDenied("u15", "crud", "a"); + } + public void testThatUnknownUserIsRejectedProperly() throws Exception { try { Request request = new Request("GET", "/"); @@ -419,6 +432,20 @@ private void assertUserExecutes(String user, String action, String index, boolea } break; + case "maintenance" : + if (userIsAllowed) { + assertAccessIsAllowed(user, "POST", "/" + index + "/_refresh"); + assertAccessIsAllowed(user, "POST", "/" + index + "/_flush"); + assertAccessIsAllowed(user, "POST", "/" + index + "/_flush/synced"); + assertAccessIsAllowed(user, "POST", "/" + index + "/_forcemerge"); + } else { + assertAccessIsDenied(user, "POST", "/" + index + "/_refresh"); + assertAccessIsDenied(user, "POST", "/" + index + "/_flush"); + assertAccessIsDenied(user, "POST", "/" + index + "/_flush/synced"); + assertAccessIsDenied(user, "POST", "/" + index + "/_forcemerge"); + } + break; + case "manage" : if (userIsAllowed) { assertAccessIsAllowed(user, "DELETE", "/" + index); diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/privileges/11_builtin.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/privileges/11_builtin.yml index 02961a2db12f8..4875247b87d73 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/privileges/11_builtin.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/privileges/11_builtin.yml @@ -16,4 +16,4 @@ setup: # I would much prefer we could just check that specific entries are in the array, but we don't have # an assertion for that - length: { "cluster" : 34 } - - length: { "index" : 17 } + - length: { "index" : 18 }