From bbda05122b0fe681885bbe0195776afc0c60e27e Mon Sep 17 00:00:00 2001 From: Doug Hoard Date: Sun, 20 Oct 2024 15:35:46 -0400 Subject: [PATCH] Fixed custom authenticator test for ibmjava:8 (#1012) Signed-off-by: dhoard --- .../AuthenticatorClassTest.java | 1 - .../prometheus/jmx/CustomAuthenticator.java | 88 +++++++++++++++---- 2 files changed, 72 insertions(+), 17 deletions(-) diff --git a/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/http/authentication/AuthenticatorClassTest.java b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/http/authentication/AuthenticatorClassTest.java index bf0dac1e..87c1b47f 100644 --- a/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/http/authentication/AuthenticatorClassTest.java +++ b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/http/authentication/AuthenticatorClassTest.java @@ -20,7 +20,6 @@ import io.prometheus.jmx.test.common.ExporterTestEnvironment; import io.prometheus.jmx.test.support.JmxExporterMode; import java.util.stream.Stream; - import org.verifyica.api.ArgumentContext; import org.verifyica.api.Verifyica; diff --git a/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/CustomAuthenticator.java b/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/CustomAuthenticator.java index 22a5d5f8..37d1b7c3 100644 --- a/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/CustomAuthenticator.java +++ b/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/CustomAuthenticator.java @@ -18,39 +18,95 @@ import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpPrincipal; -import com.sun.security.auth.UserPrincipal; +import java.io.Serializable; import java.nio.charset.StandardCharsets; +import java.security.Principal; import java.util.Base64; +import java.util.Objects; import javax.security.auth.Subject; +/** Example custom authenticator */ public class CustomAuthenticator extends Authenticator { + private static final String AUTHORIZATION = "Authorization"; + private static final String BASIC = "Basic"; + + private static final String USERNAME = "Prometheus"; + private static final String PASSWORD = "secret"; + @Override - public Result authenticate(HttpExchange exch) { + public Result authenticate(HttpExchange httpExchange) { // nothing too custom, so the test works, just to demonstrate that it is plug-able - Headers rmap = exch.getRequestHeaders(); - String auth = rmap.getFirst("Authorization"); - if (auth == null) { + Headers headers = httpExchange.getRequestHeaders(); + + String authorization = headers.getFirst(AUTHORIZATION); + if (authorization == null) { return new Authenticator.Retry(401); } - int sp = auth.indexOf(' '); - if (sp == -1 || !auth.substring(0, sp).equals("Basic")) { + + int space = authorization.indexOf(' '); + if (space == -1 || !authorization.substring(0, space).equals(BASIC)) { return new Authenticator.Failure(401); } - byte[] b = Base64.getDecoder().decode(auth.substring(sp + 1)); - String userpass = new String(b, StandardCharsets.UTF_8); - int colon = userpass.indexOf(':'); - String uname = userpass.substring(0, colon); - String pass = userpass.substring(colon + 1); - if ("Prometheus".equals(uname) && "secret".equals(pass)) { + byte[] usernamePasswordBytes = + Base64.getDecoder().decode(authorization.substring(space + 1)); + String usernamePassword = new String(usernamePasswordBytes, StandardCharsets.UTF_8); + int colon = usernamePassword.indexOf(':'); + String username = usernamePassword.substring(0, colon); + String password = usernamePassword.substring(colon + 1); + + if (USERNAME.equals(username) && PASSWORD.equals(password)) { Subject subject = new Subject(); - subject.getPrincipals().add(new UserPrincipal(uname)); + subject.getPrincipals().add(new UserPrincipal(username)); // to communicate an authenticated subject for subsequent handler calls via Subject.doAs - exch.setAttribute("io.prometheus.jmx.CustomAuthenticatorSubjectAttribute", subject); - return new Authenticator.Success(new HttpPrincipal(uname, "/")); + httpExchange.setAttribute( + "io.prometheus.jmx.CustomAuthenticatorSubjectAttribute", subject); + return new Authenticator.Success(new HttpPrincipal(username, "/")); } else { return new Authenticator.Failure(401); } } + + /** + * Class to implement Principal + * + *

Required for ibmjava:8 since it doesn't provide com.sun.security.auth.UserPrincipal + */ + public static class UserPrincipal implements Principal, Serializable { + + private final String name; + + /** + * Constructor + * + * @param name name + */ + public UserPrincipal(String name) { + this.name = Objects.requireNonNull(name, "Name cannot be null"); + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return "UserPrincipal{" + "name='" + name + '\'' + '}'; + } + + @Override + public boolean equals(Object object) { + if (this == object) return true; + if (object == null || getClass() != object.getClass()) return false; + UserPrincipal that = (UserPrincipal) object; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } + } }