From 40e1d98939dc159827741caff1752e5a0def38b6 Mon Sep 17 00:00:00 2001 From: Kai Hudalla Date: Fri, 26 Aug 2022 10:40:19 +0200 Subject: [PATCH] Fix Sonatype Lift findings Signed-off-by: Kai Hudalla --- .lift.toml | 2 + bom/pom.xml | 13 +++++ cli/pom.xml | 5 ++ .../hono/cli/adapter/amqp/AmqpAdapter.java | 8 +++ .../hono/cli/app/CommandAndControl.java | 1 + .../eclipse/hono/cli/app/NorthBoundApis.java | 8 +++ clients/amqp-connection/pom.xml | 5 ++ .../AuthenticatingClientConfigProperties.java | 8 +++ .../amqp/config/ClientConfigProperties.java | 7 ++- .../connection/impl/HonoConnectionImpl.java | 20 +++---- .../client/amqp/config/AddressHelperTest.java | 4 +- .../AsyncHandlingAutoCommitKafkaConsumer.java | 7 +-- .../kafka/consumer/HonoKafkaConsumer.java | 4 +- .../MicrometerKafkaClientMetricsSupport.java | 3 +- .../AbstractKafkaBasedMessageSender.java | 1 + core/pom.xml | 5 ++ .../eclipse/hono/config/AbstractConfig.java | 19 +++++++ .../org/eclipse/hono/config/KeyLoader.java | 7 +++ .../eclipse/hono/util/IdentityTemplate.java | 6 ++- create_dependencies_list.sh | 6 ++- .../src/main/sandbox/20-create-certificate.sh | 8 ++- deploy/src/main/sandbox/30-deploy-hono.sh | 2 +- examples/hono-client-examples/pom.xml | 5 ++ .../hono/devices/AmqpExampleDevice.java | 8 +++ .../eclipse/hono/devices/HonoHttpDevice.java | 53 +++++++++++-------- .../base/HonoExampleApplicationBase.java | 30 +++++++---- .../scripts/create_hono_device.sh | 22 ++++---- examples/quickstart-python/quickstart.py | 1 + legal/src/main/resources/legal/DEPENDENCIES | 1 + .../src/main/resources/legal/hono-maven.deps | 1 + service-base/pom.xml | 5 ++ .../auth/ValidityOnlyTrustManagerFactory.java | 9 ++++ services/base-jdbc/pom.xml | 6 +++ .../service/base/jdbc/store/Statement.java | 5 +- services/device-registry-mongodb/pom.xml | 5 ++ .../mongodb/app/DaoProducer.java | 11 +++- tests/src/test/resources/artemis/launch.sh | 7 ++- 37 files changed, 237 insertions(+), 81 deletions(-) create mode 100644 .lift.toml diff --git a/.lift.toml b/.lift.toml new file mode 100644 index 0000000000..be8f2d9b70 --- /dev/null +++ b/.lift.toml @@ -0,0 +1,2 @@ +# These two Infer rules seem to only produce false positives in Hono +# ignoreRules = [ "INTERFACE_NOT_THREAD_SAFE", "RESOURCE_LEAK" ] diff --git a/bom/pom.xml b/bom/pom.xml index db3c31f930..d3f952617c 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -557,6 +557,19 @@ quarkus.vertx.resolver.cache-max-time-to-live=0 + + com.github.spotbugs + spotbugs-annotations + 4.7.1 + true + provided + + + com.google.code.findbugs + jsr305 + + + com.bol cryptvault diff --git a/cli/pom.xml b/cli/pom.xml index b03c9e4ffa..50e7e91244 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -104,6 +104,11 @@ jansi 1.18 + + com.github.spotbugs + spotbugs-annotations + true + diff --git a/cli/src/main/java/org/eclipse/hono/cli/adapter/amqp/AmqpAdapter.java b/cli/src/main/java/org/eclipse/hono/cli/adapter/amqp/AmqpAdapter.java index ae10126aac..4caf222e43 100644 --- a/cli/src/main/java/org/eclipse/hono/cli/adapter/amqp/AmqpAdapter.java +++ b/cli/src/main/java/org/eclipse/hono/cli/adapter/amqp/AmqpAdapter.java @@ -60,6 +60,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.quarkus.runtime.ShutdownEvent; import io.vertx.core.Future; import io.vertx.core.Promise; @@ -83,6 +84,13 @@ mixinStandardHelpOptions = true, versionProvider = PropertiesVersionProvider.class, sortOptions = false) +@SuppressFBWarnings( + value = "HARD_CODE_PASSWORD", + justification = """ + We use the default passwords of the Hono Sandbox installation throughout this class + for ease of use. The passwords are publicly documented and do not affect any + private installations of Hono. + """) public class AmqpAdapter implements Callable { private static final Logger LOG = LoggerFactory.getLogger(AmqpAdapter.class); diff --git a/cli/src/main/java/org/eclipse/hono/cli/app/CommandAndControl.java b/cli/src/main/java/org/eclipse/hono/cli/app/CommandAndControl.java index 2e2b628c33..e9d8d4f480 100644 --- a/cli/src/main/java/org/eclipse/hono/cli/app/CommandAndControl.java +++ b/cli/src/main/java/org/eclipse/hono/cli/app/CommandAndControl.java @@ -157,6 +157,7 @@ private void printResponse(final DownstreamMessage response) { .orElse("-"))); } + @SuppressWarnings("CatchAndPrintStackTrace") private void readAndExecuteCommands() { AnsiConsole.systemInstall(); try { diff --git a/cli/src/main/java/org/eclipse/hono/cli/app/NorthBoundApis.java b/cli/src/main/java/org/eclipse/hono/cli/app/NorthBoundApis.java index 3bd8b4fba8..1d9f75a0c3 100644 --- a/cli/src/main/java/org/eclipse/hono/cli/app/NorthBoundApis.java +++ b/cli/src/main/java/org/eclipse/hono/cli/app/NorthBoundApis.java @@ -43,6 +43,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.quarkus.runtime.ShutdownEvent; import io.vertx.core.Future; import io.vertx.core.Promise; @@ -63,6 +64,13 @@ versionProvider = PropertiesVersionProvider.class, sortOptions = false, subcommands = { TelemetryAndEvent.class, CommandAndControl.class }) +@SuppressFBWarnings( + value = "HARD_CODE_PASSWORD", + justification = """ + We use the default passwords of the Hono Sandbox installation throughout this class + for ease of use. The passwords are publicly documented and do not affect any + private installations of Hono. + """) public class NorthBoundApis { private static final Logger LOG = LoggerFactory.getLogger(NorthBoundApis.class); diff --git a/clients/amqp-connection/pom.xml b/clients/amqp-connection/pom.xml index c9766a17db..d5a4702e85 100644 --- a/clients/amqp-connection/pom.xml +++ b/clients/amqp-connection/pom.xml @@ -43,6 +43,11 @@ smallrye-config true + + com.github.spotbugs + spotbugs-annotations + true + diff --git a/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/AuthenticatingClientConfigProperties.java b/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/AuthenticatingClientConfigProperties.java index 4d812bb535..ce196f55dd 100644 --- a/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/AuthenticatingClientConfigProperties.java +++ b/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/AuthenticatingClientConfigProperties.java @@ -23,6 +23,8 @@ import org.eclipse.hono.util.Constants; import org.eclipse.hono.util.Strings; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * Common configuration properties required for accessing and authenticating to a remote server. * @@ -232,6 +234,12 @@ public final void setCredentialsPath(final String path) { this.credentialsPath = path; } + @SuppressFBWarnings( + value = "PATH_TRAVERSAL_IN", + justification = """ + The path that the credentials are read from is determined from configuration properties that + are supposed to be passed in during startup of the component only. + """) private void loadCredentials() { if (Strings.isNullOrEmpty(username) && Strings.isNullOrEmpty(password) && !Strings.isNullOrEmpty(credentialsPath)) { diff --git a/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/ClientConfigProperties.java b/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/ClientConfigProperties.java index 94ba9527d1..c4c128bee2 100644 --- a/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/ClientConfigProperties.java +++ b/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/config/ClientConfigProperties.java @@ -636,16 +636,15 @@ public final String getAddressRewriteRule() { * {@link org.eclipse.hono.client.amqp.config.AddressHelper#rewrite(String, ClientConfigProperties)} method. * * @param addressRewriteRule The rewrite rule to be applied to the address. + * @throws PatternSyntaxException if the rewrite rule contains an invalid pattern definition. */ public final void setAddressRewriteRule(final String addressRewriteRule) { this.addressRewriteRule = addressRewriteRule; if (!Strings.isNullOrEmpty(addressRewriteRule)) { final String[] elements = addressRewriteRule.split(" ", 2); if (elements.length == 2) { - try { - addressRewritePattern = Pattern.compile(elements[0]); - addressRewriteReplacement = elements[1]; - } catch (PatternSyntaxException pe) { } + addressRewritePattern = Pattern.compile(elements[0]); + addressRewriteReplacement = elements[1]; } } } diff --git a/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/connection/impl/HonoConnectionImpl.java b/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/connection/impl/HonoConnectionImpl.java index 49f18bb1d2..8ff046e166 100644 --- a/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/connection/impl/HonoConnectionImpl.java +++ b/clients/amqp-connection/src/main/java/org/eclipse/hono/client/amqp/connection/impl/HonoConnectionImpl.java @@ -48,6 +48,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.opentracing.Tracer; import io.opentracing.noop.NoopTracerFactory; import io.vertx.core.AsyncResult; @@ -284,7 +285,7 @@ private void checkConnected(final Handler> resultHandler, fina * * @return {@code true} if the connection is established. */ - protected boolean isConnectedInternal() { + private boolean isConnectedInternal() { return connection != null && !connection.isDisconnected() && session != null; } @@ -314,17 +315,6 @@ private void setConnection(final ProtonConnection connection, final ProtonSessio } } - /** - * Gets the underlying connection object that this client uses to interact with the server. - * - * @return The connection. - */ - protected ProtonConnection getConnection() { - synchronized (connectionLock) { - return this.connection; - } - } - @Override public boolean supportsCapability(final Symbol capability) { if (capability == null) { @@ -1092,6 +1082,12 @@ private void connect() { }); } + @SuppressFBWarnings( + value = "PREDICTABLE_RANDOM", + justification = """ + The values returned by the ThreadLocalRandom are only used for calculating a + random amount of time to wait before trying to reconnect. + """) private void reconnect(final Throwable connectionFailureCause) { if (cancelled.get()) { return; diff --git a/clients/amqp-connection/src/test/java/org/eclipse/hono/client/amqp/config/AddressHelperTest.java b/clients/amqp-connection/src/test/java/org/eclipse/hono/client/amqp/config/AddressHelperTest.java index 7482b6291f..1b2d16ed26 100644 --- a/clients/amqp-connection/src/test/java/org/eclipse/hono/client/amqp/config/AddressHelperTest.java +++ b/clients/amqp-connection/src/test/java/org/eclipse/hono/client/amqp/config/AddressHelperTest.java @@ -14,8 +14,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.eclipse.hono.client.amqp.config.AddressHelper; -import org.eclipse.hono.client.amqp.config.ClientConfigProperties; import org.junit.jupiter.api.Test; /** @@ -58,7 +56,7 @@ public void testAddressRewriteWithNonValidSyntaxValue() { */ @Test public void testAddressRewriteForNonMatchingPattern() { - assertEquals(address, AddressHelper.rewrite(address, createConfig("* *"))); + assertEquals(address, AddressHelper.rewrite(address, createConfig("something $0"))); } /** diff --git a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/AsyncHandlingAutoCommitKafkaConsumer.java b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/AsyncHandlingAutoCommitKafkaConsumer.java index c859d6ce5f..9893e4d3bf 100644 --- a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/AsyncHandlingAutoCommitKafkaConsumer.java +++ b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/AsyncHandlingAutoCommitKafkaConsumer.java @@ -15,10 +15,11 @@ import java.time.Duration; import java.time.Instant; +import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collection; import java.util.Deque; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -371,7 +372,7 @@ protected void onPartitionsAssignedBlocking(final Set partitionsSet) { - final List partitionsForNextCommit = new LinkedList<>(); + final List partitionsForNextCommit = new ArrayList<>(); final Set partitionsToCheckCommittedOffsetsFor = partitionsSet.stream().map(Helper::to) .filter(partition -> !offsetsMap.containsKey(partition) && lastKnownCommittedOffsets.get(partition) == null) @@ -599,7 +600,7 @@ class TopicPartitionOffsets { private static final long UNDEFINED_OFFSET = -2; private final TopicPartition topicPartition; - private final Deque queue = new LinkedList<>(); + private final Deque queue = new ArrayDeque<>(); private long lastSequentiallyCompletedOffset = UNDEFINED_OFFSET; private long lastCommittedOffset = UNDEFINED_OFFSET; diff --git a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/HonoKafkaConsumer.java b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/HonoKafkaConsumer.java index 2de4c32a68..0cc2d0aece 100644 --- a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/HonoKafkaConsumer.java +++ b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/consumer/HonoKafkaConsumer.java @@ -18,7 +18,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -781,7 +780,7 @@ private void ensurePositionsHaveBeenSetIfNeeded(final Set assign final var partitions = Helper.to(assignedPartitions); // handle an exception across all position() invocations - the underlying server fetch that may trigger an exception is done for multiple partitions anyway try { - final List outOfRangeOffsetPartitions = new LinkedList<>(); + final List outOfRangeOffsetPartitions = new ArrayList<>(); final var beginningOffsets = getUnderlyingConsumer().beginningOffsets(partitions); partitions.forEach(partition -> { final long position = getUnderlyingConsumer().position(partition); @@ -1030,6 +1029,7 @@ protected void runOnContext(final Handler codeToRun) { * has been set yet on the Kafka consumer. * @throws NullPointerException if handler is {@code null}. */ + @SuppressWarnings("FutureReturnValueIgnored") protected void runOnKafkaWorkerThread(final Handler handler) { Objects.requireNonNull(handler); if (kafkaConsumerWorker == null) { diff --git a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/metrics/MicrometerKafkaClientMetricsSupport.java b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/metrics/MicrometerKafkaClientMetricsSupport.java index 12b7d29c45..11b5026a61 100644 --- a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/metrics/MicrometerKafkaClientMetricsSupport.java +++ b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/metrics/MicrometerKafkaClientMetricsSupport.java @@ -15,7 +15,6 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -66,7 +65,7 @@ public final class MicrometerKafkaClientMetricsSupport implements KafkaClientMet private static final Logger LOG = LoggerFactory.getLogger(MicrometerKafkaClientMetricsSupport.class); private static final String PREFIX_KAFKA = "kafka."; - private final List boundMeterRegistries = new LinkedList<>(); + private final List boundMeterRegistries = new ArrayList<>(); private final Map, KafkaClientMetrics> producerMetricsMap = new HashMap<>(); private final Map, KafkaClientMetrics> consumerMetricsMap = new HashMap<>(); private final boolean producerMetricsEnabled; diff --git a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/producer/AbstractKafkaBasedMessageSender.java b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/producer/AbstractKafkaBasedMessageSender.java index 3b07505436..c75d33bf9a 100644 --- a/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/producer/AbstractKafkaBasedMessageSender.java +++ b/clients/kafka-common/src/main/java/org/eclipse/hono/client/kafka/producer/AbstractKafkaBasedMessageSender.java @@ -399,6 +399,7 @@ private void logError( TracingHelper.logError(span, cause); } + @SuppressWarnings("unused") private int getErrorCode(final Throwable t) { /* * TODO set error code depending on type of exception? diff --git a/core/pom.xml b/core/pom.xml index 29444d8125..b3177be940 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -124,6 +124,11 @@ + + com.github.spotbugs + spotbugs-annotations + true + diff --git a/core/src/main/java/org/eclipse/hono/config/AbstractConfig.java b/core/src/main/java/org/eclipse/hono/config/AbstractConfig.java index 2a0c244087..78ad95c15a 100644 --- a/core/src/main/java/org/eclipse/hono/config/AbstractConfig.java +++ b/core/src/main/java/org/eclipse/hono/config/AbstractConfig.java @@ -33,6 +33,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.vertx.core.net.JksOptions; import io.vertx.core.net.KeyCertOptions; import io.vertx.core.net.PemKeyCertOptions; @@ -140,6 +141,12 @@ protected AbstractConfig(final GenericOptions other) { * @return The password. * @throws NullPointerException if any of the parameters are {@code null}. */ + @SuppressFBWarnings( + value = "PATH_TRAVERSAL_IN", + justification = """ + The path that the password is read from is determined from configuration properties that + are supposed to be passed in during startup of the component only. + """) protected final String getPassword(final String purpose, final String value) { Objects.requireNonNull(purpose); @@ -258,6 +265,12 @@ public final TrustOptions getTrustOptions() { } + @SuppressFBWarnings( + value = "PATH_TRAVERSAL_IN", + justification = """ + The path that the trust store is read from is determined from configuration properties that + are supposed to be passed in during startup of the component only. + """) private TrustOptions createTrustOptions() { if (trustOptions != null) { @@ -363,6 +376,12 @@ public final KeyCertOptions getKeyCertOptions() { return keyCertOptions; } + @SuppressFBWarnings( + value = "PATH_TRAVERSAL_IN", + justification = """ + The paths that the certificate and key are read from are determined from configuration properties that + are supposed to be passed in during startup of the component only. + """) private KeyCertOptions createKeyCertOptions() { if (!Strings.isNullOrEmpty(this.keyPath) && !Strings.isNullOrEmpty(this.certPath)) { diff --git a/core/src/main/java/org/eclipse/hono/config/KeyLoader.java b/core/src/main/java/org/eclipse/hono/config/KeyLoader.java index d25c7eb0ad..ad1712a6b2 100644 --- a/core/src/main/java/org/eclipse/hono/config/KeyLoader.java +++ b/core/src/main/java/org/eclipse/hono/config/KeyLoader.java @@ -42,6 +42,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.net.impl.pkcs1.PrivateKeyParser; @@ -180,6 +181,12 @@ private static PrivateKey generatePrivateKey(final String algorithm, final KeySp .generatePrivate(keySpec); } + @SuppressFBWarnings( + value = "PATH_TRAVERSAL_IN", + justification = """ + The path that the file is read from is determined from configuration properties that + are supposed to be passed in during startup of the component only. + """) private static R processFile(final Vertx vertx, final String pathName, final PemProcessor processor) { final Path path = Paths.get(pathName); diff --git a/core/src/main/java/org/eclipse/hono/util/IdentityTemplate.java b/core/src/main/java/org/eclipse/hono/util/IdentityTemplate.java index eafd748da1..946fb15f97 100644 --- a/core/src/main/java/org/eclipse/hono/util/IdentityTemplate.java +++ b/core/src/main/java/org/eclipse/hono/util/IdentityTemplate.java @@ -25,8 +25,7 @@ import javax.naming.ldap.Rdn; import javax.security.auth.x500.X500Principal; -import org.eclipse.hono.util.RegistryManagementConstants; -import org.eclipse.hono.util.Strings; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * A utility class for handling template used for generating device and authentication identifiers during @@ -131,6 +130,9 @@ String getValue(final List rdns) { * configured in the template are not present in the subject DN. * @throws NullPointerException if any of the parameters are {@code null}. */ + @SuppressFBWarnings( + value = "LDAP_INJECTION", + justification = "we never run an LDAP search but merely use the class for string parsing") public String apply(final String subjectDN) { Objects.requireNonNull(subjectDN, "subjectDN must not be null"); diff --git a/create_dependencies_list.sh b/create_dependencies_list.sh index 8b16eaeb00..21a7a49fde 100755 --- a/create_dependencies_list.sh +++ b/create_dependencies_list.sh @@ -27,7 +27,11 @@ fi HONO_MAVEN_DEPS="legal/src/main/resources/legal/hono-maven.deps" DEPENDENCIES="legal/src/main/resources/legal/DEPENDENCIES" -mvn dependency:list -DexcludeGroupIds=org.eclipse,org.junit -Pmetrics-prometheus,build-docker-image,build-native-image | grep -Poh "\S+:(runtime|compile|provided)" | sed -e 's/^\(.*\)\:.*$/\1/' | sort | uniq > $HONO_MAVEN_DEPS +# The spotbugs artifacts are being used with scope "provided", i.e. they are not copied to the +# container images and are not used/required during runtime and thus constitute something like +# a "works-with" dependency. It therefore seems ok to simply exclude them from the license check +# even though they are LGPL 2.1. +mvn dependency:list -DexcludeGroupIds=org.eclipse,org.junit,com.github.spotbugs -Pmetrics-prometheus,build-docker-image,build-native-image | grep -Poh "\S+:(runtime|compile|provided)" | sed -e 's/^\(.*\)\:.*$/\1/' | sort | uniq > $HONO_MAVEN_DEPS java -Dorg.eclipse.dash.timeout=60 -jar "${DASH_LICENSE_JAR}" -batch 90 -summary ${DEPENDENCIES} ${HONO_MAVEN_DEPS} "$@" sort -o ${DEPENDENCIES} ${DEPENDENCIES} diff --git a/deploy/src/main/sandbox/20-create-certificate.sh b/deploy/src/main/sandbox/20-create-certificate.sh index 0a58a65d49..79ef6167b0 100755 --- a/deploy/src/main/sandbox/20-create-certificate.sh +++ b/deploy/src/main/sandbox/20-create-certificate.sh @@ -1,6 +1,6 @@ #!/bin/bash #******************************************************************************* -# Copyright (c) 2021 Contributors to the Eclipse Foundation +# Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -26,17 +26,15 @@ EMAIL=$1 SCRIPTPATH="$(cd "$(dirname "$0")" && pwd -P)" retry() { - "$@" - while [ $? -ne 0 ]; do + while ! "$@"; do sleep 2s echo "retrying" "$@" - "$@" done } echo "" echo "Creating configuration..." -LE_CONFIG=$(helm template $SCRIPTPATH/letsencrypt-chart -f $SCRIPTPATH/letsencrypt-chart/values-$LE_API.yaml --set spec.acme.email=$EMAIL) +LE_CONFIG=$(helm template "${SCRIPTPATH}/letsencrypt-chart" -f "${SCRIPTPATH}/letsencrypt-chart/values-${LE_API}.yaml" --set "spec.acme.email=${EMAIL}") # checking when cert-manager is ready is tricky: https://cert-manager.io/docs/installation/kubernetes/#verifying-the-installation # we just retry the following command diff --git a/deploy/src/main/sandbox/30-deploy-hono.sh b/deploy/src/main/sandbox/30-deploy-hono.sh index 050d585f79..d0af45480c 100755 --- a/deploy/src/main/sandbox/30-deploy-hono.sh +++ b/deploy/src/main/sandbox/30-deploy-hono.sh @@ -26,4 +26,4 @@ helm repo update echo "" echo "Deploying Hono..." -helm install eclipse-hono eclipse-iot/hono -f $SCRIPTPATH/hono-values.yml -n hono --wait --timeout 5m0s +helm install eclipse-hono eclipse-iot/hono -f "${SCRIPTPATH}/hono-values.yml" -n hono --wait --timeout 5m0s diff --git a/examples/hono-client-examples/pom.xml b/examples/hono-client-examples/pom.xml index 090db7d3e3..ce501cf65f 100644 --- a/examples/hono-client-examples/pom.xml +++ b/examples/hono-client-examples/pom.xml @@ -57,6 +57,11 @@ org.eclipse.hono hono-demo-certs + + com.github.spotbugs + spotbugs-annotations + true + diff --git a/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/AmqpExampleDevice.java b/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/AmqpExampleDevice.java index 9f762fd2b8..106b49770c 100644 --- a/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/AmqpExampleDevice.java +++ b/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/AmqpExampleDevice.java @@ -21,6 +21,7 @@ import org.eclipse.hono.client.device.amqp.AmqpAdapterClient; import org.eclipse.hono.util.QoS; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.json.JsonObject; @@ -45,6 +46,13 @@ * @see The AMQP Adapter Client * documentation */ +@SuppressFBWarnings( + value = "HARD_CODE_PASSWORD", + justification = """ + We use the default passwords of the Hono Sandbox installation throughout this class + for ease of use. The passwords are publicly documented and do not affect any + private installations of Hono. + """) public class AmqpExampleDevice { private static final String HOST = "hono.eclipseprojects.io"; diff --git a/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/HonoHttpDevice.java b/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/HonoHttpDevice.java index b2a7019dc1..9f75b75553 100644 --- a/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/HonoHttpDevice.java +++ b/examples/hono-client-examples/src/main/java/org/eclipse/hono/devices/HonoHttpDevice.java @@ -15,7 +15,6 @@ import java.net.HttpURLConnection; import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Optional; @@ -78,7 +77,7 @@ public class HonoHttpDevice { private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; /** - * Different types of requests this application may send. + * Different types of request messages this application may send. */ private enum Request { EMPTY_EVENT_WITH_TTD(null, EventConstants.CONTENT_TYPE_EMPTY_NOTIFICATION, 60, true), @@ -88,25 +87,22 @@ private enum Request { TELEMETRY_WITHOUT_TTD(new JsonObject().put("weather", "sunny"), CONTENT_TYPE_APPLICATION_JSON, null, false), TELEMETRY_WITH_TTD(new JsonObject().put("weather", "cloudy"), CONTENT_TYPE_APPLICATION_JSON, 60, false); - /** - * The payload of the message, defined as JsonObject. May be {@code null}. - */ - private final JsonObject payload; - /** - * The Content-Type that is set for the message. - */ + private final String payload; private final String contentType; - /** - * The time-to-deliver of the message, which is defined as application property of the AMQP 1.0 message. - */ private final Integer ttd; + private final boolean isEvent; + /** - * Property to define if the message shall be sent as event or as telemetry message. + * Creates a new request message. + * + * @param payload The JSON payload of the message or {@code null} if the message has no payload. + * @param contentType The type of the payload or {@code null} if unknown. + * @param ttd The number of seconds after which the client will disconnect, once the request has been sent. + * May be {@code null}. + * @param isEvent {@code true} if the message represents an event rather than telemetry data. */ - private final Boolean isEvent; - - Request(final JsonObject payload, final String contentType, final Integer ttd, final Boolean isEvent) { - this.payload = payload; + Request(final JsonObject payload, final String contentType, final Integer ttd, final boolean isEvent) { + this.payload = Optional.ofNullable(payload).map(JsonObject::encode).orElse(null); this.contentType = contentType; this.ttd = ttd; this.isEvent = isEvent; @@ -129,7 +125,7 @@ public String toString() { } } - private final List requests = Arrays.asList( + private final List requests = List.of( Request.EMPTY_EVENT_WITH_TTD, Request.EMPTY_EVENT_WITH_TTD, Request.EMPTY_EVENT_WITH_TTD, @@ -157,6 +153,11 @@ private HonoHttpDevice() { .add(HttpHeaders.ORIGIN, ORIGIN_URI); } + /** + * Sends some data. + * + * @param args The command line arguments (not used). + */ public static void main(final String[] args) { final HonoHttpDevice httpDevice = new HonoHttpDevice(); httpDevice.sendData(); @@ -185,8 +186,8 @@ private CompletableFuture sendMessage(final Request request) { return httpRequest; }) .compose(httpRequest -> httpRequest.send(Optional.ofNullable(request.payload) - .map(JsonObject::toBuffer) - .orElse(Buffer.buffer()))) + .map(Buffer::buffer) + .orElseGet(Buffer::buffer))) .onFailure(result::completeExceptionally) .onSuccess(response -> { System.out.println(response.statusCode() + " " + response.statusMessage()); @@ -206,7 +207,7 @@ private CompletableFuture sendMessage(final Request request) { VERTX.setTimer(1000, l -> result.complete(null)); } else { // response contains a command - sendCommandResponse("text/plain", Buffer.buffer("ok"), commandReqId, HttpURLConnection.HTTP_OK) + sendCommandResponse(commandReqId, HttpURLConnection.HTTP_OK, Buffer.buffer("ok"), "text/plain") .map(status -> { System.out.println(String.format("sent response to command [HTTP response status: %d]", status)); VERTX.setTimer(1000, l -> result.complete(null)); @@ -221,15 +222,21 @@ private CompletableFuture sendMessage(final Request request) { return result; } - private Future sendCommandResponse(final String contentType, final Buffer payload, final String commandReqId, final int status) { + private Future sendCommandResponse( + final String commandReqId, + final int status, + final Buffer payload, + final String contentType) { return httpClient.request(HttpMethod.POST, String.format("/%s/res/%s", CommandConstants.COMMAND_ENDPOINT, commandReqId)) .map(httpRequest -> { httpRequest.putHeader(Constants.HEADER_COMMAND_RESPONSE_STATUS, Integer.toString(status)); + Optional.ofNullable(contentType) + .ifPresent(ct -> httpRequest.putHeader(HttpHeaders.CONTENT_TYPE, ct)); httpRequest.headers().addAll(standardRequestHeaders); return httpRequest; }) - .compose(httpRequest -> httpRequest.send(Optional.ofNullable(payload).orElse(Buffer.buffer()))) + .compose(httpRequest -> payload == null ? httpRequest.send() : httpRequest.send(payload)) .map(HttpClientResponse::statusCode); } diff --git a/examples/hono-client-examples/src/main/java/org/eclipse/hono/vertx/example/base/HonoExampleApplicationBase.java b/examples/hono-client-examples/src/main/java/org/eclipse/hono/vertx/example/base/HonoExampleApplicationBase.java index dc546bd759..5ddc0f35cd 100644 --- a/examples/hono-client-examples/src/main/java/org/eclipse/hono/vertx/example/base/HonoExampleApplicationBase.java +++ b/examples/hono-client-examples/src/main/java/org/eclipse/hono/vertx/example/base/HonoExampleApplicationBase.java @@ -14,6 +14,7 @@ package org.eclipse.hono.vertx.example.base; import java.io.IOException; +import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -43,6 +44,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.vertx.core.CompositeFuture; import io.vertx.core.Future; import io.vertx.core.Handler; @@ -58,6 +60,15 @@ *

* The code consumes data until it receives any input on its console (which finishes it and closes vertx). */ +@SuppressFBWarnings( + value = { "HARD_CODE_PASSWORD", "PREDICTABLE_RANDOM" }, + justification = """ + We use the default passwords of the Hono Sandbox installation throughout this class + for ease of use. The passwords are publicly documented and do not affect any + private installations of Hono. + The values returned by the Random are only used as arbitrary values in example message + payload. + """) public class HonoExampleApplicationBase { public static final String HONO_CLIENT_USER = System.getProperty("username", "consumer@HONO"); @@ -346,9 +357,6 @@ private void handlePermanentlyConnectedCommandReadinessNotification( */ private void sendCommand(final TimeUntilDisconnectNotification notification) { - final long commandTimeout = calculateCommandTimeout(notification); - // TODO set request timeout - if (SEND_ONE_WAY_COMMANDS) { sendOneWayCommandToAdapter(notification.getTenantId(), notification.getDeviceId(), notification); } else { @@ -363,14 +371,14 @@ private void sendCommand(final TimeUntilDisconnectNotification notification) { * @param notification The notification that was received for the device. * @return The timeout (milliseconds) to be set for the command. */ - private long calculateCommandTimeout(final TimeUntilDisconnectNotification notification) { + private Duration calculateCommandTimeout(final TimeUntilDisconnectNotification notification) { if (notification.getTtd() == -1) { // let the command expire directly before the next periodic timer is started - return HonoExampleConstants.COMMAND_INTERVAL_FOR_DEVICES_CONNECTED_WITH_UNLIMITED_EXPIRY * 1000L; + return Duration.ofMillis(HonoExampleConstants.COMMAND_INTERVAL_FOR_DEVICES_CONNECTED_WITH_UNLIMITED_EXPIRY * 1000L); } else { // let the command expire when the notification expires - return notification.getMillisecondsUntilExpiry(); + return Duration.ofMillis(notification.getMillisecondsUntilExpiry()); } } @@ -393,7 +401,7 @@ private void cancelPeriodicCommandSender(final TimeUntilDisconnectNotification n } private boolean isPeriodicCommandSenderActiveForDevice(final TimeUntilDisconnectNotification notification) { - return (periodicCommandSenderTimerCancelerMap.containsKey(notification.getTenantAndDeviceId())); + return periodicCommandSenderTimerCancelerMap.containsKey(notification.getTenantAndDeviceId()); } /** @@ -404,15 +412,19 @@ private boolean isPeriodicCommandSenderActiveForDevice(final TimeUntilDisconnect * If the contained ttd is set to -1, the commandClient will remain open for further commands to be sent. * @param ttdNotification The ttd notification that was received for the device. */ - private void sendCommandToAdapter(final String tenantId, final String deviceId, + private void sendCommandToAdapter( + final String tenantId, + final String deviceId, final TimeUntilDisconnectNotification ttdNotification) { + + final Duration commandTimeout = calculateCommandTimeout(ttdNotification); final Buffer commandBuffer = buildCommandPayload(); final String command = "setBrightness"; if (LOG.isDebugEnabled()) { LOG.debug("Sending command [{}] to [{}].", command, ttdNotification.getTenantAndDeviceId()); } - client.sendCommand(tenantId, deviceId, command, commandBuffer, "application/json") + client.sendCommand(tenantId, deviceId, command, commandBuffer, "application/json", null, commandTimeout, null) .onSuccess(result -> { if (LOG.isDebugEnabled()) { LOG.debug("Successfully sent command payload: [{}].", commandBuffer.toString()); diff --git a/examples/protocol-gateway-example/scripts/create_hono_device.sh b/examples/protocol-gateway-example/scripts/create_hono_device.sh index 111a4a2dcf..54d233fcaf 100755 --- a/examples/protocol-gateway-example/scripts/create_hono_device.sh +++ b/examples/protocol-gateway-example/scripts/create_hono_device.sh @@ -15,12 +15,15 @@ # A simple shell script to get IP addresses for hono-service-device-registry-ext, hono-dispatch-router-ext and hono-adapter-amqp and creates a device id and password # prior: setup hono in kubernetes namespace "hono" -export REGISTRY_IP=$(kubectl -n hono get service hono-service-device-registry-ext --output='jsonpath={.status.loadBalancer.ingress[0].ip}') +REGISTRY_IP=$(kubectl -n hono get service hono-service-device-registry-ext --output='jsonpath={.status.loadBalancer.ingress[0].ip}') echo "REGISTRY_IP=${REGISTRY_IP}" -export AMQP_NETWORK_IP=$(kubectl -n hono get service hono-dispatch-router-ext --output='jsonpath={.status.loadBalancer.ingress[0].ip}') +export REGISTRY_IP +AMQP_NETWORK_IP=$(kubectl -n hono get service hono-dispatch-router-ext --output='jsonpath={.status.loadBalancer.ingress[0].ip}') echo "AMQP_NETWORK_IP=${AMQP_NETWORK_IP}" -export AMQP_ADAPTER_PORT=$(kubectl -n hono get service hono-adapter-amqp --output='jsonpath={.status.loadBalancer.ingress[0].port}') +export AMQP_NETWORK_IP +AMQP_ADAPTER_PORT=$(kubectl -n hono get service hono-adapter-amqp --output='jsonpath={.status.loadBalancer.ingress[0].port}') echo "AMQP_ADAPTER_IP=${AMQP_ADAPTER_IP}" +export AMQP_ADAPTER_PORT # Get example tenant or export MY_TENANT="DEFAULT_TENANT" @@ -30,14 +33,15 @@ export MY_TENANT="DEFAULT_TENANT" echo "MY_TENANT=\"${MY_TENANT}\"" # register new device -export MY_DEVICE=$(curl -X POST http://$REGISTRY_IP:28080/v1/devices/$MY_TENANT 2>/dev/null | jq -r .id) +MY_DEVICE=$(curl -X POST "http://${REGISTRY_IP}:28080/v1/devices/${MY_TENANT}" 2>/dev/null | jq -r .id) echo "MY_DEVICE=\"${MY_DEVICE}\"" +export MY_DEVICE # set credential secret for device export MY_PWD="dummyDevicePassword" echo "MY_PWD=\"${MY_PWD}\"" -curl -i -X PUT -H "content-type: application/json" --data-binary '[{ - "type": "hashed-password", - "auth-id": "'$MY_DEVICE'", - "secrets": [{ "pwd-plain": "'$MY_PWD'" }] -}]' http://$REGISTRY_IP:28080/v1/credentials/$MY_TENANT/$MY_DEVICE +curl -i -X PUT -H "content-type: application/json" --data-binary "[{ + \"type\": \"hashed-password\", + \"auth-id\": \"${MY_DEVICE}\", + \"secrets\": [{ \"pwd-plain\": \"${MY_PWD}\" }] +}]" "http://${REGISTRY_IP}:28080/v1/credentials/${MY_TENANT}/${MY_DEVICE}" diff --git a/examples/quickstart-python/quickstart.py b/examples/quickstart-python/quickstart.py index 5cf0508b5d..3767d8f6bc 100644 --- a/examples/quickstart-python/quickstart.py +++ b/examples/quickstart-python/quickstart.py @@ -109,6 +109,7 @@ def on_message(self, event): # Send HTTP Message print("Send Telemetry Message via HTTP") +# nosemgrep: no-auth-over-http response = requests.post(f'http://{httpAdapterIp}:8080/telemetry', headers={"content-type": "application/json"}, data=json.dumps({"temp": 5, "transport": "http"}), auth=HTTPBasicAuth(f'{deviceId}@{tenantId}', f'{devicePassword}')) diff --git a/legal/src/main/resources/legal/DEPENDENCIES b/legal/src/main/resources/legal/DEPENDENCIES index 8a1ea6dce5..b36fccd6da 100644 --- a/legal/src/main/resources/legal/DEPENDENCIES +++ b/legal/src/main/resources/legal/DEPENDENCIES @@ -16,6 +16,7 @@ maven/mavencentral/com.github.luben/zstd-jni/1.5.2-1, BSD-2-Clause, approved, cl maven/mavencentral/com.github.mifmif/generex/1.0.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.api.grpc/proto-google-common-protos/2.9.1, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.code.gson/gson/2.9.0, Apache-2.0, approved, CQ24148 +maven/mavencentral/com.google.errorprone/error_prone_annotations/2.14.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.guava/failureaccess/1.0.1, Apache-2.0, approved, CQ22654 maven/mavencentral/com.google.guava/guava/31.1-jre, Apache-2.0 AND CC0-1.0 AND LicenseRef-Public-Domain, approved, CQ24046 maven/mavencentral/com.google.protobuf/protobuf-java/3.19.3, BSD-3-Clause, approved, clearlydefined diff --git a/legal/src/main/resources/legal/hono-maven.deps b/legal/src/main/resources/legal/hono-maven.deps index aacb529734..9c0a5a3c7e 100644 --- a/legal/src/main/resources/legal/hono-maven.deps +++ b/legal/src/main/resources/legal/hono-maven.deps @@ -16,6 +16,7 @@ com.github.luben:zstd-jni:jar:1.5.2-1 com.github.mifmif:generex:jar:1.0.2 com.google.api.grpc:proto-google-common-protos:jar:2.9.1 com.google.code.gson:gson:jar:2.9.0 +com.google.errorprone:error_prone_annotations:jar:2.14.0 com.google.guava:failureaccess:jar:1.0.1 com.google.guava:guava:jar:31.1-jre com.google.protobuf:protobuf-java:jar:3.19.3 diff --git a/service-base/pom.xml b/service-base/pom.xml index b6e4feac2c..aadd793702 100644 --- a/service-base/pom.xml +++ b/service-base/pom.xml @@ -135,6 +135,11 @@ io.quarkus quarkus-smallrye-health + + com.github.spotbugs + spotbugs-annotations + true + diff --git a/service-base/src/main/java/org/eclipse/hono/service/auth/ValidityOnlyTrustManagerFactory.java b/service-base/src/main/java/org/eclipse/hono/service/auth/ValidityOnlyTrustManagerFactory.java index eb27755553..8187edd1b5 100644 --- a/service-base/src/main/java/org/eclipse/hono/service/auth/ValidityOnlyTrustManagerFactory.java +++ b/service-base/src/main/java/org/eclipse/hono/service/auth/ValidityOnlyTrustManagerFactory.java @@ -28,6 +28,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.netty.handler.ssl.util.SimpleTrustManagerFactory; @@ -36,6 +37,14 @@ * valid according to its not before and not after properties. * */ +@SuppressFBWarnings( + value = "WEAK_TRUST_MANAGER", + justification = """ + We cannot validate the certificate chain when the TLS connection gets established because we need to + dynamically look up the trust anchors configured for the tenant that the client (device) belongs to. + Therefore, the validation of the chain of trust is done at the application level, i.e. during connection + establishment and/or request processing instead. + """) public final class ValidityOnlyTrustManagerFactory extends SimpleTrustManagerFactory { private static final Logger LOG = LoggerFactory.getLogger(ValidityOnlyTrustManagerFactory.class); diff --git a/services/base-jdbc/pom.xml b/services/base-jdbc/pom.xml index 943f5d5445..fe0ff2f7ea 100644 --- a/services/base-jdbc/pom.xml +++ b/services/base-jdbc/pom.xml @@ -80,6 +80,12 @@ smallrye-config true + + com.google.errorprone + error_prone_annotations + provided + true + diff --git a/services/base-jdbc/src/main/java/org/eclipse/hono/service/base/jdbc/store/Statement.java b/services/base-jdbc/src/main/java/org/eclipse/hono/service/base/jdbc/store/Statement.java index 197704a331..c312d33c49 100644 --- a/services/base-jdbc/src/main/java/org/eclipse/hono/service/base/jdbc/store/Statement.java +++ b/services/base-jdbc/src/main/java/org/eclipse/hono/service/base/jdbc/store/Statement.java @@ -29,6 +29,8 @@ import java.util.regex.Pattern; import com.google.common.base.MoreObjects; +import com.google.errorprone.annotations.FormatMethod; +import com.google.errorprone.annotations.FormatString; import io.opentracing.Span; import io.opentracing.SpanContext; @@ -175,7 +177,8 @@ public String toString() { * @param values The values to replace in the parameter {@code sql}. * @return The statement, or {@code null} if the provided SQL is {@code null}. */ - public static Statement statement(final String sql, final Object... values) { + @FormatMethod + public static Statement statement(@FormatString final String sql, final Object... values) { if (sql == null) { return null; } diff --git a/services/device-registry-mongodb/pom.xml b/services/device-registry-mongodb/pom.xml index f103fbe74a..568dc35682 100644 --- a/services/device-registry-mongodb/pom.xml +++ b/services/device-registry-mongodb/pom.xml @@ -66,6 +66,11 @@ io.quarkus quarkus-mongodb-client + + com.github.spotbugs + spotbugs-annotations + true + diff --git a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/DaoProducer.java b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/DaoProducer.java index 39ea3442fe..eafd4eb13d 100644 --- a/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/DaoProducer.java +++ b/services/device-registry-mongodb/src/main/java/org/eclipse/hono/deviceregistry/mongodb/app/DaoProducer.java @@ -40,10 +40,11 @@ import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; +import com.bol.config.CryptVaultAutoConfiguration; import com.bol.config.CryptVaultAutoConfiguration.CryptVaultConfigurationProperties; -import com.bol.config.CryptVaultAutoConfiguration.Key; import com.bol.crypt.CryptVault; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.opentracing.Tracer; import io.vertx.core.Vertx; import io.vertx.ext.mongo.MongoClient; @@ -145,12 +146,18 @@ public CredentialsDao credentialsDao( return dao; } + @SuppressFBWarnings( + value = "PATH_TRAVERSAL_IN", + justification = """ + The path that the CryptVault properties are read from is determined from configuration properties that + are supposed to be passed in during startup of the component only. + """) private FieldLevelEncryption fieldLevelEncryption(final String path) { try (FileInputStream in = new FileInputStream(path)) { final Yaml yaml = new Yaml(new Constructor(CryptVaultConfigurationProperties.class)); final CryptVaultConfigurationProperties config = yaml.load(in); final CryptVault cryptVault = new CryptVault(); - for (Key key : config.getKeys()) { + for (CryptVaultAutoConfiguration.Key key : config.getKeys()) { final byte[] secretKeyBytes = Base64.getDecoder().decode(key.getKey()); cryptVault.with256BitAesCbcPkcs5PaddingAnd128BitSaltKey(key.getVersion(), secretKeyBytes); } diff --git a/tests/src/test/resources/artemis/launch.sh b/tests/src/test/resources/artemis/launch.sh index badeb843df..9b820e1c81 100755 --- a/tests/src/test/resources/artemis/launch.sh +++ b/tests/src/test/resources/artemis/launch.sh @@ -19,5 +19,8 @@ # cp $AMQ_HOME/conf/* ~/broker/etc/ # . # This allows usage of a custom broker.xml and other config files, provided in the "$AMQ_HOME/conf/" directory. -sed -i -E 's/^([[:space:]]*)configure[[:space:]]*$/\0\n\1cp $AMQ_HOME\/conf\/\* ~\/broker\/etc\//g' $AMQ_HOME/bin/launch.sh -$AMQ_HOME/bin/launch.sh +# We want the sed command to add the literal string "cp $AMQ_HOME/conf/*" to the script, i.e. we do not want the +# $AMQP_HOME variable to be dereferenced. +# shellcheck disable=SC2016 +sed -i -E 's/^([[:space:]]*)configure[[:space:]]*$/\0\n\1cp $AMQ_HOME\/conf\/\* ~\/broker\/etc\//g' "${AMQ_HOME}/bin/launch.sh" +"${AMQ_HOME}/bin/launch.sh"