Skip to content

Commit 3064cd2

Browse files
Updates doc for sample resource plugin and fixes some code duplication
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
1 parent dfeaca8 commit 3064cd2

29 files changed

+103
-101
lines changed

sample-resource-plugin/README.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
# Resource Sharing and Access Control Plugin
22

33
This plugin demonstrates resource sharing and access control functionality, providing sample resource APIs and marking it as a resource sharing plugin via resource-sharing-spi. The access control is implemented on Security plugin and will be performed under the hood.
4+
At present only admin and resource owners can modify/delete the resource
45

56
## PreRequisites
67

7-
Publish SPI to local maven before proceeding:
8+
Publish SPI, Common and Client to local maven before proceeding:
89
```shell
910
./gradlew clean :opensearch-resource-sharing-spi:publishToMavenLocal
11+
12+
./gradlew clean :opensearch-security-common:publishToMavenLocal
13+
14+
./gradlew clean :opensearch-security-client:publishToMavenLocal
1015
```
1116

1217
System index feature must be enabled to prevent direct access to resource. Add the following setting in case it has not already been enabled.
@@ -16,7 +21,7 @@ plugins.security.system_indices.enabled: true
1621
1722
## Features
1823
19-
- Create, update and delete resources.
24+
- Create, update, get, delete resources, as well as share and revoke access to a resource.
2025
2126
## API Endpoints
2227
@@ -64,7 +69,6 @@ The plugin exposes the following six API endpoints:
6469
}
6570
```
6671

67-
6872
### 4. Get Resource
6973
- **Endpoint:** `GET /_plugins/sample_resource_sharing/get/{resource_id}`
7074
- **Description:** Get a specified resource owned by the requesting user, if the user has access to the resource, else fails.

sample-resource-plugin/src/integrationTest/java/org/opensearch/sample/SampleResourcePluginSystemIndexDisabledTests.java

+12-32
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import static org.opensearch.test.framework.TestSecurityConfig.User.USER_ADMIN;
3030

3131
/**
32-
* These tests run with resource sharing enabled
32+
* These tests run with resource sharing enabled but system index protection disabled
3333
*/
3434
public class SampleResourcePluginSystemIndexDisabledTests extends AbstractSampleResourcePluginFeatureEnabledTests {
3535

@@ -47,7 +47,7 @@ protected LocalCluster getLocalCluster() {
4747
}
4848

4949
@Test
50-
public void testRawAccess() throws Exception {
50+
public void testDirectAccess() throws Exception {
5151
String resourceId;
5252
// create sample resource
5353
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
@@ -101,36 +101,6 @@ public void testRawAccess() throws Exception {
101101
response.assertStatusCode(HttpStatus.SC_OK);
102102
}
103103

104-
// Create an entry in resource-sharing index
105-
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
106-
// Since test framework doesn't yet allow loading ex tensions we need to create a resource sharing entry manually
107-
String json = String.format(
108-
"{"
109-
+ " \"source_idx\": \".sample_resource_sharing_plugin\","
110-
+ " \"resource_id\": \"%s\","
111-
+ " \"created_by\": {"
112-
+ " \"user\": \"admin\""
113-
+ " }"
114-
+ "}",
115-
resourceId
116-
);
117-
HttpResponse response = client.postJson(OPENSEARCH_RESOURCE_SHARING_INDEX + "/_doc", json);
118-
assertThat(response.getStatusReason(), containsString("Created"));
119-
// Also update the in-memory map and get
120-
ResourcePluginInfo.getInstance().getResourceIndicesMutable().add(RESOURCE_INDEX_NAME);
121-
ResourceProvider provider = new ResourceProvider(
122-
SampleResource.class.getCanonicalName(),
123-
RESOURCE_INDEX_NAME,
124-
new SampleResourceParser()
125-
);
126-
ResourcePluginInfo.getInstance().getResourceProvidersMutable().put(RESOURCE_INDEX_NAME, provider);
127-
128-
Thread.sleep(1000);
129-
response = client.get(SAMPLE_RESOURCE_GET_ENDPOINT + "/" + resourceId);
130-
response.assertStatusCode(HttpStatus.SC_OK);
131-
assertThat(response.getBody(), containsString("sample"));
132-
}
133-
134104
// shared_with_user will be able to access resource directly since system index protection is disabled even-though resource is not
135105
// shared with this user, but cannot access via sample plugin APIs
136106
try (TestRestClient client = cluster.getRestClient(SHARED_WITH_USER)) {
@@ -141,6 +111,16 @@ public void testRawAccess() throws Exception {
141111
response.assertStatusCode(HttpStatus.SC_FORBIDDEN);
142112
}
143113

114+
// Update sample resource shared_with_user will be able to update admin's resource because system index protection is disabled
115+
try (TestRestClient client = cluster.getRestClient(SHARED_WITH_USER)) {
116+
String sampleResourceUpdated = "{\"name\":\"sampleUpdated\"}";
117+
TestRestClient.HttpResponse updateResponse = client.postJson(
118+
RESOURCE_INDEX_NAME + "/_doc/" + resourceId,
119+
sampleResourceUpdated
120+
);
121+
updateResponse.assertStatusCode(HttpStatus.SC_OK);
122+
}
123+
144124
// share resource with shared_with user
145125
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
146126
Thread.sleep(1000);

sample-resource-plugin/src/integrationTest/java/org/opensearch/sample/SampleResourcePluginTests.java

+12-32
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import static org.opensearch.test.framework.TestSecurityConfig.User.USER_ADMIN;
3333

3434
/**
35-
* These tests run with resource sharing enabled and system index enabled
35+
* These tests run with resource sharing enabled and system index protection enabled
3636
*/
3737
public class SampleResourcePluginTests extends AbstractSampleResourcePluginFeatureEnabledTests {
3838

@@ -51,7 +51,7 @@ protected LocalCluster getLocalCluster() {
5151
}
5252

5353
@Test
54-
public void testRawAccess() throws Exception {
54+
public void testDirectAccess() throws Exception {
5555
String resourceId;
5656
// create sample resource
5757
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
@@ -105,36 +105,6 @@ public void testRawAccess() throws Exception {
105105
response.assertStatusCode(HttpStatus.SC_OK);
106106
}
107107

108-
// Create an entry in resource-sharing index
109-
try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) {
110-
// Since test framework doesn't yet allow loading ex tensions we need to create a resource sharing entry manually
111-
String json = String.format(
112-
"{"
113-
+ " \"source_idx\": \".sample_resource_sharing_plugin\","
114-
+ " \"resource_id\": \"%s\","
115-
+ " \"created_by\": {"
116-
+ " \"user\": \"admin\""
117-
+ " }"
118-
+ "}",
119-
resourceId
120-
);
121-
HttpResponse response = client.postJson(OPENSEARCH_RESOURCE_SHARING_INDEX + "/_doc", json);
122-
assertThat(response.getStatusReason(), containsString("Created"));
123-
// Also update the in-memory map and get
124-
ResourcePluginInfo.getInstance().getResourceIndicesMutable().add(RESOURCE_INDEX_NAME);
125-
ResourceProvider provider = new ResourceProvider(
126-
SampleResource.class.getCanonicalName(),
127-
RESOURCE_INDEX_NAME,
128-
new SampleResourceParser()
129-
);
130-
ResourcePluginInfo.getInstance().getResourceProvidersMutable().put(RESOURCE_INDEX_NAME, provider);
131-
132-
Thread.sleep(1000);
133-
response = client.get(SAMPLE_RESOURCE_GET_ENDPOINT + "/" + resourceId);
134-
response.assertStatusCode(HttpStatus.SC_OK);
135-
assertThat(response.getBody(), containsString("sample"));
136-
}
137-
138108
// shared_with_user should not be able to delete the resource since system index protection is enabled
139109
try (TestRestClient client = cluster.getRestClient(SHARED_WITH_USER)) {
140110
HttpResponse response = client.delete(RESOURCE_INDEX_NAME + "/_doc/" + resourceId);
@@ -151,6 +121,16 @@ public void testRawAccess() throws Exception {
151121
response.assertStatusCode(HttpStatus.SC_FORBIDDEN);
152122
}
153123

124+
// Update sample resource (shared_with_user cannot update admin's resource) because system index protection is enabled
125+
try (TestRestClient client = cluster.getRestClient(SHARED_WITH_USER)) {
126+
String sampleResourceUpdated = "{\"name\":\"sampleUpdated\"}";
127+
TestRestClient.HttpResponse updateResponse = client.postJson(
128+
RESOURCE_INDEX_NAME + "/_doc/" + resourceId,
129+
sampleResourceUpdated
130+
);
131+
updateResponse.assertStatusCode(HttpStatus.SC_FORBIDDEN);
132+
}
133+
154134
// share resource with shared_with user
155135
try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) {
156136
Thread.sleep(1000);

sample-resource-plugin/src/main/java/org/opensearch/sample/SampleResource.java

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
import static org.opensearch.core.xcontent.ConstructingObjectParser.constructorArg;
2525
import static org.opensearch.core.xcontent.ConstructingObjectParser.optionalConstructorArg;
2626

27+
/**
28+
* Sample resource declared by this plugin.
29+
*/
2730
public class SampleResource implements Resource {
2831

2932
private String name;

sample-resource-plugin/src/main/java/org/opensearch/sample/SampleResourceParser.java

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
import org.opensearch.core.xcontent.XContentParser;
1717
import org.opensearch.security.spi.resources.ResourceParser;
1818

19+
/**
20+
* Responsible for parsing the XContent into a SampleResource object.
21+
*/
1922
public class SampleResourceParser implements ResourceParser<SampleResource> {
2023
@Override
2124
public SampleResource parseXContent(XContentParser parser) throws IOException {

sample-resource-plugin/src/main/java/org/opensearch/sample/SampleResourcePlugin.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464

6565
/**
6666
* Sample Resource plugin.
67-
* It uses ".sample_resources" index to manage its resources, and exposes a REST API
67+
* It uses ".sample_resource_sharing_plugin" index to manage its resources, and exposes few REST APIs that manage CRUD operations on sample resources.
6868
*
6969
*/
7070
public class SampleResourcePlugin extends Plugin implements ActionPlugin, SystemIndexPlugin, ResourceSharingExtension {

sample-resource-plugin/src/main/java/org/opensearch/sample/SampleResourceScope.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
import org.opensearch.security.spi.resources.ResourceAccessScope;
1515

1616
/**
17-
* This class demonstrates a sample implementation of Basic Access Scopes to fit each plugin's use-case.
18-
* The plugin then uses this scope when seeking access evaluation for a user on a particular resource.
17+
* This class implements two scopes for the sample plugin.
18+
* The first scope is SAMPLE_FULL_ACCESS, which allows full access to the sample plugin.
19+
* The second scope is PUBLIC, which allows public access to the sample plugin.
1920
*/
2021
public enum SampleResourceScope implements ResourceAccessScope<SampleResourceScope> {
2122

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/create/CreateResourceRestAction.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import static org.opensearch.rest.RestRequest.Method.PUT;
2424
import static org.opensearch.sample.utils.Constants.SAMPLE_RESOURCE_PLUGIN_API_PREFIX;
2525

26+
/**
27+
* Rest Action to create a Sample Resource. Registers Create and Update REST APIs.
28+
*/
2629
public class CreateResourceRestAction extends BaseRestHandler {
2730

2831
public CreateResourceRestAction() {}
@@ -31,13 +34,13 @@ public CreateResourceRestAction() {}
3134
public List<Route> routes() {
3235
return List.of(
3336
new Route(PUT, SAMPLE_RESOURCE_PLUGIN_API_PREFIX + "/create"),
34-
new Route(POST, SAMPLE_RESOURCE_PLUGIN_API_PREFIX + "/update/{resourceId}")
37+
new Route(POST, SAMPLE_RESOURCE_PLUGIN_API_PREFIX + "/update/{resource_id}")
3538
);
3639
}
3740

3841
@Override
3942
public String getName() {
40-
return "create_sample_resource";
43+
return "create_update_sample_resource";
4144
}
4245

4346
@Override
@@ -51,7 +54,7 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
5154
case PUT:
5255
return createResource(source, client);
5356
case POST:
54-
return updateResource(source, request.param("resourceId"), client);
57+
return updateResource(source, request.param("resource_id"), client);
5558
default:
5659
throw new IllegalArgumentException("Illegal method: " + request.method());
5760
}

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/create/UpdateResourceAction.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
*/
1616
public class UpdateResourceAction extends ActionType<CreateResourceResponse> {
1717
/**
18-
* Create sample resource action instance
18+
* Update sample resource action instance
1919
*/
2020
public static final UpdateResourceAction INSTANCE = new UpdateResourceAction();
2121
/**
22-
* Create sample resource action name
22+
* Update sample resource action name
2323
*/
2424
public static final String NAME = "cluster:admin/sample-resource-plugin/update";
2525

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/delete/DeleteResourceAction.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
import org.opensearch.action.ActionType;
1212

1313
/**
14-
* Action to create a sample resource
14+
* Action to delete a sample resource
1515
*/
1616
public class DeleteResourceAction extends ActionType<DeleteResourceResponse> {
1717
/**
18-
* Create sample resource action instance
18+
* Delete sample resource action instance
1919
*/
2020
public static final DeleteResourceAction INSTANCE = new DeleteResourceAction();
2121
/**
22-
* Create sample resource action name
22+
* Delete sample resource action name
2323
*/
2424
public static final String NAME = "cluster:admin/sample-resource-plugin/delete";
2525

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/delete/DeleteResourceRequest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import org.opensearch.core.common.io.stream.StreamOutput;
1717

1818
/**
19-
* Request object for CreateSampleResource transport action
19+
* Request object for DeleteSampleResource transport action
2020
*/
2121
public class DeleteResourceRequest extends ActionRequest {
2222

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/delete/DeleteResourceResponse.java

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
import org.opensearch.core.xcontent.ToXContentObject;
1717
import org.opensearch.core.xcontent.XContentBuilder;
1818

19+
/**
20+
* Response to a DeleteSampleResourceRequest
21+
*/
1922
public class DeleteResourceResponse extends ActionResponse implements ToXContentObject {
2023
private final String message;
2124

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/delete/DeleteResourceRestAction.java

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import static org.opensearch.rest.RestRequest.Method.DELETE;
2121
import static org.opensearch.sample.utils.Constants.SAMPLE_RESOURCE_PLUGIN_API_PREFIX;
2222

23+
/**
24+
* Rest Action to delete a Sample Resource.
25+
*/
2326
public class DeleteResourceRestAction extends BaseRestHandler {
2427

2528
public DeleteResourceRestAction() {}

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/get/GetResourceRestAction.java

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import static org.opensearch.rest.RestRequest.Method.GET;
2121
import static org.opensearch.sample.utils.Constants.SAMPLE_RESOURCE_PLUGIN_API_PREFIX;
2222

23+
/**
24+
* Rest action to get a sample resource
25+
*/
2326
public class GetResourceRestAction extends BaseRestHandler {
2427

2528
public GetResourceRestAction() {}

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/revoke/RevokeResourceAccessAction.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
*/
1616
public class RevokeResourceAccessAction extends ActionType<RevokeResourceAccessResponse> {
1717
/**
18-
* Share sample resource action instance
18+
* Revoke sample resource action instance
1919
*/
2020
public static final RevokeResourceAccessAction INSTANCE = new RevokeResourceAccessAction();
2121
/**
22-
* Share sample resource action name
22+
* Revoke sample resource action name
2323
*/
2424
public static final String NAME = "cluster:admin/sample-resource-plugin/revoke";
2525

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/revoke/RevokeResourceAccessRequest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import org.opensearch.core.common.io.stream.StreamOutput;
2121

2222
/**
23-
* Request object for revoking access to a sample resource transport action
23+
* Request object for revoking access to a sample resource
2424
*/
2525
public class RevokeResourceAccessRequest extends ActionRequest {
2626

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/revoke/RevokeResourceAccessResponse.java

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import org.opensearch.core.xcontent.XContentBuilder;
1818
import org.opensearch.security.spi.resources.sharing.ShareWith;
1919

20+
/**
21+
* Response for the RevokeResourceAccessAction
22+
*/
2023
public class RevokeResourceAccessResponse extends ActionResponse implements ToXContentObject {
2124
private final ShareWith shareWith;
2225

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/revoke/RevokeResourceAccessRestAction.java

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import static org.opensearch.rest.RestRequest.Method.POST;
2424
import static org.opensearch.sample.utils.Constants.SAMPLE_RESOURCE_PLUGIN_API_PREFIX;
2525

26+
/**
27+
* Rest Action to revoke sample resource access
28+
*/
2629
public class RevokeResourceAccessRestAction extends BaseRestHandler {
2730

2831
public RevokeResourceAccessRestAction() {}

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/share/ShareResourceResponse.java

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import org.opensearch.core.xcontent.XContentBuilder;
1818
import org.opensearch.security.spi.resources.sharing.ShareWith;
1919

20+
/**
21+
* Response object for ShareResourceAction
22+
*/
2023
public class ShareResourceResponse extends ActionResponse implements ToXContentObject {
2124
private final ShareWith shareWith;
2225

sample-resource-plugin/src/main/java/org/opensearch/sample/resource/actions/rest/share/ShareResourceRestAction.java

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import static org.opensearch.rest.RestRequest.Method.POST;
2424
import static org.opensearch.sample.utils.Constants.SAMPLE_RESOURCE_PLUGIN_API_PREFIX;
2525

26+
/**
27+
* Rest Action to share a resource
28+
*/
2629
public class ShareResourceRestAction extends BaseRestHandler {
2730

2831
public ShareResourceRestAction() {}

0 commit comments

Comments
 (0)