From 9e62096f95566fee53864e4c746cd1dd80c57190 Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Fri, 9 Aug 2024 13:22:04 -0400 Subject: [PATCH] Fixes authtoken endpoint (#4628) Signed-off-by: Darshit Chanpura --- .../CertificatesRestApiIntegrationTest.java | 11 +++++++++++ .../InternalUsersRestApiIntegrationTest.java | 12 ++++++++++++ .../dlic/rest/api/CertificatesApiAction.java | 1 + .../dlic/rest/api/InternalUsersApiAction.java | 6 +++--- .../opensearch/security/user/UserService.java | 19 ++++++------------- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/integrationTest/java/org/opensearch/security/api/CertificatesRestApiIntegrationTest.java b/src/integrationTest/java/org/opensearch/security/api/CertificatesRestApiIntegrationTest.java index ebac5b80a5..8a69406bff 100644 --- a/src/integrationTest/java/org/opensearch/security/api/CertificatesRestApiIntegrationTest.java +++ b/src/integrationTest/java/org/opensearch/security/api/CertificatesRestApiIntegrationTest.java @@ -90,6 +90,17 @@ public void availableForRestAdmin() throws Exception { withUser(REST_API_ADMIN_SSL_INFO, this::verifySSLCertsInfo); } + @Test + public void timeoutTest() throws Exception { + withUser(REST_ADMIN_USER, this::verifyTimeoutRequest); + } + + private void verifyTimeoutRequest(final TestRestClient client) throws Exception { + TestRestClient.HttpResponse response = ok(() -> client.get(sslCertsPath() + "?timeout=0")); + final var body = response.bodyAsJsonNode(); + assertThat(body.get("nodes").size(), is(0)); + } + private void verifySSLCertsInfo(final TestRestClient client) throws Exception { assertSSLCertsInfo( localCluster.nodes(), diff --git a/src/integrationTest/java/org/opensearch/security/api/InternalUsersRestApiIntegrationTest.java b/src/integrationTest/java/org/opensearch/security/api/InternalUsersRestApiIntegrationTest.java index 1ea18c4363..18769949fe 100644 --- a/src/integrationTest/java/org/opensearch/security/api/InternalUsersRestApiIntegrationTest.java +++ b/src/integrationTest/java/org/opensearch/security/api/InternalUsersRestApiIntegrationTest.java @@ -440,6 +440,18 @@ void assertFilterByUsers(final HttpResponse response, final boolean hasServiceUs assertThat(response.getBody(), response.bodyAsJsonNode().has(NEW_USER), is(hasInternalUser)); } + @Test + public void verifyPOSTOnlyForAuthTokenEndpoint() throws Exception { + withUser(ADMIN_USER_NAME, client -> { + badRequest(() -> client.post(apiPath(ADMIN_USER_NAME, "authtoken"))); + ok(() -> client.post(apiPath(SERVICE_ACCOUNT_USER, "authtoken"))); + /* + should be notImplement but the call doesn't reach {@link org.opensearch.security.dlic.rest.api.InternalUsersApiAction#withAuthTokenPath(RestRequest)} + */ + methodNotAllowed(() -> client.post(apiPath("randomPath"))); + }); + } + @Test public void userApiWithDotsInName() throws Exception { withUser(ADMIN_USER_NAME, client -> { diff --git a/src/main/java/org/opensearch/security/dlic/rest/api/CertificatesApiAction.java b/src/main/java/org/opensearch/security/dlic/rest/api/CertificatesApiAction.java index ea045c3aef..e1cd51e95d 100644 --- a/src/main/java/org/opensearch/security/dlic/rest/api/CertificatesApiAction.java +++ b/src/main/java/org/opensearch/security/dlic/rest/api/CertificatesApiAction.java @@ -71,6 +71,7 @@ protected CType getConfigType() { protected void consumeParameters(RestRequest request) { request.param("nodeId"); request.param("cert_type"); + request.param("timeout"); } private void securitySSLCertsRequestHandlers(RequestHandler.RequestHandlersBuilder requestHandlersBuilder) { diff --git a/src/main/java/org/opensearch/security/dlic/rest/api/InternalUsersApiAction.java b/src/main/java/org/opensearch/security/dlic/rest/api/InternalUsersApiAction.java index 0f4330fb79..3a16028b54 100644 --- a/src/main/java/org/opensearch/security/dlic/rest/api/InternalUsersApiAction.java +++ b/src/main/java/org/opensearch/security/dlic/rest/api/InternalUsersApiAction.java @@ -160,10 +160,10 @@ protected final UserFilterType filterParam(final RestRequest request) { ValidationResult withAuthTokenPath(final RestRequest request) throws IOException { return endpointValidator.withRequiredEntityName(nameParam(request)).map(username -> { // Handle auth token fetching - if (!(request.uri().contains("/internalusers/" + username + "/authtoken") && request.uri().endsWith("/authtoken"))) { - return ValidationResult.error(RestStatus.NOT_IMPLEMENTED, methodNotImplementedMessage(request.method())); + if (request.uri().contains("/internalusers/" + username + "/authtoken") && request.uri().endsWith("/authtoken")) { + return ValidationResult.success(username); } - return ValidationResult.success(username); + return ValidationResult.error(RestStatus.NOT_IMPLEMENTED, methodNotImplementedMessage(request.method())); }); } diff --git a/src/main/java/org/opensearch/security/user/UserService.java b/src/main/java/org/opensearch/security/user/UserService.java index 449c496c37..f380fdb328 100644 --- a/src/main/java/org/opensearch/security/user/UserService.java +++ b/src/main/java/org/opensearch/security/user/UserService.java @@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableList; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -243,14 +242,8 @@ public static String generatePassword() { CharacterRule lowercaseCharacterRule = new CharacterRule(EnglishCharacterData.LowerCase, 1); CharacterRule uppercaseCharacterRule = new CharacterRule(EnglishCharacterData.UpperCase, 1); CharacterRule numericCharacterRule = new CharacterRule(EnglishCharacterData.Digit, 1); - CharacterRule specialCharacterRule = new CharacterRule(EnglishCharacterData.Special, 1); - List rules = Arrays.asList( - lowercaseCharacterRule, - uppercaseCharacterRule, - numericCharacterRule, - specialCharacterRule - ); + List rules = Arrays.asList(lowercaseCharacterRule, uppercaseCharacterRule, numericCharacterRule); PasswordGenerator passwordGenerator = new PasswordGenerator(); Random random = Randomness.get(); @@ -275,17 +268,17 @@ public AuthToken generateAuthToken(String accountName) throws IOException { String authToken = null; try { - final ObjectMapper mapper = DefaultObjectMapper.objectMapper; - JsonNode accountDetails = mapper.readTree(internalUsersConfiguration.getCEntry(accountName).toString()); + final var accountEntry = DefaultObjectMapper.writeValueAsString(internalUsersConfiguration.getCEntry(accountName), false); + JsonNode accountDetails = DefaultObjectMapper.readTree(accountEntry); final ObjectNode contentAsNode = (ObjectNode) accountDetails; SecurityJsonNode securityJsonNode = new SecurityJsonNode(contentAsNode); - Optional.ofNullable(securityJsonNode.get("service")) + Optional.ofNullable(securityJsonNode.get("attributes").get("service")) .map(SecurityJsonNode::asString) .filter("true"::equalsIgnoreCase) .orElseThrow(() -> new UserServiceException(AUTH_TOKEN_GENERATION_MESSAGE)); - Optional.ofNullable(securityJsonNode.get("enabled")) + Optional.ofNullable(securityJsonNode.get("attributes").get("enabled")) .map(SecurityJsonNode::asString) .filter("true"::equalsIgnoreCase) .orElseThrow(() -> new UserServiceException(AUTH_TOKEN_GENERATION_MESSAGE)); @@ -306,7 +299,7 @@ public AuthToken generateAuthToken(String accountName) throws IOException { saveAndUpdateConfigs(getUserConfigName().toString(), client, CType.INTERNALUSERS, internalUsersConfiguration); authToken = Base64.getUrlEncoder().encodeToString((accountName + ":" + plainTextPassword).getBytes(StandardCharsets.UTF_8)); - return new BasicAuthToken(authToken); + return new BasicAuthToken("Basic " + authToken); } catch (JsonProcessingException ex) { throw new UserServiceException(FAILED_ACCOUNT_RETRIEVAL_MESSAGE);