diff --git a/src/integrationTest/java/org/opensearch/security/ConfigurationFiles.java b/src/integrationTest/java/org/opensearch/security/ConfigurationFiles.java index e77d6a9f73..813b0e39de 100644 --- a/src/integrationTest/java/org/opensearch/security/ConfigurationFiles.java +++ b/src/integrationTest/java/org/opensearch/security/ConfigurationFiles.java @@ -25,6 +25,11 @@ public static void createRoleMappingFile(File destination) { copyResourceToFile(resource, destination); } + public static void createConfigFile(File destination) { + String resource = "config.yml"; + copyResourceToFile(resource, destination); + } + public static Path createConfigurationDirectory() { try { Path tempDirectory = Files.createTempDirectory("test-security-config"); diff --git a/src/integrationTest/java/org/opensearch/security/SecurityAdminLauncher.java b/src/integrationTest/java/org/opensearch/security/SecurityAdminLauncher.java index 0cd8b23f5d..997f879225 100644 --- a/src/integrationTest/java/org/opensearch/security/SecurityAdminLauncher.java +++ b/src/integrationTest/java/org/opensearch/security/SecurityAdminLauncher.java @@ -38,4 +38,17 @@ public int updateRoleMappings(File roleMappingsConfigurationFile) throws Excepti return SecurityAdmin.execute(commandLineArguments); } + + public int updateConfig(File configFile) throws Exception { + String[] commandLineArguments = {"-cacert", certificates.getRootCertificate().getAbsolutePath(), + "-cert", certificates.getAdminCertificate().getAbsolutePath(), + "-key", certificates.getAdminKey(null).getAbsolutePath(), + "-nhnv", + "-p", String.valueOf(port), + "-f", configFile.getAbsolutePath(), + "-t", "config" + }; + + return SecurityAdmin.execute(commandLineArguments); + } } diff --git a/src/integrationTest/java/org/opensearch/security/SecurityConfigurationTests.java b/src/integrationTest/java/org/opensearch/security/SecurityConfigurationTests.java index 2caf05536b..9ad311dfa9 100644 --- a/src/integrationTest/java/org/opensearch/security/SecurityConfigurationTests.java +++ b/src/integrationTest/java/org/opensearch/security/SecurityConfigurationTests.java @@ -15,6 +15,7 @@ import java.util.Map; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import com.fasterxml.jackson.databind.JsonNode; import org.awaitility.Awaitility; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -22,7 +23,6 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; - import org.opensearch.client.Client; import org.opensearch.test.framework.TestSecurityConfig.Role; import org.opensearch.test.framework.TestSecurityConfig.User; @@ -46,7 +46,7 @@ public class SecurityConfigurationTests { private static final User USER_ADMIN = new User("admin").roles(ALL_ACCESS); private static final User LIMITED_USER = new User("limited-user") - .roles(new Role("limited-role").indexPermissions("indices:data/read/search", "indices:data/read/get").on("user-${user.name}")); + .roles(new Role("limited-role").indexPermissions("indices:data/read/search", "indices:data/read/get").on("user-${user.name}")); public static final String LIMITED_USER_INDEX = "user-" + LIMITED_USER.getName(); public static final String ADDITIONAL_USER_1 = "additional00001"; public static final String ADDITIONAL_PASSWORD_1 = ADDITIONAL_USER_1; @@ -61,11 +61,11 @@ public class SecurityConfigurationTests { @ClassRule public static LocalCluster cluster = new LocalCluster.Builder() - .clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS) - .authc(AUTHC_HTTPBASIC_INTERNAL).users(USER_ADMIN, LIMITED_USER).anonymousAuth(false) - .nodeSettings(Map.of(SECURITY_RESTAPI_ROLES_ENABLED, List.of("user_" + USER_ADMIN.getName() +"__" + ALL_ACCESS.getName()), - SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, true)) - .build(); + .clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS) + .authc(AUTHC_HTTPBASIC_INTERNAL).users(USER_ADMIN, LIMITED_USER).anonymousAuth(false) + .nodeSettings(Map.of(SECURITY_RESTAPI_ROLES_ENABLED, List.of("user_" + USER_ADMIN.getName() +"__" + ALL_ACCESS.getName()), + SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, true)) + .build(); @Rule public TemporaryFolder configurationDirectory = new TemporaryFolder(); @@ -82,7 +82,7 @@ public static void initData() { public void shouldCreateUserViaRestApi_success() { try(TestRestClient client = cluster.getRestClient(USER_ADMIN)) { HttpResponse httpResponse = client.putJson(INTERNAL_USERS_RESOURCE + ADDITIONAL_USER_1, String.format(CREATE_USER_BODY, - ADDITIONAL_PASSWORD_1)); + ADDITIONAL_PASSWORD_1)); assertThat(httpResponse.getStatusCode(), equalTo(201)); } @@ -98,7 +98,7 @@ public void shouldCreateUserViaRestApi_success() { public void shouldCreateUserViaRestApi_failure() { try(TestRestClient client = cluster.getRestClient(LIMITED_USER)) { HttpResponse httpResponse = client.putJson(INTERNAL_USERS_RESOURCE + ADDITIONAL_USER_1, String.format(CREATE_USER_BODY, - ADDITIONAL_PASSWORD_1)); + ADDITIONAL_PASSWORD_1)); httpResponse.assertStatusCode(403); } @@ -141,7 +141,7 @@ public void shouldCreateUserViaRestApiWhenAdminIsAuthenticatedViaCertificate_pos try(TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) { HttpResponse httpResponse = client.putJson(INTERNAL_USERS_RESOURCE + ADDITIONAL_USER_2, String.format(CREATE_USER_BODY, - ADDITIONAL_PASSWORD_2)); + ADDITIONAL_PASSWORD_2)); httpResponse.assertStatusCode(201); } @@ -158,7 +158,7 @@ public void shouldCreateUserViaRestApiWhenAdminIsAuthenticatedViaCertificate_neg TestCertificates testCertificates = cluster.getTestCertificates(); try(TestRestClient client = cluster.getRestClient(testCertificates.createSelfSignedCertificate("CN=attacker"))) { HttpResponse httpResponse = client.putJson(INTERNAL_USERS_RESOURCE + ADDITIONAL_USER_2, String.format(CREATE_USER_BODY, - ADDITIONAL_PASSWORD_2)); + ADDITIONAL_PASSWORD_2)); httpResponse.assertStatusCode(401); } @@ -209,7 +209,28 @@ public void shouldUseSecurityAdminTool() throws Exception { assertThat(exitCode, equalTo(0)); try(TestRestClient client = cluster.getRestClient(USER_ADMIN)) { Awaitility.await().alias("Waiting for rolemapping 'readall' availability.") - .until(() -> client.get("_plugins/_security/api/rolesmapping/readall").getStatusCode(), equalTo(200)); + .until(() -> client.get("_plugins/_security/api/rolesmapping/readall").getStatusCode(), equalTo(200)); + } + } + + @Test + public void shouldReloadExtensionsConfigurationFromFile() throws Exception { + SecurityAdminLauncher securityAdminLauncher = new SecurityAdminLauncher(cluster.getHttpPort(), cluster.getTestCertificates()); + File config = configurationDirectory.newFile("config.yml"); + ConfigurationFiles.createConfigFile(config); + int exitCode = securityAdminLauncher.updateConfig(config); + assertThat(exitCode, equalTo(0)); + + try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) { + Awaitility.await() + .until(() -> + { + HttpResponse httpResponse = client.get("_plugins/_security/api/securityconfig"); + JsonNode jsonNode = DefaultObjectMapper.objectMapper.readTree(httpResponse.getBody()); + return jsonNode.get("config").get("dynamic").get("extensions"); + + }, jsonNode -> jsonNode.get("encryption_key").asText().equals("encryption key") && jsonNode.get("signing_key").asText().equals("signing key") + ); } } } diff --git a/src/integrationTest/resources/config.yml b/src/integrationTest/resources/config.yml index 5e929c0e2a..3d4be02946 100644 --- a/src/integrationTest/resources/config.yml +++ b/src/integrationTest/resources/config.yml @@ -15,3 +15,6 @@ config: authentication_backend: type: "internal" config: {} + extensions: + signing_key: "signing key" + encryption_key: "encryption key"