Skip to content

Commit

Permalink
Updates the ResourceAccessControlPlugin to have noop actions, renames…
Browse files Browse the repository at this point in the history
… noopRACplugin to defaultRACplugin since we now list all accessible resources and updates comments

Signed-off-by: Darshit Chanpura <[email protected]>
  • Loading branch information
DarshitChanpura committed Dec 13, 2024
1 parent 0548fc2 commit 193112b
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 184 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.OpenSearchException;
import org.opensearch.plugins.NoOpResourceAccessControlPlugin;
import org.opensearch.accesscontrol.resources.fallback.DefaultResourceAccessControlPlugin;
import org.opensearch.client.Client;
import org.opensearch.common.inject.Inject;
import org.opensearch.plugins.ResourceAccessControlPlugin;
import org.opensearch.plugins.ResourcePlugin;
import org.opensearch.threadpool.ThreadPool;

import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -29,12 +32,18 @@ public class ResourceService {
private final ResourceAccessControlPlugin resourceACPlugin;
private final List<ResourcePlugin> resourcePlugins;

public ResourceService(final List<ResourceAccessControlPlugin> resourceACPlugins, List<ResourcePlugin> resourcePlugins) {
@Inject
public ResourceService(
final List<ResourceAccessControlPlugin> resourceACPlugins,
List<ResourcePlugin> resourcePlugins,
Client client,
ThreadPool threadPool
) {
this.resourcePlugins = resourcePlugins;

if (resourceACPlugins.isEmpty()) {
log.info("Security plugin disabled: Using NoOpResourceAccessControlPlugin");
resourceACPlugin = new NoOpResourceAccessControlPlugin();
log.info("Security plugin disabled: Using DefaultResourceAccessControlPlugin");
resourceACPlugin = new DefaultResourceAccessControlPlugin(client, threadPool);
} else if (resourceACPlugins.size() == 1) {
log.info("Security plugin enabled: Using OpenSearchSecurityPlugin");
resourceACPlugin = resourceACPlugins.get(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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.
*/

package org.opensearch.accesscontrol.resources.fallback;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.OpenSearchException;
import org.opensearch.action.search.ClearScrollRequest;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.action.search.SearchResponse;
import org.opensearch.action.search.SearchScrollAction;
import org.opensearch.action.search.SearchScrollRequest;
import org.opensearch.client.Client;
import org.opensearch.common.inject.Inject;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.index.query.QueryBuilders;
import org.opensearch.plugins.Plugin;
import org.opensearch.plugins.ResourceAccessControlPlugin;
import org.opensearch.search.SearchHit;
import org.opensearch.search.builder.SearchSourceBuilder;
import org.opensearch.threadpool.ThreadPool;

import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

/**
* This plugin class defines a pass-through implementation of ResourceAccessControlPlugin.
*
* @opensearch.experimental
*/
@SuppressWarnings("removal")
public class DefaultResourceAccessControlPlugin extends Plugin implements ResourceAccessControlPlugin {

private static final Logger log = LogManager.getLogger(DefaultResourceAccessControlPlugin.class);

private Client client;

private final ThreadPool threadPool;

@Inject
public DefaultResourceAccessControlPlugin(Client client, ThreadPool threadPool) {
this.client = client;
this.threadPool = threadPool;
}

/**
* Returns a list of all resource ids in provided systemIndex
* @param resourceIndex index where resources are stored
*
* @return Set of resource ids
*/
@Override
public <T> Set<T> getAccessibleResourcesForCurrentUser(String resourceIndex, Class<T> clazz) {
final Set<T> documents = new HashSet<>();
final TimeValue scrollTimeout = TimeValue.timeValueMinutes(1);
String scrollId;

log.info("Searching for accessible resources in index {}", resourceIndex);
// stashContext is required in case resourceIndex is a system index
try (ThreadContext.StoredContext ctx = threadPool.getThreadContext().stashContext()) {
final SearchRequest searchRequest = buildSearchRequest(resourceIndex, scrollTimeout);

SearchResponse searchResponse = client.search(searchRequest).actionGet();
scrollId = searchResponse.getScrollId();
SearchHit[] searchHits = searchResponse.getHits().getHits();

while (searchHits != null && searchHits.length > 0) {
parseAndAddToDocuments(Arrays.stream(searchHits).map(SearchHit::getSourceAsMap), clazz, documents);

final SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(scrollTimeout);
searchResponse = client.execute(SearchScrollAction.INSTANCE, scrollRequest).actionGet();
scrollId = searchResponse.getScrollId();
searchHits = searchResponse.getHits().getHits();
}

final ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
client.clearScroll(clearScrollRequest).actionGet();
} catch (Exception e) {
log.error("Exception: {}", e.getMessage());
return Set.of();
}
log.info("Found {} documents", documents.size());
return Collections.unmodifiableSet(documents);
}

private SearchRequest buildSearchRequest(String resourceIndex, TimeValue scrollTimeout) {
final SearchRequest searchRequest = new SearchRequest(resourceIndex);
final SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery());
sourceBuilder.fetchSource(true);
sourceBuilder.size(10000);

searchRequest.scroll(scrollTimeout);
searchRequest.source(sourceBuilder);

return searchRequest;
}

private static <T> T parse(Map<String, Object> sourceMap, Class<T> clazz) {
return AccessController.doPrivileged((PrivilegedAction<T>) () -> {
try {
final T instance = clazz.getDeclaredConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Object value = sourceMap.get(field.getName());
if (value != null) {
field.set(instance, value);
}
}
return instance;
} catch (Exception e) {
throw new OpenSearchException("Failed to parse source map into " + clazz.getName(), e);
}
});
}

private static <T> void parseAndAddToDocuments(Stream<Map<String, Object>> searchHits, Class<T> clazz, Set<T> documents) {
searchHits.map(hit -> parse(hit, clazz)).forEach(documents::add);
}

}
2 changes: 1 addition & 1 deletion server/src/main/java/org/opensearch/node/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ protected Node(
ResourceAccessControlPlugin.class
);
final List<ResourcePlugin> resourcePlugins = pluginsService.filterPlugins(ResourcePlugin.class);
ResourceService resourceService = new ResourceService(resourceAccessControlPlugins, resourcePlugins);
ResourceService resourceService = new ResourceService(resourceAccessControlPlugins, resourcePlugins, client, threadPool);

final RestController restController = actionModule.getRestController();

Expand Down

This file was deleted.

Loading

0 comments on commit 193112b

Please sign in to comment.