diff --git a/core/src/main/java/org/apache/cxf/ws/addressing/AddressingConstants.java b/core/src/main/java/org/apache/cxf/ws/addressing/AddressingConstants.java index 12313374908..f2b50c4c470 100644 --- a/core/src/main/java/org/apache/cxf/ws/addressing/AddressingConstants.java +++ b/core/src/main/java/org/apache/cxf/ws/addressing/AddressingConstants.java @@ -30,7 +30,7 @@ * Encapsulation of version-specific WS-Addressing constants. */ public class AddressingConstants { - private static final ResourceBundle BUNDLE = + static final ResourceBundle BUNDLE = BundleUtils.getBundle(AddressingConstants.class); diff --git a/core/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java b/core/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java index 9648bcfb8c8..aa53aee113f 100644 --- a/core/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java +++ b/core/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; +import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; @@ -330,7 +331,7 @@ public static RelatesToType getRelatesTo(String uri) { relatesTo.setValue(uri); return relatesTo; } - + private static boolean startsWith(String value, String ref) { if (StringUtils.isEmpty(value)) { return false; @@ -637,6 +638,106 @@ public static boolean isDecoupledDestinationAllowed(String uri) { return isDecoupledDestinationSchemeAllowed(uri); } + /** + * Log a message after {@link #isDecoupledDestinationAllowed(String)} returned {@code false}. + * + * @param logger the {@link Logger} to pass the message to + * @param level log {@link Level} on which the message should be logged + * @param destinationUri the URI banned due to the configuration + */ + public static void logDisallowedDecoupledDestinationScheme(Logger logger, Level level, String destinationUri) { + logger.logrb(level, + AddressingConstants.BUNDLE, + "DISALLOWED_DECOUPLED_DESTINATION_SCHEME", + new Object[] { + destinationUri, + ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY + }); + } + + /** + * Log a message after {@link #isDecoupledDestinationAllowed(String)} returned {@code false} + * for messages having {@value #DECOUPLED_DESTINATION_APPROVED_PROPERTY} set to {@code true}. + * + * @param logger the {@link Logger} to pass the message to + * @param level log {@link Level} on which the message should be logged + * @param destinationUri the URI banned due to the configuration + */ + public static void logRejectedDecoupledDestination(Logger logger, Level level, String destinationUri) { + logger.logrb(level, + AddressingConstants.BUNDLE, + "REJECTED_DECOUPLED_DESTINATION", + new Object[] { + destinationUri, + WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY, + ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY + }); + } + + /** + * Log a message after {@link #isDecoupledDestinationSchemeAllowed(String)} returned {@code false} + * for messages having {@value #DECOUPLED_DESTINATION_APPROVED_PROPERTY} set to {@code true}. + * + * @param logger the {@link Logger} to pass the message to + * @param level log {@link Level} on which the message should be logged + * @param destinationUri the URI banned due to the configuration + */ + public static void logDecoupledFaultToSchemeNotAllowed(Logger logger, Level level, String destinationUri) { + logger.logrb(level, + AddressingConstants.BUNDLE, + "DECOUPLED_FAULT_TO_SCHEME_NOT_ALLOWED", + new Object[] { + destinationUri, + ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY + }); + } + + /** + * Log a message after {@link #isDecoupledDestinationAllowed(String)} returned {@code false} + * for {@code FaultTo} URI. + * + * @param logger the {@link Logger} to pass the message to + * @param level log {@link Level} on which the message should be logged + * @param destinationUri the URI banned due to the configuration + */ + public static void logDecoupledFaultToNotAllowed(Logger logger, Level level, String destinationUri) { + logger.logrb(level, + AddressingConstants.BUNDLE, + "DECOUPLED_FAULT_TO_NOT_ALLOWED", + new Object[] { + destinationUri, + WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY, + ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY + }); + } + + /** + * Create a SOAP Fault reason after {@link #isDecoupledDestinationAllowed(String)} returned {@code false}. + * + * @param destinationUri the URI banned due to the configuration + * @return a formatted message + */ + public static String formatDecoupledReplyToNotPermittedMessage(String destinationUri) { + return MessageFormat.format( + AddressingConstants.BUNDLE.getString("DECOUPLED_REPLY_TO_NOT_PERMITTED"), + destinationUri, + WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY, + ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY); + } + + /** + * Create a SOAP Fault reason after {@link #isDecoupledDestinationSchemeAllowed(String)} returned {@code false}. + * + * @param destinationUri the URI banned due to the configuration + * @return a formatted message + */ + public static String formatDecoupledReplyToSchemeNotPermittedMessage(String destinationUri) { + return MessageFormat.format( + AddressingConstants.BUNDLE.getString("DECOUPLED_REPLY_TO_SCHEME_NOT_PERMITTED"), + destinationUri, + ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY); + } + /** * Validates the URI scheme for {@link #isDecoupledDestinationAllowed}. */ @@ -697,23 +798,11 @@ public Conduit getBackChannel(Message inMessage) throws IOException { // Higher-level protocol (e.g. WS-RM) pre-approved decoupled addressing // for this exchange; still enforce the scheme allowlist. if (!isDecoupledDestinationSchemeAllowed(destinationUri)) { - LOG.log(Level.WARNING, - "Rejected pre-approved decoupled destination with disallowed scheme: {0}. " - + "Configure permitted URI schemes with system property {1}", - new Object[] {destinationUri, ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY}); + logDisallowedDecoupledDestinationScheme(LOG, Level.WARNING, destinationUri); return null; } } else if (!isDecoupledDestinationAllowed(destinationUri)) { - LOG.log(Level.WARNING, - "Rejected wsa:ReplyTo/FaultTo decoupled destination: {0}. " - + "Decoupled WS-Addressing is disabled by default; " - + "enable with system property {1}=true, " - + "or configure permitted URI schemes with {2}", - new Object[] { - destinationUri, - WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY, - ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY - }); + logRejectedDecoupledDestination(LOG, Level.WARNING, destinationUri); return null; } Bus bus = inMessage.getExchange().getBus(); diff --git a/core/src/main/java/org/apache/cxf/ws/addressing/Messages.properties b/core/src/main/java/org/apache/cxf/ws/addressing/Messages.properties index 1cd0213d926..872862f6bf2 100644 --- a/core/src/main/java/org/apache/cxf/ws/addressing/Messages.properties +++ b/core/src/main/java/org/apache/cxf/ws/addressing/Messages.properties @@ -18,7 +18,7 @@ # under the License. # # -BUILDER_CLASS_NOT_FOUND_MSG = WS-Addressing builder class {0} not found +BUILDER_CLASS_NOT_FOUND_MSG = WS-Addressing builder class {0} not found BUILDER_INSTANTIATION_FAILED_MSG = WS-Addressing builder {0} could not be instantiated: MAPS_RETRIEVAL_FAILURE_MSG = WS-Addressing - failed to retrieve Message Addressing Properties from context ACTION_NOT_SUPPORTED_MSG = Action {0} not supported @@ -29,4 +29,19 @@ MAP_REQUIRED_MSG = Message Addressing Property {0} required DUPLICATE_MESSAGE_ID_MSG = Duplicate Message ID {0} INVALID_ADDRESSING_PROPERTY_MESSAGE = A header representing a Message Addressing Property is not valid and the message cannot be processed MISSING_ACTION_MESSAGE = A required header representing a Message Addressing Property is not present -REPLYTO_NOT_SUPPORTED_MSG = ReplyTo {0} is not supported for request-response MEP \ No newline at end of file +REPLYTO_NOT_SUPPORTED_MSG = ReplyTo {0} is not supported for request-response MEP +DISALLOWED_DECOUPLED_DESTINATION_SCHEME = Rejected pre-approved decoupled destination with disallowed scheme: {0}. \ + Configure permitted URI schemes with system property {1} +REJECTED_DECOUPLED_DESTINATION = Rejected wsa:ReplyTo/FaultTo decoupled destination: {0}. \ + Decoupled WS-Addressing is disabled by default; enable with system property {1}=true, \ + or configure permitted URI schemes with {2} +DECOUPLED_REPLY_TO_NOT_PERMITTED = Decoupled WS-Addressing ReplyTo ({0}) is not permitted by this server. Enable with system property {1}=true, \ + or configure permitted URI schemes with {2} +DECOUPLED_REPLY_TO_SCHEME_NOT_PERMITTED = Decoupled WS-Addressing ReplyTo ({0}) is not permitted by this server: URI scheme is not allowed. \ + Configure permitted schemes with system property {1} +DECOUPLED_FAULT_TO_SCHEME_NOT_ALLOWED = Decoupled pre-approved FaultTo ({0}) is not permitted: URI scheme is not allowed. \ + Fault will be delivered to ReplyTo instead. Configure permitted schemes with {1} +DECOUPLED_FAULT_TO_NOT_ALLOWED = Fault will be delivered to ReplyTo instead. Configure permitted schemes with {1} \ + Decoupled WS-Addressing FaultTo ({0}) is not permitted; \ + fault will be delivered to ReplyTo instead. \ + Enable with system property {1}=true, or configure permitted URI schemes with {2} diff --git a/core/src/test/java/org/apache/cxf/ws/addressing/ContextUtilsTest.java b/core/src/test/java/org/apache/cxf/ws/addressing/ContextUtilsTest.java index f3bf48c4877..6e78244cef3 100644 --- a/core/src/test/java/org/apache/cxf/ws/addressing/ContextUtilsTest.java +++ b/core/src/test/java/org/apache/cxf/ws/addressing/ContextUtilsTest.java @@ -19,7 +19,14 @@ package org.apache.cxf.ws.addressing; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; import java.util.Random; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.logging.StreamHandler; import org.apache.cxf.message.ExchangeImpl; import org.apache.cxf.message.Message; @@ -213,4 +220,78 @@ public void testHasEmptyAddress() { assertThat(hasEmptyAction(maps), is(false)); assertThat(maps.getAction(), notNullValue()); } + + @Test + public void formatMessages() { + assertThat( + ContextUtils.formatDecoupledReplyToNotPermittedMessage("http://localhost:1234/decoupled"), + is("Decoupled WS-Addressing ReplyTo (http://localhost:1234/decoupled) is not permitted by this server." + + " Enable with system property org.apache.cxf.ws.addressing.decoupled.enabled=true," + + " or configure permitted URI schemes with" + + " org.apache.cxf.ws.addressing.decoupled.allowedSchemes")); + assertThat( + ContextUtils.formatDecoupledReplyToSchemeNotPermittedMessage("http://localhost:1234/decoupled"), + is("Decoupled WS-Addressing ReplyTo (http://localhost:1234/decoupled) is not permitted by this server:" + + " URI scheme is not allowed." + + " Configure permitted schemes with system property" + + " org.apache.cxf.ws.addressing.decoupled.allowedSchemes")); + } + + @Test + public void logMessages() { + assertLogMessage(log -> ContextUtils.logDisallowedDecoupledDestinationScheme( + log, + Level.WARNING, + "http://localhost:1234/decoupled"), + "Rejected pre-approved decoupled destination with disallowed scheme: http://localhost:1234/decoupled." + + " Configure permitted URI schemes with system property " + + ContextUtils.ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY); + assertLogMessage( + log -> ContextUtils.logRejectedDecoupledDestination( + log, + Level.WARNING, + "http://localhost:1234/decoupled"), + "Rejected wsa:ReplyTo/FaultTo decoupled destination: http://localhost:1234/decoupled." + + " Decoupled WS-Addressing is disabled by default;" + + " enable with system property org.apache.cxf.ws.addressing.decoupled.enabled=true," + + " or configure permitted URI schemes with" + + " org.apache.cxf.ws.addressing.decoupled.allowedSchemes"); + assertLogMessage( + log -> ContextUtils.logDecoupledFaultToSchemeNotAllowed( + log, + Level.WARNING, + "http://localhost:1234/decoupled"), + "Decoupled pre-approved FaultTo (http://localhost:1234/decoupled) is not permitted:" + + " URI scheme is not allowed. Fault will be delivered to ReplyTo instead." + + " Configure permitted schemes with org.apache.cxf.ws.addressing.decoupled.allowedSchemes"); + assertLogMessage( + log -> ContextUtils.logDecoupledFaultToNotAllowed( + log, + Level.WARNING, + "http://localhost:1234/decoupled"), + "Fault will be delivered to ReplyTo instead. Configure permitted schemes with" + + " org.apache.cxf.ws.addressing.decoupled.enabled Decoupled WS-Addressing FaultTo" + + " (http://localhost:1234/decoupled) is not permitted; fault will be delivered to ReplyTo" + + " instead. Enable with system property org.apache.cxf.ws.addressing.decoupled.enabled=true," + + " or configure permitted URI schemes with" + + " org.apache.cxf.ws.addressing.decoupled.allowedSchemes"); + } + + static void assertLogMessage(Consumer logMethod, String expected) { + Logger log = Logger.getLogger("test" + logMethod.toString()); + log.setLevel(Level.FINEST); + log.setUseParentHandlers(false); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + StreamHandler handler = new StreamHandler(out, new SimpleFormatter()); + handler.setLevel(Level.FINEST); + log.addHandler(handler); + logMethod.accept(log); + handler.flush(); + String logOutput = out.toString(StandardCharsets.UTF_8); + assertThat( + logOutput, + org.hamcrest.Matchers.containsString("WARNING: " + expected)); + log.removeHandler(handler); + } + } diff --git a/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/InternalContextUtils.java b/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/InternalContextUtils.java index 5b74976b914..704bb0c58ea 100644 --- a/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/InternalContextUtils.java +++ b/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/InternalContextUtils.java @@ -99,23 +99,11 @@ public Conduit getBackChannel(Message inMessage) throws IOException { inMessage.getExchange().get(ContextUtils.DECOUPLED_DESTINATION_APPROVED_PROPERTY)); if (approved) { if (!ContextUtils.isDecoupledDestinationSchemeAllowed(destinationUri)) { - LOG.log(Level.WARNING, - "Rejected pre-approved decoupled destination with disallowed scheme: {0}. " - + "Configure permitted URI schemes with system property {1}", - new Object[] {destinationUri, ContextUtils.ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY}); + ContextUtils.logDisallowedDecoupledDestinationScheme(LOG, Level.WARNING, destinationUri); return null; } } else if (!ContextUtils.isDecoupledDestinationAllowed(destinationUri)) { - LOG.log(Level.WARNING, - "Rejected wsa:ReplyTo/FaultTo decoupled destination: {0}. " - + "Decoupled WS-Addressing is disabled by default; " - + "enable with system property {1}=true, " - + "and/or configure permitted URI schemes with {2}", - new Object[] { - destinationUri, - ContextUtils.WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY, - ContextUtils.ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY - }); + ContextUtils.logRejectedDecoupledDestination(LOG, Level.WARNING, destinationUri); return null; } Bus bus = inMessage.getExchange().getBus(); diff --git a/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/MAPAggregatorImpl.java b/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/MAPAggregatorImpl.java index 321b78d7945..e3aff4e603d 100644 --- a/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/MAPAggregatorImpl.java +++ b/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/impl/MAPAggregatorImpl.java @@ -1235,10 +1235,7 @@ private void assertDecoupledReplyToAllowed(Message message, AddressingProperties if (ContextUtils.isDecoupledDestinationSchemeAllowed(uri)) { return; } - final String reason = "Decoupled WS-Addressing ReplyTo (" + uri - + ") is not permitted by this server: URI scheme is not allowed. " - + "Configure permitted schemes with system property " - + ContextUtils.ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY; + final String reason = ContextUtils.formatDecoupledReplyToSchemeNotPermittedMessage(uri); if (isSOAP12(message)) { SoapFault f = new SoapFault(reason, Soap12.getInstance().getSender()); f.setSubCode(Names.DESTINATION_UNREACHABLE_QNAME); @@ -1250,9 +1247,7 @@ private void assertDecoupledReplyToAllowed(Message message, AddressingProperties if (ContextUtils.isDecoupledDestinationAllowed(uri)) { return; } - final String reason = "Decoupled WS-Addressing ReplyTo (" + uri - + ") is not permitted by this server. Enable with system property " - + ContextUtils.WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY + "=true"; + final String reason = ContextUtils.formatDecoupledReplyToNotPermittedMessage(uri); if (isSOAP12(message)) { SoapFault f = new SoapFault(reason, Soap12.getInstance().getSender()); f.setSubCode(Names.DESTINATION_UNREACHABLE_QNAME); @@ -1284,22 +1279,14 @@ private void rebaseOrFallbackFaultTo(Message message, m.getExchange().setDestination(destination); return; } - LOG.log(Level.WARNING, - "Decoupled pre-approved FaultTo ({0}) is not permitted: URI scheme is not allowed. " - + "Fault will be delivered to ReplyTo instead. Configure permitted schemes with {1}", - new Object[]{faultToUri, ContextUtils.ALLOWED_DECOUPLED_DEST_SCHEMES_PROPERTY}); + ContextUtils.logDecoupledFaultToSchemeNotAllowed(LOG, Level.WARNING, faultToUri); if (inMAPs.getReplyTo() != null) { maps.setTo(inMAPs.getReplyTo()); } return; } if (!ContextUtils.isDecoupledDestinationAllowed(faultToUri)) { - LOG.log(Level.WARNING, - "Decoupled WS-Addressing FaultTo ({0}) is not permitted; " - + "fault will be delivered to ReplyTo instead. " - + "Enable with system property {1}=true", - new Object[]{faultToUri, - ContextUtils.WS_ADDRESSING_DECOUPLED_ENABLED_PROPERTY}); + ContextUtils.logDecoupledFaultToNotAllowed(LOG, Level.WARNING, faultToUri); if (inMAPs.getReplyTo() != null) { maps.setTo(inMAPs.getReplyTo()); }