Skip to content

Commit

Permalink
Spotless formatting
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Nied <peternied@hotmail.com>
  • Loading branch information
peternied committed Mar 7, 2024
1 parent 5db53a9 commit 1c0f623
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,22 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import com.fasterxml.jackson.databind.JsonNode;

import org.apache.commons.io.FileUtils;
import org.awaitility.Awaitility;
import org.junit.AfterClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.opensearch.test.framework.TestSecurityConfig.User;
import org.opensearch.test.framework.cluster.ClusterManager;
import org.opensearch.test.framework.cluster.LocalCluster;
import org.opensearch.test.framework.cluster.TestRestClient;
import org.opensearch.test.framework.cluster.TestRestClient.HttpResponse;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.aMapWithSize;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;

@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class)
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
Expand Down Expand Up @@ -68,18 +61,17 @@ public static void cleanConfigurationDirectory() throws IOException {

// @Test
// public void shouldLoadDefaultConfiguration() {
// try (TestRestClient client = cluster.getRestClient(NEW_USER)) {
// Awaitility.await().alias("Load default configuration").until(() -> client.getAuthInfo().getStatusCode(), equalTo(200));
// }
// try (TestRestClient client = cluster.getRestClient(ADMIN_USER)) {
// client.confirmCorrectCredentials(ADMIN_USER.getName());
// HttpResponse response = client.get("_plugins/_security/api/internalusers");
// response.assertStatusCode(200);
// Map<String, Object> users = response.getBodyAs(Map.class);
// assertThat(users, allOf(aMapWithSize(3), hasKey(ADMIN_USER.getName()), hasKey(NEW_USER.getName()), hasKey(LIMITED_USER.getName())));
// }
// try (TestRestClient client = cluster.getRestClient(NEW_USER)) {
// Awaitility.await().alias("Load default configuration").until(() -> client.getAuthInfo().getStatusCode(), equalTo(200));
// }
// try (TestRestClient client = cluster.getRestClient(ADMIN_USER)) {
// client.confirmCorrectCredentials(ADMIN_USER.getName());
// HttpResponse response = client.get("_plugins/_security/api/internalusers");
// response.assertStatusCode(200);
// Map<String, Object> users = response.getBodyAs(Map.class);
// assertThat(users, allOf(aMapWithSize(3), hasKey(ADMIN_USER.getName()), hasKey(NEW_USER.getName()), hasKey(LIMITED_USER.getName())));
// }
// }


@Test
public void securityRolesUgrade() throws Exception {
Expand All @@ -92,7 +84,6 @@ public void securityRolesUgrade() throws Exception {
final var checkForUpgrade = client.get("_plugins/_security/api/_upgrade_check");
System.out.println("checkForUpgrade Response: " + checkForUpgrade.getBody());


final var roleToDelete = "flow_framework_full_access";
final var deleteRoleResponse = client.delete("_plugins/_security/api/roles/" + roleToDelete);
deleteRoleResponse.assertStatusCode(200);
Expand All @@ -103,12 +94,12 @@ public void securityRolesUgrade() throws Exception {
final var roleToAlter = "flow_framework_read_access";
final String patchBody = "[{ \"op\": \"replace\", \"path\": \"/cluster_permissions\", \"value\":"
+ "[\"a\",\"b\",\"c\"]"
+ "},{ \"op\": \"add\", \"path\": \"/index_permissions\", \"value\":"
+ "},{ \"op\": \"add\", \"path\": \"/index_permissions\", \"value\":"
+ "[{\"index_patterns\":[\"*\"],\"allowed_actions\":[\"*\"]}]"
+ "}]";
+ "}]";
final var updateRoleResponse = client.patch("_plugins/_security/api/roles/" + roleToAlter, patchBody);
updateRoleResponse.assertStatusCode(200);
System.out.println("Updated Role Response: " +updateRoleResponse.getBody());
System.out.println("Updated Role Response: " + updateRoleResponse.getBody());

final var checkForUpgrade2 = client.get("_plugins/_security/api/_upgrade_check");
System.out.println("checkForUpgrade2 Response: " + checkForUpgrade2.getBody());
Expand All @@ -125,6 +116,6 @@ public void securityRolesUgrade() throws Exception {
private List<String> extractFieldNames(final JsonNode json) {
final var list = new ArrayList<String>();
json.fieldNames().forEachRemaining(list::add);
return list;
return list;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@

package org.opensearch.security.dlic.rest.api;

import static org.opensearch.security.dlic.rest.api.Responses.badRequestMessage;
import static org.opensearch.security.dlic.rest.api.Responses.ok;
import static org.opensearch.security.dlic.rest.api.Responses.response;
import static org.opensearch.security.dlic.rest.support.Utils.addRoutesPrefix;
import static org.opensearch.security.dlic.rest.support.Utils.withIOException;

import java.io.IOException;
import java.nio.file.Path;
import java.security.AccessController;
Expand All @@ -31,14 +25,23 @@
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.opensearch.client.Client;
import org.opensearch.cluster.service.ClusterService;
import org.opensearch.common.collect.Tuple;
import org.opensearch.common.inject.Inject;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.xcontent.XContentType;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.rest.BytesRestResponse;
import org.opensearch.rest.RestChannel;
import org.opensearch.rest.RestRequest;
import org.opensearch.rest.RestRequest.Method;
Expand All @@ -53,49 +56,24 @@
import org.opensearch.security.support.ConfigHelper;
import org.opensearch.threadpool.ThreadPool;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.flipkart.zjsonpatch.DiffFlags;
import com.flipkart.zjsonpatch.JsonDiff;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import org.opensearch.common.inject.Inject;
import org.opensearch.common.xcontent.XContentType;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.rest.BytesRestResponse;
import org.opensearch.rest.RestChannel;
import org.opensearch.rest.RestRequest;
import org.opensearch.rest.RestRequest.Method;
import org.opensearch.security.configuration.ConfigurationRepository;
import org.opensearch.security.dlic.rest.support.Utils;
import org.opensearch.security.dlic.rest.validation.ValidationResult;
import org.opensearch.security.securityconf.impl.CType;
import org.opensearch.security.support.ConfigHelper;
import org.opensearch.threadpool.ThreadPool;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.flipkart.zjsonpatch.DiffFlags;
import com.flipkart.zjsonpatch.JsonDiff;
import com.google.common.collect.ImmutableList;

import static org.opensearch.security.dlic.rest.api.Responses.badRequestMessage;
import static org.opensearch.security.dlic.rest.api.Responses.ok;
import static org.opensearch.security.dlic.rest.api.Responses.response;
import static org.opensearch.security.dlic.rest.support.Utils.addRoutesPrefix;
import static org.opensearch.security.dlic.rest.support.Utils.withIOException;

public class ConfigUpgradeApiAction extends AbstractApiAction {

private final static Logger LOGGER = LogManager.getLogger(ConfigUpgradeApiAction.class);

private final static Set<CType> SUPPORTED_CTYPES = ImmutableSet.of(CType.ROLES);

private static final List<Route> routes = addRoutesPrefix(ImmutableList.of(
new Route(Method.GET, "/_upgrade_check"),
new Route(Method.POST, "/_upgrade_perform")
));
private static final List<Route> routes = addRoutesPrefix(
ImmutableList.of(new Route(Method.GET, "/_upgrade_check"), new Route(Method.POST, "/_upgrade_perform"))
);

@Inject
public ConfigUpgradeApiAction(
Expand All @@ -110,64 +88,66 @@ public ConfigUpgradeApiAction(
}

void handleCanUpgrade(final RestChannel channel, final RestRequest request, final Client client) throws IOException {
withIOException(() -> getAndValidateConfigurationsToUpgrade(request)
.map(this::configurationDifferences))
.valid(differencesList -> {
final var canUpgrade = differencesList.stream().anyMatch(entry -> entry.v2().size() > 0);

final ObjectNode response = JsonNodeFactory.instance.objectNode();
response.put("can_upgrade", canUpgrade);

if (canUpgrade) {
final ObjectNode differences = JsonNodeFactory.instance.objectNode();
differencesList.forEach(t -> {
differences.set(t.v1().toLCString(), t.v2());
});
response.set("differences", differences);
}
channel.sendResponse(new BytesRestResponse(RestStatus.OK, XContentType.JSON.mediaType(), response.toPrettyString()));
})
.error((status, toXContent) -> response(channel, status, toXContent));
withIOException(() -> getAndValidateConfigurationsToUpgrade(request).map(this::configurationDifferences)).valid(differencesList -> {
final var canUpgrade = differencesList.stream().anyMatch(entry -> entry.v2().size() > 0);

final ObjectNode response = JsonNodeFactory.instance.objectNode();
response.put("can_upgrade", canUpgrade);

if (canUpgrade) {
final ObjectNode differences = JsonNodeFactory.instance.objectNode();
differencesList.forEach(t -> { differences.set(t.v1().toLCString(), t.v2()); });
response.set("differences", differences);
}
channel.sendResponse(new BytesRestResponse(RestStatus.OK, XContentType.JSON.mediaType(), response.toPrettyString()));
}).error((status, toXContent) -> response(channel, status, toXContent));
}

private void handleUpgrade(final RestChannel channel, final RestRequest request, final Client client) throws IOException {
withIOException(() -> getConfigurations(request)
.map(this::configurationDifferences))
.map(diffs -> applyDifferences(request, diffs))
.valid(updatedResources -> {
ok(channel, "Applied all differences: " + updatedResources);
})
.error((status, toXContent) -> response(channel, status, toXContent));
withIOException(() -> getAndValidateConfigurationsToUpgrade(request).map(this::configurationDifferences)).map(
diffs -> applyDifferences(request, diffs)
).valid(updatedResources -> {
ok(channel, "Applied all differences: " + updatedResources);
}).error((status, toXContent) -> response(channel, status, toXContent));
}

ValidationResult<List<Tuple<CType, Map<String, List<String>>>>> applyDifferences(final RestRequest request, final List<Tuple<CType, JsonNode>> differencesToUpdate) throws IOException {
ValidationResult<List<Tuple<CType, Map<String, List<String>>>>> applyDifferences(
final RestRequest request,
final List<Tuple<CType, JsonNode>> differencesToUpdate
) throws IOException {
final var updatedResources = new ArrayList<ValidationResult<Tuple<CType, Map<String, List<String>>>>>();
for (final Tuple<CType, JsonNode> difference : differencesToUpdate) {
updatedResources.add(loadConfiguration(difference.v1(), false, false)
.map(configuration -> patchEntities(request, difference.v2(), SecurityConfiguration.of(null, configuration))
.map(patchResults -> {
final var items = new HashMap<String, String>();
difference.v2().forEach(node -> {
final var item = pathRoot(node);
final var operation = node.get("op").asText();
if (items.containsKey(item) && !items.get(item).equals(operation)) {
items.put(item, "modified");
} else {
items.put(item, operation);
}
});

final var itemsGroupedByOperation = items.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

return ValidationResult.success(new Tuple<>(difference.v1(), itemsGroupedByOperation));
})
updatedResources.add(
loadConfiguration(difference.v1(), false, false).map(
configuration -> patchEntities(request, difference.v2(), SecurityConfiguration.of(null, configuration)).map(
patchResults -> {
final var items = new HashMap<String, String>();
difference.v2().forEach(node -> {
final var item = pathRoot(node);
final var operation = node.get("op").asText();
if (items.containsKey(item) && !items.get(item).equals(operation)) {
items.put(item, "modified");
} else {
items.put(item, operation);
}
});

final var itemsGroupedByOperation = items.entrySet()
.stream()
.collect(
Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList()))
);

return ValidationResult.success(new Tuple<>(difference.v1(), itemsGroupedByOperation));
}
)
)
);
}

return ValidationResult.merge(updatedResources);
}

private ValidationResult<List<Tuple<CType, JsonNode>>> configurationDifferences(final Set<CType> configurations) throws IOException {
final var differences = new ArrayList<ValidationResult<Tuple<CType, JsonNode>>>();
for (final var configuration : configurations) {
Expand All @@ -187,15 +167,16 @@ private ValidationResult<Tuple<CType, JsonNode>> computeDifferenceToUpdate(final

private ValidationResult<Set<CType>> getAndValidateConfigurationsToUpgrade(final RestRequest request) {
final String[] configs = request.paramAsStringArray("configs", null);

final var configurations = Optional.ofNullable(configs)
.map(CType::fromStringValues)
.orElse(SUPPORTED_CTYPES);

final var configurations = Optional.ofNullable(configs).map(CType::fromStringValues).orElse(SUPPORTED_CTYPES);

if (!configurations.stream().allMatch(SUPPORTED_CTYPES::contains)) {
// Remove all supported configurations
configurations.removeAll(SUPPORTED_CTYPES);
return ValidationResult.error(RestStatus.BAD_REQUEST, badRequestMessage("Unsupported configurations for upgrade" + configurations));
return ValidationResult.error(
RestStatus.BAD_REQUEST,
badRequestMessage("Unsupported configurations for upgrade" + configurations)
);
}

return ValidationResult.success(configurations);
Expand Down Expand Up @@ -305,7 +286,6 @@ public ValidationResult<JsonNode> validate(RestRequest request, JsonNode jsonCon
return super.validate(request, jsonContent);
}


}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@

package org.opensearch.security.dlic.rest.validation;

import static org.opensearch.security.dlic.rest.api.Responses.badRequestMessage;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.databind.JsonNode;

import org.opensearch.common.CheckedBiConsumer;
import org.opensearch.common.CheckedConsumer;
Expand All @@ -29,8 +26,6 @@
import org.opensearch.core.xcontent.ToXContent;
import org.opensearch.security.securityconf.impl.CType;

import com.fasterxml.jackson.databind.JsonNode;

public class ValidationResult<C> {

private final RestStatus status;
Expand Down Expand Up @@ -70,7 +65,8 @@ public static <L> ValidationResult<List<L>> merge(final List<ValidationResult<L>
return success(results.stream().map(result -> result.content).collect(Collectors.toList()));
}

return results.stream().filter(result -> !result.isValid())
return results.stream()
.filter(result -> !result.isValid())
.map(failedResult -> new ValidationResult<List<L>>(failedResult.status, failedResult.errorMessage))
.findFirst()
.get();
Expand Down

0 comments on commit 1c0f623

Please sign in to comment.