Skip to content

Commit

Permalink
add read_ilm cluster privilege
Browse files Browse the repository at this point in the history
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
  • Loading branch information
talevy committed Dec 11, 2018
1 parent c1e3bdd commit 6cae7e5
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
import org.elasticsearch.common.Strings;
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.RefreshTokenAction;
import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesAction;
Expand Down Expand Up @@ -47,6 +49,7 @@ public final class ClusterPrivilege extends Privilege {
private static final Automaton MANAGE_CCR_AUTOMATON =
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_ILM_AUTOMATON = patterns(GetLifecycleAction.NAME, GetStatusAction.NAME);

public static final ClusterPrivilege NONE = new ClusterPrivilege("none", Automatons.EMPTY);
public static final ClusterPrivilege ALL = new ClusterPrivilege("all", ALL_CLUSTER_AUTOMATON);
Expand All @@ -69,6 +72,7 @@ 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_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_ILM = new ClusterPrivilege("read_ilm", READ_ILM_AUTOMATON);

public static final Predicate<String> ACTION_MATCHER = ClusterPrivilege.ALL.predicate();

Expand All @@ -92,6 +96,7 @@ public final class ClusterPrivilege extends Privilege {
.put("manage_rollup", MANAGE_ROLLUP)
.put("manage_ccr", MANAGE_CCR)
.put("read_ccr", READ_CCR)
.put("read_ilm", READ_ILM)
.immutableMap();

private static final ConcurrentHashMap<Set<String>, ClusterPrivilege> CACHE = new ConcurrentHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.xpack.core.ccr.action.PutFollowAction;
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 java.util.Arrays;
Expand Down Expand Up @@ -57,7 +58,8 @@ public final class IndexPrivilege extends Privilege {
private static final Automaton DELETE_INDEX_AUTOMATON = patterns(DeleteIndexAction.NAME);
private static final Automaton VIEW_METADATA_AUTOMATON = patterns(GetAliasesAction.NAME, AliasesExistAction.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,
CloseIndexAction.NAME);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,31 @@ public void testManageCcrPrivilege() {
assertThat(predicate.test("cluster:admin/xpack/whatever"), is(false));
}

public void testManageIlmPrivilege() {
{
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.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));
}
}
}
3 changes: 3 additions & 0 deletions x-pack/plugin/ilm/qa/with-security/roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ ilm:
- monitor
- manage
indices:
- names: [ 'view-only-*' ]
privileges:
- view_index_metadata
- names: [ 'ilm-*' ]
privileges:
- monitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ public void testCanManageIndexWithNoPermissions() throws Exception {
});
}

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 {
Phase phase = new Phase(phaseName, TimeValue.ZERO, singletonMap(action.getWriteableName(), action));
LifecyclePolicy lifecyclePolicy = new LifecyclePolicy(policy, singletonMap(phase.getName(), phase));
Expand Down

0 comments on commit 6cae7e5

Please sign in to comment.