|
@@ -48,6 +48,7 @@ import java.util.Set;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
|
+import static org.hamcrest.Matchers.containsString;
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
import static org.hamcrest.Matchers.hasItem;
|
|
|
import static org.hamcrest.Matchers.is;
|
|
@@ -877,62 +878,56 @@ public class FailureStoreSecurityRestIT extends ESRestTestCase {
|
|
|
|
|
|
public void testRoleWithSelectorInIndexPattern() throws Exception {
|
|
|
setupDataStream();
|
|
|
-
|
|
|
createUser("user", PASSWORD, "role");
|
|
|
- upsertRole("""
|
|
|
- {
|
|
|
- "cluster": ["all"],
|
|
|
- "indices": [
|
|
|
- {
|
|
|
- "names": ["*::failures"],
|
|
|
- "privileges": ["read"]
|
|
|
- }
|
|
|
- ]
|
|
|
- }""", "role");
|
|
|
- createAndStoreApiKey("user", null);
|
|
|
-
|
|
|
- expectThrows("user", new Search("test1::failures"), 403);
|
|
|
- expectSearch("user", new Search("*::failures"));
|
|
|
-
|
|
|
- upsertRole("""
|
|
|
- {
|
|
|
- "cluster": ["all"],
|
|
|
- "indices": [
|
|
|
- {
|
|
|
- "names": ["test1::failures"],
|
|
|
- "privileges": ["read"]
|
|
|
- }
|
|
|
- ]
|
|
|
- }""", "role");
|
|
|
+ expectThrowsSelectorsNotAllowed(
|
|
|
+ () -> upsertRole(
|
|
|
+ Strings.format("""
|
|
|
+ {
|
|
|
+ "cluster": ["all"],
|
|
|
+ "indices": [
|
|
|
+ {
|
|
|
+ "names": ["%s"],
|
|
|
+ "privileges": ["%s"]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }""", randomFrom("*::failures", "test1::failures", "test1::data", "*::data"), randomFrom("read", "read_failure_store")),
|
|
|
+ "role",
|
|
|
+ false
|
|
|
+ )
|
|
|
+ );
|
|
|
|
|
|
- expectThrows("user", new Search("test1::failures"), 403);
|
|
|
- expectSearch("user", new Search("*::failures"));
|
|
|
+ AssertionError bulkFailedError = expectThrows(
|
|
|
+ AssertionError.class,
|
|
|
+ () -> upsertRole(
|
|
|
+ Strings.format("""
|
|
|
+ {
|
|
|
+ "cluster": ["all"],
|
|
|
+ "indices": [
|
|
|
+ {
|
|
|
+ "names": ["%s"],
|
|
|
+ "privileges": ["%s"]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }""", randomFrom("*::failures", "test1::failures", "test1::data", "*::data"), randomFrom("read", "read_failure_store")),
|
|
|
+ "role",
|
|
|
+ true
|
|
|
+ )
|
|
|
+ );
|
|
|
+ assertThat(bulkFailedError.getMessage(), containsString("selectors [::] are not allowed in the index name expression"));
|
|
|
|
|
|
- upsertRole("""
|
|
|
+ expectThrowsSelectorsNotAllowed(() -> createApiKey("user", Strings.format("""
|
|
|
{
|
|
|
- "cluster": ["all"],
|
|
|
- "indices": [
|
|
|
- {
|
|
|
- "names": ["*::failures"],
|
|
|
- "privileges": ["read_failure_store"]
|
|
|
+ "role": {
|
|
|
+ "cluster": ["all"],
|
|
|
+ "indices": [
|
|
|
+ {
|
|
|
+ "names": ["%s"],
|
|
|
+ "privileges": ["%s"]
|
|
|
+ }
|
|
|
+ ]
|
|
|
}
|
|
|
- ]
|
|
|
- }""", "role");
|
|
|
- expectThrows("user", new Search("test1::failures"), 403);
|
|
|
- expectSearch("user", new Search("*::failures"));
|
|
|
+ }""", randomFrom("*::failures", "test1::failures", "test1::data", "*::data"), randomFrom("read", "read_failure_store"))));
|
|
|
|
|
|
- upsertRole("""
|
|
|
- {
|
|
|
- "cluster": ["all"],
|
|
|
- "indices": [
|
|
|
- {
|
|
|
- "names": ["test1::failures"],
|
|
|
- "privileges": ["read_failure_store"]
|
|
|
- }
|
|
|
- ]
|
|
|
- }""", "role");
|
|
|
- expectThrows("user", new Search("test1::failures"), 403);
|
|
|
- expectSearch("user", new Search("*::failures"));
|
|
|
}
|
|
|
|
|
|
public void testFailureStoreAccess() throws Exception {
|
|
@@ -2489,7 +2484,7 @@ public class FailureStoreSecurityRestIT extends ESRestTestCase {
|
|
|
protected String createAndStoreApiKey(String username, @Nullable String roleDescriptors) throws IOException {
|
|
|
assertThat("API key already registered for user: " + username, apiKeys.containsKey(username), is(false));
|
|
|
apiKeys.put(username, createApiKey(username, roleDescriptors));
|
|
|
- return createApiKey(username, roleDescriptors);
|
|
|
+ return apiKeys.get(username);
|
|
|
}
|
|
|
|
|
|
private String createApiKey(String username, String roleDescriptors) throws IOException {
|
|
@@ -2514,22 +2509,35 @@ public class FailureStoreSecurityRestIT extends ESRestTestCase {
|
|
|
return (String) responseAsMap.get("encoded");
|
|
|
}
|
|
|
|
|
|
- protected void upsertRole(String roleDescriptor, String roleName) throws IOException {
|
|
|
- Request createRoleRequest = roleRequest(roleDescriptor, roleName);
|
|
|
+ protected Response upsertRole(String roleDescriptor, String roleName) throws IOException {
|
|
|
+ return upsertRole(roleDescriptor, roleName, randomBoolean());
|
|
|
+ }
|
|
|
+
|
|
|
+ protected Response upsertRole(String roleDescriptor, String roleName, boolean bulk) throws IOException {
|
|
|
+ Request createRoleRequest = roleRequest(roleDescriptor, roleName, bulk);
|
|
|
Response createRoleResponse = adminClient().performRequest(createRoleRequest);
|
|
|
assertOK(createRoleResponse);
|
|
|
+ if (bulk) {
|
|
|
+ Map<String, Object> flattenedResponse = Maps.flatten(responseAsMap(createRoleResponse), true, true);
|
|
|
+ if (flattenedResponse.containsKey("errors.count") && (int) flattenedResponse.get("errors.count") > 0) {
|
|
|
+ throw new AssertionError(
|
|
|
+ "Failed to create role [" + roleName + "], reason: " + flattenedResponse.get("errors.details." + roleName + ".reason")
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return createRoleResponse;
|
|
|
}
|
|
|
|
|
|
- protected Request roleRequest(String roleDescriptor, String roleName) {
|
|
|
+ protected Request roleRequest(String roleDescriptor, String roleName, boolean bulk) {
|
|
|
Request createRoleRequest;
|
|
|
- if (randomBoolean()) {
|
|
|
- createRoleRequest = new Request(randomFrom(HttpPut.METHOD_NAME, HttpPost.METHOD_NAME), "/_security/role/" + roleName);
|
|
|
- createRoleRequest.setJsonEntity(roleDescriptor);
|
|
|
- } else {
|
|
|
+ if (bulk) {
|
|
|
createRoleRequest = new Request(HttpPost.METHOD_NAME, "/_security/role");
|
|
|
createRoleRequest.setJsonEntity(org.elasticsearch.core.Strings.format("""
|
|
|
{"roles": {"%s": %s}}
|
|
|
""", roleName, roleDescriptor));
|
|
|
+ } else {
|
|
|
+ createRoleRequest = new Request(randomFrom(HttpPut.METHOD_NAME, HttpPost.METHOD_NAME), "/_security/role/" + roleName);
|
|
|
+ createRoleRequest.setJsonEntity(roleDescriptor);
|
|
|
}
|
|
|
return createRoleRequest;
|
|
|
}
|
|
@@ -2592,4 +2600,10 @@ public class FailureStoreSecurityRestIT extends ESRestTestCase {
|
|
|
Response response = performRequestWithApiKey(apiKey, req);
|
|
|
assertThat(responseAsMap(response), equalTo(mapFromJson(expectedResponse)));
|
|
|
}
|
|
|
+
|
|
|
+ private static void expectThrowsSelectorsNotAllowed(ThrowingRunnable runnable) {
|
|
|
+ ResponseException exception = expectThrows(ResponseException.class, runnable);
|
|
|
+ assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(400));
|
|
|
+ assertThat(exception.getMessage(), containsString("selectors [::] are not allowed in the index name expression"));
|
|
|
+ }
|
|
|
}
|