diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSaf.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSaf.java index 1f9116019f..6d1429f0b5 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSaf.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSaf.java @@ -97,7 +97,8 @@ private boolean checkPermission(String userId, String resourceType, String resou @Override public boolean hasSafResourceAccess(Authentication authentication, String resourceClass, String resourceName, String accessLevel) { String userid = authentication.getName(); - if (StringUtils.isEmpty(userid)) { + if (StringUtils.isEmpty(userid) || userid.length() > 8) { + log.debug("UserId {} is not valid for SAF permissions check", userid); return false; } AccessLevel level = AccessLevel.valueOf(accessLevel); diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilter.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilter.java index da94e26914..50ab77085b 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilter.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilter.java @@ -67,9 +67,9 @@ public class CategorizeCertsFilter extends OncePerRequestFilter { */ private void categorizeCerts(ServletRequest request) { X509Certificate[] certs = (X509Certificate[]) request.getAttribute(ATTRNAME_JAKARTA_SERVLET_REQUEST_X509_CERTIFICATE); - if (certs != null) { + if (certs != null && certs.length > 0 && certs[0] != null) { Optional clientCert = getClientCertFromHeader((HttpServletRequest) request); - if (certificateValidator.isForwardingEnabled() && certificateValidator.isTrusted(certs) && clientCert.isPresent()) { + if (certificateValidator.isForwardingEnabled() && certificateValidator.hasGatewayChain(certs) && clientCert.isPresent()) { certificateValidator.updateAPIMLPublicKeyCertificates(certs); // add the client certificate to the certs array String subjectDN = ((X509Certificate) clientCert.get()).getSubjectX500Principal().getName(); diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/NonCompulsoryAuthenticationProcessingFilter.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/NonCompulsoryAuthenticationProcessingFilter.java index 466e682987..1442edc142 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/NonCompulsoryAuthenticationProcessingFilter.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/NonCompulsoryAuthenticationProcessingFilter.java @@ -10,13 +10,16 @@ package org.zowe.apiml.security.common.login; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; -import jakarta.servlet.*; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; /** @@ -41,9 +44,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) try { authResult = attemptAuthentication(request, response); - } - - catch (AuthenticationException failed) { + } catch (AuthenticationException failed) { // Authentication failed unsuccessfulAuthentication(request, response, failed); return; diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthAwareFilter.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthAwareFilter.java index 31e384ccbf..015937b9d1 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthAwareFilter.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthAwareFilter.java @@ -10,22 +10,21 @@ package org.zowe.apiml.security.common.login; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AuthenticationFailureHandler; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import java.io.IOException; -public class X509AuthAwareFilter extends X509AuthenticationFilter { +public class X509AuthAwareFilter extends X509ForwardingAwareAuthenticationFilter { private final AuthenticationFailureHandler failureHandler; public X509AuthAwareFilter(String endpoint, AuthenticationFailureHandler failureHandler, AuthenticationProvider authenticationProvider) { diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthenticationFilter.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509ForwardingAwareAuthenticationFilter.java similarity index 85% rename from apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthenticationFilter.java rename to apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509ForwardingAwareAuthenticationFilter.java index b38c41f656..002a99c183 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509AuthenticationFilter.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/login/X509ForwardingAwareAuthenticationFilter.java @@ -10,28 +10,28 @@ package org.zowe.apiml.security.common.login; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.zowe.apiml.security.common.token.X509AuthenticationToken; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.cert.X509Certificate; @Slf4j -public class X509AuthenticationFilter extends NonCompulsoryAuthenticationProcessingFilter { +public class X509ForwardingAwareAuthenticationFilter extends NonCompulsoryAuthenticationProcessingFilter { private final AuthenticationProvider authenticationProvider; private final AuthenticationSuccessHandler successHandler; - public X509AuthenticationFilter(String endpoint, - AuthenticationSuccessHandler successHandler, - AuthenticationProvider authenticationProvider) { + public X509ForwardingAwareAuthenticationFilter(String endpoint, + AuthenticationSuccessHandler successHandler, + AuthenticationProvider authenticationProvider) { super(endpoint); this.authenticationProvider = authenticationProvider; this.successHandler = successHandler; diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/verify/CertificateValidator.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/verify/CertificateValidator.java index ca2aafa8f6..db2131035c 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/verify/CertificateValidator.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/verify/CertificateValidator.java @@ -56,7 +56,7 @@ public CertificateValidator(TrustedCertificatesProvider trustedCertificatesProvi * @param certs Certificates to compare with known trusted ones * @return true if all given certificates are known false otherwise */ - public boolean isTrusted(X509Certificate[] certs) { + public boolean hasGatewayChain(X509Certificate[] certs) { if ((proxyCertificatesEndpoints == null) || (proxyCertificatesEndpoints.length == 0)) { log.debug("No endpoint configured to retrieve trusted certificates. Provide URL via apiml.security.x509.certificatesUrls"); return false; diff --git a/apiml-security-common/src/test/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSafTest.java b/apiml-security-common/src/test/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSafTest.java index 88fdc8f2c4..c87c87b465 100644 --- a/apiml-security-common/src/test/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSafTest.java +++ b/apiml-security-common/src/test/java/org/zowe/apiml/security/common/auth/saf/SafResourceAccessSafTest.java @@ -16,14 +16,15 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class SafResourceAccessSafTest { @@ -92,6 +93,15 @@ void testHasSafResourceAccess_whenNoResponse_thenTrue() { void testHasSafResourceAccess_whenUseridEmpty_thenFalse() { assertFalse(safResourceAccessVerifying.hasSafResourceAccess(new UsernamePasswordAuthenticationToken("", "token"), CLASS, RESOURCE, LEVEL.name())); } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", "tooLongUserId"}) + void testInvalidUserIds_thenSkipped(String userId) { + var auth = new UsernamePasswordAuthenticationToken(userId, ""); + assertFalse(assertDoesNotThrow(() -> safResourceAccessVerifying.hasSafResourceAccess(auth, CLASS, RESOURCE, LEVEL.name()))); + verify(checkPermissionMock, never()).checkPermission(any(), any(), any(), anyInt()); + } @Builder public static class TestPlatformReturned { diff --git a/apiml-security-common/src/test/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilterTest.java b/apiml-security-common/src/test/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilterTest.java index c71467b3c4..dff641bfbc 100644 --- a/apiml-security-common/src/test/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilterTest.java +++ b/apiml-security-common/src/test/java/org/zowe/apiml/security/common/filter/CategorizeCertsFilterTest.java @@ -10,6 +10,8 @@ package org.zowe.apiml.security.common.filter; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -20,8 +22,6 @@ import org.zowe.apiml.security.common.utils.X509Utils; import org.zowe.apiml.security.common.verify.CertificateValidator; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -86,7 +86,7 @@ public void setUp() { chain = new MockFilterChain(); certificateValidator = mock(CertificateValidator.class); when(certificateValidator.isForwardingEnabled()).thenReturn(false); - when(certificateValidator.isTrusted(any())).thenReturn(false); + when(certificateValidator.hasGatewayChain(any())).thenReturn(false); } @Nested @@ -118,7 +118,7 @@ class WhenForwardingEnabled { @BeforeEach void setUp() { when(certificateValidator.isForwardingEnabled()).thenReturn(true); - when(certificateValidator.isTrusted(any())).thenReturn(true); + when(certificateValidator.hasGatewayChain(any())).thenReturn(true); } @Test @@ -200,7 +200,7 @@ public void setUp() { @Test void givenTrustedCerts_thenClientCertHeaderAccepted() throws ServletException, IOException { - when(certificateValidator.isTrusted(certificates)).thenReturn(true); + when(certificateValidator.hasGatewayChain(certificates)).thenReturn(true); // when incoming certs are all trusted means that all their public keys are added to the filter filter.getPublicKeyCertificatesBase64().add(X509Utils.correctBase64("apimlCert1")); filter.getPublicKeyCertificatesBase64().add(X509Utils.correctBase64("apimlCertCA")); @@ -225,7 +225,7 @@ void givenTrustedCerts_thenClientCertHeaderAccepted() throws ServletException, I @Test void givenNotTrustedCerts_thenClientCertHeaderIgnored() throws ServletException, IOException { - when(certificateValidator.isTrusted(certificates)).thenReturn(false); + when(certificateValidator.hasGatewayChain(certificates)).thenReturn(false); filter.doFilter(request, response, chain); HttpServletRequest nextRequest = (HttpServletRequest) chain.getRequest(); assertNotNull(nextRequest); @@ -280,7 +280,7 @@ class WhenInvalidCertificateInHeaderAndForwardingEnabled { public void setUp() { request.addHeader(CLIENT_CERT_HEADER, "invalid_cert"); when(certificateValidator.isForwardingEnabled()).thenReturn(true); - when(certificateValidator.isTrusted(certificates)).thenReturn(true); + when(certificateValidator.hasGatewayChain(certificates)).thenReturn(true); } @Test @@ -410,7 +410,7 @@ public void setUp() { @Test void givenTrustedCerts_thenClientCertHeaderAccepted() throws ServletException, IOException { - when(certificateValidator.isTrusted(certificates)).thenReturn(true); + when(certificateValidator.hasGatewayChain(certificates)).thenReturn(true); // when incoming certs are all trusted means that all their public keys are added to the filter filter.getPublicKeyCertificatesBase64().add(X509Utils.correctBase64("apimlCert1")); filter.getPublicKeyCertificatesBase64().add(X509Utils.correctBase64("apimlCertCA")); @@ -435,7 +435,7 @@ void givenTrustedCerts_thenClientCertHeaderAccepted() throws ServletException, I @Test void givenNotTrustedCerts_thenClientCertHeaderIgnored() throws ServletException, IOException { - when(certificateValidator.isTrusted(certificates)).thenReturn(false); + when(certificateValidator.hasGatewayChain(certificates)).thenReturn(false); filter.doFilter(request, response, chain); HttpServletRequest nextRequest = (HttpServletRequest) chain.getRequest(); assertNotNull(nextRequest); diff --git a/apiml-security-common/src/test/java/org/zowe/apiml/security/common/verify/CertificateValidatorTest.java b/apiml-security-common/src/test/java/org/zowe/apiml/security/common/verify/CertificateValidatorTest.java index fde6fa6ecd..cface17c63 100644 --- a/apiml-security-common/src/test/java/org/zowe/apiml/security/common/verify/CertificateValidatorTest.java +++ b/apiml-security-common/src/test/java/org/zowe/apiml/security/common/verify/CertificateValidatorTest.java @@ -56,20 +56,20 @@ class WhenTrustedCertsProvided { @BeforeEach void setUp() { - ReflectionTestUtils.setField(certificateValidator, "proxyCertificatesEndpoints", new String[] {URL_PROVIDE_TWO_TRUSTED_CERTS}); + ReflectionTestUtils.setField(certificateValidator, "proxyCertificatesEndpoints", new String[]{URL_PROVIDE_TWO_TRUSTED_CERTS}); } @Test void whenAllCertificatesFoundThenTheyAreTrusted() { - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert1})); - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert2})); - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert1, cert2})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert1})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert2})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert1, cert2})); } @Test void whenSomeCertificateNotFoundThenAllUntrusted() { - assertFalse(certificateValidator.isTrusted(new X509Certificate[]{cert3})); - assertFalse(certificateValidator.isTrusted(new X509Certificate[]{cert1, cert3})); - assertFalse(certificateValidator.isTrusted(new X509Certificate[]{cert2, cert3})); + assertFalse(certificateValidator.hasGatewayChain(new X509Certificate[]{cert3})); + assertFalse(certificateValidator.hasGatewayChain(new X509Certificate[]{cert1, cert3})); + assertFalse(certificateValidator.hasGatewayChain(new X509Certificate[]{cert2, cert3})); } } @@ -78,13 +78,13 @@ class WhenNoTrustedCertsProvided { @BeforeEach void setUp() { - ReflectionTestUtils.setField(certificateValidator, "proxyCertificatesEndpoints", new String[] {URL_WITH_NO_TRUSTED_CERTS}); + ReflectionTestUtils.setField(certificateValidator, "proxyCertificatesEndpoints", new String[]{URL_WITH_NO_TRUSTED_CERTS}); } @Test void thenAnyCertificateIsNotTrusted() { - assertFalse(certificateValidator.isTrusted(new X509Certificate[]{cert1})); - assertFalse(certificateValidator.isTrusted(new X509Certificate[]{cert2})); - assertFalse(certificateValidator.isTrusted(new X509Certificate[]{cert3})); + assertFalse(certificateValidator.hasGatewayChain(new X509Certificate[]{cert1})); + assertFalse(certificateValidator.hasGatewayChain(new X509Certificate[]{cert2})); + assertFalse(certificateValidator.hasGatewayChain(new X509Certificate[]{cert3})); } } @@ -114,15 +114,15 @@ class WhenMultipleSources { @BeforeEach void setUp() { - ReflectionTestUtils.setField(certificateValidator, "proxyCertificatesEndpoints", new String[] {URL_PROVIDE_TWO_TRUSTED_CERTS, URL_PROVIDE_THIRD_TRUSTED_CERT}); + ReflectionTestUtils.setField(certificateValidator, "proxyCertificatesEndpoints", new String[]{URL_PROVIDE_TWO_TRUSTED_CERTS, URL_PROVIDE_THIRD_TRUSTED_CERT}); } @Test void whenAllCertificatesFoundThenTheyAreTrusted() { - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert1})); - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert2})); - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert3})); - assertTrue(certificateValidator.isTrusted(new X509Certificate[]{cert1, cert3})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert1})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert2})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert3})); + assertTrue(certificateValidator.hasGatewayChain(new X509Certificate[]{cert1, cert3})); } } @@ -146,7 +146,7 @@ class OldPropertyValue { @Test void thenUrlIsSetAsListCorrectly() { - assertArrayEquals(new String[] {"url1"}, (String[]) ReflectionTestUtils.getField(certificateValidator, "proxyCertificatesEndpoints")); + assertArrayEquals(new String[]{"url1"}, (String[]) ReflectionTestUtils.getField(certificateValidator, "proxyCertificatesEndpoints")); } } @@ -163,7 +163,7 @@ class NewPropertyValue { @Test void thenUrlsAreSetCorrectly() { - assertArrayEquals(new String[] {"url1", "url2"}, (String[]) ReflectionTestUtils.getField(certificateValidator, "proxyCertificatesEndpoints")); + assertArrayEquals(new String[]{"url1", "url2"}, (String[]) ReflectionTestUtils.getField(certificateValidator, "proxyCertificatesEndpoints")); } } diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactory.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactory.java index 7bf1fb8e13..54826b3651 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactory.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactory.java @@ -60,7 +60,7 @@ public GatewayFilter apply(AcceptForwardedClientCertFilterFactory.Config config) return (exchange, chain) -> { SslInfo sslInfo = exchange.getRequest().getSslInfo(); X509Certificate[] x509Certificates = sslInfo == null ? null : sslInfo.getPeerCertificates(); - if ((x509Certificates != null) && (x509Certificates.length > 0) && certificateValidator.isTrusted(x509Certificates)) { + if ((x509Certificates != null) && (x509Certificates.length > 0) && certificateValidator.hasGatewayChain(x509Certificates)) { X509Certificate[] forwardedClientCertificate = getClientCertificateFromHeader(exchange.getRequest()); if (forwardedClientCertificate.length > 0) { log.debug("Accepting forwarded client certificate {}", forwardedClientCertificate[0].getSubjectX500Principal().getName()); diff --git a/gateway-service/src/test/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactoryTest.java b/gateway-service/src/test/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactoryTest.java index e542a7c638..6f9b3d28b8 100644 --- a/gateway-service/src/test/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactoryTest.java +++ b/gateway-service/src/test/java/org/zowe/apiml/gateway/x509/AcceptForwardedClientCertFilterFactoryTest.java @@ -64,7 +64,7 @@ class AcceptForwardedClientCertFilterFactoryTest { @Test void givenClientCertificateInHeader_andTrustedClientCertificateInHandshake_thenUpdateWebExchange() { var validator = mock(CertificateValidator.class); - when(validator.isTrusted(any())).thenReturn(true); + when(validator.hasGatewayChain(any())).thenReturn(true); var factory = new AcceptForwardedClientCertFilterFactory(validator); var exchange = mock(ServerWebExchange.class); var req = mock(ServerHttpRequest.class); @@ -89,7 +89,7 @@ void givenClientCertificateInHeader_andTrustedClientCertificateInHandshake_thenU @Test void givenClientCertificateInHeader_andInvalidClientCertificateInHandshake_thenDoNothing() { var validator = mock(CertificateValidator.class); - when(validator.isTrusted(any())).thenReturn(false); + when(validator.hasGatewayChain(any())).thenReturn(false); var factory = new AcceptForwardedClientCertFilterFactory(validator); var exchange = mock(ServerWebExchange.class); var req = mock(ServerHttpRequest.class); diff --git a/integration-tests/src/test/java/org/zowe/apiml/integration/authentication/pat/AccessTokenServiceTest.java b/integration-tests/src/test/java/org/zowe/apiml/integration/authentication/pat/AccessTokenServiceTest.java index 725868aabb..7610d336c6 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/integration/authentication/pat/AccessTokenServiceTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/integration/authentication/pat/AccessTokenServiceTest.java @@ -14,7 +14,6 @@ import io.restassured.http.ContentType; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.zowe.apiml.util.SecurityUtils; @@ -288,7 +287,6 @@ void givenAuthorizedRequest_thenEvictRules() { } @Test - @Disabled("Disable for now; fix is in progress") void givenNotAuthorizedCall_thenDontAllowToRevokeTokensForUser() { String pat = SecurityUtils.personalAccessTokenWithClientCert(SslContext.clientCertValid); bodyContent = new ValidateRequestModel(); @@ -315,12 +313,12 @@ void givenNotAuthorizedCall_thenDontAllowToRevokeTokensForUser() { requestBody.put("userId", SecurityUtils.USERNAME); given() .contentType(ContentType.JSON) - .config(SslContext.clientCertApiml) + .config(SslContext.clientCertUnknownUser) .body(requestBody) .when() .delete(REVOKE_FOR_USER_ENDPOINT) .then() - .statusCode(403); + .statusCode(401); } } diff --git a/integration-tests/src/test/java/org/zowe/apiml/integration/zos/PassTicketTest.java b/integration-tests/src/test/java/org/zowe/apiml/integration/zos/PassTicketTest.java index a72e97914b..a023b53b25 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/integration/zos/PassTicketTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/integration/zos/PassTicketTest.java @@ -11,6 +11,8 @@ package org.zowe.apiml.integration.zos; import io.restassured.RestAssured; +import io.restassured.config.RestAssuredConfig; +import io.restassured.config.SSLConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -205,6 +207,11 @@ void givenInvalidApplicationName() { @Nested class ReturnForbidden { + @BeforeEach + void resetCertsToNone() { + RestAssured.config = RestAssuredConfig.newConfig().sslConfig(SSLConfig.sslConfig().relaxedHTTPSValidation()); + } + @Test void givenNoCertificate() { given() @@ -220,6 +227,11 @@ void givenNoCertificate() { @Nested class ReturnMethodNotAllowed { + @BeforeEach + void setUpCertificate() { + RestAssured.config = RestAssured.config().sslConfig(getConfiguredSslConfig()); + } + @Test void givenInvalidHttpMethod() { String expectedMessage = "Authentication method 'GET' is not supported for URL '" + ZAAS_PASSTICKET_PATH + "'"; diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java index 791be2595a..88da3baf33 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java @@ -33,7 +33,6 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutHandler; @@ -140,13 +139,12 @@ public SecurityFilterChain authenticationFunctionalityFilterChain(HttpSecurity h .authorizeHttpRequests(requests -> requests .anyRequest().permitAll()) - .x509(x509 -> x509.userDetailsService(x509UserDetailsService())) .logout(logout -> logout - .logoutRequestMatcher(new AntPathRequestMatcher( - authConfigurationProperties.getZaasLogoutEndpoint(), HttpMethod.POST.name() - )) - .addLogoutHandler(logoutHandler()) - .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.NO_CONTENT))) + .logoutRequestMatcher(new AntPathRequestMatcher( + authConfigurationProperties.getZaasLogoutEndpoint(), HttpMethod.POST.name() + )) + .addLogoutHandler(logoutHandler()) + .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.NO_CONTENT))) .authenticationProvider(compoundAuthProvider) // for authenticating credentials .authenticationProvider(new CertificateAuthenticationProvider()) // this is a dummy auth provider so the x509 prefiltering doesn't fail with nullpointer (no auth provider) or No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken @@ -162,8 +160,8 @@ public void configure(HttpSecurity http) throws Exception { //drive filter order this way http.addFilterBefore(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) .addFilterBefore(loginFilter("/**", authenticationManager), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) - .addFilterAfter(x509AuthenticationFilter("/**"), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) // this filter consumes certificates from custom attribute and maps them to credentials and authenticates them - .addFilterAfter(new ShouldBeAlreadyAuthenticatedFilter("/**", handlerInitializer.getAuthenticationFailureHandler()), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); // this filter stops processing of filter chaing because there is nothing on /auth/login endpoint + .addFilterAfter(x509ForwardingAwareAuthenticationFilter("/**"), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) // this filter consumes certificates from custom attribute and maps them to credentials and authenticates them + .addFilterAfter(new ShouldBeAlreadyAuthenticatedFilter("/**", handlerInitializer.getAuthenticationFailureHandler()), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); // this filter stops processing of filter chain because there is nothing on /auth/login endpoint } private LoginFilter loginFilter(String loginEndpoint, AuthenticationManager authenticationManager) { @@ -176,8 +174,8 @@ private LoginFilter loginFilter(String loginEndpoint, AuthenticationManager auth handlerInitializer.getResourceAccessExceptionHandler()); } - private X509AuthenticationFilter x509AuthenticationFilter(String loginEndpoint) { - return new X509AuthenticationFilter(loginEndpoint, + private X509ForwardingAwareAuthenticationFilter x509ForwardingAwareAuthenticationFilter(String loginEndpoint) { + return new X509ForwardingAwareAuthenticationFilter(loginEndpoint, handlerInitializer.getSuccessfulLoginHandler(), x509AuthenticationProvider); } @@ -190,7 +188,18 @@ private LogoutHandler logoutHandler() { } /** - * Access token endpoint share single filter that handles auth with and without certificate. + * Secures endpoints: + * - /auth/access-token/generate + * + * Requires authentication by a client certificate forwarded form Gateway or basic authentication, supports credentials in header and body. + * The request is fulfilled by the filter chain only, there is no controller to handle it. + * Order of custom filters: + * - CategorizeCertsFilter - checks for forwarded client certificate and put it into a custom request attribute + * - StoreAccessTokenInfoFilter - extracts access token filter from request to a custom attribute + * - LoginFilter - attempts to log in a user using basic authentication credentials, generates access token and stops the chain on success, reply with the token + * - X509ForwardingAwareAuthenticationFilter - attempts to log in a user using forwarded client certificate, generates access token and stops the chain on success, reply with the token + * - ShouldBeAlreadyAuthenticatedFilter - stops filter chain if none of the authentications was successful + * */ @Configuration @RequiredArgsConstructor @@ -204,13 +213,12 @@ public SecurityFilterChain accessTokenFilterChain(HttpSecurity http) throws Exce baseConfigure(http.securityMatchers(matchers -> matchers.requestMatchers( // no http method to catch all attempts to login and handle them here. Otherwise it falls to default filterchain and tries to route the calls, which doesnt make sense authConfigurationProperties.getZaasAccessTokenEndpoint() ))) - .authorizeHttpRequests(requests -> requests - .anyRequest().permitAll()) - .x509(x509 -> x509.userDetailsService(x509UserDetailsService())) - .authenticationProvider(compoundAuthProvider) // for authenticating credentials - .authenticationProvider(tokenAuthenticationProvider) - .authenticationProvider(new CertificateAuthenticationProvider()) // this is a dummy auth provider so the x509 prefiltering doesn't fail with nullpointer (no auth provider) or No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken - .with(new CustomSecurityFilters(), Customizer.withDefaults()); + .authorizeHttpRequests(requests -> requests + .anyRequest().permitAll()) + .authenticationProvider(compoundAuthProvider) // for authenticating credentials + .authenticationProvider(tokenAuthenticationProvider) + .authenticationProvider(new CertificateAuthenticationProvider()) // this is a dummy auth provider so the x509 prefiltering doesn't fail with nullpointer (no auth provider) or No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken + .with(new CustomSecurityFilters(), Customizer.withDefaults()); return http.build(); } @@ -223,8 +231,8 @@ public void configure(HttpSecurity http) throws Exception { http.addFilterBefore(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) .addFilterBefore(new StoreAccessTokenInfoFilter(handlerInitializer.getUnAuthorizedHandler().getHandler()), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) .addFilterBefore(accessTokenFilter("/**", authenticationManager), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) - .addFilterAfter(x509AuthenticationFilter("/**"), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) // this filter consumes certificates from custom attribute and maps them to credentials and authenticates them - .addFilterAfter(new ShouldBeAlreadyAuthenticatedFilter("/**", handlerInitializer.getAuthenticationFailureHandler()), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); // this filter stops processing of filter chaing because there is nothing on /auth/login endpoint + .addFilterAfter(x509ForwardingAwareAuthenticationFilter("/**"), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) // this filter consumes certificates from custom attribute and maps them to credentials and authenticates them + .addFilterAfter(new ShouldBeAlreadyAuthenticatedFilter("/**", handlerInitializer.getAuthenticationFailureHandler()), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); // this filter stops processing of filter chain because there is nothing on /auth/access-token/generate endpoint } private LoginFilter accessTokenFilter(String endpoint, AuthenticationManager authenticationManager) { @@ -237,13 +245,24 @@ private LoginFilter accessTokenFilter(String endpoint, AuthenticationManager aut handlerInitializer.getResourceAccessExceptionHandler()); } - private X509AuthenticationFilter x509AuthenticationFilter(String loginEndpoint) { - return new X509AuthenticationFilter(loginEndpoint, + private X509ForwardingAwareAuthenticationFilter x509ForwardingAwareAuthenticationFilter(String loginEndpoint) { + return new X509ForwardingAwareAuthenticationFilter(loginEndpoint, successfulAuthAccessTokenHandler, x509AuthenticationProvider); } } + /** + * Secures endpoints: + * - /auth/access-token/revoke/tokens/** + * - /auth/access-token/evict + * + * Requires authentication by a client certificate forwarded form Gateway or basic authentication, supports only credentials in header. + * Order of custom filters: + * - CategorizeCertsFilter - checks for forwarded client certificate and put it into a custom request attribute + * - X509AuthAwareFilter - attempts to log in using a user using forwarded client certificate, replaces pre-authentication in security context by the authentication result + * - BasicAuthFilter - attempts to log in a user using credentials from basic authentication header + */ @Configuration @RequiredArgsConstructor @Order(8) @@ -257,20 +276,19 @@ public SecurityFilterChain authProtectedEndpointsFilterChain(HttpSecurity http) authConfigurationProperties.getZaasRevokeMultipleAccessTokens() + "/**", authConfigurationProperties.getZaasEvictAccessTokensAndRules() ))) - .authorizeHttpRequests(requests -> requests - .anyRequest().authenticated()) - .x509(x509 -> x509.userDetailsService(x509UserDetailsService())) - .authenticationProvider(compoundAuthProvider) // for authenticating credentials - .with(new CustomSecurityFilters(), Customizer.withDefaults()); + .authorizeHttpRequests(requests -> requests + .anyRequest().authenticated()) + .authenticationProvider(compoundAuthProvider) // for authenticating credentials + .with(new CustomSecurityFilters(), Customizer.withDefaults()); return http.build(); } private class CustomSecurityFilters extends AbstractHttpConfigurer { @Override public void configure(HttpSecurity http) { - http.addFilterBefore(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) - .addFilterBefore(loginFilter(http), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) - .addFilterAfter(x509AuthenticationFilter(), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); + http.addFilterAfter(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) + .addFilterAfter(x509ForwardingAwareAuthenticationFilter(), CategorizeCertsFilter.class) + .addFilterAfter(loginFilter(http), X509AuthAwareFilter.class); } private NonCompulsoryAuthenticationProcessingFilter loginFilter(HttpSecurity http) { @@ -282,7 +300,7 @@ private NonCompulsoryAuthenticationProcessingFilter loginFilter(HttpSecurity htt handlerInitializer.getResourceAccessExceptionHandler()); } - private X509AuthenticationFilter x509AuthenticationFilter() { + private X509ForwardingAwareAuthenticationFilter x509ForwardingAwareAuthenticationFilter() { return new X509AuthAwareFilter("/**", handlerInitializer.getAuthenticationFailureHandler(), x509AuthenticationProvider); @@ -302,12 +320,12 @@ public SecurityFilterChain authZaasEndpointsFilterChain(HttpSecurity http) throw baseConfigure(http.securityMatchers(matchers -> matchers.requestMatchers( // no http method to catch all attempts to login and handle them here. Otherwise it falls to default filterchain and tries to route the calls, which doesnt make sense "/zaas/scheme/**" ))) - .authorizeHttpRequests(requests -> requests - .anyRequest().authenticated()) - .x509(x509 -> x509.userDetailsService(x509UserDetailsService())) - .addFilterAfter(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) - .addFilterAfter(new ExtractAuthSourceFilter(authSourceService, authExceptionHandler), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) - .addFilterAfter(new ZaasAuthenticationFilter(authSourceService, authExceptionHandler), CategorizeCertsFilter.class); + .authorizeHttpRequests(requests -> requests + .anyRequest().authenticated()) + .x509(x509 -> x509.userDetailsService(x509UserDetailsService())) + .addFilterAfter(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) + .addFilterAfter(new ExtractAuthSourceFilter(authSourceService, authExceptionHandler), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) + .addFilterAfter(new ZaasAuthenticationFilter(authSourceService, authExceptionHandler), CategorizeCertsFilter.class); return http.build(); } @@ -373,14 +391,13 @@ class Ticket { @Bean public SecurityFilterChain ticketFilterChain(HttpSecurity http) throws Exception { return baseConfigure(http.securityMatchers(matchers -> matchers.requestMatchers( - authConfigurationProperties.getZaasTicketEndpoint() - ))).authorizeHttpRequests(requests -> requests.anyRequest().authenticated()) - .addFilterBefore(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class) + authConfigurationProperties.getZaasTicketEndpoint() + ))).authorizeHttpRequests(requests -> requests.anyRequest().authenticated()) .authenticationProvider(tokenAuthenticationProvider) - .logout(logout -> logout.disable()) // logout filter in this chain not needed + .logout(AbstractHttpConfigurer::disable) // logout filter in this chain not needed .x509(x509 -> x509 //default x509 filter, authenticates trusted cert, ticketFilter(..) depends on this .userDetailsService(new SimpleUserDetailService()) - ).with(new CustomSecurityFilters(), Customizer.withDefaults()) + ).with(new CustomSecurityFilters(), withDefaults()) .build(); } @@ -423,11 +440,11 @@ public SecurityFilterChain refreshFilterChain(HttpSecurity http) throws Exceptio authConfigurationProperties.getZaasRefreshEndpoint() ))).authorizeHttpRequests(requests -> requests .anyRequest().authenticated()) - .authenticationProvider(tokenAuthenticationProvider) - .logout(logout -> logout.disable()) // logout filter in this chain not needed - .x509(x509 -> x509 //default x509 filter, authenticates trusted cert, ticketFilter(..) depends on this - .userDetailsService(new SimpleUserDetailService())) - .with(new CustomSecurityFilters(), Customizer.withDefaults()); + .authenticationProvider(tokenAuthenticationProvider) + .logout(logout -> logout.disable()) // logout filter in this chain not needed + .x509(x509 -> x509 //default x509 filter, authenticates trusted cert, refreshFilter(..) depends on this + .userDetailsService(new SimpleUserDetailService())) + .with(new CustomSecurityFilters(), Customizer.withDefaults()); return http.build(); } @@ -463,12 +480,12 @@ class CertificateProtectedEndpoints { @Bean public SecurityFilterChain certificateEndpointsFilterChain(HttpSecurity http) throws Exception { return baseConfigure(http.securityMatchers(matchers -> matchers - .requestMatchers(AuthController.CONTROLLER_PATH + AuthController.INVALIDATE_PATH, AuthController.CONTROLLER_PATH + AuthController.DISTRIBUTE_PATH)) + .requestMatchers(AuthController.CONTROLLER_PATH + AuthController.INVALIDATE_PATH, AuthController.CONTROLLER_PATH + AuthController.DISTRIBUTE_PATH)) ).authorizeHttpRequests(requests -> requests .anyRequest().authenticated()) - .logout(AbstractHttpConfigurer::disable) // logout filter in this chain not needed - .x509(x509 -> x509 // default x509 filter, authenticates trusted cert - .userDetailsService(new SimpleUserDetailService())).build(); + .logout(AbstractHttpConfigurer::disable) // logout filter in this chain not needed + .x509(x509 -> x509 // default x509 filter, authenticates trusted cert + .userDetailsService(new SimpleUserDetailService())).build(); } } @@ -485,36 +502,23 @@ class CertificateOrAuthProtectedEndpoints { private final CompoundAuthProvider compoundAuthProvider; private final AuthenticationProvider tokenAuthenticationProvider; - private final String[] protectedEndpoints = { - SafResourceAccessController.FULL_CONTEXT_PATH, - "/application", - "/gateway/conformance", - "/gateway/api/v1/conformance", - "/gateway/validate", - "/gateway/api/v1/validate" - }; - @Bean public SecurityFilterChain certificateOrAuthEndpointsFilterChain(HttpSecurity http) throws Exception { baseConfigure( http.securityMatchers(matchers -> matchers - .requestMatchers("/application/**") - .requestMatchers(HttpMethod.POST, SafResourceAccessController.FULL_CONTEXT_PATH) - .requestMatchers("/gateway/conformance/**") - .requestMatchers("/gateway/api/v1/conformance/**") - .requestMatchers("/gateway/validate") - .requestMatchers("/gateway/api/v1/validate") - ) + .requestMatchers("/application/**") + .requestMatchers(HttpMethod.POST, SafResourceAccessController.FULL_CONTEXT_PATH) + ) ).authorizeHttpRequests(requests -> requests - .anyRequest() - .authenticated() - ) - .logout(logout -> logout.disable()); // logout filter in this chain not needed + .anyRequest() + .authenticated() + ) + .logout(AbstractHttpConfigurer::disable); // logout filter in this chain not needed if (isAttlsEnabled) { http.x509(withDefaults()) - // filter out API ML certificate - .addFilterBefore(reversedCategorizeCertFilter(), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); + // filter out API ML certificate + .addFilterBefore(reversedCategorizeCertFilter(), org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter.class); } else { http.x509(x509 -> x509.userDetailsService(x509UserDetailsService())); // default x509 filter, authenticates trusted cert } @@ -545,7 +549,7 @@ private BasicContentFilter basicFilter(AuthenticationManager authenticationManag authenticationManager, handlerInitializer.getAuthenticationFailureHandler(), handlerInitializer.getResourceAccessExceptionHandler(), - protectedEndpoints); + new String[] {"/"}); } /** @@ -557,7 +561,7 @@ private CookieContentFilter cookieFilter(AuthenticationManager authenticationMan handlerInitializer.getAuthenticationFailureHandler(), handlerInitializer.getResourceAccessExceptionHandler(), authConfigurationProperties, - protectedEndpoints); + new String[] {"/"}); } /** @@ -568,7 +572,7 @@ private BearerContentFilter bearerContentFilter(AuthenticationManager authentica authenticationManager, handlerInitializer.getAuthenticationFailureHandler(), handlerInitializer.getResourceAccessExceptionHandler(), - protectedEndpoints); + new String[] {"/"}); } } @@ -612,12 +616,10 @@ public WebSecurityCustomizer webSecurityCustomizer() { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return baseConfigure(http.securityMatchers(matchers -> matchers.requestMatchers("/**", "/gateway/version"))) - .authorizeHttpRequests(requests -> requests - .anyRequest() - .permitAll()).logout(logout -> logout.disable()) - // sort out client and apiml internal certificates - .addFilterBefore(new CategorizeCertsFilter(publicKeyCertificatesBase64, certificateValidator), AnonymousAuthenticationFilter.class) - .build(); + .authorizeHttpRequests(requests -> requests + .anyRequest() + .permitAll()).logout(AbstractHttpConfigurer::disable) + .build(); } } diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/zaas/ZaasAuthenticationFilter.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/zaas/ZaasAuthenticationFilter.java index 38cecd15e1..292caab8bc 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/zaas/ZaasAuthenticationFilter.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/zaas/ZaasAuthenticationFilter.java @@ -37,7 +37,7 @@ public class ZaasAuthenticationFilter extends OncePerRequestFilter { protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException { try { Optional authSource = Optional.ofNullable((AuthSource) request.getAttribute(AUTH_SOURCE_ATTR)); - if (!authSource.isPresent() || !authSourceService.isValid(authSource.get())) { + if (authSource.isEmpty() || !authSourceService.isValid(authSource.get())) { throw new InsufficientAuthenticationException("Authentication failed."); } filterChain.doFilter(request, response); diff --git a/zaas-service/src/test/java/org/zowe/apiml/zaas/security/config/X509AuthenticationFilterTest.java b/zaas-service/src/test/java/org/zowe/apiml/zaas/security/config/X509ForwardingAwareAuthenticationFilterTest.java similarity index 83% rename from zaas-service/src/test/java/org/zowe/apiml/zaas/security/config/X509AuthenticationFilterTest.java rename to zaas-service/src/test/java/org/zowe/apiml/zaas/security/config/X509ForwardingAwareAuthenticationFilterTest.java index 2f225d4c96..e4cc64f403 100644 --- a/zaas-service/src/test/java/org/zowe/apiml/zaas/security/config/X509AuthenticationFilterTest.java +++ b/zaas-service/src/test/java/org/zowe/apiml/zaas/security/config/X509ForwardingAwareAuthenticationFilterTest.java @@ -11,6 +11,8 @@ package org.zowe.apiml.zaas.security.config; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; @@ -18,26 +20,24 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.zowe.apiml.zaas.security.service.AuthenticationService; -import org.zowe.apiml.zaas.utils.X509Utils; -import org.zowe.apiml.security.common.login.X509AuthenticationFilter; +import org.zowe.apiml.security.common.login.X509ForwardingAwareAuthenticationFilter; import org.zowe.apiml.security.common.token.TokenAuthentication; import org.zowe.apiml.security.common.token.X509AuthenticationToken; +import org.zowe.apiml.zaas.security.service.AuthenticationService; +import org.zowe.apiml.zaas.utils.X509Utils; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; import java.io.IOException; import java.security.cert.X509Certificate; import java.util.Optional; import static org.mockito.Mockito.*; -class X509AuthenticationFilterTest { +class X509ForwardingAwareAuthenticationFilterTest { private MockHttpServletRequest httpServletRequest; private MockHttpServletResponse httpServletResponse; - private X509AuthenticationFilter x509AuthenticationFilter; + private X509ForwardingAwareAuthenticationFilter x509ForwardingAwareAuthenticationFilter; private AuthenticationSuccessHandler successHandler; @@ -55,7 +55,7 @@ void setup() { authenticationProvider = mock(AuthenticationProvider.class); filterChain = mock(FilterChain.class); authenticationService = mock(AuthenticationService.class); - x509AuthenticationFilter = new X509AuthenticationFilter("/api/v1/zaas/auth/login", successHandler, authenticationProvider); + x509ForwardingAwareAuthenticationFilter = new X509ForwardingAwareAuthenticationFilter("/api/v1/zaas/auth/login", successHandler, authenticationProvider); when(authenticationService.getJwtTokenFromRequest(httpServletRequest)).thenReturn(Optional.of("jwt")); } @@ -67,7 +67,7 @@ void shouldCallAuthProviderWithCertificate() { httpServletRequest.setAttribute("client.auth.X509Certificate", x509Certificate); httpServletResponse = new MockHttpServletResponse(); - x509AuthenticationFilter.attemptAuthentication(httpServletRequest, httpServletResponse); + x509ForwardingAwareAuthenticationFilter.attemptAuthentication(httpServletRequest, httpServletResponse); verify(authenticationProvider).authenticate(new X509AuthenticationToken(x509Certificate)); } @@ -82,7 +82,7 @@ void shouldAuthenticateWithCertificate() throws ServletException, IOException { httpServletResponse = new MockHttpServletResponse(); when(authenticationProvider.authenticate(new X509AuthenticationToken(x509Certificate))) .thenReturn(new TokenAuthentication("user", "jwt")); - x509AuthenticationFilter.doFilter(httpServletRequest, httpServletResponse, filterChain); + x509ForwardingAwareAuthenticationFilter.doFilter(httpServletRequest, httpServletResponse, filterChain); verify(authenticationProvider).authenticate(new X509AuthenticationToken(x509Certificate)); } @@ -93,7 +93,7 @@ void shouldNotAuthenticate() { httpServletRequest.setMethod(HttpMethod.POST.name()); httpServletResponse = new MockHttpServletResponse(); - x509AuthenticationFilter.attemptAuthentication(httpServletRequest, httpServletResponse); + x509ForwardingAwareAuthenticationFilter.attemptAuthentication(httpServletRequest, httpServletResponse); verify(authenticationProvider, times(0)).authenticate(new X509AuthenticationToken(x509Certificate)); } diff --git a/zaas-service/src/test/resources/application-test.yml b/zaas-service/src/test/resources/application-test.yml index 614a771fa3..2e624a2895 100644 --- a/zaas-service/src/test/resources/application-test.yml +++ b/zaas-service/src/test/resources/application-test.yml @@ -2,7 +2,7 @@ environment.older: false logging: level: - ROOT: TRACE + ROOT: INFO apiml: # The `apiml` node contains API Mediation Layer specific configuration @@ -177,4 +177,4 @@ management: --- spring.config.activate.on-profile: dev -logbackServiceName: ZWEAGW1 +logbackServiceName: ZWEAZS1 diff --git a/zaas-service/src/test/resources/application.yml b/zaas-service/src/test/resources/application.yml index 4e3ebcd815..a5f9f1ea6b 100644 --- a/zaas-service/src/test/resources/application.yml +++ b/zaas-service/src/test/resources/application.yml @@ -1,6 +1,6 @@ logging: level: - ROOT: TRACE + ROOT: INFO apiml: service: @@ -188,4 +188,4 @@ management: --- spring.config.activate.on-profile: dev -logbackServiceName: ZWEAGW1 +logbackServiceName: ZWEAZS1