From cce201d848c901be78ecce9ff29ef0427b8fe05b Mon Sep 17 00:00:00 2001 From: Manfred Riem Date: Mon, 30 Dec 2024 09:27:06 -0600 Subject: [PATCH] Fixes #4438 - Add security constraints to SecurityManager API (#4439) --- .gitignore | 1 + .../piranha/core/api/SecurityConstraint.java | 118 ++++++++++++++++++ .../piranha/core/api/SecurityManager.java | 15 +++ .../api/SecurityWebResourceCollection.java | 118 ++++++++++++++++++ core/impl/pom.xml | 39 +++++- .../core/impl/DefaultSecurityManager.java | 25 ++++ .../core/impl/DefaultSecurityManagerTest.java | 50 ++++++++ .../exousia/AuthorizationPostInitializer.java | 8 +- .../exousia/PiranhaToExousiaConverter.java | 17 ++- extension/security-servlet/pom.xml | 44 ++++++- .../servlet/ServletSecurityManager.java | 95 ++++++++------ .../servlet/ServletSecurityManagerTest.java | 50 ++++++++ extension/webxml/pom.xml | 32 ++++- .../internal/InternalWebXmlProcessor.java | 33 ++++- .../internal/InternalWebXmlProcessorTest.java | 59 +++++++++ test/coreprofile/pom.xml | 3 +- 16 files changed, 642 insertions(+), 65 deletions(-) create mode 100644 core/api/src/main/java/cloud/piranha/core/api/SecurityConstraint.java create mode 100644 core/api/src/main/java/cloud/piranha/core/api/SecurityWebResourceCollection.java create mode 100644 core/impl/src/test/java/cloud/piranha/core/impl/DefaultSecurityManagerTest.java create mode 100644 extension/security-servlet/src/test/java/cloud/piranha/extension/security/servlet/ServletSecurityManagerTest.java create mode 100644 extension/webxml/src/test/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessorTest.java diff --git a/.gitignore b/.gitignore index c580a602bd..53b413e313 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ dist/server/tmp/ dist/platform/tmp/ .flattened-pom.xml bin/ +piranha.pid diff --git a/core/api/src/main/java/cloud/piranha/core/api/SecurityConstraint.java b/core/api/src/main/java/cloud/piranha/core/api/SecurityConstraint.java new file mode 100644 index 0000000000..750d78c339 --- /dev/null +++ b/core/api/src/main/java/cloud/piranha/core/api/SecurityConstraint.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2002-2024 Manorrock.com. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package cloud.piranha.core.api; + +import java.util.ArrayList; +import java.util.List; + +/** + * A security constraint. + * + * @author Manfred Riem (mriem@manorrock.com) + */ +public class SecurityConstraint { + + /** + * Stores the role names. + */ + private List roleNames; + + /** + * Stores the security web resource collections. + */ + private List securityWebResourceCollections; + + /** + * Stores the transport guarantee. + */ + private String transportGuarantee; + + /** + * Constructor. + */ + public SecurityConstraint() { + roleNames = new ArrayList<>(); + securityWebResourceCollections = new ArrayList<>(); + transportGuarantee = "NONE"; + } + + /** + * Get the role names. + * + * @return the role names. + */ + public List getRoleNames() { + return roleNames; + } + + /** + * Get the security web resource collection. + * + * @return the security web resource collection. + */ + public List getSecurityWebResourceCollections() { + return securityWebResourceCollections; + } + + /** + * Get the transport guarantee. + * + * @return the transport guarantee. + */ + public String getTransportGuarantee() { + return transportGuarantee; + } + + /** + * Set the role names. + * + * @param roleNames the role names. + */ + public void setRoleNames(List roleNames) { + this.roleNames = roleNames; + } + + /** + * Set the security web resource collections. + * + * @param securityWebResourceCollections the security web resource collections. + */ + public void setSecurityWebResourceCollections( + List securityWebResourceCollections) { + this.securityWebResourceCollections = securityWebResourceCollections; + } + + /** + * Set the transport guarantee. + * + * @param transportGuarantee the transport guarantee. + */ + public void setTransportGuarantee(String transportGuarantee) { + this.transportGuarantee = transportGuarantee; + } +} diff --git a/core/api/src/main/java/cloud/piranha/core/api/SecurityManager.java b/core/api/src/main/java/cloud/piranha/core/api/SecurityManager.java index a17d00d914..b5612e7d25 100644 --- a/core/api/src/main/java/cloud/piranha/core/api/SecurityManager.java +++ b/core/api/src/main/java/cloud/piranha/core/api/SecurityManager.java @@ -32,6 +32,7 @@ import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Collection; +import java.util.List; import java.util.Set; /** @@ -201,6 +202,13 @@ default String getRealmName() { * @return the roles */ Set getRoles(); + + /** + * Get the security constraints. + * + * @return the security constraints. + */ + List getSecurityConstraints(); /** * Get the handler that may be used by the login method to contact an @@ -350,6 +358,13 @@ default void setFormLoginPage(String formLoginPage) { */ default void setRealmName(String realmName) { } + + /** + * Set the security constraints. + * + * @param securityConstraints the security constraints. + */ + void setSecurityConstraints(List securityConstraints); /** * Set the handler that may be used by the login method to contact an diff --git a/core/api/src/main/java/cloud/piranha/core/api/SecurityWebResourceCollection.java b/core/api/src/main/java/cloud/piranha/core/api/SecurityWebResourceCollection.java new file mode 100644 index 0000000000..ae118af96c --- /dev/null +++ b/core/api/src/main/java/cloud/piranha/core/api/SecurityWebResourceCollection.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2002-2024 Manorrock.com. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package cloud.piranha.core.api; + +import java.util.ArrayList; +import java.util.List; + +/** + * A security web resource collection. + * + * @author Manfred Riem (mriem@manorrock.com) + */ +public class SecurityWebResourceCollection { + + /** + * Stores the HTTP methods. + */ + private List httpMethods; + + /** + * Stores the HTTP method omissions. + */ + private List httpMethodOmissions; + + /** + * Stores the URL patterns. + */ + private List urlPatterns; + + /** + * Constructor. + */ + public SecurityWebResourceCollection() { + this.httpMethods = new ArrayList<>(); + this.httpMethodOmissions = new ArrayList<>(); + this.urlPatterns = new ArrayList<>(); + } + + /** + * Get the HTTP methods. + * + * @return the HTTP methods. + */ + public List getHttpMethods() { + return httpMethods; + } + + /** + * Get the HTTP method omissions. + * + * @return the HTTP method omissions. + */ + public List getHttpMethodOmissions() { + return httpMethodOmissions; + } + + /** + * Get the URL patterns. + * + * @return the URL patterns. + */ + public List getUrlPatterns() { + return urlPatterns; + } + + /** + * Set the HTTP methods. + * + * @param httpMethods the HTTP methods. + */ + public void setHttpMethods(List httpMethods) { + this.httpMethods = httpMethods; + } + + /** + * Set the HTTP method omissions. + * + * @param httpMethodOmissions the HTTP method omissions. + */ + public void setHttpMethodOmissions(List httpMethodOmissions) { + this.httpMethodOmissions = httpMethodOmissions; + } + + /** + * Set the URL patterns. + * + * @param urlPatterns the URL patterns. + */ + public void setUrlPatterns(List urlPatterns) { + this.urlPatterns = urlPatterns; + } +} diff --git a/core/impl/pom.xml b/core/impl/pom.xml index 6f64cf4dde..1caa41b5a1 100644 --- a/core/impl/pom.xml +++ b/core/impl/pom.xml @@ -13,7 +13,41 @@ jar Piranha - Core - Implementation - + + + + org.jacoco + jacoco-maven-plugin + + + check + + check + + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + 0.72 + + + BRANCH + COVEREDRATIO + 0.59 + + + + + + + + + + @@ -50,19 +84,16 @@ org.junit.jupiter junit-jupiter-api test - 5.10.3 org.junit.jupiter junit-jupiter-params test - 5.10.3 org.junit.jupiter junit-jupiter-engine test - 5.10.3 diff --git a/core/impl/src/main/java/cloud/piranha/core/impl/DefaultSecurityManager.java b/core/impl/src/main/java/cloud/piranha/core/impl/DefaultSecurityManager.java index a1285aaa95..fd9ac8d4cd 100644 --- a/core/impl/src/main/java/cloud/piranha/core/impl/DefaultSecurityManager.java +++ b/core/impl/src/main/java/cloud/piranha/core/impl/DefaultSecurityManager.java @@ -27,12 +27,15 @@ */ package cloud.piranha.core.impl; +import cloud.piranha.core.api.SecurityConstraint; import cloud.piranha.core.api.WebApplication; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Set; /** @@ -46,6 +49,18 @@ */ public class DefaultSecurityManager implements cloud.piranha.core.api.SecurityManager { + /** + * Stores the security constraints. + */ + private List securityConstraints; + + /** + * Constructor. + */ + public DefaultSecurityManager() { + securityConstraints = new ArrayList<>(); + } + @Override public boolean authenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { return false; @@ -60,6 +75,11 @@ public Set getRoles() { return Collections.emptySet(); } + @Override + public List getSecurityConstraints() { + return securityConstraints; + } + @Override public WebApplication getWebApplication() { return null; @@ -79,6 +99,11 @@ public void login(HttpServletRequest request, String username, String password) public void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException { } + @Override + public void setSecurityConstraints(List securityConstraints) { + this.securityConstraints = securityConstraints; + } + @Override public void setWebApplication(WebApplication webApplication) { } diff --git a/core/impl/src/test/java/cloud/piranha/core/impl/DefaultSecurityManagerTest.java b/core/impl/src/test/java/cloud/piranha/core/impl/DefaultSecurityManagerTest.java new file mode 100644 index 0000000000..87a197f821 --- /dev/null +++ b/core/impl/src/test/java/cloud/piranha/core/impl/DefaultSecurityManagerTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2024 Manorrock.com. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package cloud.piranha.core.impl; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +/** + * The JUnit tests for the DefaultSecurityManager class. + * + * @author Manfred Riem (mriem@manorrock.com) + */ +public class DefaultSecurityManagerTest { + + /** + * Test getSecurityConstraints method. + */ + @Test + public void testGetSecurityConstraints() { + DefaultSecurityManager manager = new DefaultSecurityManager(); + assertNotNull(manager.getSecurityConstraints()); + manager.setSecurityConstraints(null); + assertNull(manager.getSecurityConstraints()); + } +} diff --git a/extension/exousia/src/main/java/cloud/piranha/extension/exousia/AuthorizationPostInitializer.java b/extension/exousia/src/main/java/cloud/piranha/extension/exousia/AuthorizationPostInitializer.java index 4865edbe30..a3ca42645d 100644 --- a/extension/exousia/src/main/java/cloud/piranha/extension/exousia/AuthorizationPostInitializer.java +++ b/extension/exousia/src/main/java/cloud/piranha/extension/exousia/AuthorizationPostInitializer.java @@ -114,7 +114,7 @@ private AuthorizationService getAuthorizationService(WebApplication context) thr } private List getAllScurityConstraints(WebApplication context) { - List webXmlConstraints = getConstraintsFromWebXml(context); + List webXmlConstraints = getConstraintsFromSecurityManager(context); List annotationConstraints = filterAnnotatedConstraints( webXmlConstraints, getConstraintsFromSecurityAnnotations(context)); @@ -219,9 +219,9 @@ private List getConstraintsFromSecurityAnnotations(ServletCo * @param webApplication the web application. * @return the list of security constraints. */ - private List getConstraintsFromWebXml(WebApplication webApplication) { - WebXmlManager manager = (WebXmlManager) webApplication.getAttribute("cloud.piranha.extension.webxml.WebXmlManager"); - return piranhaToExousiaConverter.getConstraintsFromWebXml(manager.getWebXml()); + private List getConstraintsFromSecurityManager(WebApplication webApplication) { + return piranhaToExousiaConverter.getConstraintsFromSecurityManager( + webApplication.getManager().getSecurityManager()); } /** diff --git a/extension/exousia/src/main/java/cloud/piranha/extension/exousia/PiranhaToExousiaConverter.java b/extension/exousia/src/main/java/cloud/piranha/extension/exousia/PiranhaToExousiaConverter.java index 2d313ae4da..0bd831f4c8 100644 --- a/extension/exousia/src/main/java/cloud/piranha/extension/exousia/PiranhaToExousiaConverter.java +++ b/extension/exousia/src/main/java/cloud/piranha/extension/exousia/PiranhaToExousiaConverter.java @@ -27,9 +27,10 @@ */ package cloud.piranha.extension.exousia; +import cloud.piranha.core.api.SecurityManager; +import cloud.piranha.core.api.SecurityWebResourceCollection; import cloud.piranha.extension.webxml.WebXmlServletSecurityRoleRef; import cloud.piranha.extension.webxml.WebXml; -import cloud.piranha.extension.webxml.WebXmlSecurityConstraint; import cloud.piranha.extension.webxml.WebXmlServlet; import jakarta.servlet.ServletSecurityElement; import jakarta.servlet.annotation.ServletSecurity; @@ -102,22 +103,20 @@ public List getConstraintsFromSecurityAnnotations(List getConstraintsFromWebXml(WebXml webXml) { - if (webXml == null || webXml.getSecurityConstraints() == null) { - return null; - } + public List getConstraintsFromSecurityManager(SecurityManager securityManager) { List constraints = new ArrayList<>(); - for (WebXmlSecurityConstraint xmlConstraint : webXml.getSecurityConstraints()) { + for (cloud.piranha.core.api.SecurityConstraint xmlConstraint + : securityManager.getSecurityConstraints()) { List webResourceCollections = new ArrayList<>(); - for (WebXmlSecurityConstraint.WebResourceCollection xmlCollection : xmlConstraint.getWebResourceCollections()) { + for (SecurityWebResourceCollection xmlCollection : xmlConstraint.getSecurityWebResourceCollections()) { webResourceCollections.add(new WebResourceCollection( xmlCollection.getUrlPatterns(), xmlCollection.getHttpMethods(), diff --git a/extension/security-servlet/pom.xml b/extension/security-servlet/pom.xml index 64662cc62d..b0cbe5a62f 100644 --- a/extension/security-servlet/pom.xml +++ b/extension/security-servlet/pom.xml @@ -1,19 +1,53 @@ - + 4.0.0 - cloud.piranha.extension project 25.1.0-SNAPSHOT - piranha-extension-security-servlet jar - Piranha - Extension - Security - Servlet - + + + + org.jacoco + jacoco-maven-plugin + + + check + + check + + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + 0.13 + + + BRANCH + COVEREDRATIO + 0.00 + + + + + + + + + + diff --git a/extension/security-servlet/src/main/java/cloud/piranha/extension/security/servlet/ServletSecurityManager.java b/extension/security-servlet/src/main/java/cloud/piranha/extension/security/servlet/ServletSecurityManager.java index 2cd4401db8..6cc449eac5 100644 --- a/extension/security-servlet/src/main/java/cloud/piranha/extension/security/servlet/ServletSecurityManager.java +++ b/extension/security-servlet/src/main/java/cloud/piranha/extension/security/servlet/ServletSecurityManager.java @@ -42,6 +42,7 @@ import org.glassfish.exousia.AuthorizationService; import cloud.piranha.core.api.AuthenticatedIdentity; +import cloud.piranha.core.api.SecurityConstraint; import cloud.piranha.core.api.SecurityManager; import cloud.piranha.core.api.WebApplication; import cloud.piranha.core.api.WebApplicationRequest; @@ -52,6 +53,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import java.util.ArrayList; +import java.util.List; import org.glassfish.epicyro.config.helper.Caller; import org.glassfish.epicyro.services.DefaultAuthenticationService; @@ -93,6 +96,11 @@ public class ServletSecurityManager implements SecurityManager { */ protected final Set roles = ConcurrentHashMap.newKeySet(); + /** + * Stores the security constraints. + */ + protected List securityConstraints; + /** * Handler for the specific HttpServletRequest#login method call */ @@ -103,6 +111,13 @@ public class ServletSecurityManager implements SecurityManager { */ protected WebApplication webApplication; + /** + * Constructor. + */ + public ServletSecurityManager() { + this.securityConstraints = new ArrayList<>(); + } + @Override public boolean authenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { return authenticate(request, response, MID_REQUEST_USER); @@ -216,6 +231,11 @@ public Set getRoles() { return roles; } + @Override + public List getSecurityConstraints() { + return securityConstraints; + } + private String getServletName(HttpServletRequest request) { ServletConfig servletConfig = (ServletConfig) request.getAttribute(DefaultServletEnvironment.class.getName()); if (servletConfig != null && servletConfig.getServletName() != null) { @@ -226,17 +246,13 @@ private String getServletName(HttpServletRequest request) { } @Override - public boolean isRequestSecurityAsRequired(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - if (getAuthorizationService(request) != null) { - return getAuthorizationService(request).checkWebUserDataPermission(request); - } else { - return false; - } + public UsernamePasswordLoginHandler getUsernamePasswordLoginHandler() { + return usernamePasswordLoginHandler; } @Override - public boolean isRequestedResourcePublic(HttpServletRequest request) { - return getAuthorizationService(request).checkPublicWebResourcePermission(request); + public WebApplication getWebApplication() { + return webApplication; } @Override @@ -244,6 +260,19 @@ public boolean isCallerAuthorizedForResource(HttpServletRequest request) { return getAuthorizationService(request).checkWebResourcePermission(request); } + @Override + public boolean isRequestedResourcePublic(HttpServletRequest request) { + return getAuthorizationService(request).checkPublicWebResourcePermission(request); + } + + @Override + public boolean isRequestSecurityAsRequired(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + if (getAuthorizationService(request) != null) { + return getAuthorizationService(request).checkWebUserDataPermission(request); + } else { + return false; + } + } @Override public boolean isUserInRole(HttpServletRequest request, String role) { return getAuthorizationService(request).checkWebRoleRefPermission(getServletName(request), role); @@ -259,11 +288,6 @@ public void login(HttpServletRequest request, String username, String password) setIdentityForCurrentRequest(request, resultIdentity.getCallerPrincipal(), resultIdentity.getGroups(), "login"); } - @Override - public void postRequestProcess(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - getAuthenticationService(request).secureResponse(request, response); - } - @Override public void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException { getAuthenticationService(request).clearSubject(request, response, getCurrentSubject()); @@ -276,28 +300,28 @@ public void logout(HttpServletRequest request, HttpServletResponse response) thr } @Override - public UsernamePasswordLoginHandler getUsernamePasswordLoginHandler() { - return usernamePasswordLoginHandler; + public void postRequestProcess(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + getAuthenticationService(request).secureResponse(request, response); } @Override - public WebApplication getWebApplication() { - return webApplication; + public void setAuthMethod(String authMethod) { + this.authMethod = authMethod; } @Override - public void setWebApplication(WebApplication webApplication) { - this.webApplication = webApplication; + public void setDenyUncoveredHttpMethods(boolean denyUncoveredHttpMethods) { + this.denyUncoveredHttpMethods = denyUncoveredHttpMethods; } @Override - public void setUsernamePasswordLoginHandler(UsernamePasswordLoginHandler usernamePasswordLoginHandler) { - this.usernamePasswordLoginHandler = usernamePasswordLoginHandler; - } - + public void setFormErrorPage(String formErrorPage) { + this.formErrorPage = formErrorPage; + } + @Override - public void setDenyUncoveredHttpMethods(boolean denyUncoveredHttpMethods) { - this.denyUncoveredHttpMethods = denyUncoveredHttpMethods; + public void setFormLoginPage(String formLoginPage) { + this.formLoginPage = formLoginPage; } private void setIdentityForCurrentRequest(HttpServletRequest request, Principal callerPrincipal, Set groups, String authType) { @@ -312,23 +336,24 @@ private void setIdentityForCurrentRequest(HttpServletRequest request, Principal DefaultAuthenticatedIdentity.setCurrentIdentity(currentPrincipal, groups); } + @Override - public void setAuthMethod(String authMethod) { - this.authMethod = authMethod; + public void setRealmName(String realmName) { + this.realmName = realmName; } @Override - public void setFormErrorPage(String formErrorPage) { - this.formErrorPage = formErrorPage; - } - + public void setSecurityConstraints(List securityConstraints) { + this.securityConstraints = securityConstraints; + } + @Override - public void setFormLoginPage(String formLoginPage) { - this.formLoginPage = formLoginPage; + public void setUsernamePasswordLoginHandler(UsernamePasswordLoginHandler usernamePasswordLoginHandler) { + this.usernamePasswordLoginHandler = usernamePasswordLoginHandler; } @Override - public void setRealmName(String realmName) { - this.realmName = realmName; + public void setWebApplication(WebApplication webApplication) { + this.webApplication = webApplication; } } diff --git a/extension/security-servlet/src/test/java/cloud/piranha/extension/security/servlet/ServletSecurityManagerTest.java b/extension/security-servlet/src/test/java/cloud/piranha/extension/security/servlet/ServletSecurityManagerTest.java new file mode 100644 index 0000000000..a6a4580fd3 --- /dev/null +++ b/extension/security-servlet/src/test/java/cloud/piranha/extension/security/servlet/ServletSecurityManagerTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2024 Manorrock.com. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package cloud.piranha.extension.security.servlet; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/** + * The JUnit tests for the ServletSecurityManager class. + * + * @author Manfred Riem (mriem@manorrock.com) + */ +public class ServletSecurityManagerTest { + + /** + * Test getSecurityConstraints method. + */ + @Test + public void testGetSecurityConstraints() { + ServletSecurityManager manager = new ServletSecurityManager(); + assertNotNull(manager.getSecurityConstraints()); + manager.setSecurityConstraints(null); + assertNull(manager.getSecurityConstraints()); + } +} diff --git a/extension/webxml/pom.xml b/extension/webxml/pom.xml index dc4100914f..502dea76a8 100644 --- a/extension/webxml/pom.xml +++ b/extension/webxml/pom.xml @@ -69,7 +69,6 @@ test - @@ -79,6 +78,37 @@ false + + org.jacoco + jacoco-maven-plugin + + + check + + check + + + + + BUNDLE + + + INSTRUCTION + COVEREDRATIO + 0.78 + + + BRANCH + COVEREDRATIO + 0.64 + + + + + + + + diff --git a/extension/webxml/src/main/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessor.java b/extension/webxml/src/main/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessor.java index 760aaa11e7..e555af3e4a 100644 --- a/extension/webxml/src/main/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessor.java +++ b/extension/webxml/src/main/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessor.java @@ -47,7 +47,9 @@ import cloud.piranha.core.api.ErrorPageManager; import cloud.piranha.core.api.LocaleEncodingManager; +import cloud.piranha.core.api.SecurityConstraint; import cloud.piranha.core.api.SecurityManager; +import cloud.piranha.core.api.SecurityWebResourceCollection; import cloud.piranha.core.api.WebApplication; import cloud.piranha.extension.webxml.WebXml; import cloud.piranha.extension.webxml.WebXmlContextParam; @@ -64,6 +66,7 @@ import cloud.piranha.core.api.WelcomeFileManager; import cloud.piranha.core.impl.DefaultJspConfigDescriptor; import cloud.piranha.core.impl.DefaultTaglibDescriptor; +import cloud.piranha.extension.webxml.WebXmlSecurityConstraint; import jakarta.servlet.DispatcherType; import jakarta.servlet.FilterRegistration; import jakarta.servlet.MultipartConfigElement; @@ -578,6 +581,16 @@ private void processLocaleEncodingMapping(WebApplication webApplication, WebXml } } + /** + * Is the string empty. + * + * @param string the string. + * @return true if it is, false otherwise. + */ + private boolean isEmpty(String string) { + return string == null || string.isEmpty(); + } + /** * Process the session config. * @@ -591,10 +604,6 @@ private void processSessionConfig(WebApplication webApplication, WebXml webXml) } } - private boolean isEmpty(String string) { - return string == null || string.isEmpty(); - } - /** * Process the security constraints. * @@ -602,6 +611,20 @@ private boolean isEmpty(String string) { * @param webXml the web.xml. */ private void processSecurityConstraints(WebApplication webApplication, WebXml webXml) { - // what are we to do here? + SecurityManager securityManager = webApplication.getManager().getSecurityManager(); + for(WebXmlSecurityConstraint constraint : webXml.getSecurityConstraints()) { + SecurityConstraint securityConstraint = new SecurityConstraint(); + securityConstraint.getRoleNames().addAll(constraint.getRoleNames()); + securityConstraint.setTransportGuarantee(constraint.getTransportGuarantee()); + for(WebXmlSecurityConstraint.WebResourceCollection collection : + constraint.getWebResourceCollections()) { + SecurityWebResourceCollection swrc = new SecurityWebResourceCollection(); + swrc.getHttpMethodOmissions().addAll(collection.getHttpMethodOmissions()); + swrc.getHttpMethods().addAll(collection.getHttpMethods()); + swrc.getUrlPatterns().addAll(collection.getUrlPatterns()); + securityConstraint.getSecurityWebResourceCollections().add(swrc); + } + securityManager.getSecurityConstraints().add(securityConstraint); + } } } diff --git a/extension/webxml/src/test/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessorTest.java b/extension/webxml/src/test/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessorTest.java new file mode 100644 index 0000000000..94958d7aa8 --- /dev/null +++ b/extension/webxml/src/test/java/cloud/piranha/extension/webxml/internal/InternalWebXmlProcessorTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002-2024 Manorrock.com. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package cloud.piranha.extension.webxml.internal; + +import cloud.piranha.core.api.SecurityManager; +import cloud.piranha.core.api.WebApplication; +import cloud.piranha.core.impl.DefaultWebApplication; +import cloud.piranha.extension.webxml.WebXml; +import cloud.piranha.extension.webxml.WebXmlSecurityConstraint; +import static org.junit.jupiter.api.Assertions.assertFalse; +import org.junit.jupiter.api.Test; + +/** + * The JUnit tests for the InternalWebXmlProcessor class. + * + * @author Manfred Riem (mriem@manorrock.com) + */ +public class InternalWebXmlProcessorTest { + + /** + * Test process method. + */ + @Test + public void testProcessWithSecurityConstraints() { + WebXml webXml = new WebXml(); + webXml.getSecurityConstraints().add(new WebXmlSecurityConstraint()); + WebApplication webApplication = new DefaultWebApplication(); + InternalWebXmlProcessor processor = new InternalWebXmlProcessor(); + processor.process(webXml, webApplication); + + SecurityManager securityManager = webApplication.getManager().getSecurityManager(); + assertFalse(securityManager.getSecurityConstraints().isEmpty()); + } +} diff --git a/test/coreprofile/pom.xml b/test/coreprofile/pom.xml index a985c1ae3e..83c90273d1 100644 --- a/test/coreprofile/pom.xml +++ b/test/coreprofile/pom.xml @@ -25,8 +25,7 @@ cloud.piranha.dist piranha-dist-coreprofile ${project.version} - provided - pom + test