Skip to content

Commit

Permalink
Enforce security on get resource
Browse files Browse the repository at this point in the history
Signed-off-by: Craig Perkins <[email protected]>
  • Loading branch information
cwperks committed Dec 16, 2024
1 parent 20c24d0 commit e676819
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,25 @@ public void testSecurityRoles() throws Exception {

@Test
public void testCreateAndUpdateOwnSampleResource() throws Exception {
String resourceId;
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
String sampleResource = "{\"name\":\"sample\"}";
HttpResponse response = client.postJson("_plugins/resource_sharing_example/resource", sampleResource);
response.assertStatusCode(HttpStatus.SC_OK);
System.out.println("Response: " + response.getBody());

String resourceId = response.getTextFromJsonBody("/resourceId");
resourceId = response.getTextFromJsonBody("/resourceId");

System.out.println("resourceId: " + resourceId);
Thread.sleep(2000);
}
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
HttpResponse response = client.postJson(".resource-sharing/_search", "{\"query\" : {\"match_all\" : {}}}");
System.out.println("Resource sharing entries: " + response.getBody());
}

try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
Thread.sleep(1000);

HttpResponse getResponse = client.get("_plugins/resource_sharing_example/resource/" + resourceId);
getResponse.assertStatusCode(HttpStatus.SC_OK);
Expand Down
10 changes: 10 additions & 0 deletions spi/src/main/java/org/opensearch/security/spi/ResourceUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
package org.opensearch.security.spi;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.opensearch.core.xcontent.ToXContent;
Expand All @@ -34,6 +37,13 @@ public Set<String> getBackendRoles() {
return backendRoles;
}

@SuppressWarnings("unchecked")
public static ResourceUser fromSource(Map<String, Object> sourceAsMap) {
String name = (String) sourceAsMap.get("name");
Set<String> backendRoles = new HashSet<>((List<String>) sourceAsMap.get("backend_roles"));
return new ResourceUser(name, backendRoles);
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
return builder.startObject().field("name", name).field("backend_roles", backendRoles).endObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
package org.opensearch.security.resource;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.opensearch.core.xcontent.ToXContentFragment;
import org.opensearch.core.xcontent.XContentBuilder;
Expand All @@ -32,6 +34,27 @@ public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUse
this.shareWith = shareWith;
}

@SuppressWarnings("unchecked")
public static ResourceSharingEntry fromSource(Map<String, Object> sourceAsMap) {
String resourceIndex = (String) sourceAsMap.get("resource_index");
String resourceId = (String) sourceAsMap.get("resource_id");
ResourceUser resourceUser = ResourceUser.fromSource((Map<String, Object>) sourceAsMap.get("resource_user"));
List<Map<String, Object>> sharedWithList = (List<Map<String, Object>>) sourceAsMap.get("share_with");
List<ShareWith> sharedWith = new ArrayList<>();
for (Map<String, Object> sharedWithMap : sharedWithList) {
sharedWith.add(ShareWith.fromSource(sharedWithMap));
}
return new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, sharedWith);
}

public ResourceUser getResourceUser() {
return resourceUser;
}

public List<ShareWith> getShareWith() {
return shareWith;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return builder.startObject()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,23 @@ public SecurityResourceSharingService(Client client, String resourceIndex, Resou
this.resourceFactory = resourceFactory;
}

private boolean hasPermissionsFor(User authenticatedUser, Resource resource, ShareWith sharedWith) {
System.out.println("hasPermissionsFor: " + authenticatedUser + " " + resource + " " + sharedWith);
private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry sharedWith) {
// 1. The resource_user is the currently authenticated user
// 2. The resource has been shared with the authenticated user
// 3. The resource has been shared with a backend role that the authenticated user has
if (authenticatedUser.getName().equals(resource.getResourceUser().getName())) {
if (authenticatedUser.getName().equals(sharedWith.getResourceUser().getName())) {
return true;
}
WildcardMatcher userMatcher = WildcardMatcher.from(sharedWith.getUsers());
if (userMatcher.test(authenticatedUser.getName())) {
return true;
}
WildcardMatcher backendRoleMatcher = WildcardMatcher.from(sharedWith.getBackendRoles());
if (authenticatedUser.getRoles().stream().anyMatch(backendRoleMatcher::test)) {
return true;

for (ShareWith shareWith : sharedWith.getShareWith()) {
WildcardMatcher userMatcher = WildcardMatcher.from(shareWith.getUsers());
if (userMatcher.test(authenticatedUser.getName())) {
return true;
}
WildcardMatcher backendRoleMatcher = WildcardMatcher.from(shareWith.getBackendRoles());
if (authenticatedUser.getRoles().stream().anyMatch(backendRoleMatcher::test)) {
return true;
}
}
return false;
}
Expand Down Expand Up @@ -192,9 +194,11 @@ private void finishGetResourceIfUserIsAllowed(T resource, User authenticatedUser
try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) {
SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
System.out.println("resourceIndex: " + resourceIndex);
System.out.println("resource.getResourceId(): " + resource.getResourceId());
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("resource_index", resourceIndex))
.must(QueryBuilders.termQuery("resource_id", resource.getResourceId()));
.must(QueryBuilders.matchQuery("resource_index", resourceIndex))
.must(QueryBuilders.matchQuery("resource_id", resource.getResourceId()));

searchSourceBuilder.query(boolQuery);
searchSourceBuilder.size(1); // Limit to 1 result
Expand All @@ -206,8 +210,8 @@ public void onResponse(SearchResponse searchResponse) {
SearchHit[] hits = searchResponse.getHits().getHits();
if (hits.length > 0) {
SearchHit hit = hits[0];
ShareWith sharedWith = ShareWith.fromSource(hit.getSourceAsMap());
if (hasPermissionsFor(authenticatedUser, resource, sharedWith)) {
ResourceSharingEntry sharedWith = ResourceSharingEntry.fromSource(hit.getSourceAsMap());
if (hasPermissionsFor(authenticatedUser, sharedWith)) {
getResourceListener.onResponse(resource);
} else {
getResourceListener.onFailure(new OpenSearchException("User is not authorized to access this resource"));
Expand Down

0 comments on commit e676819

Please sign in to comment.