From 074987ed5926668338b06f81f28e286dbf9f87f9 Mon Sep 17 00:00:00 2001 From: Dominic Wenig Date: Thu, 24 Apr 2025 17:14:54 +0200 Subject: [PATCH 1/2] added feature for verbose logging without password --- src/hivemq-extension/conf/examples/config.xml | 1 + .../log/FullConfigNoPasswordInVerboseIT.java | 168 ++++++++++++++++++ .../FullConfigXmlNoPasswordInVerboseIT.java | 168 ++++++++++++++++++ .../resources/fullConfig.properties | 1 + src/integrationTest/resources/fullConfig.xml | 1 + .../fullConfigNoPasswordInVerbose.properties | 37 ++++ .../fullConfigNoPasswordInVerbose.xml | 43 +++++ .../resources/fullConfigNoPayload.properties | 1 + .../resources/fullConfigNoPayload.xml | 1 + .../fullConfigNoPayloadNoVerbose.properties | 1 + .../fullConfigNoPayloadNoVerbose.xml | 1 + .../resources/fullConfigNoVerbose.properties | 1 + .../resources/fullConfigNoVerbose.xml | 1 + .../mqtt/message/config/ExtensionConfig.java | 2 + .../config/ExtensionConfigProperties.java | 5 + .../message/config/ExtensionConfigReader.java | 4 + .../message/config/ExtensionConfigXml.java | 9 + .../initializer/ClientInitializerImpl.java | 3 +- .../initializer/ClientInitializerImpl4_2.java | 9 +- .../ConnectDisconnectEventListener.java | 7 +- .../ConnectInboundInterceptorImpl.java | 6 +- .../log/mqtt/message/util/MessageLogUtil.java | 81 ++++++--- src/main/resources/config.xsd | 1 + .../config/ExtensionConfigReaderTest.java | 7 +- .../mqtt/message/util/MessageLogUtilTest.java | 54 +++++- 25 files changed, 573 insertions(+), 40 deletions(-) create mode 100644 src/integrationTest/java/com/hivemq/extensions/log/FullConfigNoPasswordInVerboseIT.java create mode 100644 src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlNoPasswordInVerboseIT.java create mode 100644 src/integrationTest/resources/fullConfigNoPasswordInVerbose.properties create mode 100644 src/integrationTest/resources/fullConfigNoPasswordInVerbose.xml diff --git a/src/hivemq-extension/conf/examples/config.xml b/src/hivemq-extension/conf/examples/config.xml index 7c73a7e..9d7542d 100644 --- a/src/hivemq-extension/conf/examples/config.xml +++ b/src/hivemq-extension/conf/examples/config.xml @@ -9,6 +9,7 @@ false true + true false diff --git a/src/integrationTest/java/com/hivemq/extensions/log/FullConfigNoPasswordInVerboseIT.java b/src/integrationTest/java/com/hivemq/extensions/log/FullConfigNoPasswordInVerboseIT.java new file mode 100644 index 0000000..30170e0 --- /dev/null +++ b/src/integrationTest/java/com/hivemq/extensions/log/FullConfigNoPasswordInVerboseIT.java @@ -0,0 +1,168 @@ +/* + * Copyright 2019-present HiveMQ GmbH + * + * Licensed 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 com.hivemq.extensions.log; + +import com.hivemq.client.mqtt.datatypes.MqttQos; +import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient; +import com.hivemq.client.mqtt.mqtt5.Mqtt5Client; +import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator; +import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.testcontainers.hivemq.HiveMQContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.MountableFile; + +import java.nio.charset.StandardCharsets; + +import static org.awaitility.Awaitility.await; + +/** + * @since 1.1.3 + */ +@Testcontainers +public class FullConfigNoPasswordInVerboseIT { + + @Container + final @NotNull HiveMQContainer hivemq = + new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension") + .asCompatibleSubstituteFor("hivemq/hivemq4")) // + .withCopyToContainer(MountableFile.forClasspathResource("fullConfigNoPasswordInVerbose.properties"), + "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/mqttMessageLog.properties") + .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String())); + + @Test + void test() { + final Mqtt5BlockingClient client = Mqtt5Client.builder() + .identifier("test-client") + .serverHost(hivemq.getHost()) + .serverPort(hivemq.getMqttPort()) + .buildBlocking(); + + client.connectWith() + .willPublish() + .topic("will") + .qos(MqttQos.EXACTLY_ONCE) + .payload("willPayload".getBytes(StandardCharsets.UTF_8)) + .contentType("text/plain") + .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8)) + .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8) + .responseTopic("willResponse") + .retain(false) + .messageExpiryInterval(10_000) + .userProperties() + .add("willProperty", "willValue") + .applyUserProperties() + .delayInterval(50_000) + .applyWillPublish() + .send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0', Keep Alive: '60', Maximum Packet Size: '268435460', Receive Maximum: '65535', Topic Alias Maximum: '0', Request Problem Information: 'true', Request Response Information: 'false', Username: 'null', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null', Will: { Topic: 'will', Payload: 'willPayload', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'willResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'willProperty', Value: 'willValue'], Will Delay: '50000' }")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false', Session Expiry Interval: 'null', Assigned ClientId 'null', Maximum QoS: 'EXACTLY_ONCE', Maximum Packet Size: '268435460', Receive Maximum: '10', Topic Alias Maximum: '5', Reason String: 'null', Response Information: 'null', Server Keep Alive: 'null', Server Reference: 'null', Shared Subscription Available: 'true', Wildcards Available: 'true', Retain Available: 'true', Subscription Identifiers Available: 'true', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null'")); + + client.subscribeWith().topicFilter("#").send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2', Retain As Published: 'false', No Local: 'false', Retain Handling: 'SEND'] }, Subscription Identifier: '1', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }, Reason String: 'null', User Properties: 'null'")); + + client.publishWith() + .topic("publish") + .qos(MqttQos.EXACTLY_ONCE) + .payload("payload1".getBytes(StandardCharsets.UTF_8)) + .contentType("text/plain") + .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8)) + .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8) + .responseTopic("publishResponse") + .retain(false) + .messageExpiryInterval(10_000) + .userProperties() + .add("publishProperty", "publishValue") + .applyUserProperties() + .send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBREL from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBREC from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + + client.publishWith() + .topic("publish") + .qos(MqttQos.AT_LEAST_ONCE) + .payload("payload2".getBytes(StandardCharsets.UTF_8)) + .contentType("text/plain") + .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8)) + .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8) + .responseTopic("publishResponse") + .retain(false) + .messageExpiryInterval(10_000) + .userProperties() + .add("publishProperty", "publishValue") + .applyUserProperties() + .send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBACK from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + + client.unsubscribeWith().topicFilter("#").send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }, User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }, Reason String: 'null', User Properties: 'null'")); + + client.disconnect(); + await().until(() -> hivemq.getLogs() + .contains( + "Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION', Reason String: 'null', Server Reference: 'null', Session Expiry: 'null', User Properties: 'null'")); + } +} diff --git a/src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlNoPasswordInVerboseIT.java b/src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlNoPasswordInVerboseIT.java new file mode 100644 index 0000000..537617b --- /dev/null +++ b/src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlNoPasswordInVerboseIT.java @@ -0,0 +1,168 @@ +/* + * Copyright 2019-present HiveMQ GmbH + * + * Licensed 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 com.hivemq.extensions.log; + +import com.hivemq.client.mqtt.datatypes.MqttQos; +import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient; +import com.hivemq.client.mqtt.mqtt5.Mqtt5Client; +import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator; +import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.testcontainers.hivemq.HiveMQContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.MountableFile; + +import java.nio.charset.StandardCharsets; + +import static org.awaitility.Awaitility.await; + +/** + * @since 1.2.0 + */ +@Testcontainers +public class FullConfigXmlNoPasswordInVerboseIT { + + @Container + final @NotNull HiveMQContainer hivemq = + new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension") + .asCompatibleSubstituteFor("hivemq/hivemq4")) // + .withCopyToContainer(MountableFile.forClasspathResource("fullConfigNoPasswordInVerbose.xml"), + "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/conf/config.xml") + .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String())); + + @Test + void test() { + final Mqtt5BlockingClient client = Mqtt5Client.builder() + .identifier("test-client") + .serverHost(hivemq.getHost()) + .serverPort(hivemq.getMqttPort()) + .buildBlocking(); + + client.connectWith() + .willPublish() + .topic("will") + .qos(MqttQos.EXACTLY_ONCE) + .payload("willPayload".getBytes(StandardCharsets.UTF_8)) + .contentType("text/plain") + .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8)) + .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8) + .responseTopic("willResponse") + .retain(false) + .messageExpiryInterval(10_000) + .userProperties() + .add("willProperty", "willValue") + .applyUserProperties() + .delayInterval(50_000) + .applyWillPublish() + .send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0', Keep Alive: '60', Maximum Packet Size: '268435460', Receive Maximum: '65535', Topic Alias Maximum: '0', Request Problem Information: 'true', Request Response Information: 'false', Username: 'null', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null', Will: { Topic: 'will', Payload: 'willPayload', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'willResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'willProperty', Value: 'willValue'], Will Delay: '50000' }")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false', Session Expiry Interval: 'null', Assigned ClientId 'null', Maximum QoS: 'EXACTLY_ONCE', Maximum Packet Size: '268435460', Receive Maximum: '10', Topic Alias Maximum: '5', Reason String: 'null', Response Information: 'null', Server Keep Alive: 'null', Server Reference: 'null', Shared Subscription Available: 'true', Wildcards Available: 'true', Retain Available: 'true', Subscription Identifiers Available: 'true', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null'")); + + client.subscribeWith().topicFilter("#").send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2', Retain As Published: 'false', No Local: 'false', Retain Handling: 'SEND'] }, Subscription Identifier: '1', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }, Reason String: 'null', User Properties: 'null'")); + + client.publishWith() + .topic("publish") + .qos(MqttQos.EXACTLY_ONCE) + .payload("payload1".getBytes(StandardCharsets.UTF_8)) + .contentType("text/plain") + .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8)) + .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8) + .responseTopic("publishResponse") + .retain(false) + .messageExpiryInterval(10_000) + .userProperties() + .add("publishProperty", "publishValue") + .applyUserProperties() + .send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBREL from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBREC from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + + client.publishWith() + .topic("publish") + .qos(MqttQos.AT_LEAST_ONCE) + .payload("payload2".getBytes(StandardCharsets.UTF_8)) + .contentType("text/plain") + .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8)) + .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8) + .responseTopic("publishResponse") + .retain(false) + .messageExpiryInterval(10_000) + .userProperties() + .add("publishProperty", "publishValue") + .applyUserProperties() + .send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']")); + await().until(() -> hivemq.getLogs() + .contains( + "Received PUBACK from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'")); + + client.unsubscribeWith().topicFilter("#").send(); + await().until(() -> hivemq.getLogs() + .contains( + "Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }, User Properties: 'null'")); + await().until(() -> hivemq.getLogs() + .contains( + "Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }, Reason String: 'null', User Properties: 'null'")); + + client.disconnect(); + await().until(() -> hivemq.getLogs() + .contains( + "Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION', Reason String: 'null', Server Reference: 'null', Session Expiry: 'null', User Properties: 'null'")); + } +} diff --git a/src/integrationTest/resources/fullConfig.properties b/src/integrationTest/resources/fullConfig.properties index 4b865b5..ab3fa9f 100644 --- a/src/integrationTest/resources/fullConfig.properties +++ b/src/integrationTest/resources/fullConfig.properties @@ -15,6 +15,7 @@ # verbose=true payload=true +passwordinverbose=true publish-received=true publish-send=true client-connect=true diff --git a/src/integrationTest/resources/fullConfig.xml b/src/integrationTest/resources/fullConfig.xml index 3e6fb45..26a7ac7 100644 --- a/src/integrationTest/resources/fullConfig.xml +++ b/src/integrationTest/resources/fullConfig.xml @@ -20,6 +20,7 @@ xsi:noNamespaceSchemaLocation="../../main/resources/config.xsd"> true true + true true true true diff --git a/src/integrationTest/resources/fullConfigNoPasswordInVerbose.properties b/src/integrationTest/resources/fullConfigNoPasswordInVerbose.properties new file mode 100644 index 0000000..56f07b2 --- /dev/null +++ b/src/integrationTest/resources/fullConfigNoPasswordInVerbose.properties @@ -0,0 +1,37 @@ +# +# Copyright 2019-present HiveMQ GmbH +# +# Licensed 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. +# +verbose=true +payload=true +passwordinverbose=false +publish-received=true +publish-send=true +client-connect=true +connack-send=true +client-disconnect=true +subscribe-received=true +suback-send=true +unsubscribe-received=true +unsuback-send=true +ping-request-received=true +ping-response-send=true +puback-received=true +puback-send=true +pubrec-received=true +pubrec-send=true +pubrel-received=true +pubrel-send=true +pubcomp-received=true +pubcomp-send=true diff --git a/src/integrationTest/resources/fullConfigNoPasswordInVerbose.xml b/src/integrationTest/resources/fullConfigNoPasswordInVerbose.xml new file mode 100644 index 0000000..db54891 --- /dev/null +++ b/src/integrationTest/resources/fullConfigNoPasswordInVerbose.xml @@ -0,0 +1,43 @@ + + + + true + true + false + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + diff --git a/src/integrationTest/resources/fullConfigNoPayload.properties b/src/integrationTest/resources/fullConfigNoPayload.properties index 6321166..64d9bd7 100644 --- a/src/integrationTest/resources/fullConfigNoPayload.properties +++ b/src/integrationTest/resources/fullConfigNoPayload.properties @@ -15,6 +15,7 @@ # verbose=true payload=false +passwordinverbose=true publish-received=true publish-send=true client-connect=true diff --git a/src/integrationTest/resources/fullConfigNoPayload.xml b/src/integrationTest/resources/fullConfigNoPayload.xml index 048efb7..306b714 100644 --- a/src/integrationTest/resources/fullConfigNoPayload.xml +++ b/src/integrationTest/resources/fullConfigNoPayload.xml @@ -20,6 +20,7 @@ xsi:noNamespaceSchemaLocation="../../main/resources/config.xsd"> true false + true true true true diff --git a/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.properties b/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.properties index 822eb26..2099219 100644 --- a/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.properties +++ b/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.properties @@ -15,6 +15,7 @@ # verbose=false payload=false +passwordinverbose=true publish-received=true publish-send=true client-connect=true diff --git a/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.xml b/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.xml index 557b16e..7a44a46 100644 --- a/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.xml +++ b/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.xml @@ -20,6 +20,7 @@ xsi:noNamespaceSchemaLocation="../../main/resources/config.xsd"> false false + true true true true diff --git a/src/integrationTest/resources/fullConfigNoVerbose.properties b/src/integrationTest/resources/fullConfigNoVerbose.properties index 6463635..e841e08 100644 --- a/src/integrationTest/resources/fullConfigNoVerbose.properties +++ b/src/integrationTest/resources/fullConfigNoVerbose.properties @@ -15,6 +15,7 @@ # verbose=false payload=true +passwordinverbose=true publish-received=true publish-send=true client-connect=true diff --git a/src/integrationTest/resources/fullConfigNoVerbose.xml b/src/integrationTest/resources/fullConfigNoVerbose.xml index 9fe4b7a..6d122bd 100644 --- a/src/integrationTest/resources/fullConfigNoVerbose.xml +++ b/src/integrationTest/resources/fullConfigNoVerbose.xml @@ -20,6 +20,7 @@ xsi:noNamespaceSchemaLocation="../../main/resources/config.xsd"> false true + true true true true diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfig.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfig.java index 1b035c7..0cd68bd 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfig.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfig.java @@ -62,6 +62,8 @@ public interface ExtensionConfig { boolean isPayload(); + boolean isPasswordInVerbose(); + default boolean allDisabled() { return !isClientConnect() && !isClientDisconnect() && diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigProperties.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigProperties.java index f33ec56..ad4c7f4 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigProperties.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigProperties.java @@ -26,6 +26,7 @@ public class ExtensionConfigProperties implements ExtensionConfig { static final @NotNull String FALSE = "false"; static final @NotNull String VERBOSE = "verbose"; static final @NotNull String PAYLOAD = "payload"; + static final @NotNull String PASSWORDINVERBOSE = "passwordinverbose"; static final @NotNull String CLIENT_CONNECT = "client-connect"; static final @NotNull String CLIENT_DISCONNECT = "client-disconnect"; static final @NotNull String CONNACK_SEND = "connack-send"; @@ -136,6 +137,10 @@ public boolean isPayload() { return getForKey(PAYLOAD); } + public boolean isPasswordInVerbose() { + return getForKey(PASSWORDINVERBOSE); + } + private boolean getForKey(final @NotNull String key) { return properties.getProperty(key, TRUE).equalsIgnoreCase(TRUE); } diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReader.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReader.java index 64db534..e961056 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReader.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReader.java @@ -33,6 +33,7 @@ import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.CLIENT_DISCONNECT; import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.CONNACK_SEND; import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.FALSE; +import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PASSWORDINVERBOSE; import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PAYLOAD; import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PING_REQUEST_RECEIVED; import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PING_RESPONSE_SEND; @@ -172,6 +173,9 @@ private static ExtensionConfig readPropertiesFile(final @NotNull File extensionH properties.setProperty(VERBOSE, FALSE); properties.setProperty(PAYLOAD, TRUE); + + properties.setProperty(PASSWORDINVERBOSE, TRUE); + return properties; } } diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigXml.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigXml.java index 986e6ee..25ea804 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigXml.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigXml.java @@ -38,6 +38,9 @@ public class ExtensionConfigXml implements ExtensionConfig { @XmlElement(name = "payload", defaultValue = "true") private boolean payload = true; + @XmlElement(name = "passwordinverbose", defaultValue = "true") + private boolean passwordinverbose = true; + @XmlElement(name = "publish-received", defaultValue = "true") private boolean publishReceived = true; @@ -103,6 +106,10 @@ public boolean isPayload() { return payload; } + public boolean isPasswordInVerbose() { + return passwordinverbose; + } + public boolean isPublishReceived() { return publishReceived; } @@ -186,6 +193,8 @@ public String toString() { verbose + ", payload=" + payload + + ", passwordInVerbose=" + + passwordinverbose + ", publishReceived=" + publishReceived + ", publishSend=" + diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl.java index 663352d..40a6492 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl.java @@ -62,7 +62,8 @@ public ClientInitializerImpl(final @NotNull ExtensionConfig config) { private void init() { if (config.isClientConnect()) { Services.interceptorRegistry().setConnectInboundInterceptorProvider( // - ignored -> new ConnectInboundInterceptorImpl(config.isVerbose(), config.isPayload())); + ignored -> new ConnectInboundInterceptorImpl(config.isVerbose(), + config.isPayload(), config.isPasswordInVerbose())); } if (config.isConnackSend()) { diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl4_2.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl4_2.java index e80d798..11a4230 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl4_2.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl4_2.java @@ -47,13 +47,16 @@ public ClientInitializerImpl4_2(final @NotNull ExtensionConfig config) { private void init() { if (config.isClientConnect() && config.isClientDisconnect()) { Services.eventRegistry().setClientLifecycleEventListener( // - input -> new ConnectDisconnectEventListener(true, config.isVerbose(), config.isPayload())); + input -> new ConnectDisconnectEventListener(true, config.isVerbose(), + config.isPayload(), config.isPasswordInVerbose())); } else if (config.isClientDisconnect()) { Services.eventRegistry().setClientLifecycleEventListener( // - input -> new ConnectDisconnectEventListener(false, config.isVerbose(), config.isPayload())); + input -> new ConnectDisconnectEventListener(false, config.isVerbose(), + config.isPayload(), config.isPasswordInVerbose())); } else if (config.isClientConnect()) { Services.interceptorRegistry().setConnectInboundInterceptorProvider( // - input -> new ConnectInboundInterceptorImpl(config.isVerbose(), config.isPayload())); + input -> new ConnectInboundInterceptorImpl(config.isVerbose(), config.isPayload(), + config.isPasswordInVerbose())); } } diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectDisconnectEventListener.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectDisconnectEventListener.java index b1ea82c..cec1f9b 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectDisconnectEventListener.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectDisconnectEventListener.java @@ -39,11 +39,14 @@ public class ConnectDisconnectEventListener implements ClientLifecycleEventListe private final boolean logConnect; private final boolean verbose; private final boolean payload; + private final boolean passwordInVerbose; - public ConnectDisconnectEventListener(final boolean logConnect, final boolean verbose, final boolean payload) { + public ConnectDisconnectEventListener(final boolean logConnect, final boolean verbose, final boolean payload, + final boolean passwordInVerbose) { this.logConnect = logConnect; this.verbose = verbose; this.payload = payload; + this.passwordInVerbose = passwordInVerbose; } @Override @@ -53,7 +56,7 @@ public void onMqttConnectionStart(final @NotNull ConnectionStartInput connection } try { final ConnectPacket connectPacket = connectionStartInput.getConnectPacket(); - MessageLogUtil.logConnect(connectPacket, verbose, payload); + MessageLogUtil.logConnect(connectPacket, verbose, payload, passwordInVerbose); } catch (final Exception e) { LOG.debug("Exception thrown at inbound connect logging: ", e); } diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectInboundInterceptorImpl.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectInboundInterceptorImpl.java index 2d52407..9302602 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectInboundInterceptorImpl.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectInboundInterceptorImpl.java @@ -32,10 +32,12 @@ public class ConnectInboundInterceptorImpl implements ConnectInboundInterceptor private static final @NotNull Logger LOG = LoggerFactory.getLogger(ConnectInboundInterceptorImpl.class); private final boolean verbose; private final boolean payload; + private final boolean passwordInVerbose; - public ConnectInboundInterceptorImpl(final boolean verbose, final boolean payload) { + public ConnectInboundInterceptorImpl(final boolean verbose, final boolean payload, final boolean passwordInVerbose) { this.verbose = verbose; this.payload = payload; + this.passwordInVerbose = passwordInVerbose; } @Override @@ -44,7 +46,7 @@ public void onConnect( final @NotNull ConnectInboundOutput connectInboundOutput) { try { final ConnectPacket connectPacket = connectInboundInput.getConnectPacket(); - MessageLogUtil.logConnect(connectPacket, verbose, payload); + MessageLogUtil.logConnect(connectPacket, verbose, payload, passwordInVerbose); } catch (final Exception e) { LOG.debug("Exception thrown at inbound connect logging: ", e); } diff --git a/src/main/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtil.java b/src/main/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtil.java index e66f72d..2338203 100644 --- a/src/main/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtil.java +++ b/src/main/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtil.java @@ -128,7 +128,8 @@ public static void logDisconnect( } public static void logConnect( - final @NotNull ConnectPacket connectPacket, final boolean verbose, final boolean payload) { + final @NotNull ConnectPacket connectPacket, final boolean verbose, final boolean payload, + final boolean passwordInVerbose) { if (!verbose) { LOG.info( "Received CONNECT from client '{}': Protocol version: '{}', Clean Start: '{}', Session Expiry Interval: '{}'", @@ -142,11 +143,16 @@ public static void logConnect( final String userPropertiesAsString = getUserPropertiesAsString(connectPacket.getUserProperties()); final String passwordAsString = getStringFromByteBuffer(connectPacket.getPassword().orElse(null)); final String passwordProperty; - if (StringUtils.isAsciiPrintable(passwordAsString) || passwordAsString == null) { - passwordProperty = "Password: '" + passwordAsString + "'"; + + if(passwordInVerbose == true) { + if (StringUtils.isAsciiPrintable(passwordAsString) || passwordAsString == null) { + passwordProperty = "Password: '" + passwordAsString + "'"; + } else { + passwordProperty = + "Password (Hex): '" + getHexStringFromByteBuffer(connectPacket.getPassword().orElse(null)) + "'"; + } } else { - passwordProperty = - "Password (Hex): '" + getHexStringFromByteBuffer(connectPacket.getPassword().orElse(null)) + "'"; + passwordProperty = ""; } final String authDataAsString; @@ -164,27 +170,50 @@ public static void logConnect( willString = ""; } - LOG.info( - "Received CONNECT from client '{}': Protocol version: '{}', Clean Start: '{}', Session Expiry Interval: '{}'," + - " Keep Alive: '{}', Maximum Packet Size: '{}', Receive Maximum: '{}', Topic Alias Maximum: '{}'," + - " Request Problem Information: '{}', Request Response Information: '{}', " + - " Username: '{}', {}, Auth Method: '{}', Auth Data (Base64): '{}', {}{}", - connectPacket.getClientId(), - connectPacket.getMqttVersion().name(), - connectPacket.getCleanStart(), - connectPacket.getSessionExpiryInterval(), - connectPacket.getKeepAlive(), - connectPacket.getMaximumPacketSize(), - connectPacket.getReceiveMaximum(), - connectPacket.getTopicAliasMaximum(), - connectPacket.getRequestProblemInformation(), - connectPacket.getRequestResponseInformation(), - connectPacket.getUserName().orElse(null), - passwordProperty, - connectPacket.getAuthenticationMethod().orElse(null), - authDataAsString, - userPropertiesAsString, - willString); + if(passwordInVerbose == true) { + LOG.info( + "Received CONNECT from client '{}': Protocol version: '{}', Clean Start: '{}', Session Expiry Interval: '{}'," + + " Keep Alive: '{}', Maximum Packet Size: '{}', Receive Maximum: '{}', Topic Alias Maximum: '{}'," + + " Request Problem Information: '{}', Request Response Information: '{}', " + + " Username: '{}', {}, Auth Method: '{}', Auth Data (Base64): '{}', {}{}", + connectPacket.getClientId(), + connectPacket.getMqttVersion().name(), + connectPacket.getCleanStart(), + connectPacket.getSessionExpiryInterval(), + connectPacket.getKeepAlive(), + connectPacket.getMaximumPacketSize(), + connectPacket.getReceiveMaximum(), + connectPacket.getTopicAliasMaximum(), + connectPacket.getRequestProblemInformation(), + connectPacket.getRequestResponseInformation(), + connectPacket.getUserName().orElse(null), + passwordProperty, + connectPacket.getAuthenticationMethod().orElse(null), + authDataAsString, + userPropertiesAsString, + willString); + } else { + LOG.info( + "Received CONNECT from client '{}': Protocol version: '{}', Clean Start: '{}', Session Expiry Interval: '{}'," + + " Keep Alive: '{}', Maximum Packet Size: '{}', Receive Maximum: '{}', Topic Alias Maximum: '{}'," + + " Request Problem Information: '{}', Request Response Information: '{}', " + + " Username: '{}', Auth Method: '{}', Auth Data (Base64): '{}', {}{}", + connectPacket.getClientId(), + connectPacket.getMqttVersion().name(), + connectPacket.getCleanStart(), + connectPacket.getSessionExpiryInterval(), + connectPacket.getKeepAlive(), + connectPacket.getMaximumPacketSize(), + connectPacket.getReceiveMaximum(), + connectPacket.getTopicAliasMaximum(), + connectPacket.getRequestProblemInformation(), + connectPacket.getRequestResponseInformation(), + connectPacket.getUserName().orElse(null), + connectPacket.getAuthenticationMethod().orElse(null), + authDataAsString, + userPropertiesAsString, + willString); + } } public static void logConnack(final @NotNull ConnackOutboundInput connackOutboundInput, final boolean verbose) { diff --git a/src/main/resources/config.xsd b/src/main/resources/config.xsd index 722c1db..3e68138 100644 --- a/src/main/resources/config.xsd +++ b/src/main/resources/config.xsd @@ -22,6 +22,7 @@ + diff --git a/src/test/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReaderTest.java b/src/test/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReaderTest.java index 0728c21..315a6ac 100644 --- a/src/test/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReaderTest.java +++ b/src/test/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReaderTest.java @@ -35,7 +35,7 @@ */ class ExtensionConfigReaderTest { - private final int totalAvailableFlags = 21; + private final int totalAvailableFlags = 22; private final @NotNull List defaultProperties = List.of(ExtensionConfigProperties.CLIENT_CONNECT, ExtensionConfigProperties.CONNACK_SEND, @@ -57,7 +57,8 @@ class ExtensionConfigReaderTest { ExtensionConfigProperties.PUBCOMP_RECEIVED, ExtensionConfigProperties.PUBCOMP_SEND, ExtensionConfigProperties.VERBOSE, - ExtensionConfigProperties.PAYLOAD); + ExtensionConfigProperties.PAYLOAD, + ExtensionConfigProperties.PASSWORDINVERBOSE); @Test void defaultPropertiesWhenNoPropertyFileInConfigFolder(@TempDir final @NotNull Path tempDir) { @@ -92,6 +93,7 @@ void defaultPropertiesWhenNoPropertyFileInConfigFolder(@TempDir final @NotNull P assertTrue(extensionConfigProperties.isPubcompSend()); assertFalse(extensionConfigProperties.isVerbose()); assertTrue(extensionConfigProperties.isPayload()); + assertTrue(extensionConfigProperties.isPasswordInVerbose()); } @Test @@ -156,6 +158,7 @@ void defaultPropertiesWhenInvalidConfigFileInConfFolder() { assertTrue(extensionConfigXml.isPubcompSend()); assertFalse(extensionConfigXml.isVerbose()); assertTrue(extensionConfigXml.isPayload()); + assertTrue(extensionConfigXml.isPasswordInVerbose()); } } diff --git a/src/test/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtilTest.java b/src/test/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtilTest.java index a459819..3ffdc89 100644 --- a/src/test/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtilTest.java +++ b/src/test/java/com/hivemq/extensions/log/mqtt/message/util/MessageLogUtilTest.java @@ -177,7 +177,7 @@ void test_log_outound_disconnect_not_verbose_none_set() { @Test void test_log_connect_verbose_all_set() { - MessageLogUtil.logConnect(createFullConnect(), true, true); + MessageLogUtil.logConnect(createFullConnect(), true, true, true); assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + "Session Expiry Interval: '10000', Keep Alive: '20000', Maximum Packet Size: '40000', " + "Receive Maximum: '30000', Topic Alias Maximum: '50000', Request Problem Information: 'true', " + @@ -195,7 +195,7 @@ void test_log_connect_verbose_all_set() { @Test void test_log_connect_verbose_no_payload_all_set() { - MessageLogUtil.logConnect(createFullConnect(), true, false); + MessageLogUtil.logConnect(createFullConnect(), true, false, true); assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + "Session Expiry Interval: '10000', Keep Alive: '20000', Maximum Packet Size: '40000', " + "Receive Maximum: '30000', Topic Alias Maximum: '50000', Request Problem Information: 'true', " + @@ -213,7 +213,7 @@ void test_log_connect_verbose_no_payload_all_set() { @Test void test_log_connect_verbose_none_set() { - MessageLogUtil.logConnect(createEmptyConnect(), true, true); + MessageLogUtil.logConnect(createEmptyConnect(), true, true, true); assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + "Session Expiry Interval: '10000', Keep Alive: '0', Maximum Packet Size: '0', Receive Maximum: '0', " + "Topic Alias Maximum: '0', Request Problem Information: 'false', Request Response Information: 'false', " + @@ -223,11 +223,57 @@ void test_log_connect_verbose_none_set() { @Test void test_log_connect_not_verbose_all_set() { - MessageLogUtil.logConnect(createFullConnect(), false, true); + MessageLogUtil.logConnect(createFullConnect(), false, true, true); assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + "Session Expiry Interval: '10000'", logbackTestAppender.getEvents().get(0).getFormattedMessage()); } + @Test + void test_log_connect_verbose_no_password_all_set() { + MessageLogUtil.logConnect(createFullConnect(), true, true, false); + assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + + "Session Expiry Interval: '10000', Keep Alive: '20000', Maximum Packet Size: '40000', " + + "Receive Maximum: '30000', Topic Alias Maximum: '50000', Request Problem Information: 'true', " + + "Request Response Information: 'false', Username: 'the username', " + + "Auth Method: 'auth method', Auth Data (Base64): 'YXV0aCBkYXRh', " + + "User Properties: [Name: 'name0', Value: 'value0'], [Name: 'name1', Value: 'value1'], " + + "Will: { Topic: 'willtopic', Payload: 'payload', QoS: '1', Retained: 'false', " + + "Message Expiry Interval: '1234', Duplicate Delivery: 'false', Correlation Data: 'data', " + + "Response Topic: 'response topic', Content Type: 'content type', " + + "Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1, 2, 3, 4]', " + + "User Properties: [Name: 'name0', Value: 'value0'], [Name: 'name1', Value: 'value1'], " + + "[Name: 'name2', Value: 'value2'], Will Delay: '100' }", + logbackTestAppender.getEvents().get(0).getFormattedMessage()); + } + + @Test + void test_log_connect_verbose_no_payload_no_password_all_set() { + MessageLogUtil.logConnect(createFullConnect(), true, false, false); + assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + + "Session Expiry Interval: '10000', Keep Alive: '20000', Maximum Packet Size: '40000', " + + "Receive Maximum: '30000', Topic Alias Maximum: '50000', Request Problem Information: 'true', " + + "Request Response Information: 'false', Username: 'the username', " + + "Auth Method: 'auth method', Auth Data (Base64): 'YXV0aCBkYXRh', " + + "User Properties: [Name: 'name0', Value: 'value0'], [Name: 'name1', Value: 'value1'], " + + "Will: { Topic: 'willtopic', QoS: '1', Retained: 'false', " + + "Message Expiry Interval: '1234', Duplicate Delivery: 'false', Correlation Data: 'data', " + + "Response Topic: 'response topic', Content Type: 'content type', " + + "Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1, 2, 3, 4]', " + + "User Properties: [Name: 'name0', Value: 'value0'], [Name: 'name1', Value: 'value1'], " + + "[Name: 'name2', Value: 'value2'], Will Delay: '100' }", + logbackTestAppender.getEvents().get(0).getFormattedMessage()); + } + + @Test + void test_log_connect_verbose_no_password_none_set() { + MessageLogUtil.logConnect(createEmptyConnect(), true, true, false); + assertEquals("Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', " + + "Session Expiry Interval: '10000', Keep Alive: '0', Maximum Packet Size: '0', Receive Maximum: '0', " + + "Topic Alias Maximum: '0', Request Problem Information: 'false', Request Response Information: 'false', " + + "Username: 'null', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null'", + logbackTestAppender.getEvents().get(0).getFormattedMessage()); + } + @Test void test_log_connack_verbose_all_set() { MessageLogUtil.logConnack(createFullConnack(), true); From ff3f2cd5a03f6918874cc58a344539295b565f71 Mon Sep 17 00:00:00 2001 From: Dominic Wenig Date: Fri, 25 Apr 2025 12:33:48 +0200 Subject: [PATCH 2/2] updated readme --- README.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.adoc b/README.adoc index ae02385..82de207 100644 --- a/README.adoc +++ b/README.adoc @@ -73,6 +73,7 @@ An example configuration file is available in `conf/examples/`, which removes th |verbose |Log detailed information about an MQTT event | false |payload |Log the payload of a message | true +|passwordinverbose |Log the password when verbose is `true` | true |=== Normally, events only log important information. @@ -83,6 +84,8 @@ CAUTION: use `verbose=true` very carefully as it will flood your log immediately Set the `payload` property to `false` if you want to suppress logging payloads (i.e. for publish-received, publish-send, and will messages). +Set the `passwordinverbose` property to `false` to prevent logging the password, even when verbose is `true`. + == First Steps Connect with an {hivemq-blog-tools}[MQTT client] of your choice.