You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by as...@apache.org on 2020/06/27 19:25:41 UTC

[cxf] 01/01: CXF-8099: mask sensitive logging elements

This is an automated email from the ASF dual-hosted git repository.

ashakirin pushed a commit to branch feature/CXF-8099_mask_sensitive_logging_elements
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 6870b040452032c557ec6a93af717139737801fd
Author: ashakirin <49...@users.noreply.github.com>
AuthorDate: Sat Jun 27 21:25:18 2020 +0200

    CXF-8099: mask sensitive logging elements
---
 rt/features/logging/pom.xml                        |   4 +
 .../ext/logging/AbstractLoggingInterceptor.java    |  16 +-
 .../org/apache/cxf/ext/logging/LoggingFeature.java |  89 ++++++-----
 .../cxf/ext/logging/LoggingInInterceptor.java      |   6 +-
 .../cxf/ext/logging/LoggingOutInterceptor.java     |   6 +-
 .../cxf/ext/logging/MaskSensitiveHelper.java       |  74 ++++++++++
 .../apache/cxf/ext/logging/MaskSensitiveTest.java  | 162 +++++++++++++++++++++
 .../org/apache/cxf/ext/logging/TransformTest.java  |   8 +-
 8 files changed, 323 insertions(+), 42 deletions(-)

diff --git a/rt/features/logging/pom.xml b/rt/features/logging/pom.xml
index b8396a0..aa515f4 100644
--- a/rt/features/logging/pom.xml
+++ b/rt/features/logging/pom.xml
@@ -38,6 +38,10 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>org.slf4j</groupId>
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java
index 9302a43..9a452b8 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/AbstractLoggingInterceptor.java
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.ext.logging;
 
+import java.util.List;
 import java.util.UUID;
 
 import org.apache.cxf.common.util.PropertyUtils;
@@ -34,7 +35,8 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto
     public static final int DEFAULT_LIMIT = 48 * 1024;
     public static final int DEFAULT_THRESHOLD = -1;
     public static final String CONTENT_SUPPRESSED = "--- Content suppressed ---";
-    private static final String  LIVE_LOGGING_PROP = "org.apache.cxf.logging.enable"; 
+    private static final String  LIVE_LOGGING_PROP = "org.apache.cxf.logging.enable";
+
     protected int limit = DEFAULT_LIMIT;
     protected long threshold = DEFAULT_THRESHOLD;
     protected boolean logBinary;
@@ -43,6 +45,8 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto
     protected LogEventSender sender;
     protected final DefaultLogEventMapper eventMapper = new DefaultLogEventMapper();
 
+    private List<String> sensitiveElementNames;
+
     public AbstractLoggingInterceptor(String phase, LogEventSender sender) {
         super(phase);
         this.sender = sender;
@@ -73,6 +77,10 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto
         return threshold;
     }
 
+    public void setSensitiveElementNames(final List<String> sensitiveElementNames) {
+        this.sensitiveElementNames = sensitiveElementNames;
+    }
+
     public void setPrettyLogging(boolean prettyLogging) {
         if (sender instanceof PrettyLoggingFilter) {
             ((PrettyLoggingFilter)this.sender).setPrettyLogging(prettyLogging);
@@ -102,8 +110,12 @@ public abstract class AbstractLoggingInterceptor extends AbstractPhaseIntercepto
         }
     }
 
-    protected String transform(final String originalLogString) {
+    protected String transform(final Message message, final String originalLogString) {
         return originalLogString;
     }
 
+    protected String maskSensitiveElements(final Message message, String originalLogString) {
+        return (new MaskSensitiveHelper(sensitiveElementNames))
+                .maskSensitiveElements(message, originalLogString);
+    }
 }
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java
index 0646ff6..afd905f 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingFeature.java
@@ -18,6 +18,8 @@
  */
 package org.apache.cxf.ext.logging;
 
+import java.util.List;
+
 import org.apache.cxf.Bus;
 import org.apache.cxf.annotations.Provider;
 import org.apache.cxf.annotations.Provider.Type;
@@ -88,18 +90,67 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> {
         delegate.setVerbose(verbose);
     }
 
+    /**
+     * Add additional binary media types to the default values in the LoggingInInterceptor.
+     * Content for these types will not be logged.
+     * For example:
+     * <pre>
+     * &lt;bean id="loggingFeature" class="org.apache.cxf.ext.logging.LoggingFeature"&gt;
+     *   &lt;property name="addInBinaryContentMediaTypes" value="audio/mpeg;application/zip"/&gt;
+     * &lt;/bean&gt;
+     * </pre>
+     * @param mediaTypes list of mediaTypes. symbol ; - delimeter
+     */
     public void addInBinaryContentMediaTypes(String mediaTypes) {
         delegate.addInBinaryContentMediaTypes(mediaTypes);
     }
 
+    /**
+     * Add additional binary media types to the default values in the LoggingOutInterceptor.
+     * Content for these types will not be logged.
+     * For example:
+     * <pre>
+     * &lt;bean id="loggingFeature" class="org.apache.cxf.ext.logging.LoggingFeature"&gt;
+     *   &lt;property name="addOutBinaryContentMediaTypes" value="audio/mpeg;application/zip"/&gt;
+     * &lt;/bean&gt;
+     * </pre>
+     * @param mediaTypes list of mediaTypes. symbol ; - delimeter
+     */
     public void addOutBinaryContentMediaTypes(String mediaTypes) {
         delegate.addOutBinaryContentMediaTypes(mediaTypes);
     }
 
+    /**
+     * Add additional binary media types to the default values for both logging interceptors
+     * Content for these types will not be logged.
+     * For example:
+     * <pre>
+     * &lt;bean id="loggingFeature" class="org.apache.cxf.ext.logging.LoggingFeature"&gt;
+     *   &lt;property name="addBinaryContentMediaTypes" value="audio/mpeg;application/zip"/&gt;
+     * &lt;/bean&gt;
+     * </pre>
+     * @param mediaTypes list of mediaTypes. symbol ; - delimeter
+     */
     public void addBinaryContentMediaTypes(String mediaTypes) {
         delegate.addBinaryContentMediaTypes(mediaTypes);
     }
 
+    /**
+     * Sets list of XML or JSON elements containing sensitive information to be masked.
+     * Corresponded data will be replaced with configured mask
+     * For example:
+     * <pre>
+     * sensitiveElementNames: {password}
+     *
+     * Initial logging statement: <user>my user</user><password>my secret password</password>
+     * Result logging statement: <user>my user</user><password>XXXX</password>
+     * </pre>
+     * @param sensitiveElementNames list of sensitive element names to be replaced
+     */
+    public void setSensitiveElementNames(final List<String> sensitiveElementNames) {
+        delegate.setSensitiveElementNames(sensitiveElementNames);
+    }
+
     public static class Portable implements AbstractPortableFeature {
         private LoggingInInterceptor in;
         private LoggingOutInterceptor out;
@@ -172,50 +223,22 @@ public class LoggingFeature extends DelegatingFeature<LoggingFeature.Portable> {
             setSender(verbose ? new Slf4jVerboseEventSender() : new Slf4jEventSender());
         }
 
-        /**
-         * Add additional binary media types to the default values in the LoggingInInterceptor.
-         * Content for these types will not be logged.
-         * For example:
-         * <pre>
-         * &lt;bean id="loggingFeature" class="org.apache.cxf.ext.logging.LoggingFeature"&gt;
-         *   &lt;property name="addInBinaryContentMediaTypes" value="audio/mpeg;application/zip"/&gt;
-         * &lt;/bean&gt;
-         * </pre>
-         * @param mediaTypes list of mediaTypes. symbol ; - delimeter
-         */
         public void addInBinaryContentMediaTypes(String mediaTypes) {
             in.addBinaryContentMediaTypes(mediaTypes);
         }
 
-        /**
-         * Add additional binary media types to the default values in the LoggingOutInterceptor.
-         * Content for these types will not be logged.
-         * For example:
-         * <pre>
-         * &lt;bean id="loggingFeature" class="org.apache.cxf.ext.logging.LoggingFeature"&gt;
-         *   &lt;property name="addOutBinaryContentMediaTypes" value="audio/mpeg;application/zip"/&gt;
-         * &lt;/bean&gt;
-         * </pre>
-         * @param mediaTypes list of mediaTypes. symbol ; - delimeter
-         */
         public void addOutBinaryContentMediaTypes(String mediaTypes) {
             out.addBinaryContentMediaTypes(mediaTypes);
         }
 
-        /**
-         * Add additional binary media types to the default values for both logging interceptors
-         * Content for these types will not be logged.
-         * For example:
-         * <pre>
-         * &lt;bean id="loggingFeature" class="org.apache.cxf.ext.logging.LoggingFeature"&gt;
-         *   &lt;property name="addBinaryContentMediaTypes" value="audio/mpeg;application/zip"/&gt;
-         * &lt;/bean&gt;
-         * </pre>
-         * @param mediaTypes list of mediaTypes. symbol ; - delimeter
-         */
         public void addBinaryContentMediaTypes(String mediaTypes) {
             addInBinaryContentMediaTypes(mediaTypes);
             addOutBinaryContentMediaTypes(mediaTypes);
         }
+
+        public void setSensitiveElementNames(final List<String> sensitiveElementNames) {
+            in.setSensitiveElementNames(sensitiveElementNames);
+            out.setSensitiveElementNames(sensitiveElementNames);
+        }
     }
 }
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
index db677f0..e703bf7 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
@@ -72,6 +72,8 @@ public class LoggingInInterceptor extends AbstractLoggingInterceptor {
         } else {
             event.setPayload(AbstractLoggingInterceptor.CONTENT_SUPPRESSED);
         }
+        final String maskedContent = maskSensitiveElements(message, event.getPayload());
+        event.setPayload(transform(message, maskedContent));
         sender.send(event);
     }
 
@@ -99,7 +101,7 @@ public class LoggingInInterceptor extends AbstractLoggingInterceptor {
         StringBuilder payload = new StringBuilder();
         cos.writeCacheTo(payload, encoding, limit);
         cos.close();
-        event.setPayload(transform(payload.toString()));
+        event.setPayload(payload.toString());
         boolean isTruncated = cos.size() > limit && limit != -1;
         event.setTruncated(isTruncated);
         event.setFullContentFile(cos.getTempFile());
@@ -110,7 +112,7 @@ public class LoggingInInterceptor extends AbstractLoggingInterceptor {
         StringBuilder payload = new StringBuilder();
         writer.writeCacheTo(payload, limit);
         writer.close();
-        event.setPayload(transform(payload.toString()));
+        event.setPayload(payload.toString());
         event.setTruncated(isTruncated);
         event.setFullContentFile(writer.getTempFile());
     }
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
index 2580649..0d53aa0 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
@@ -146,7 +146,8 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
             }
 
             String payload = shouldLogContent(event) ? getPayload(event, w2) : CONTENT_SUPPRESSED;
-            event.setPayload(transform(payload));
+            final String maskedContent = maskSensitiveElements(message, payload);
+            event.setPayload(transform(message, maskedContent));
             sender.send(event);
             message.setContent(Writer.class, out);
             super.close();
@@ -212,7 +213,8 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
                 String encoding = (String) message.get(Message.ENCODING);
                 StringBuilder payload = new StringBuilder();
                 writePayload(payload, cos, encoding, event.getContentType());
-                event.setPayload(transform(payload.toString()));
+                final String maskedContent = maskSensitiveElements(message, payload.toString());
+                event.setPayload(transform(message, maskedContent));
                 boolean isTruncated = cos.size() > limit && limit != -1;
                 event.setTruncated(isTruncated);
             } catch (Exception ex) {
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java
new file mode 100644
index 0000000..3130680
--- /dev/null
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/MaskSensitiveHelper.java
@@ -0,0 +1,74 @@
+/**
+ * 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.cxf.ext.logging;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.message.Message;
+
+import static org.apache.commons.lang3.ObjectUtils.isEmpty;
+
+public class MaskSensitiveHelper {
+    private static final String ELEMENT_NAME_TEMPLATE = "-ELEMENT_NAME-";
+    private static final String MATCH_PATTERN_XML = "<-ELEMENT_NAME->(.*?)</-ELEMENT_NAME->";
+    private static final String MATCH_PATTERN_JSON = "\"-ELEMENT_NAME-\"[ \\t]*:[ \\t]*\"(.*?)\"";
+    private static final String REPLACEMENT_PATTERN_XML = "<-ELEMENT_NAME->XXX</-ELEMENT_NAME->";
+    private static final String REPLACEMENT_PATTERN_JSON = "\"-ELEMENT_NAME-\": \"XXX\"";
+
+    private static final String XML_CONTENT = "xml";
+    private static final String HTML_CONTENT = "html";
+    private static final String JSON_CONTENT = "json";
+
+    final List<String> sensitiveElementNames;
+
+    public MaskSensitiveHelper(final List<String> sensitiveElementNames) {
+        this.sensitiveElementNames = sensitiveElementNames;
+    }
+
+    public String maskSensitiveElements(
+            final Message message,
+            final String originalLogString) {
+        if (isEmpty(sensitiveElementNames)) {
+            return originalLogString;
+        }
+        String contentType = (String) message.get(Message.CONTENT_TYPE);
+        if (StringUtils.containsIgnoreCase(contentType, XML_CONTENT)
+                || StringUtils.containsIgnoreCase(contentType, HTML_CONTENT)) {
+            return applyExpression(originalLogString, MATCH_PATTERN_XML, REPLACEMENT_PATTERN_XML);
+        } else if (StringUtils.containsIgnoreCase(contentType, JSON_CONTENT)) {
+            return applyExpression(originalLogString, MATCH_PATTERN_JSON, REPLACEMENT_PATTERN_JSON);
+        } else {
+            return originalLogString;
+        }
+    }
+
+    private String applyExpression(
+            final String originalLogString,
+            final String matchPatternTemplate,
+            final String replacementTemplate) {
+        String resultString = originalLogString;
+        for (final String elementName : sensitiveElementNames) {
+            final String matchPattern = matchPatternTemplate.replaceAll(ELEMENT_NAME_TEMPLATE, elementName);
+            final String replacement = replacementTemplate.replaceAll(ELEMENT_NAME_TEMPLATE, elementName);
+            resultString = resultString.replaceAll(matchPattern, replacement);
+        }
+        return resultString;
+    }
+}
diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveTest.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveTest.java
new file mode 100644
index 0000000..997dcb9
--- /dev/null
+++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/MaskSensitiveTest.java
@@ -0,0 +1,162 @@
+/**
+ * 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.cxf.ext.logging;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.cxf.ext.logging.event.LogEvent;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.phase.PhaseInterceptor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(Parameterized.class)
+public class MaskSensitiveTest {
+
+    private static final String SENSITIVE_LOGGING_CONTENT_XML =
+            "<user>testUser</user><password>my secret password</password>";
+    private static final String MASKED_LOGGING_CONTENT_XML =
+            "<user>testUser</user><password>XXX</password>";
+
+    private static final String SENSITIVE_LOGGING_CONTENT_JSON =
+            "\"user\":\"testUser\", \"password\": \"my secret password\"";
+    private static final String MASKED_LOGGING_CONTENT_JSON =
+            "\"user\":\"testUser\", \"password\": \"XXX\"";
+
+    private static final List<String> SENSITIVE_ELEMENTS = Arrays.asList("password");
+    private static final String APPLICATION_XML = "application/xml";
+    private static final String APPLICATION_JSON = "application/json";
+
+    private final String loggingContent;
+    private final String maskedContent;
+    private final String contentType;
+    private LogEventSenderMock logEventSender = new LogEventSenderMock();
+    public MaskSensitiveTest(String loggingContent, String maskedContent, String contentType) {
+        this.loggingContent = loggingContent;
+        this.maskedContent = maskedContent;
+        this.contentType = contentType;
+    }
+
+    @Parameterized.Parameters
+    public static Collection primeNumbers() {
+        return Arrays.asList(new Object[][]{
+            {SENSITIVE_LOGGING_CONTENT_XML, MASKED_LOGGING_CONTENT_XML, APPLICATION_XML},
+            {SENSITIVE_LOGGING_CONTENT_JSON, MASKED_LOGGING_CONTENT_JSON, APPLICATION_JSON}
+        });
+    }
+
+    @Test
+    public void shouldReplaceSensitiveDataIn() throws IOException {
+        // Arrange
+        final LoggingInInterceptor inInterceptor = new LoggingInInterceptor(logEventSender);
+        inInterceptor.setSensitiveElementNames(SENSITIVE_ELEMENTS);
+
+        final Message message = prepareInMessage();
+
+        // Act
+        Collection<PhaseInterceptor<? extends Message>> interceptors = inInterceptor.getAdditionalInterceptors();
+        for (PhaseInterceptor intercept : interceptors) {
+            intercept.handleMessage(message);
+        }
+        inInterceptor.handleMessage(message);
+
+        // Verify
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals(maskedContent, event.getPayload());
+    }
+
+    @Test
+    public void shouldReplaceSensitiveDataOut() throws IOException {
+        // Arrange
+        final LoggingOutInterceptor outInterceptor = new LoggingOutInterceptor(logEventSender);
+        outInterceptor.setSensitiveElementNames(SENSITIVE_ELEMENTS);
+
+        final Message message = prepareOutMessage();
+
+        // Act
+        outInterceptor.handleMessage(message);
+        byte[] payload = loggingContent.getBytes(StandardCharsets.UTF_8);
+        OutputStream out = message.getContent(OutputStream.class);
+        out.write(payload);
+        out.close();
+
+        // Verify
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals(maskedContent, event.getPayload());
+    }
+
+    @Test
+    public void shouldNotReplaceSensitiveDataEmptyExpression() throws IOException {
+        // Arrange
+        final LoggingOutInterceptor outInterceptor = new LoggingOutInterceptor(logEventSender);
+        final Message message = prepareOutMessage();
+
+        // Act
+        outInterceptor.handleMessage(message);
+        byte[] payload = loggingContent.getBytes(StandardCharsets.UTF_8);
+        OutputStream out = message.getContent(OutputStream.class);
+        out.write(payload);
+        out.close();
+
+        // Verify
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals(loggingContent, event.getPayload());
+    }
+
+    private Message prepareInMessage() {
+        Message message = new MessageImpl();
+        ByteArrayInputStream inputStream =
+                new ByteArrayInputStream(loggingContent.getBytes(StandardCharsets.UTF_8));
+        message.put(Message.CONTENT_TYPE, contentType);
+        message.setContent(InputStream.class, inputStream);
+        Exchange exchange = new ExchangeImpl();
+        message.setExchange(exchange);
+        return message;
+    }
+
+    private Message prepareOutMessage() {
+        Message message = new MessageImpl();
+        message.put(Message.CONTENT_TYPE, contentType);
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        message.setContent(OutputStream.class, outputStream);
+        Exchange exchange = new ExchangeImpl();
+        message.setExchange(exchange);
+        return message;
+    }
+
+}
diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TransformTest.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TransformTest.java
index 2adcb10..48d53b0 100644
--- a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TransformTest.java
+++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TransformTest.java
@@ -53,7 +53,8 @@ public class TransformTest {
             super(sender);
         }
 
-        protected String transform(String content) {
+        @Override
+        protected String transform(final Message message, final String content) {
             return content.replace(ORIG_LOGGING_CONTENT, TRANSFORMED_LOGGING_CONTENT);
         }
     }
@@ -63,7 +64,8 @@ public class TransformTest {
             super(sender);
         }
 
-        protected String transform(String content) {
+        @Override
+        protected String transform(final Message message, final String content) {
             return content.replace(ORIG_LOGGING_CONTENT, TRANSFORMED_LOGGING_CONTENT);
         }
     }
@@ -89,7 +91,7 @@ public class TransformTest {
         // Verify
         LogEvent event = logEventSender.getLogEvent();
         assertNotNull(event);
-        assertEquals(TRANSFORMED_LOGGING_CONTENT, event.getPayload()); // only the first byte is read!
+        assertEquals(TRANSFORMED_LOGGING_CONTENT, event.getPayload());
     }
 
     @Test