|
16 | 16 | import org.apache.logging.log4j.LogManager;
|
17 | 17 | import org.apache.logging.log4j.Logger;
|
18 | 18 |
|
19 |
| -import org.opensearch.OpenSearchSecurityException; |
20 |
| -import org.opensearch.cluster.service.ClusterService; |
21 |
| -import org.opensearch.common.util.concurrent.ThreadContext; |
22 |
| -import org.opensearch.core.common.transport.TransportAddress; |
23 |
| -import org.opensearch.security.securityconf.ConfigModel; |
24 |
| -import org.opensearch.security.securityconf.SecurityRoles; |
25 |
| -import org.opensearch.security.support.ConfigConstants; |
26 | 19 | import org.opensearch.security.user.User;
|
27 |
| -import org.opensearch.threadpool.ThreadPool; |
28 |
| - |
29 |
| -import org.greenrobot.eventbus.Subscribe; |
30 | 20 |
|
31 | 21 | public class RestLayerPrivilegesEvaluator {
|
32 | 22 | protected final Logger log = LogManager.getLogger(this.getClass());
|
33 |
| - private final ClusterService clusterService; |
34 |
| - private ThreadContext threadContext; |
35 |
| - private ConfigModel configModel; |
36 |
| - |
37 |
| - public RestLayerPrivilegesEvaluator(final ClusterService clusterService, final ThreadPool threadPool) { |
38 |
| - this.clusterService = clusterService; |
39 |
| - this.threadContext = threadPool.getThreadContext(); |
40 |
| - } |
41 |
| - |
42 |
| - @Subscribe |
43 |
| - public void onConfigModelChanged(final ConfigModel configModel) { |
44 |
| - this.configModel = configModel; |
45 |
| - } |
46 |
| - |
47 |
| - SecurityRoles getSecurityRoles(final Set<String> roles) { |
48 |
| - return configModel.getSecurityRoles().filter(roles); |
49 |
| - } |
| 23 | + private final PrivilegesEvaluator privilegesEvaluator; |
50 | 24 |
|
51 |
| - boolean isInitialized() { |
52 |
| - return configModel != null && configModel.getSecurityRoles() != null; |
| 25 | + public RestLayerPrivilegesEvaluator(PrivilegesEvaluator privilegesEvaluator) { |
| 26 | + this.privilegesEvaluator = privilegesEvaluator; |
53 | 27 | }
|
54 | 28 |
|
55 |
| - public PrivilegesEvaluatorResponse evaluate(final User user, final Set<String> actions) { |
56 |
| - if (!isInitialized()) { |
57 |
| - throw new OpenSearchSecurityException("OpenSearch Security is not initialized."); |
58 |
| - } |
59 |
| - |
60 |
| - final TransportAddress caller = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS); |
61 |
| - |
62 |
| - final Set<String> mappedRoles = mapRoles(user, caller); |
63 |
| - |
64 |
| - final SecurityRoles securityRoles = getSecurityRoles(mappedRoles); |
| 29 | + public PrivilegesEvaluatorResponse evaluate(final User user, final String routeName, final Set<String> actions) { |
| 30 | + PrivilegesEvaluationContext context = privilegesEvaluator.createContext(user, routeName); |
65 | 31 |
|
66 | 32 | final boolean isDebugEnabled = log.isDebugEnabled();
|
67 | 33 | if (isDebugEnabled) {
|
68 |
| - log.debug("Evaluate permissions for {} on {}", user, clusterService.localNode().getName()); |
| 34 | + log.debug("Evaluate permissions for {}", user); |
69 | 35 | log.debug("Action: {}", actions);
|
70 |
| - log.debug("Mapped roles: {}", mappedRoles.toString()); |
| 36 | + log.debug("Mapped roles: {}", context.getMappedRoles().toString()); |
71 | 37 | }
|
72 | 38 |
|
73 |
| - for (final String action : actions) { |
74 |
| - if (!securityRoles.impliesClusterPermissionPermission(action)) { |
75 |
| - // TODO This will exhibit a weird behaviour when a REST action specifies two permissions, and |
76 |
| - // if the user has no permissions for the first one, but has permissions for the second one: |
77 |
| - // First, the information "No permission match" will be logged, but then the action will be |
78 |
| - // allowed nevertheless. |
79 |
| - log.info( |
80 |
| - "No permission match for {} [Action [{}]] [RolesChecked {}]. No permissions for {}", |
81 |
| - user, |
82 |
| - action, |
83 |
| - securityRoles.getRoleNames(), |
84 |
| - action |
85 |
| - ); |
86 |
| - } else { |
87 |
| - if (isDebugEnabled) { |
88 |
| - log.debug("Allowed because we have permissions for {}", actions); |
89 |
| - } |
90 |
| - return PrivilegesEvaluatorResponse.ok(); |
91 |
| - } |
92 |
| - } |
| 39 | + PrivilegesEvaluatorResponse result = privilegesEvaluator.getActionPrivileges().hasAnyClusterPrivilege(context, actions); |
93 | 40 |
|
94 |
| - return PrivilegesEvaluatorResponse.insufficient(actions).resolvedSecurityRoles(mappedRoles); |
95 |
| - } |
| 41 | + if (!result.allowed) { |
| 42 | + log.info( |
| 43 | + "No permission match for {} [Action [{}]] [RolesChecked {}]. No permissions for {}", |
| 44 | + user, |
| 45 | + routeName, |
| 46 | + context.getMappedRoles(), |
| 47 | + result.getMissingPrivileges() |
| 48 | + ); |
| 49 | + } |
96 | 50 |
|
97 |
| - Set<String> mapRoles(final User user, final TransportAddress caller) { |
98 |
| - return this.configModel.mapSecurityRoles(user, caller); |
| 51 | + return result; |
99 | 52 | }
|
100 | 53 | }
|
0 commit comments