Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Tenants REST API test and partial fix #4166 #4462

Closed
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

package org.opensearch.security.api;

import java.util.Optional;

import com.fasterxml.jackson.databind.JsonNode;

import org.opensearch.core.xcontent.ToXContentObject;
import org.opensearch.security.dlic.rest.api.Endpoint;
import org.opensearch.test.framework.cluster.TestRestClient;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.opensearch.security.api.PatchPayloadHelper.addOp;
import static org.opensearch.security.api.PatchPayloadHelper.patch;
import static org.opensearch.security.api.PatchPayloadHelper.removeOp;
import static org.opensearch.security.api.PatchPayloadHelper.replaceOp;

public class TenantsRestApiIntegrationTest extends AbstractConfigEntityApiIntegrationTest {

private final static String REST_API_ADMIN_TENANTS_ONLY = "rest_api_admin_tenants_only";

static {
testSecurityConfig.withRestAdminUser(REST_API_ADMIN_TENANTS_ONLY, restAdminPermission(Endpoint.TENANTS));
}

public TenantsRestApiIntegrationTest() {
super("tenants", new TestDescriptor() {
@Override
public String entityJsonProperty() {
return "description";
}

@Override
public ToXContentObject entityPayload(Boolean hidden, Boolean reserved, Boolean _static) {
return tenant(hidden, reserved, _static);
}

@Override
public ToXContentObject jsonPropertyPayload() {
return (builder, params) -> builder.value(randomAsciiAlphanumOfLength(10));
}

@Override
public Optional<String> restAdminLimitedUser() {
return Optional.of(REST_API_ADMIN_TENANTS_ONLY);
}
});
}

static ToXContentObject tenant(final Boolean hidden, final Boolean reserved, final String description) {
return tenant(hidden, reserved, null, description);
}

static ToXContentObject tenant(final Boolean hidden, final Boolean reserved, final Boolean _static) {
return tenant(hidden, reserved, _static, randomAsciiAlphanumOfLength(10));
}

static ToXContentObject tenant(final Boolean hidden, final Boolean reserved, final Boolean _static, String description) {
return (builder, params) -> {
builder.startObject();
if (hidden != null) {
builder.field("hidden", hidden);
}
if (reserved != null) {
builder.field("reserved", reserved);
}
if (_static != null) {
builder.field("static", _static);
}
builder.field("description", description);
return builder.endObject();
};
}

@Override
void verifyBadRequestOperations(TestRestClient client) throws Exception {
// put
badRequest(() -> client.putJson(apiPath(randomAsciiAlphanumOfLength(4)), EMPTY_BODY));
badRequest(
() -> client.putJson(
apiPath(randomAsciiAlphanumOfLength(4)),
(builder, params) -> builder.startObject().field("description", "a").field("description", "b").endObject()
)
);
assertInvalidKeys(
client.putJson(
apiPath(randomAsciiAlphanumOfLength(10)),
(builder, params) -> builder.startObject().field("a", "b").field("c", "d").field("description", "e").endObject()
),
"a,c"
);
// patch
badRequest(() -> client.patch(apiPath(), EMPTY_BODY));
badRequest(
() -> client.patch(
apiPath(),
patch(
addOp(
randomAsciiAlphanumOfLength(4),
(ToXContentObject) (builder, params) -> builder.startObject()
.field("description", "a")
.field("description", "b")
.endObject()
)
)
)
);
assertInvalidKeys(
client.patch(
apiPath(),
patch(
addOp(
randomAsciiAlphanumOfLength(10),
(ToXContentObject) (builder, params) -> builder.startObject()
.field("a", "b")
.field("c", "d")
.field("description", "e")
.endObject()
)
)
),
"a,c"
);

}

@Override
void verifyCrudOperations(Boolean hidden, Boolean reserved, TestRestClient client) throws Exception {
// put
final var putDescription = randomAsciiAlphanumOfLength(10);
final var putTenantName = randomAsciiAlphanumOfLength(4);
created(() -> client.putJson(apiPath(putTenantName), tenant(hidden, reserved, putDescription)));
assertTenant(ok(() -> client.get(apiPath(putTenantName))).bodyAsJsonNode().get(putTenantName), hidden, reserved, putDescription);

final var putUpdatedDescription = randomAsciiAlphanumOfLength(10);
ok(() -> client.putJson(apiPath(putTenantName), tenant(hidden, reserved, putUpdatedDescription)));
assertTenant(
ok(() -> client.get(apiPath(putTenantName))).bodyAsJsonNode().get(putTenantName),
hidden,
reserved,
putUpdatedDescription
);
ok(() -> client.delete(apiPath(putTenantName)));
notFound(() -> client.get(apiPath(putTenantName)));
// patch
final var patchTenantName = randomAsciiAlphanumOfLength(4);
final var patchDescription = randomAsciiAlphanumOfLength(10);
ok(() -> client.patch(apiPath(), patch(addOp(patchTenantName, tenant(hidden, reserved, patchDescription)))));
assertTenant(
ok(() -> client.get(apiPath(patchTenantName))).bodyAsJsonNode().get(patchTenantName),
hidden,
reserved,
patchDescription
);

final var patchUpdatedDescription = randomAsciiAlphanumOfLength(10);
ok(() -> client.patch(apiPath(patchTenantName), patch(replaceOp("description", patchUpdatedDescription))));
assertTenant(
ok(() -> client.get(apiPath(patchTenantName))).bodyAsJsonNode().get(patchTenantName),
hidden,
reserved,
patchUpdatedDescription
);

ok(() -> client.patch(apiPath(), patch(removeOp(patchTenantName))));
notFound(() -> client.get(apiPath(patchTenantName)));
}

void assertTenant(final JsonNode actualJson, final Boolean hidden, final Boolean reserved, final String expectedDescription) {
assertThat(actualJson.toPrettyString(), actualJson.get("hidden").asBoolean(), is(hidden != null && hidden));
assertThat(actualJson.toPrettyString(), actualJson.get("reserved").asBoolean(), is(reserved != null && reserved));
assertThat(actualJson.toPrettyString(), actualJson.get("description").asText(), is(expectedDescription));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
public Map<String, RequestContentValidator.DataType> allowedKeys() {
final ImmutableMap.Builder<String, DataType> allowedKeys = ImmutableMap.builder();
if (isCurrentUserAdmin()) {
allowedKeys.put("hidden", DataType.BOOLEAN);

Check warning on line 111 in src/main/java/org/opensearch/security/dlic/rest/api/TenantsApiAction.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/security/dlic/rest/api/TenantsApiAction.java#L111

Added line #L111 was not covered by tests
allowedKeys.put("reserved", DataType.BOOLEAN);
}
return allowedKeys.put("description", DataType.STRING).build();
Expand Down
Loading