Skip to content

Commit

Permalink
Expand RoleV7 to include Resources
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Crawford <[email protected]>
  • Loading branch information
stephen-crawford committed Aug 12, 2024
1 parent 13262cd commit fb40a6f
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
import org.opensearch.security.identity.SecurityTokenManager;
import org.opensearch.security.privileges.PrivilegesEvaluator;
import org.opensearch.security.privileges.PrivilegesInterceptor;
import org.opensearch.security.privileges.ResourceAccessEvaluator;
import org.opensearch.security.privileges.RestLayerPrivilegesEvaluator;
import org.opensearch.security.resolver.IndexResolverReplacer;
import org.opensearch.security.rest.DashboardsInfoAction;
Expand Down Expand Up @@ -246,6 +247,7 @@ public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin
private volatile PrivilegesEvaluator evaluator;
private volatile UserService userService;
private volatile RestLayerPrivilegesEvaluator restLayerEvaluator;
private volatile ResourceAccessEvaluator resourceAccessEvaluator;
private volatile ConfigurationRepository cr;
private volatile AdminDNs adminDns;
private volatile ClusterService cs;
Expand Down Expand Up @@ -1139,6 +1141,8 @@ public Collection<Object> createComponents(

restLayerEvaluator = new RestLayerPrivilegesEvaluator(clusterService, threadPool);

resourceAccessEvaluator = new ResourceAccessEvaluator(clusterService, threadPool);

securityRestHandler = new SecurityRestFilter(
backendRegistry,
restLayerEvaluator,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

package org.opensearch.security.privileges;

import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.opensearch.OpenSearchSecurityException;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.core.common.transport.TransportAddress;
import org.opensearch.security.securityconf.ConfigModel;
import org.opensearch.security.securityconf.SecurityRoles;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.security.user.User;
import org.opensearch.threadpool.ThreadPool;

import org.greenrobot.eventbus.Subscribe;

public class ResourceAccessEvaluator {
protected final Logger log = LogManager.getLogger(this.getClass());
private final ClusterService clusterService;
private ThreadContext threadContext;
private ConfigModel configModel;

public ResourceAccessEvaluator(final ClusterService clusterService, final ThreadPool threadPool) {
this.clusterService = clusterService;
this.threadContext = threadPool.getThreadContext();
}

@Subscribe
public void onConfigModelChanged(final ConfigModel configModel) {
this.configModel = configModel;
}

SecurityRoles getSecurityRoles(final Set<String> roles) {
return configModel.getSecurityRoles().filter(roles);
}

boolean isInitialized() {
return configModel != null && configModel.getSecurityRoles() != null;
}

public PrivilegesEvaluatorResponse evaluate(final User user, final Set<String> actions) {
if (!isInitialized()) {
throw new OpenSearchSecurityException("OpenSearch Security is not initialized.");
}

final PrivilegesEvaluatorResponse presponse = new PrivilegesEvaluatorResponse();

final TransportAddress caller = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS);

final Set<String> mappedRoles = mapRoles(user, caller);

presponse.resolvedSecurityRoles.addAll(mappedRoles);
final SecurityRoles securityRoles = getSecurityRoles(mappedRoles);

final boolean isDebugEnabled = log.isDebugEnabled();
if (isDebugEnabled) {
log.debug("Evaluate permissions for {} on {}", user, clusterService.localNode().getName());
log.debug("Action: {}", actions);
log.debug("Mapped roles: {}", mappedRoles.toString());
}

for (final String action : actions) {
if (!securityRoles.impliesResourcePermission(action)) {
presponse.missingPrivileges.add(action);
presponse.allowed = false;
log.info(
"No permission match for {} [Action [{}]] [RolesChecked {}]. No permissions for {}",
user,
action,
securityRoles.getRoleNames(),
presponse.missingPrivileges
);
} else {
if (isDebugEnabled) {
log.debug("Allowed because we have permissions for {}", actions);
}
presponse.allowed = true;

// break the loop as we found the matching permission
break;
}
}

return presponse;
}

Set<String> mapRoles(final User user, final TransportAddress caller) {
return this.configModel.mapSecurityRoles(user, caller);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,6 @@ Set<String> getAllPermittedIndicesForDashboards(
SecurityRoles filter(Set<String> roles);

boolean isPermittedOnSystemIndex(String indexName);

boolean impliesResourcePermission(String action0);
}

0 comments on commit fb40a6f

Please sign in to comment.