Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Adding Alerting V2 roles to roles.yml ([#5747](https://github.com/opensearch-project/security/pull/5747))
- add suggest api to ad read access role ([#5754](https://github.com/opensearch-project/security/pull/5754))
- Get list of headersToCopy from core and use getHeader(String headerName) instead of getHeaders() ([#5769](https://github.com/opensearch-project/security/pull/5769))
- [Resource Sharing] Keep track of resource_type on resource sharing document ([#5772](https://github.com/opensearch-project/security/pull/5772))
- Add support for X509 v3 extensions (SAN) for authentication ([#5701](https://github.com/opensearch-project/security/pull/5701))

### Bug Fixes
Expand Down
2 changes: 0 additions & 2 deletions RESOURCE_SHARING_AND_ACCESS_CONTROL.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,6 @@ Read documents from a plugin’s index and migrate ownership and backend role-ba
| `source_index` | string | yes | Name of the plugin index containing the existing resource documents |
| `username_path` | string | yes | JSON Pointer to the username field inside each document |
| `backend_roles_path` | string | yes | JSON Pointer to the backend_roles field (must point to a JSON array) |
| `type_path` | string | no | JSON Pointer to the resource type field inside each document (required if multiple resource types in same resource index) |
| `default_access_level` | object | yes | Default access level to assign migrated backend_roles. Must be one from the available action-groups for this type. See `resource-action-groups.yml`. |

**Example Request**
Expand All @@ -621,7 +620,6 @@ Read documents from a plugin’s index and migrate ownership and backend role-ba
"source_index": ".sample_resource",
"username_path": "/owner",
"backend_roles_path": "/backend_roles",
"type_path": "/type",
"default_access_level": {
"sample-resource": "read_only",
"sample-resource-group": "read-only-group"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ public void wipeOutResourceEntries() {
// Helper to create a sample resource and return its ID
public String createSampleResourceAs(TestSecurityConfig.User user, Header... headers) {
try (TestRestClient client = cluster.getRestClient(user)) {
String sample = "{\"name\":\"sample\"}";
String sample = "{\"name\":\"sample\",\"resource_type\":\"" + RESOURCE_TYPE + "\"}";
TestRestClient.HttpResponse resp = client.putJson(SAMPLE_RESOURCE_CREATE_ENDPOINT, sample, headers);
resp.assertStatusCode(HttpStatus.SC_OK);
return resp.getTextFromJsonBody("/message").split(":")[1].trim();
Expand All @@ -353,7 +353,7 @@ public String createSampleResourceAs(TestSecurityConfig.User user, Header... hea

public String createSampleResourceGroupAs(TestSecurityConfig.User user, Header... headers) {
try (TestRestClient client = cluster.getRestClient(user)) {
String sample = "{\"name\":\"samplegroup\"}";
String sample = "{\"name\":\"samplegroup\",\"resource_type\":\"" + RESOURCE_GROUP_TYPE + "\"}";
TestRestClient.HttpResponse resp = client.putJson(SAMPLE_RESOURCE_GROUP_CREATE_ENDPOINT, sample, headers);
resp.assertStatusCode(HttpStatus.SC_OK);
return resp.getTextFromJsonBody("/message").split(":")[1].trim();
Expand All @@ -362,7 +362,7 @@ public String createSampleResourceGroupAs(TestSecurityConfig.User user, Header..

public String createRawResourceAs(CertificateData adminCert) {
try (TestRestClient client = cluster.getRestClient(adminCert)) {
String sample = "{\"name\":\"sample\"}";
String sample = "{\"name\":\"sample\",\"resource_type\":\"" + RESOURCE_TYPE + "\"}";
TestRestClient.HttpResponse resp = client.postJson(RESOURCE_INDEX_NAME + "/_doc", sample);
resp.assertStatusCode(HttpStatus.SC_CREATED);
return resp.getTextFromJsonBody("/_id");
Expand Down Expand Up @@ -680,6 +680,8 @@ public void awaitSharingEntry(String resourceId, String expectedString) {
TestRestClient.HttpResponse response = client.get(RESOURCE_SHARING_INDEX + "/_doc/" + resourceId);
response.assertStatusCode(200);
String body = response.getBody();
String resourceType = response.getTextFromJsonBody("/_source/resource_type");
assert resourceType != null : "resource_type cannot be null";
assertThat(body, containsString(expectedString));
assertThat(body, containsString(resourceId));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ private ArrayNode expectedHits(String resourceId, String accessLevel) {
// 3) Build the _source sub-object
ObjectNode source = hit.putObject("_source");
source.put("resource_id", resourceId);
source.put("resource_type", RESOURCE_TYPE);

ObjectNode createdBy = source.putObject("created_by");
createdBy.put("user", MIGRATION_USER.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ public SampleResource(StreamInput in) throws IOException {
}
s.setName((String) a[0]);
s.setDescription((String) a[1]);
s.setAttributes((Map<String, String>) a[2]);
s.setUser((User) a[3]);
// ignore a[2] as we know the type
s.setAttributes((Map<String, String>) a[3]);
s.setUser((User) a[4]);
return s;
});

static {
PARSER.declareString(constructorArg(), new ParseField("name"));
PARSER.declareStringOrNull(optionalConstructorArg(), new ParseField("description"));
PARSER.declareStringOrNull(optionalConstructorArg(), new ParseField("resource_type"));
PARSER.declareObjectOrNull(optionalConstructorArg(), (p, c) -> p.mapStrings(), null, new ParseField("attributes"));
PARSER.declareObjectOrNull(optionalConstructorArg(), (p, c) -> User.parse(p), null, new ParseField("user"));
}
Expand All @@ -80,6 +82,7 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par
return builder.startObject()
.field("name", name)
.field("description", description)
.field("resource_type", RESOURCE_TYPE)
.field("attributes", attributes)
.field("user", user)
.endObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public String resourceType() {
public String resourceIndexName() {
return RESOURCE_INDEX_NAME;
}

@Override
public String typeField() {
return "resource_type";
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public String resourceType() {
public String resourceIndexName() {
return RESOURCE_INDEX_NAME;
}

@Override
public String typeField() {
return "resource_type";
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ public CreateResourceGroupTransportAction(TransportService transportService, Act

@Override
protected void doExecute(Task task, CreateResourceGroupRequest request, ActionListener<CreateResourceGroupResponse> listener) {
createResource(request, listener);
createResourceGroup(request, listener);
}

private void createResource(CreateResourceGroupRequest request, ActionListener<CreateResourceGroupResponse> listener) {
private void createResourceGroup(CreateResourceGroupRequest request, ActionListener<CreateResourceGroupResponse> listener) {
SampleResourceGroup sampleGroup = request.getResourceGroup();

// 1. Read mapping JSON from the config file
Expand Down
3 changes: 3 additions & 0 deletions sample-resource-plugin/src/main/resources/mappings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"schema_version": 1
},
"properties": {
"resource_type": {
"type": "keyword"
},
"all_shared_principals": {
"type": "keyword"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,13 @@ public interface ResourceProvider {

String resourceIndexName();

/**
* Returns the name of the field representing the resource type in the resource document.
*
* @return the field name containing the resource type
*/
default String typeField() {
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re

log.debug("postIndex called on {}", resourceIndex);

String resourceType = resourcePluginInfo.getResourceTypeForIndexOp(resourceIndex, index);

String resourceId = index.id();

// Only proceed if this was a create operation and for primary shard
Expand Down Expand Up @@ -107,8 +109,10 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re
resourceIndex
);
}, e -> { log.debug(e.getMessage()); });
// User.getRequestedTenant() is null if multi-tenancy is disabled
ResourceSharing.Builder builder = ResourceSharing.builder()
.resourceId(resourceId)
.resourceType(resourceType)
.createdBy(new CreatedBy(user.getName(), user.getRequestedTenant()));
ResourceSharing sharingInfo = builder.build();
// User.getRequestedTenant() is null if multi-tenancy is disabled
Expand Down
Loading
Loading