This is an automated email from the ASF dual-hosted git repository. rzo1 pushed a commit to branch tomee-10.x in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 8837cb67151542a9bc7cac8488e581621f2d6a04 Author: Richard Zowalla <[email protected]> AuthorDate: Wed Oct 7 17:33:21 2026 +0200 protect all http methods on jax-ws endpoint security constraint (#3061) The generated constraint only covered GET and POST. Cover every method and deny uncovered methods on contexts TomEE creates for the endpoint. (cherry picked from commit ed25e7c03a6c7b7ac5d51b12dee572b73b7ef614) --- .../apache/tomee/webservices/TomcatWsRegistry.java | 44 +++++++++++------- .../tomee/webservices/TomcatWsRegistryTest.java | 53 ++++++++++++++++++++++ 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java b/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java index a4212c0338..523733b010 100644 --- a/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java +++ b/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java @@ -286,23 +286,7 @@ public class TomcatWsRegistry implements WsRegistry { context.setLoginConfig(loginConfig); //Setup a default Security Constraint - final String securityRole = SystemInstance.get().getProperty(TOMEE_JAXWS_SECURITY_ROLE_PREFIX + name, "default"); - for (final String role : securityRole.split(",")) { - final SecurityCollection collection = new SecurityCollection(); - collection.addMethod("GET"); - collection.addMethod("POST"); - collection.addPattern("/*"); - collection.setName(role); - - final SecurityConstraint sc = new SecurityConstraint(); - sc.addAuthRole("*"); - sc.addCollection(collection); - sc.setAuthConstraint(true); - sc.setUserConstraint(transportGuarantee); - - context.addConstraint(sc); - context.addSecurityRole(role); - } + addSecurityConstraints(context, name, transportGuarantee); //Set the proper authenticator if ("BASIC".equals(authMethod)) { @@ -324,6 +308,32 @@ public class TomcatWsRegistry implements WsRegistry { return context; } + /** + * Protects the whole endpoint context (TomEE owned, never a user webapp) for every HTTP method. + * No method is added to the collection on purpose: a collection without methods covers all verbs, + * whereas enumerating some (e.g. GET/POST) would leave the others (PUT, DELETE, ...) unauthenticated. + */ + static void addSecurityConstraints(final Context context, final String name, final String transportGuarantee) { + final String securityRole = SystemInstance.get().getProperty(TOMEE_JAXWS_SECURITY_ROLE_PREFIX + name, "default"); + for (final String role : securityRole.split(",")) { + final SecurityCollection collection = new SecurityCollection(); + collection.addPattern("/*"); + collection.setName(role); + + final SecurityConstraint sc = new SecurityConstraint(); + sc.addAuthRole("*"); + sc.addCollection(collection); + sc.setAuthConstraint(true); + sc.setUserConstraint(transportGuarantee); + + context.addConstraint(sc); + context.addSecurityRole(role); + } + + // reject any method a constraint would not cover + context.setDenyUncoveredHttpMethods(true); + } + private void addServlet(final Container host, final Context context, final String mapping, final HttpListener httpListener, final String path, final List<String> addresses, final boolean fakeDeployment, final String moduleId) { // build the servlet diff --git a/tomee/tomee-webservices/src/test/java/org/apache/tomee/webservices/TomcatWsRegistryTest.java b/tomee/tomee-webservices/src/test/java/org/apache/tomee/webservices/TomcatWsRegistryTest.java new file mode 100644 index 0000000000..678be4ddda --- /dev/null +++ b/tomee/tomee-webservices/src/test/java/org/apache/tomee/webservices/TomcatWsRegistryTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomee.webservices; + +import org.apache.catalina.core.StandardContext; +import org.apache.tomcat.util.descriptor.web.SecurityCollection; +import org.apache.tomcat.util.descriptor.web.SecurityConstraint; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TomcatWsRegistryTest { + + @Test + public void securityConstraintCoversAllHttpMethods() { + final StandardContext context = new StandardContext(); + + TomcatWsRegistry.addSecurityConstraints(context, "ws-test", "CONFIDENTIAL"); + + final SecurityConstraint[] constraints = context.findConstraints(); + assertEquals(1, constraints.length); + final SecurityConstraint constraint = constraints[0]; + assertTrue(constraint.getAuthConstraint()); + assertEquals("CONFIDENTIAL", constraint.getUserConstraint()); + + final SecurityCollection[] collections = constraint.findCollections(); + assertEquals(1, collections.length); + final SecurityCollection collection = collections[0]; + assertTrue(collection.findPattern("/*")); + assertEquals(0, collection.findMethods().length); + assertEquals(0, collection.findOmittedMethods().length); + for (final String method : new String[]{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD", "TRACE", "FOO"}) { + assertTrue(method + " must be covered", collection.findMethod(method)); + } + + assertTrue(context.getDenyUncoveredHttpMethods()); + } +}
