This adds a new cluster privilege `monitor_snapshot` which is a restricted version of `create_snapshot`, granting the same privileges to view snapshot and repository info and status but not granting the actual privilege to create a snapshot. Co-authored-by: j-bean <anton.shuvaev91@gmail.com>
This commit is contained in:
parent
0f2d26bdca
commit
9ae3cd2a78
|
@ -87,6 +87,7 @@ A successful call returns an object with "cluster" and "index" fields.
|
|||
"monitor_data_frame_transforms",
|
||||
"monitor_ml",
|
||||
"monitor_rollup",
|
||||
"monitor_snapshot",
|
||||
"monitor_transform",
|
||||
"monitor_watcher",
|
||||
"none",
|
||||
|
|
|
@ -16,6 +16,9 @@ settings update, rerouting, or managing users and roles.
|
|||
Privileges to create snapshots for existing repositories. Can also list and view
|
||||
details on existing repositories and snapshots.
|
||||
|
||||
`monitor_snapshot`::
|
||||
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
|
||||
|
|
|
@ -75,6 +75,8 @@ public class ClusterPrivilegeResolver {
|
|||
private static final Set<String> CREATE_SNAPSHOT_PATTERN = Collections.unmodifiableSet(
|
||||
Sets.newHashSet(CreateSnapshotAction.NAME, SnapshotsStatusAction.NAME + "*",
|
||||
GetSnapshotsAction.NAME, SnapshotsStatusAction.NAME, GetRepositoriesAction.NAME));
|
||||
private static final Set<String> MONITOR_SNAPSHOT_PATTERN = Collections.unmodifiableSet(Sets.newHashSet(
|
||||
SnapshotsStatusAction.NAME + "*", GetSnapshotsAction.NAME, SnapshotsStatusAction.NAME, GetRepositoriesAction.NAME));
|
||||
private static final Set<String> READ_CCR_PATTERN = Collections.unmodifiableSet(Sets.newHashSet(ClusterStateAction.NAME,
|
||||
HasPrivilegesAction.NAME));
|
||||
private static final Set<String> MANAGE_ILM_PATTERN = Collections.singleton("cluster:admin/ilm/*");
|
||||
|
@ -121,6 +123,7 @@ public class ClusterPrivilegeResolver {
|
|||
public static final NamedClusterPrivilege MANAGE_CCR = new ActionClusterPrivilege("manage_ccr", MANAGE_CCR_PATTERN);
|
||||
public static final NamedClusterPrivilege READ_CCR = new ActionClusterPrivilege("read_ccr", READ_CCR_PATTERN);
|
||||
public static final NamedClusterPrivilege CREATE_SNAPSHOT = new ActionClusterPrivilege("create_snapshot", CREATE_SNAPSHOT_PATTERN);
|
||||
public static final NamedClusterPrivilege MONITOR_SNAPSHOT = new ActionClusterPrivilege("monitor_snapshot", MONITOR_SNAPSHOT_PATTERN);
|
||||
public static final NamedClusterPrivilege MANAGE_ILM = new ActionClusterPrivilege("manage_ilm", MANAGE_ILM_PATTERN);
|
||||
public static final NamedClusterPrivilege READ_ILM = new ActionClusterPrivilege("read_ilm", READ_ILM_PATTERN);
|
||||
public static final NamedClusterPrivilege MANAGE_SLM = new ActionClusterPrivilege("manage_slm", MANAGE_SLM_PATTERN);
|
||||
|
@ -159,6 +162,7 @@ public class ClusterPrivilegeResolver {
|
|||
MANAGE_CCR,
|
||||
READ_CCR,
|
||||
CREATE_SNAPSHOT,
|
||||
MONITOR_SNAPSHOT,
|
||||
MANAGE_ILM,
|
||||
READ_ILM,
|
||||
MANAGE_SLM,
|
||||
|
|
|
@ -36,13 +36,17 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
" - names: 'someindex'\n" +
|
||||
" privileges: [ all ]\n" +
|
||||
"role_d:\n" +
|
||||
" cluster: [ create_snapshot ]\n";
|
||||
" cluster: [ create_snapshot ]\n" +
|
||||
"\n" +
|
||||
"role_e:\n" +
|
||||
" cluster: [ monitor_snapshot]\n";
|
||||
|
||||
private static final String USERS_ROLES =
|
||||
"role_a:user_a\n" +
|
||||
"role_b:user_b\n" +
|
||||
"role_c:user_c\n" +
|
||||
"role_d:user_d\n";
|
||||
"role_d:user_d\n" +
|
||||
"role_e:user_e\n";
|
||||
|
||||
private static Path repositoryLocation;
|
||||
|
||||
|
@ -81,7 +85,8 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
"user_a:" + usersPasswdHashed + "\n" +
|
||||
"user_b:" + usersPasswdHashed + "\n" +
|
||||
"user_c:" + usersPasswdHashed + "\n" +
|
||||
"user_d:" + usersPasswdHashed + "\n";
|
||||
"user_d:" + usersPasswdHashed + "\n" +
|
||||
"user_e:" + usersPasswdHashed + "\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -139,6 +144,19 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
assertAccessIsDenied("user_d", "GET", "/_nodes/infos");
|
||||
assertAccessIsDenied("user_d", "POST", "/_cluster/reroute");
|
||||
assertAccessIsDenied("user_d", "PUT", "/_cluster/settings", "{ \"transient\" : { \"search.default_search_timeout\": \"1m\" } }");
|
||||
|
||||
// user_e can view repos and snapshots on existing repos, everything else is DENIED
|
||||
assertAccessIsDenied("user_e", "GET", "/_cluster/state");
|
||||
assertAccessIsDenied("user_e", "GET", "/_cluster/health");
|
||||
assertAccessIsDenied("user_e", "GET", "/_cluster/settings");
|
||||
assertAccessIsDenied("user_e", "GET", "/_cluster/stats");
|
||||
assertAccessIsDenied("user_e", "GET", "/_cluster/pending_tasks");
|
||||
assertAccessIsDenied("user_e", "GET", "/_nodes/stats");
|
||||
assertAccessIsDenied("user_e", "GET", "/_nodes/hot_threads");
|
||||
assertAccessIsDenied("user_e", "GET", "/_nodes/infos");
|
||||
assertAccessIsDenied("user_e", "POST", "/_cluster/reroute");
|
||||
assertAccessIsDenied("user_e", "PUT", "/_cluster/settings", "{ \"transient\" : { \"search.default_search_timeout\": \"1m\" } }");
|
||||
|
||||
}
|
||||
|
||||
public void testThatSnapshotAndRestore() throws Exception {
|
||||
|
@ -147,6 +165,7 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
assertAccessIsDenied("user_b", "PUT", "/_snapshot/my-repo", repoJson);
|
||||
assertAccessIsDenied("user_c", "PUT", "/_snapshot/my-repo", repoJson);
|
||||
assertAccessIsDenied("user_d", "PUT", "/_snapshot/my-repo", repoJson);
|
||||
assertAccessIsDenied("user_e", "PUT", "/_snapshot/my-repo", repoJson);
|
||||
assertAccessIsAllowed("user_a", "PUT", "/_snapshot/my-repo", repoJson);
|
||||
|
||||
Request createBar = new Request("PUT", "/someindex/bar/1");
|
||||
|
@ -155,16 +174,19 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
assertAccessIsDenied("user_a", createBar);
|
||||
assertAccessIsDenied("user_b", createBar);
|
||||
assertAccessIsDenied("user_d", createBar);
|
||||
assertAccessIsDenied("user_e", createBar);
|
||||
assertAccessIsAllowed("user_c", createBar);
|
||||
|
||||
assertAccessIsDenied("user_b", "PUT", "/_snapshot/my-repo/my-snapshot", "{ \"indices\": \"someindex\" }");
|
||||
assertAccessIsDenied("user_c", "PUT", "/_snapshot/my-repo/my-snapshot", "{ \"indices\": \"someindex\" }");
|
||||
assertAccessIsDenied("user_e", "PUT", "/_snapshot/my-repo/my-snapshot", "{ \"indices\": \"someindex\" }");
|
||||
assertAccessIsAllowed("user_a", "PUT", "/_snapshot/my-repo/my-snapshot", "{ \"indices\": \"someindex\" }");
|
||||
|
||||
assertAccessIsDenied("user_b", "GET", "/_snapshot/my-repo/my-snapshot/_status");
|
||||
assertAccessIsDenied("user_c", "GET", "/_snapshot/my-repo/my-snapshot/_status");
|
||||
assertAccessIsAllowed("user_a", "GET", "/_snapshot/my-repo/my-snapshot/_status");
|
||||
assertAccessIsAllowed("user_d", "GET", "/_snapshot/my-repo/my-snapshot/_status");
|
||||
assertAccessIsAllowed("user_e", "GET", "/_snapshot/my-repo/my-snapshot/_status");
|
||||
|
||||
// This snapshot needs to be finished in order to be restored
|
||||
waitForSnapshotToFinish("my-repo", "my-snapshot");
|
||||
|
@ -175,6 +197,7 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
assertAccessIsDenied("user_a", "DELETE", "/someindex");
|
||||
assertAccessIsDenied("user_b", "DELETE", "/someindex");
|
||||
assertAccessIsDenied("user_d", "DELETE", "/someindex");
|
||||
assertAccessIsDenied("user_e", "DELETE", "/someindex");
|
||||
assertAccessIsAllowed("user_c", "DELETE", "/someindex");
|
||||
|
||||
Request restoreSnapshotRequest = new Request("POST", "/_snapshot/my-repo/my-snapshot/_restore");
|
||||
|
@ -182,21 +205,25 @@ public class ClusterPrivilegeTests extends AbstractPrivilegeTestCase {
|
|||
assertAccessIsDenied("user_b", restoreSnapshotRequest);
|
||||
assertAccessIsDenied("user_c", restoreSnapshotRequest);
|
||||
assertAccessIsDenied("user_d", restoreSnapshotRequest);
|
||||
assertAccessIsDenied("user_e", restoreSnapshotRequest);
|
||||
assertAccessIsAllowed("user_a", restoreSnapshotRequest);
|
||||
|
||||
assertAccessIsDenied("user_a", "GET", "/someindex/bar/1");
|
||||
assertAccessIsDenied("user_b", "GET", "/someindex/bar/1");
|
||||
assertAccessIsDenied("user_d", "GET", "/someindex/bar/1");
|
||||
assertAccessIsDenied("user_e", "GET", "/someindex/bar/1");
|
||||
assertAccessIsAllowed("user_c", "GET", "/someindex/bar/1");
|
||||
|
||||
assertAccessIsDenied("user_b", "DELETE", "/_snapshot/my-repo/my-snapshot");
|
||||
assertAccessIsDenied("user_c", "DELETE", "/_snapshot/my-repo/my-snapshot");
|
||||
assertAccessIsDenied("user_d", "DELETE", "/_snapshot/my-repo/my-snapshot");
|
||||
assertAccessIsDenied("user_e", "DELETE", "/_snapshot/my-repo/my-snapshot");
|
||||
assertAccessIsAllowed("user_a", "DELETE", "/_snapshot/my-repo/my-snapshot");
|
||||
|
||||
assertAccessIsDenied("user_b", "DELETE", "/_snapshot/my-repo");
|
||||
assertAccessIsDenied("user_c", "DELETE", "/_snapshot/my-repo");
|
||||
assertAccessIsDenied("user_d", "DELETE", "/_snapshot/my-repo");
|
||||
assertAccessIsDenied("user_e", "DELETE", "/_snapshot/my-repo");
|
||||
assertAccessIsAllowed("user_a", "DELETE", "/_snapshot/my-repo");
|
||||
}
|
||||
|
||||
|
|
|
@ -15,5 +15,5 @@ setup:
|
|||
# This is fragile - it needs to be updated every time we add a new cluster/index privilege
|
||||
# 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" : 33 }
|
||||
- length: { "cluster" : 34 }
|
||||
- length: { "index" : 17 }
|
||||
|
|
Loading…
Reference in New Issue