Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Changed
- Use extendedPlugins in integrationTest framework for sample resource plugin testing ([#5322](https://github.com/opensearch-project/security/pull/5322))
- Refactor ResourcePermissions to refer to action groups as access levels ([#5335](https://github.com/opensearch-project/security/pull/5335))

### Dependencies
- Bump `guava_version` from 33.4.6-jre to 33.4.8-jre ([#5284](https://github.com/opensearch-project/security/pull/5284))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@

package org.opensearch.sample;

import java.util.List;
import java.util.Map;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import org.apache.http.HttpStatus;
import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.opensearch.Version;
import org.opensearch.painless.PainlessModulePlugin;
import org.opensearch.sample.resource.client.ResourceSharingClientAccessor;
import org.opensearch.security.resources.ResourcePluginInfo;
import org.opensearch.security.spi.resources.ResourceAccessActionGroups;
import org.opensearch.security.spi.resources.ResourceSharingExtension;
import org.opensearch.plugins.PluginInfo;
import org.opensearch.security.OpenSearchSecurityPlugin;
import org.opensearch.security.spi.resources.ResourceAccessLevels;
import org.opensearch.test.framework.cluster.ClusterManager;
import org.opensearch.test.framework.cluster.LocalCluster;
import org.opensearch.test.framework.cluster.TestRestClient;
Expand All @@ -32,14 +32,14 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SAMPLE_RESOURCE_CREATE_ENDPOINT;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SAMPLE_RESOURCE_DELETE_ENDPOINT;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SAMPLE_RESOURCE_GET_ENDPOINT;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SAMPLE_RESOURCE_REVOKE_ENDPOINT;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SAMPLE_RESOURCE_SHARE_ENDPOINT;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SAMPLE_RESOURCE_UPDATE_ENDPOINT;
import static org.opensearch.sample.SampleResourcePluginTestHelper.SHARED_WITH_USER_LIMITED_PERMISSIONS;
import static org.opensearch.sample.SampleResourcePluginTestHelper.createResourceAccessControlClient;
import static org.opensearch.sample.SampleResourcePluginTestHelper.revokeAccessPayload;
import static org.opensearch.sample.SampleResourcePluginTestHelper.shareWithPayload;
import static org.opensearch.sample.utils.Constants.RESOURCE_INDEX_NAME;
Expand All @@ -56,29 +56,33 @@
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
public class SampleResourcePluginLimitedPermissionsTests {

ResourcePluginInfo resourcePluginInfo;
final ResourceSharingExtension resourceSharingExtension = new SampleResourceExtension();

@ClassRule
public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.SINGLENODE)
.plugin(SampleResourcePlugin.class, PainlessModulePlugin.class)
.plugin(PainlessModulePlugin.class)
.plugin(
new PluginInfo(
SampleResourcePlugin.class.getName(),
"classpath plugin",
"NA",
Version.CURRENT,
"1.8",
SampleResourcePlugin.class.getName(),
null,
List.of(OpenSearchSecurityPlugin.class.getName()),
false
)
)
.anonymousAuth(true)
.authc(AUTHC_HTTPBASIC_INTERNAL)
.users(USER_ADMIN, SHARED_WITH_USER_LIMITED_PERMISSIONS)
.nodeSettings(Map.of(SECURITY_SYSTEM_INDICES_ENABLED_KEY, true, OPENSEARCH_RESOURCE_SHARING_ENABLED, true))
.build();

@Before
public void setup() {
resourcePluginInfo = cluster.nodes().getFirst().getInjectable(ResourcePluginInfo.class);
}

@After
public void clearIndices() {
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
client.delete(RESOURCE_INDEX_NAME);
client.delete(OPENSEARCH_RESOURCE_SHARING_INDEX);
resourcePluginInfo.getResourceSharingExtensionsMutable().remove(resourceSharingExtension);
}
}

Expand All @@ -94,7 +98,6 @@ public void testPluginInstalledCorrectly() {
@Test
public void testCreateUpdateDeleteSampleResource() throws Exception {
String resourceId;
String resourceSharingDocId;
// create sample resource
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
String sampleResource = """
Expand All @@ -109,31 +112,6 @@ public void testCreateUpdateDeleteSampleResource() throws Exception {

// Create an entry in resource-sharing index
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
// Since test framework doesn't yet allow loading ex tensions we need to create a resource sharing entry manually
String json = """
{
"source_idx": ".sample_resource_sharing_plugin",
"resource_id": "%s",
"created_by": {
"user": "admin"
}
}
""".formatted(resourceId);

TestRestClient.HttpResponse response = client.postJson(OPENSEARCH_RESOURCE_SHARING_INDEX + "/_doc", json);
assertThat(response.getStatusReason(), containsString("Created"));
resourceSharingDocId = response.bodyAsJsonNode().get("_id").asText();
// update extension list
resourcePluginInfo.getResourceSharingExtensionsMutable().add(resourceSharingExtension);

ResourceSharingClientAccessor.getInstance().setResourceSharingClient(createResourceAccessControlClient(cluster));

Awaitility.await()
.alias("Wait until resource data is populated")
.until(() -> client.get(SAMPLE_RESOURCE_GET_ENDPOINT + "/" + resourceId).getStatusCode(), equalTo(200));
response = client.get(SAMPLE_RESOURCE_GET_ENDPOINT + "/" + resourceId);
response.assertStatusCode(HttpStatus.SC_OK);
assertThat(response.getBody(), containsString("sample"));
// Wait until resource-sharing entry is successfully created
Awaitility.await()
.alias("Wait until resource-sharing data is populated")
Expand Down Expand Up @@ -211,7 +189,7 @@ public void testCreateUpdateDeleteSampleResource() throws Exception {
);
response.assertStatusCode(HttpStatus.SC_OK);
assertThat(
response.bodyAsJsonNode().get("share_with").get(ResourceAccessActionGroups.PLACE_HOLDER).get("users").get(0).asText(),
response.bodyAsJsonNode().get("share_with").get(ResourceAccessLevels.PLACE_HOLDER).get("users").get(0).asText(),
containsString(SHARED_WITH_USER_LIMITED_PERMISSIONS.getName())
);
}
Expand Down Expand Up @@ -241,7 +219,7 @@ public void testCreateUpdateDeleteSampleResource() throws Exception {
revokeAccessPayload(SHARED_WITH_USER_LIMITED_PERMISSIONS.getName())
);
response.assertStatusCode(HttpStatus.SC_OK);
assertThat(response.bodyAsJsonNode().get("share_with").size(), equalTo(0));
assertThat(response.getBody(), not(containsString("resource_sharing_test_user_limited_perms")));
}

// get sample resource with SHARED_WITH_USER_LIMITED_PERMISSIONS, user no longer has access to resource
Expand All @@ -268,10 +246,6 @@ public void testCreateUpdateDeleteSampleResource() throws Exception {

// corresponding entry should be removed from resource-sharing index
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
// Since test framework doesn't yet allow loading ex tensions we need to delete the resource sharing entry manually
TestRestClient.HttpResponse response = client.delete(OPENSEARCH_RESOURCE_SHARING_INDEX + "/_doc/" + resourceSharingDocId);
response.assertStatusCode(HttpStatus.SC_OK);

Awaitility.await()
.alias("Wait until resource-sharing data is updated")
.until(
Expand Down Expand Up @@ -310,35 +284,12 @@ public void testAccessWithLimitedIP() throws Exception {

// Create an entry in resource-sharing index
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
// Since test framework doesn't yet allow loading ex tensions we need to create a resource sharing entry manually

String json = """
{
"source_idx": "%s",
"resource_id": "%s",
"created_by": {
"user": "%s"
}
}
""".formatted(RESOURCE_INDEX_NAME, resourceId, SHARED_WITH_USER_LIMITED_PERMISSIONS.getName());

HttpResponse response = client.postJson(OPENSEARCH_RESOURCE_SHARING_INDEX + "/_doc", json);
assertThat(response.getStatusReason(), containsString("Created"));

resourcePluginInfo.getResourceSharingExtensionsMutable().add(resourceSharingExtension);

ResourceSharingClientAccessor.getInstance().setResourceSharingClient(createResourceAccessControlClient(cluster));

Awaitility.await()
.alias("Wait until resource-sharing data is populated")
.until(
() -> client.get(OPENSEARCH_RESOURCE_SHARING_INDEX + "/_search").bodyAsJsonNode().get("hits").get("hits").size(),
equalTo(1)
);
response = client.get(SAMPLE_RESOURCE_GET_ENDPOINT);
response.assertStatusCode(HttpStatus.SC_OK);
assertThat(response.bodyAsJsonNode().get("resources").size(), equalTo(1));
assertThat(response.getBody(), containsString("sample"));
}

// user should be able to get its own resource as it has get API access
Expand Down
Loading
Loading