From f86be817cffd071dcee83277b518213fc4e5be32 Mon Sep 17 00:00:00 2001 From: Marc Becker Date: Fri, 5 Jan 2024 08:30:35 +0000 Subject: [PATCH 1/2] Use jetty-ee10 instead of jetty-ee9 --- java-security-test/pom.xml | 12 +-- .../sap/cloud/security/test/SecurityTest.java | 60 ++++++++------ .../cloud/security/test/SecurityTestRule.java | 10 ++- .../api/ApplicationServerConfiguration.java | 4 +- .../test/extension/SecurityTestExtension.java | 2 +- .../test/jetty/JettyTokenAuthenticator.java | 83 +++++++++---------- .../security/test/SecurityTestRuleTest.java | 2 +- pom.xml | 4 +- 8 files changed, 93 insertions(+), 84 deletions(-) diff --git a/java-security-test/pom.xml b/java-security-test/pom.xml index b76143c91e..c3f1b588a1 100644 --- a/java-security-test/pom.xml +++ b/java-security-test/pom.xml @@ -40,16 +40,16 @@ jetty-server - org.eclipse.jetty.ee9 - jetty-ee9-servlet + org.eclipse.jetty.ee10 + jetty-ee10-servlet - org.eclipse.jetty.ee9 - jetty-ee9-webapp + org.eclipse.jetty.ee10 + jetty-ee10-webapp - org.eclipse.jetty.ee9 - jetty-ee9-annotations + org.eclipse.jetty.ee10 + jetty-ee10-annotations org.eclipse.jetty diff --git a/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTest.java b/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTest.java index 7a9c99c5a8..930a220afd 100644 --- a/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTest.java +++ b/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTest.java @@ -5,6 +5,40 @@ */ package com.sap.cloud.security.test; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static com.sap.cloud.security.config.Service.IAS; +import static com.sap.cloud.security.config.Service.XSUAA; +import static com.sap.cloud.security.xsuaa.client.OidcConfigurationService.DISCOVERY_ENDPOINT_DEFAULT; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; +import java.util.Base64; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.annotation.Nullable; + +import org.apache.commons.io.IOUtils; +import org.eclipse.jetty.ee10.servlet.FilterHolder; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler; +import org.eclipse.jetty.ee10.webapp.WebAppContext; +import org.eclipse.jetty.server.Server; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.github.tomakehurst.wiremock.WireMockServer; import com.sap.cloud.environment.servicebinding.SapVcapServicesServiceBindingAccessor; import com.sap.cloud.environment.servicebinding.api.ServiceBinding; @@ -25,32 +59,10 @@ import com.sap.cloud.security.xsuaa.client.XsuaaDefaultEndpoints; import com.sap.cloud.security.xsuaa.http.HttpHeaders; import com.sap.cloud.security.xsuaa.http.MediaType; + import jakarta.servlet.DispatcherType; import jakarta.servlet.Filter; import jakarta.servlet.Servlet; -import org.apache.commons.io.IOUtils; -import org.eclipse.jetty.ee9.security.ConstraintSecurityHandler; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.ee9.servlet.FilterHolder; -import org.eclipse.jetty.ee9.servlet.ServletHolder; -import org.eclipse.jetty.ee9.webapp.WebAppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.util.*; - -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static com.sap.cloud.security.config.Service.IAS; -import static com.sap.cloud.security.config.Service.XSUAA; -import static com.sap.cloud.security.xsuaa.client.OidcConfigurationService.DISCOVERY_ENDPOINT_DEFAULT; public class SecurityTest implements SecurityTestContext, ServiceMockConfiguration, ApplicationServerConfiguration { @@ -228,7 +240,7 @@ void startApplicationServer() throws Exception { WebAppContext context = new WebAppContext(); context.setContextPath("/"); - context.setResourceBase("src/main/webapp"); + context.setBaseResourceAsString("src/main/webapp"); context.setSecurityHandler(security); applicationServletsByPath diff --git a/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTestRule.java b/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTestRule.java index a63b93bbc1..70ffb2827e 100644 --- a/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTestRule.java +++ b/java-security-test/src/main/java/com/sap/cloud/security/test/SecurityTestRule.java @@ -5,6 +5,11 @@ */ package com.sap.cloud.security.test; +import javax.annotation.Nullable; + +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.junit.rules.ExternalResource; + import com.github.tomakehurst.wiremock.WireMockServer; import com.sap.cloud.security.config.OAuth2ServiceConfigurationBuilder; import com.sap.cloud.security.config.Service; @@ -12,12 +17,9 @@ import com.sap.cloud.security.test.api.SecurityTestContext; import com.sap.cloud.security.test.api.ServiceMockConfiguration; import com.sap.cloud.security.token.Token; + import jakarta.servlet.Filter; import jakarta.servlet.Servlet; -import org.eclipse.jetty.ee9.servlet.ServletHolder; -import org.junit.rules.ExternalResource; - -import javax.annotation.Nullable; public class SecurityTestRule extends ExternalResource implements SecurityTestContext, ServiceMockConfiguration, ApplicationServerConfiguration { diff --git a/java-security-test/src/main/java/com/sap/cloud/security/test/api/ApplicationServerConfiguration.java b/java-security-test/src/main/java/com/sap/cloud/security/test/api/ApplicationServerConfiguration.java index 962a66f453..eb39604f64 100644 --- a/java-security-test/src/main/java/com/sap/cloud/security/test/api/ApplicationServerConfiguration.java +++ b/java-security-test/src/main/java/com/sap/cloud/security/test/api/ApplicationServerConfiguration.java @@ -5,12 +5,14 @@ */ package com.sap.cloud.security.test.api; +import org.eclipse.jetty.ee10.servlet.ServletHolder; + import com.sap.cloud.security.config.Service; import com.sap.cloud.security.test.ApplicationServerOptions; import com.sap.cloud.security.test.SecurityTestRule; + import jakarta.servlet.Filter; import jakarta.servlet.Servlet; -import org.eclipse.jetty.ee9.servlet.ServletHolder; public interface ApplicationServerConfiguration { diff --git a/java-security-test/src/main/java/com/sap/cloud/security/test/extension/SecurityTestExtension.java b/java-security-test/src/main/java/com/sap/cloud/security/test/extension/SecurityTestExtension.java index 693be82f40..639f041728 100644 --- a/java-security-test/src/main/java/com/sap/cloud/security/test/extension/SecurityTestExtension.java +++ b/java-security-test/src/main/java/com/sap/cloud/security/test/extension/SecurityTestExtension.java @@ -13,7 +13,7 @@ import com.sap.cloud.security.test.api.ServiceMockConfiguration; import jakarta.servlet.Filter; import jakarta.servlet.Servlet; -import org.eclipse.jetty.ee9.servlet.ServletHolder; +import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.junit.jupiter.api.extension.*; /** diff --git a/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java b/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java index dd1897ec75..74171dbd8a 100644 --- a/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java +++ b/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java @@ -5,31 +5,37 @@ */ package com.sap.cloud.security.test.jetty; +import java.security.Principal; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; + +import javax.security.auth.Subject; + +import org.eclipse.jetty.ee10.servlet.ServletContextRequest; +import org.eclipse.jetty.ee10.servlet.ServletContextResponse; +import org.eclipse.jetty.security.AuthenticationState; +import org.eclipse.jetty.security.Authenticator; +import org.eclipse.jetty.security.Constraint.Authorization; +import org.eclipse.jetty.security.ServerAuthException; +import org.eclipse.jetty.security.authentication.LoginAuthenticator; +import org.eclipse.jetty.security.internal.DefaultUserIdentity; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.server.Session; +import org.eclipse.jetty.util.Callback; + import com.sap.cloud.security.servlet.TokenAuthenticationResult; import com.sap.cloud.security.servlet.TokenAuthenticator; + import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletResponse; -import org.eclipse.jetty.ee9.security.Authenticator; -import org.eclipse.jetty.ee9.security.UserAuthentication; -import org.eclipse.jetty.ee9.nested.Authentication; -import org.eclipse.jetty.security.internal.DefaultUserIdentity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.security.auth.Subject; -import java.io.IOException; -import java.security.Principal; -import java.util.HashSet; -import java.util.Set; - /** * Decorates the TokenAuthenticator and adapts it to Jetty. */ public class JettyTokenAuthenticator implements Authenticator { - private static final Logger LOGGER = LoggerFactory.getLogger(JettyTokenAuthenticator.class); - private final TokenAuthenticator tokenAuthenticator; public JettyTokenAuthenticator(TokenAuthenticator tokenAuthenticator) { @@ -37,52 +43,39 @@ public JettyTokenAuthenticator(TokenAuthenticator tokenAuthenticator) { } @Override - public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) { - TokenAuthenticationResult tokenAuthenticationResult = tokenAuthenticator.validateRequest(request, response); - if (tokenAuthenticationResult.isAuthenticated()) { - return createAuthentication(tokenAuthenticationResult); - } else { - sendUnauthenticatedResponse(response, tokenAuthenticationResult.getUnauthenticatedReason()); - return Authentication.UNAUTHENTICATED; - } - } - - private void sendUnauthenticatedResponse(ServletResponse response, String unauthenticatedReason) { - if (response instanceof HttpServletResponse) { - try { - HttpServletResponse httpServletResponse = (HttpServletResponse) response; - httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, unauthenticatedReason); // 401 - } catch (IOException e) { - LOGGER.error("Failed to send error response", e); - } - } + public void setConfiguration(Configuration configuration) { } @Override - public void setConfiguration(AuthConfiguration configuration) { - } - - @Override - public String getAuthMethod() { + public String getAuthenticationType() { return "Token"; } @Override - public void prepareRequest(ServletRequest request) { + public Authorization getConstraintAuthentication(String pathInContext, Authorization existing, Function getSession) { + return Authorization.ANY_USER; } @Override - public boolean secureResponse(ServletRequest request, ServletResponse response, boolean mandatory, - Authentication.User validatedUser) { - return true; + public AuthenticationState validateRequest(Request request, Response response, Callback callback) throws ServerAuthException { + ServletRequest servletRequest = request instanceof ServletContextRequest scr ? scr.getServletApiRequest() : null; + ServletResponse servletResponse = response instanceof ServletContextResponse scr ? scr.getServletApiResponse() : null; + + TokenAuthenticationResult tokenAuthenticationResult = tokenAuthenticator.validateRequest(servletRequest, servletResponse); + if (tokenAuthenticationResult != null && tokenAuthenticationResult.isAuthenticated()) { + return createAuthentication(tokenAuthenticationResult); + } else { + Response.writeError(request, response, callback, HttpServletResponse.SC_UNAUTHORIZED, tokenAuthenticationResult.getUnauthenticatedReason()); + return AuthenticationState.SEND_FAILURE; + } } - private Authentication createAuthentication(TokenAuthenticationResult tokenAuthentication) { + private AuthenticationState createAuthentication(TokenAuthenticationResult tokenAuthentication) { Principal principal = tokenAuthentication.getPrincipal(); Set principals = new HashSet<>(); principals.add(principal); Subject subject = new Subject(true, principals, new HashSet<>(), new HashSet<>()); String[] scopes = tokenAuthentication.getScopes().toArray(new String[0]); - return new UserAuthentication(getAuthMethod(), new DefaultUserIdentity(subject, principal, scopes)); + return new LoginAuthenticator.UserAuthenticationSucceeded(getAuthenticationType(), new DefaultUserIdentity(subject, principal, scopes)); } } diff --git a/java-security-test/src/test/java/com/sap/cloud/security/test/SecurityTestRuleTest.java b/java-security-test/src/test/java/com/sap/cloud/security/test/SecurityTestRuleTest.java index bf2a3bcfc7..9ef9776af7 100644 --- a/java-security-test/src/test/java/com/sap/cloud/security/test/SecurityTestRuleTest.java +++ b/java-security-test/src/test/java/com/sap/cloud/security/test/SecurityTestRuleTest.java @@ -21,7 +21,7 @@ import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClients; -import org.eclipse.jetty.ee9.servlet.ServletHolder; +import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; diff --git a/pom.xml b/pom.xml index d5a1215a9c..63e75e576f 100644 --- a/pom.xml +++ b/pom.xml @@ -127,8 +127,8 @@ import - org.eclipse.jetty.ee9 - jetty-ee9-bom + org.eclipse.jetty.ee10 + jetty-ee10-bom ${org.eclipse.jetty.bom.version} pom import From 9a645a2d0d088b1810517a1bca2fcaf00c94e1e3 Mon Sep 17 00:00:00 2001 From: Marc Becker Date: Fri, 5 Jan 2024 08:44:28 +0000 Subject: [PATCH 2/2] Remove unnecessary null check --- .../sap/cloud/security/test/jetty/JettyTokenAuthenticator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java b/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java index 74171dbd8a..cf53cd76ff 100644 --- a/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java +++ b/java-security-test/src/main/java/com/sap/cloud/security/test/jetty/JettyTokenAuthenticator.java @@ -62,7 +62,7 @@ public AuthenticationState validateRequest(Request request, Response response, C ServletResponse servletResponse = response instanceof ServletContextResponse scr ? scr.getServletApiResponse() : null; TokenAuthenticationResult tokenAuthenticationResult = tokenAuthenticator.validateRequest(servletRequest, servletResponse); - if (tokenAuthenticationResult != null && tokenAuthenticationResult.isAuthenticated()) { + if (tokenAuthenticationResult.isAuthenticated()) { return createAuthentication(tokenAuthenticationResult); } else { Response.writeError(request, response, callback, HttpServletResponse.SC_UNAUTHORIZED, tokenAuthenticationResult.getUnauthenticatedReason());