Skip to content

Commit

Permalink
Adds concrete implementations of remainder methods
Browse files Browse the repository at this point in the history
Signed-off-by: Darshit Chanpura <[email protected]>
  • Loading branch information
DarshitChanpura committed Nov 27, 2024
1 parent 45b002e commit a30be57
Show file tree
Hide file tree
Showing 7 changed files with 930 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,9 @@ public void onIndexModule(IndexModule indexModule) {

log.info("Indices to listen to: {}", this.indicesToListen);
if (this.indicesToListen.contains(indexModule.getIndex().getName())) {
indexModule.addIndexOperationListener(ResourceSharingIndexListener.getInstance());
ResourceSharingIndexListener resourceSharingIndexListener = ResourceSharingIndexListener.getInstance();
resourceSharingIndexListener.initialize(threadPool, localClient);
indexModule.addIndexOperationListener(resourceSharingIndexListener);
log.warn("Security plugin started listening to operations on index {}", indexModule.getIndex().getName());
}

Expand Down Expand Up @@ -1205,7 +1207,7 @@ public Collection<Object> createComponents(

// NOTE: We need to create DefaultInterClusterRequestEvaluator before creating ConfigurationRepository since the latter requires
// security index to be accessible which means
// communciation with other nodes is already up. However for the communication to be up, there needs to be trusted nodes_dn. Hence
// communication with other nodes is already up. However for the communication to be up, there needs to be trusted nodes_dn. Hence
// the base values from opensearch.yml
// is used to first establish trust between same cluster nodes and there after dynamic config is loaded if enabled.
if (DEFAULT_INTERCLUSTER_REQUEST_EVALUATOR_CLASS.equals(className)) {
Expand All @@ -1217,7 +1219,7 @@ public Collection<Object> createComponents(
ResourceSharingIndexHandler rsIndexHandler = new ResourceSharingIndexHandler(resourceSharingIndex, localClient, threadPool);
resourceAccessHandler = new ResourceAccessHandler(threadPool, rsIndexHandler, adminDns);

rmr = ResourceManagementRepository.create(settings, threadPool, localClient, rsIndexHandler);
rmr = ResourceManagementRepository.create(rsIndexHandler);

components.add(adminDns);
components.add(cr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ public boolean authenticate(final SecurityRequestChannel request) {
if (adminDns.isAdminDN(sslPrincipal)) {
// PKI authenticated REST call
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, new User(sslPrincipal));
threadContext.putPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER, new User(sslPrincipal));
auditLog.logSucceededLogin(sslPrincipal, true, null, request);
return true;
}
Expand Down Expand Up @@ -389,6 +390,8 @@ public boolean authenticate(final SecurityRequestChannel request) {
final User impersonatedUser = impersonate(request, authenticatedUser);
threadPool.getThreadContext()
.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, impersonatedUser == null ? authenticatedUser : impersonatedUser);
threadPool.getThreadContext()
.putPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER, impersonatedUser == null ? authenticatedUser : impersonatedUser);
auditLog.logSucceededLogin(
(impersonatedUser == null ? authenticatedUser : impersonatedUser).getName(),
false,
Expand Down Expand Up @@ -422,6 +425,7 @@ public boolean authenticate(final SecurityRequestChannel request) {
anonymousUser.setRequestedTenant(tenant);

threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, anonymousUser);
threadPool.getThreadContext().putPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER, anonymousUser);
auditLog.logSucceededLogin(anonymousUser.getName(), false, null, request);
if (isDebugEnabled) {
log.debug("Anonymous User is authenticated");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ private <Request extends ActionRequest, Response extends ActionResponse> void ap
log.info("Transport auth in passive mode and no user found. Injecting default user");
user = User.DEFAULT_TRANSPORT_USER;
threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, user);
threadContext.putPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER, user);
} else {
log.error(
"No user found for "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,41 +49,41 @@ public ResourceAccessHandler(
this.adminDNs = adminDns;
}

public List<String> listAccessibleResourcesInPlugin(String systemIndex) {
final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
public List<String> listAccessibleResourcesInPlugin(String pluginIndex) {
final User user = threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER);
if (user == null) {
LOGGER.info("Unable to fetch user details ");
return Collections.emptyList();
}

LOGGER.info("Listing accessible resource within a system index {} for : {}", systemIndex, user.getName());
LOGGER.info("Listing accessible resource within a system index {} for : {}", pluginIndex, user.getName());

// TODO check if user is admin, if yes all resources should be accessible
// check if user is admin, if yes all resources should be accessible
if (adminDNs.isAdmin(user)) {
return loadAllResources(systemIndex);
return loadAllResources(pluginIndex);
}

Set<String> result = new HashSet<>();

// 0. Own resources
result.addAll(loadOwnResources(systemIndex, user.getName()));
result.addAll(loadOwnResources(pluginIndex, user.getName()));

// 1. By username
result.addAll(loadSharedWithResources(systemIndex, Set.of(user.getName()), "users"));
result.addAll(loadSharedWithResources(pluginIndex, Set.of(user.getName()), EntityType.USERS.toString()));

// 2. By roles
Set<String> roles = user.getSecurityRoles();
result.addAll(loadSharedWithResources(systemIndex, roles, "roles"));
result.addAll(loadSharedWithResources(pluginIndex, roles, EntityType.ROLES.toString()));

// 3. By backend_roles
Set<String> backendRoles = user.getRoles();
result.addAll(loadSharedWithResources(systemIndex, backendRoles, "backend_roles"));
result.addAll(loadSharedWithResources(pluginIndex, backendRoles, EntityType.BACKEND_ROLES.toString()));

return result.stream().toList();
}

public boolean hasPermission(String resourceId, String systemIndexName, String scope) {
final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
final User user = threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER);
LOGGER.info("Checking if {} has {} permission to resource {}", user.getName(), scope, resourceId);

Set<String> userRoles = user.getSecurityRoles();
Expand All @@ -109,24 +109,22 @@ public boolean hasPermission(String resourceId, String systemIndexName, String s
}

public ResourceSharing shareWith(String resourceId, String systemIndexName, ShareWith shareWith) {
final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
final User user = threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER);
LOGGER.info("Sharing resource {} created by {} with {}", resourceId, user, shareWith.toString());

// TODO fix this to fetch user-name correctly, need to hydrate user context since context might have been stashed.
// (persistentHeader?)
CreatedBy createdBy = new CreatedBy("", "");
CreatedBy createdBy = new CreatedBy(user.getName());
return this.resourceSharingIndexHandler.updateResourceSharingInfo(resourceId, systemIndexName, createdBy, shareWith);
}

public ResourceSharing revokeAccess(String resourceId, String systemIndexName, Map<EntityType, List<String>> revokeAccess) {
final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
final User user = threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER);
LOGGER.info("Revoking access to resource {} created by {} for {}", resourceId, user.getName(), revokeAccess);

return this.resourceSharingIndexHandler.revokeAccess(resourceId, systemIndexName, revokeAccess);
}

public boolean deleteResourceSharingRecord(String resourceId, String systemIndexName) {
final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
final User user = threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER);
LOGGER.info("Deleting resource sharing record for resource {} in {} created by {}", resourceId, systemIndexName, user.getName());

ResourceSharing document = this.resourceSharingIndexHandler.fetchDocumentById(systemIndexName, resourceId);
Expand All @@ -142,7 +140,7 @@ public boolean deleteResourceSharingRecord(String resourceId, String systemIndex
}

public boolean deleteAllResourceSharingRecordsForCurrentUser() {
final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);
final User user = threadContext.getPersistent(ConfigConstants.OPENDISTRO_SECURITY_USER);
LOGGER.info("Deleting all resource sharing records for resource {}", user.getName());

return this.resourceSharingIndexHandler.deleteAllRecordsForUser(user.getName());
Expand All @@ -159,8 +157,8 @@ private List<String> loadOwnResources(String systemIndex, String username) {
return this.resourceSharingIndexHandler.fetchDocumentsByField(systemIndex, "created_by.user", username);
}

private List<String> loadSharedWithResources(String systemIndex, Set<String> accessWays, String shareWithType) {
return this.resourceSharingIndexHandler.fetchDocumentsForAllScopes(systemIndex, accessWays, shareWithType);
private List<String> loadSharedWithResources(String systemIndex, Set<String> entities, String shareWithType) {
return this.resourceSharingIndexHandler.fetchDocumentsForAllScopes(systemIndex, entities, shareWithType);
}

private boolean isOwnerOfResource(ResourceSharing document, String userName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,25 @@

package org.opensearch.security.resources;

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

import org.opensearch.client.Client;
import org.opensearch.common.settings.Settings;
import org.opensearch.security.configuration.ConfigurationRepository;
import org.opensearch.threadpool.ThreadPool;

public class ResourceManagementRepository {

private static final Logger LOGGER = LogManager.getLogger(ConfigurationRepository.class);

private final Client client;

private final ThreadPool threadPool;

private final ResourceSharingIndexHandler resourceSharingIndexHandler;

protected ResourceManagementRepository(
final ThreadPool threadPool,
final Client client,
final ResourceSharingIndexHandler resourceSharingIndexHandler
) {
this.client = client;
this.threadPool = threadPool;
protected ResourceManagementRepository(final ResourceSharingIndexHandler resourceSharingIndexHandler) {
this.resourceSharingIndexHandler = resourceSharingIndexHandler;
}

public static ResourceManagementRepository create(
Settings settings,
final ThreadPool threadPool,
Client client,
ResourceSharingIndexHandler resourceSharingIndexHandler
) {
public static ResourceManagementRepository create(ResourceSharingIndexHandler resourceSharingIndexHandler) {

return new ResourceManagementRepository(threadPool, client, resourceSharingIndexHandler);
return new ResourceManagementRepository(resourceSharingIndexHandler);
}

/**
* Creates the resource sharing index if it doesn't already exist.
* This method is called during the initialization phase of the repository.
* It ensures that the index is set up with the necessary mappings and settings
* before any operations are performed on the index.
*/
public void createResourceSharingIndexIfAbsent() {
// TODO check if this should be wrapped in an atomic completable future

Expand Down
Loading

0 comments on commit a30be57

Please sign in to comment.