Skip to content

Commit 0083161

Browse files
authored
Extend ClusterPermission to consider requests (#31998)
This lays the foundation for OLS on cluster privileges as it means that a cluster permission can be applied not just to actions, but also the objects being acted upon by the request.
1 parent 610e587 commit 0083161

File tree

7 files changed

+313
-211
lines changed

7 files changed

+313
-211
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/ClusterPermission.java

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,92 @@
55
*/
66
package org.elasticsearch.xpack.core.security.authz.permission;
77

8+
import org.elasticsearch.transport.TransportRequest;
89
import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege;
910

11+
import java.util.Collection;
12+
import java.util.Set;
1013
import java.util.function.Predicate;
14+
import java.util.stream.Collectors;
1115

1216
/**
13-
* A permission that is based on privileges for cluster wide actions
17+
* A permission that is based on privileges for cluster wide actions, with the optional ability to inspect the request object
1418
*/
15-
public final class ClusterPermission {
16-
17-
public static final ClusterPermission NONE = new ClusterPermission(ClusterPrivilege.NONE);
18-
19+
public abstract class ClusterPermission {
1920
private final ClusterPrivilege privilege;
20-
private final Predicate<String> predicate;
2121

2222
ClusterPermission(ClusterPrivilege privilege) {
2323
this.privilege = privilege;
24-
this.predicate = privilege.predicate();
2524
}
2625

2726
public ClusterPrivilege privilege() {
2827
return privilege;
2928
}
3029

31-
public boolean check(String action) {
32-
return predicate.test(action);
30+
public abstract boolean check(String action, TransportRequest request);
31+
32+
/**
33+
* A permission that is based solely on cluster privileges and does not consider request state
34+
*/
35+
public static class SimpleClusterPermission extends ClusterPermission {
36+
37+
public static final SimpleClusterPermission NONE = new SimpleClusterPermission(ClusterPrivilege.NONE);
38+
39+
private final Predicate<String> predicate;
40+
41+
SimpleClusterPermission(ClusterPrivilege privilege) {
42+
super(privilege);
43+
this.predicate = privilege.predicate();
44+
}
45+
46+
@Override
47+
public boolean check(String action, TransportRequest request) {
48+
return predicate.test(action);
49+
}
50+
}
51+
52+
/**
53+
* A permission that makes use of both cluster privileges and request inspection
54+
*/
55+
public static class ConditionalClusterPermission extends ClusterPermission {
56+
private final Predicate<String> actionPredicate;
57+
private final Predicate<TransportRequest> requestPredicate;
58+
59+
public ConditionalClusterPermission(ClusterPrivilege privilege, Predicate<TransportRequest> requestPredicate) {
60+
super(privilege);
61+
this.actionPredicate = privilege.predicate();
62+
this.requestPredicate = requestPredicate;
63+
}
64+
65+
@Override
66+
public boolean check(String action, TransportRequest request) {
67+
return actionPredicate.test(action) && requestPredicate.test(request);
68+
}
69+
}
70+
71+
/**
72+
* A permission that composes a number of other cluster permissions
73+
*/
74+
public static class CompositeClusterPermission extends ClusterPermission {
75+
private final Collection<ClusterPermission> children;
76+
77+
public CompositeClusterPermission(Collection<ClusterPermission> children) {
78+
super(buildPrivilege(children));
79+
this.children = children;
80+
}
81+
82+
private static ClusterPrivilege buildPrivilege(Collection<ClusterPermission> children) {
83+
final Set<String> names = children.stream()
84+
.map(ClusterPermission::privilege)
85+
.map(ClusterPrivilege::name)
86+
.flatMap(Set::stream)
87+
.collect(Collectors.toSet());
88+
return ClusterPrivilege.get(names);
89+
}
90+
91+
@Override
92+
public boolean check(String action, TransportRequest request) {
93+
return children.stream().anyMatch(p -> p.check(action, request));
94+
}
3395
}
3496
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/Role.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public IndicesAccessControl authorize(String action, Set<String> requestedIndice
9595
public static class Builder {
9696

9797
private final String[] names;
98-
private ClusterPermission cluster = ClusterPermission.NONE;
98+
private ClusterPermission cluster = ClusterPermission.SimpleClusterPermission.NONE;
9999
private RunAsPermission runAs = RunAsPermission.NONE;
100100
private List<IndicesPermission.Group> groups = new ArrayList<>();
101101
private List<Tuple<ApplicationPrivilege, Set<String>>> applicationPrivs = new ArrayList<>();
@@ -107,7 +107,7 @@ private Builder(String[] names) {
107107
private Builder(RoleDescriptor rd, @Nullable FieldPermissionsCache fieldPermissionsCache) {
108108
this.names = new String[] { rd.getName() };
109109
if (rd.getClusterPrivileges().length == 0) {
110-
cluster = ClusterPermission.NONE;
110+
cluster = ClusterPermission.SimpleClusterPermission.NONE;
111111
} else {
112112
this.cluster(ClusterPrivilege.get(Sets.newHashSet(rd.getClusterPrivileges())));
113113
}
@@ -125,7 +125,7 @@ private Builder(RoleDescriptor rd, @Nullable FieldPermissionsCache fieldPermissi
125125
}
126126

127127
public Builder cluster(ClusterPrivilege privilege) {
128-
cluster = new ClusterPermission(privilege);
128+
cluster = new ClusterPermission.SimpleClusterPermission(privilege);
129129
return this;
130130
}
131131

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class ReservedRolesStore {
2727
new String[] { "all" },
2828
new RoleDescriptor.IndicesPrivileges[] {
2929
RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").build()},
30-
new RoleDescriptor.ApplicationResourcePrivileges[]{
30+
new RoleDescriptor.ApplicationResourcePrivileges[] {
3131
RoleDescriptor.ApplicationResourcePrivileges.builder().application("*").privileges("*").resources("*").build()
3232
},
3333
new String[] { "*" },

0 commit comments

Comments
 (0)