This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 4a6d8e876920 CAMEL-25096: camel-core - Properties component: mask the
values of vault functions and sensitive keys when logging (#26997)
4a6d8e876920 is described below
commit 4a6d8e8769204895b3b6e87de0f5021d41f80656
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Sep 29 07:35:26 2026 +0200
CAMEL-25096: camel-core - Properties component: mask the values of vault
functions and sensitive keys when logging (#26997)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../apache/camel/catalog/main/sensitive-keys.json | 2 +
.../ParameterStorePropertiesFunction.java | 6 +
.../SecretsManagerPropertiesFunction.java | 6 +
.../key/vault/KeyVaultPropertiesFunction.java | 6 +
.../vault/CyberArkVaultPropertiesFunction.java | 6 +
.../GoogleSecretManagerPropertiesFunction.java | 6 +
.../vault/HashicorpVaultPropertiesFunction.java | 6 +
.../IBMSecretsManagerPropertiesFunction.java | 6 +
.../properties/BaseSecretPropertiesFunction.java | 6 +
.../org/apache/camel/spi/PropertiesFunction.java | 11 ++
.../properties/DefaultPropertiesLookup.java | 15 ++-
.../properties/DefaultPropertiesParser.java | 26 ++--
.../component/properties/PropertiesComponent.java | 52 +++++++-
.../camel/impl/console/PropertiesDevConsole.java | 7 +-
.../PropertiesComponentMaskSensitiveLogTest.java | 140 +++++++++++++++++++++
.../java/org/apache/camel/util/SensitiveUtils.java | 4 +
.../org/apache/camel/util/SensitiveUtilsTest.java | 2 +
.../maven/packaging/UpdateSensitizeHelper.java | 3 +-
18 files changed, 296 insertions(+), 14 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/sensitive-keys.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/sensitive-keys.json
index f34b628431b6..c42327768a19 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/sensitive-keys.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/sensitive-keys.json
@@ -10,6 +10,7 @@
"api_secret",
"apikey",
"apipassword",
+ "apisecret",
"apiuser",
"apiusername",
"authenticationtoken",
@@ -34,6 +35,7 @@
"databasesslkeystorepassword",
"databasesslpassword",
"databasessltruststorepassword",
+ "db_password",
"emailaddress",
"functionkey",
"hostkey",
diff --git
a/components/camel-aws/camel-aws-parameter-store/src/main/java/org/apache/camel/component/aws/parameterstore/ParameterStorePropertiesFunction.java
b/components/camel-aws/camel-aws-parameter-store/src/main/java/org/apache/camel/component/aws/parameterstore/ParameterStorePropertiesFunction.java
index 646980fdce4a..799ef380c079 100644
---
a/components/camel-aws/camel-aws-parameter-store/src/main/java/org/apache/camel/component/aws/parameterstore/ParameterStorePropertiesFunction.java
+++
b/components/camel-aws/camel-aws-parameter-store/src/main/java/org/apache/camel/component/aws/parameterstore/ParameterStorePropertiesFunction.java
@@ -207,6 +207,12 @@ public class ParameterStorePropertiesFunction extends
ServiceSupport implements
return "aws-parameterstore";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
index e606a2a25ccc..8813a510e721 100644
---
a/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
+++
b/components/camel-aws/camel-aws-secrets-manager/src/main/java/org/apache/camel/component/aws/secretsmanager/SecretsManagerPropertiesFunction.java
@@ -211,6 +211,12 @@ public class SecretsManagerPropertiesFunction extends
ServiceSupport implements
return "aws";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java
b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java
index c6903b40ee22..97b04ef74835 100644
---
a/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java
+++
b/components/camel-azure/camel-azure-key-vault/src/main/java/org/apache/camel/component/azure/key/vault/KeyVaultPropertiesFunction.java
@@ -160,6 +160,12 @@ public class KeyVaultPropertiesFunction extends
ServiceSupport implements Proper
return "azure";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-cyberark-vault/src/main/java/org/apache/camel/component/cyberark/vault/CyberArkVaultPropertiesFunction.java
b/components/camel-cyberark-vault/src/main/java/org/apache/camel/component/cyberark/vault/CyberArkVaultPropertiesFunction.java
index d1bc3a40453b..365bb2d5ba69 100644
---
a/components/camel-cyberark-vault/src/main/java/org/apache/camel/component/cyberark/vault/CyberArkVaultPropertiesFunction.java
+++
b/components/camel-cyberark-vault/src/main/java/org/apache/camel/component/cyberark/vault/CyberArkVaultPropertiesFunction.java
@@ -162,6 +162,12 @@ public class CyberArkVaultPropertiesFunction extends
ServiceSupport implements P
return "cyberark";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-google/camel-google-secret-manager/src/main/java/org/apache/camel/component/google/secret/manager/GoogleSecretManagerPropertiesFunction.java
b/components/camel-google/camel-google-secret-manager/src/main/java/org/apache/camel/component/google/secret/manager/GoogleSecretManagerPropertiesFunction.java
index dc2539badc3b..7acba28405ed 100644
---
a/components/camel-google/camel-google-secret-manager/src/main/java/org/apache/camel/component/google/secret/manager/GoogleSecretManagerPropertiesFunction.java
+++
b/components/camel-google/camel-google-secret-manager/src/main/java/org/apache/camel/component/google/secret/manager/GoogleSecretManagerPropertiesFunction.java
@@ -143,6 +143,12 @@ public class GoogleSecretManagerPropertiesFunction extends
ServiceSupport implem
return "gcp";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-hashicorp-vault/src/main/java/org/apache/camel/component/hashicorp/vault/HashicorpVaultPropertiesFunction.java
b/components/camel-hashicorp-vault/src/main/java/org/apache/camel/component/hashicorp/vault/HashicorpVaultPropertiesFunction.java
index 60b40d0a1f3a..bb195d3ac1cf 100644
---
a/components/camel-hashicorp-vault/src/main/java/org/apache/camel/component/hashicorp/vault/HashicorpVaultPropertiesFunction.java
+++
b/components/camel-hashicorp-vault/src/main/java/org/apache/camel/component/hashicorp/vault/HashicorpVaultPropertiesFunction.java
@@ -145,6 +145,12 @@ public class HashicorpVaultPropertiesFunction extends
ServiceSupport implements
return "hashicorp";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-ibm/camel-ibm-secrets-manager/src/main/java/org/apache/camel/component/ibm/secrets/manager/IBMSecretsManagerPropertiesFunction.java
b/components/camel-ibm/camel-ibm-secrets-manager/src/main/java/org/apache/camel/component/ibm/secrets/manager/IBMSecretsManagerPropertiesFunction.java
index b63deca23517..bf57267763fa 100644
---
a/components/camel-ibm/camel-ibm-secrets-manager/src/main/java/org/apache/camel/component/ibm/secrets/manager/IBMSecretsManagerPropertiesFunction.java
+++
b/components/camel-ibm/camel-ibm-secrets-manager/src/main/java/org/apache/camel/component/ibm/secrets/manager/IBMSecretsManagerPropertiesFunction.java
@@ -127,6 +127,12 @@ public class IBMSecretsManagerPropertiesFunction extends
ServiceSupport implemen
return "ibm";
}
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
public String apply(String remainder) {
String key = remainder;
diff --git
a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/BaseSecretPropertiesFunction.java
b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/BaseSecretPropertiesFunction.java
index 452458960dba..1f2fad46e535 100644
---
a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/BaseSecretPropertiesFunction.java
+++
b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/BaseSecretPropertiesFunction.java
@@ -28,6 +28,12 @@ import org.apache.camel.spi.PropertiesFunction;
*/
abstract class BaseSecretPropertiesFunction extends BasePropertiesFunction {
+ @Override
+ public boolean isSensitive() {
+ // the values are secrets
+ return true;
+ }
+
@Override
Path getMountPath() {
if (getMountPathSecrets() != null) {
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
index 331f1c9b281c..bc0484ae324b 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PropertiesFunction.java
@@ -70,4 +70,15 @@ public interface PropertiesFunction {
return false;
}
+ /**
+ * Whether the values returned by this function are sensitive (such as
secrets from a vault), which should not be
+ * logged.
+ *
+ * @return true if the values are sensitive
+ * @since 4.23
+ */
+ default boolean isSensitive() {
+ return false;
+ }
+
}
diff --git
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
index 61578449bb00..5ca67644b06a 100644
---
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
+++
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesLookup.java
@@ -24,6 +24,7 @@ import org.apache.camel.RuntimeCamelException;
import org.apache.camel.spi.LoadablePropertiesSource;
import org.apache.camel.spi.PropertiesSource;
import org.apache.camel.util.OrderedLocationProperties;
+import org.apache.camel.util.SensitiveUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +46,9 @@ public class DefaultPropertiesLookup implements
PropertiesLookup {
public String lookup(String name, String defaultValue) {
try {
String answer = doLookup(name, defaultValue);
- LOG.trace("lookup(name: {} default: {}) -> {}", name,
defaultValue, answer);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("lookup(name: {} default: {}) -> {}", name,
mask(name, defaultValue), mask(name, answer));
+ }
return answer;
} catch (NoTypeConversionAvailableException e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
@@ -126,7 +129,10 @@ public class DefaultPropertiesLookup implements
PropertiesLookup {
}
private void onLookup(String name, String value, String defaultValue,
String source) {
- LOG.trace("Property (name: {} default: {}) resolved from source: {} ->
{}", name, defaultValue, source, value);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Property (name: {} default: {}) resolved from source:
{} -> {}", name, mask(name, defaultValue), source,
+ mask(name, value));
+ }
for (PropertiesLookupListener listener :
component.getPropertiesLookupListeners()) {
try {
listener.onLookup(name, value, defaultValue, source);
@@ -147,4 +153,9 @@ public class DefaultPropertiesLookup implements
PropertiesLookup {
}
return loc;
}
+
+ private static String mask(String name, String value) {
+ // do not log sensitive values (such as passwords)
+ return value != null && name != null &&
SensitiveUtils.containsSensitive(name) ? "xxxxxx" : value;
+ }
}
diff --git
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
index 932936182470..3bb4eb201663 100644
---
a/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
+++
b/core/camel-base/src/main/java/org/apache/camel/component/properties/DefaultPropertiesParser.java
@@ -24,6 +24,7 @@ import org.apache.camel.PropertiesLookupListener;
import org.apache.camel.spi.PropertiesFunction;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.OrderedLocationProperties;
+import org.apache.camel.util.SensitiveUtils;
import org.apache.camel.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,6 +39,9 @@ import static
org.apache.camel.util.IOHelper.lookupEnvironmentVariable;
*/
public class DefaultPropertiesParser implements PropertiesParser {
+ // the mask of sensitive values (such as passwords) when logged
+ private static final String MASK = "xxxxxx";
+
private static final String UNRESOLVED_PREFIX_TOKEN = "@@[";
private static final String UNRESOLVED_SUFFIX_TOKEN = "]@@";
@@ -401,7 +405,7 @@ public class DefaultPropertiesParser implements
PropertiesParser {
} else {
if (log.isDebugEnabled()) {
log.debug("Property with key [{}] applied by
function [{}] -> {}", key, function.getName(),
- value);
+ function.isSensitive() ? MASK :
mask(StringHelper.after(key, ":"), value));
}
String k = prevKey != null ? prevKey : key;
propertiesComponent.updateResolvedValue(k, value,
function.getName());
@@ -419,7 +423,7 @@ public class DefaultPropertiesParser implements
PropertiesParser {
String value = doGetPropertyValue(key, defaultValue);
if (value == null && defaultValue != null) {
- log.debug("Property with key [{}] not found, using default
value: {}", key, defaultValue);
+ log.debug("Property with key [{}] not found, using default
value: {}", key, mask(key, defaultValue));
value = defaultValue;
for (PropertiesLookupListener listener :
propertiesComponent.getPropertiesLookupListeners()) {
try {
@@ -481,7 +485,7 @@ public class DefaultPropertiesParser implements
PropertiesParser {
}
}
onLookup(key, value, localDefaultValue, loc);
- log.debug("Found local property: {} with value: {} to be
used.", key, value);
+ log.debug("Found local property: {} with value: {} to be
used.", key, mask(key, value));
}
}
@@ -497,21 +501,21 @@ public class DefaultPropertiesParser implements
PropertiesParser {
value = lookupEnvironmentVariable(key);
if (value != null) {
onLookup(key, value, defaultValue, "ENV");
- log.debug("Found an OS environment property: {} with
value: {} to be used.", key, value);
+ log.debug("Found an OS environment property: {} with
value: {} to be used.", key, mask(key, value));
}
}
if (value == null && sysMode ==
PropertiesComponent.SYSTEM_PROPERTIES_MODE_OVERRIDE) {
value = System.getProperty(key);
if (value != null) {
onLookup(key, value, defaultValue, "SYS");
- log.debug("Found a JVM system property: {} with value: {}
to be used.", key, value);
+ log.debug("Found a JVM system property: {} with value: {}
to be used.", key, mask(key, value));
}
}
if (value == null && properties != null) {
value = properties.lookup(key, defaultValue);
if (value != null) {
- log.debug("Found property: {} with value: {} to be used.",
key, value);
+ log.debug("Found property: {} with value: {} to be used.",
key, mask(key, value));
}
}
@@ -519,7 +523,7 @@ public class DefaultPropertiesParser implements
PropertiesParser {
// custom lookup in spring boot or other runtimes
value = customLookup(key);
if (value != null) {
- log.debug("Found property (custom lookup): {} with value:
{} to be used.", key, value);
+ log.debug("Found property (custom lookup): {} with value:
{} to be used.", key, mask(key, value));
}
}
@@ -527,14 +531,14 @@ public class DefaultPropertiesParser implements
PropertiesParser {
value = lookupEnvironmentVariable(key);
if (value != null) {
onLookup(key, value, defaultValue, "ENV");
- log.debug("Found an OS environment property: {} with
value: {} to be used.", key, value);
+ log.debug("Found an OS environment property: {} with
value: {} to be used.", key, mask(key, value));
}
}
if (value == null && sysMode ==
PropertiesComponent.SYSTEM_PROPERTIES_MODE_FALLBACK) {
value = System.getProperty(key);
if (value != null) {
onLookup(key, value, defaultValue, "SYS");
- log.debug("Found a JVM system property: {} with value: {}
to be used.", key, value);
+ log.debug("Found a JVM system property: {} with value: {}
to be used.", key, mask(key, value));
}
}
@@ -612,4 +616,8 @@ public class DefaultPropertiesParser implements
PropertiesParser {
return value;
}
}
+
+ private static Object mask(String key, Object value) {
+ return value != null && key != null &&
SensitiveUtils.containsSensitive(key) ? MASK : value;
+ }
}
diff --git
a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
index 0a91a401e08a..513e8aa38e3f 100644
---
a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
+++
b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
@@ -51,6 +51,8 @@ import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.OrderedLocationProperties;
import org.apache.camel.util.OrderedProperties;
import org.apache.camel.util.PropertiesHelper;
+import org.apache.camel.util.SensitiveUtils;
+import org.apache.camel.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -320,6 +322,52 @@ public class PropertiesComponent extends ServiceSupport
return prop;
}
+ private boolean isSensitive(String uri) {
+ // the uri uses a function with sensitive values (such as a vault) or
refers to a sensitive key
+ for (PropertiesFunction function :
propertiesFunctionResolver.getFunctions().values()) {
+ if (function.isSensitive() && uri.contains(function.getName() +
":")) {
+ return true;
+ }
+ }
+ // the keys of the placeholders (without any default value)
+ int start = uri.indexOf(PREFIX_TOKEN);
+ if (start == -1) {
+ return isSensitiveKey(uri);
+ }
+ while (start != -1) {
+ int end = uri.indexOf(SUFFIX_TOKEN, start);
+ if (end == -1) {
+ return false;
+ }
+ if (isSensitiveKey(uri.substring(start + PREFIX_TOKEN.length(),
end))) {
+ return true;
+ }
+ start = uri.indexOf(PREFIX_TOKEN, end);
+ }
+ return false;
+ }
+
+ private boolean isSensitiveKey(String key) {
+ // the key with a default value (key:default), or the key of a
function (such as env:DB_PASSWORD)
+ String name = StringHelper.before(key, ":", key);
+ String remainder = StringHelper.after(key, ":");
+ if (remainder != null) {
+ remainder = StringHelper.before(remainder, ":", remainder);
+ }
+ if (!name.isEmpty() && SensitiveUtils.containsSensitive(name)
+ || remainder != null && !remainder.isEmpty() &&
SensitiveUtils.containsSensitive(remainder)) {
+ return true;
+ }
+ // the value of the key is resolved by a function with sensitive
values (such as {{app.db.conn}} set to a vault)
+ PropertiesResolvedValue resolved =
defaultPropertiesLookupListener.getProperty(name);
+ return resolved != null && isSensitiveFunction(resolved.source());
+ }
+
+ private boolean isSensitiveFunction(String name) {
+ PropertiesFunction function = name != null ?
propertiesFunctionResolver.getFunctions().get(name) : null;
+ return function != null && function.isSensitive();
+ }
+
protected String parseUri(final String uri, PropertiesLookup properties,
boolean keepUnresolvedOptional) {
LOG.trace("Parsing uri {}", uri);
@@ -351,7 +399,9 @@ public class PropertiesComponent extends ServiceSupport
// Remove the escape characters if any
answer = unescape(answer);
}
- LOG.trace("Parsed uri {} -> {}", uri, answer);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Parsed uri {} -> {}", uri, isSensitive(uri) ? "xxxxxx"
: answer);
+ }
return answer;
}
diff --git
a/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
b/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
index d0e6a38a5b21..4af30cdefa44 100644
---
a/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
+++
b/core/camel-console/src/main/java/org/apache/camel/impl/console/PropertiesDevConsole.java
@@ -157,13 +157,18 @@ public class PropertiesDevConsole extends
AbstractDevConsole {
source = m.get().source();
v = m.get().value();
}
- boolean sensitive = SensitiveUtils.containsSensitive(k);
+ // a sensitive key, or a value from a function with sensitive values
(such as a vault)
+ boolean sensitive = SensitiveUtils.containsSensitive(k) ||
isSensitiveFunction(pc, source);
String value = sensitive ? "xxxxxx" : String.valueOf(v);
String originalValueOut = originalValue != null ? (sensitive ?
"xxxxxx" : originalValue) : null;
Boolean internal = loc != null ? isInternal(loc) : null;
return new PropertyEntry(k, value, originalValueOut, defaultValue,
source, loc, internal);
}
+ private static boolean isSensitiveFunction(PropertiesComponent pc, String
source) {
+ return source != null && pc.hasPropertiesFunction(source) &&
pc.getPropertiesFunction(source).isSensitive();
+ }
+
private static boolean isInternal(String loc) {
if (loc == null) {
return false;
diff --git
a/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentMaskSensitiveLogTest.java
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentMaskSensitiveLogTest.java
new file mode 100644
index 000000000000..6fae46f2b879
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/component/properties/PropertiesComponentMaskSensitiveLogTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.properties;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.component.log.ConsumingAppender;
+import org.apache.camel.spi.PropertiesFunction;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PropertiesComponentMaskSensitiveLogTest extends
ContextTestSupport {
+
+ private static final String LOGGER =
"org.apache.camel.component.properties";
+
+ private final List<String> messages = new CopyOnWriteArrayList<>();
+
+ private static class MyVaultFunction implements PropertiesFunction {
+
+ @Override
+ public String getName() {
+ return "myvault";
+ }
+
+ @Override
+ public String apply(String remainder) {
+ return "Vault-" + remainder;
+ }
+
+ @Override
+ public boolean isSensitive() {
+ return true;
+ }
+ }
+
+ private static class MyUpperFunction implements PropertiesFunction {
+
+ @Override
+ public String getName() {
+ return "myupper";
+ }
+
+ @Override
+ public String apply(String remainder) {
+ return remainder.toUpperCase();
+ }
+ }
+
+ @Override
+ @BeforeEach
+ public void setUp() throws Exception {
+ ConsumingAppender.newAppender(LOGGER,
"PropertiesComponentMaskSensitiveLogTest", Level.TRACE,
+ e -> messages.add(e.getMessage().getFormattedMessage()));
+ super.setUp();
+ }
+
+ @Override
+ @AfterEach
+ public void tearDown() throws Exception {
+ super.tearDown();
+ LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+ ctx.getConfiguration().removeLogger(LOGGER);
+ ctx.updateLoggers();
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ Properties props = new Properties();
+ props.put("db.password", "Secret-db");
+ props.put("DB_PASSWORD", "Secret-env");
+ props.put("my.apiSecret", "Secret-api");
+ props.put("greeting", "Hello-public");
+ props.put("app.db.conn", "{{myvault:db/conn}}");
+ context.getPropertiesComponent().setInitialProperties(props);
+ context.getPropertiesComponent().addPropertiesFunction(new
MyVaultFunction());
+ context.getPropertiesComponent().addPropertiesFunction(new
MyUpperFunction());
+ return context;
+ }
+
+ @Test
+ public void testSensitiveValuesAreMasked() {
+ assertEquals("Vault-db/password",
context.resolvePropertyPlaceholders("{{myvault:db/password}}"));
+ assertEquals("Secret-db",
context.resolvePropertyPlaceholders("{{db.password}}"));
+ assertEquals("Secret-env",
context.resolvePropertyPlaceholders("{{DB_PASSWORD}}"));
+ assertEquals("Secret-api",
context.resolvePropertyPlaceholders("{{my.apiSecret}}"));
+ assertEquals("jdbc:Secret-db",
context.resolvePropertyPlaceholders("jdbc:{{db.password}}"));
+ // a vault value by way of an ordinary property
+ assertEquals("Vault-db/conn",
context.resolvePropertyPlaceholders("{{app.db.conn}}"));
+ // a sensitive key of a function that is not sensitive
+ System.setProperty("DB_PASSWORD", "Secret-sys");
+ try {
+ assertEquals("Secret-sys",
context.resolvePropertyPlaceholders("{{sys:DB_PASSWORD}}"));
+ } finally {
+ System.clearProperty("DB_PASSWORD");
+ }
+
+ assertFalse(messages.isEmpty());
+ for (String msg : messages) {
+ assertFalse(msg.contains("Vault-"), msg);
+ assertFalse(msg.contains("Secret-"), msg);
+ }
+ assertTrue(messages.stream().anyMatch(m -> m.contains("xxxxxx")));
+ }
+
+ @Test
+ public void testOtherValuesAreLogged() {
+ assertEquals("Hello-public",
context.resolvePropertyPlaceholders("{{greeting}}"));
+ assertEquals("HELLO",
context.resolvePropertyPlaceholders("{{myupper:hello}}"));
+
+ assertTrue(messages.stream().anyMatch(m ->
m.contains("Hello-public")));
+ assertTrue(messages.stream().anyMatch(m -> m.contains("HELLO")));
+ }
+}
diff --git
a/core/camel-util/src/main/java/org/apache/camel/util/SensitiveUtils.java
b/core/camel-util/src/main/java/org/apache/camel/util/SensitiveUtils.java
index 27ee2244656f..005f3e82cc31 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/SensitiveUtils.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/SensitiveUtils.java
@@ -49,6 +49,7 @@ public final class SensitiveUtils {
"api_secret",
"apikey",
"apipassword",
+ "apisecret",
"apiuser",
"apiusername",
"authenticationtoken",
@@ -73,6 +74,7 @@ public final class SensitiveUtils {
"databasesslkeystorepassword",
"databasesslpassword",
"databasessltruststorepassword",
+ "db_password",
"emailaddress",
"functionkey",
"hostkey",
@@ -156,6 +158,7 @@ public final class SensitiveUtils {
+ "|\\Qapi_secret\\E"
+ "|\\Qapikey\\E"
+ "|\\Qapipassword\\E"
+ + "|\\Qapisecret\\E"
+ "|\\Qapiuser\\E"
+ "|\\Qapiusername\\E"
+
"|\\Qauthenticationtoken\\E"
@@ -180,6 +183,7 @@ public final class SensitiveUtils {
+
"|\\Qdatabasesslkeystorepassword\\E"
+
"|\\Qdatabasesslpassword\\E"
+
"|\\Qdatabasessltruststorepassword\\E"
+ + "|\\Qdb_password\\E"
+ "|\\Qemailaddress\\E"
+ "|\\Qfunctionkey\\E"
+ "|\\Qhostkey\\E"
diff --git
a/core/camel-util/src/test/java/org/apache/camel/util/SensitiveUtilsTest.java
b/core/camel-util/src/test/java/org/apache/camel/util/SensitiveUtilsTest.java
index 78a604198124..ab496424dd0f 100644
---
a/core/camel-util/src/test/java/org/apache/camel/util/SensitiveUtilsTest.java
+++
b/core/camel-util/src/test/java/org/apache/camel/util/SensitiveUtilsTest.java
@@ -30,6 +30,8 @@ class SensitiveUtilsTest {
assertThat(SensitiveUtils.containsSensitive("authorizationtoken")).isTrue();
assertThat(SensitiveUtils.containsSensitive("clientsecret")).isTrue();
assertThat(SensitiveUtils.containsSensitive("passphrase")).isTrue();
+ assertThat(SensitiveUtils.containsSensitive("DB_PASSWORD")).isTrue();
+ assertThat(SensitiveUtils.containsSensitive("app.apiSecret")).isTrue();
assertThat(SensitiveUtils.containsSensitive("password")).isTrue();
assertThat(SensitiveUtils.containsSensitive("sasljaasconfig")).isTrue();
assertThat(SensitiveUtils.containsSensitive("sasl-jaas-config")).isTrue();
diff --git
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateSensitizeHelper.java
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateSensitizeHelper.java
index 5efc85fb5c19..c8074a0fd34d 100644
---
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateSensitizeHelper.java
+++
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateSensitizeHelper.java
@@ -83,7 +83,8 @@ public class UpdateSensitizeHelper extends
AbstractGeneratorMojo {
// OpenAI api-key header, and "authorization" covers the standard
Authorization header.
private static final String[] EXTRA_KEYS
= new String[] {
- "apipassword", "apiuser", "apiusername", "api_key",
"api-key", "api_secret", "authorization",
+ "apipassword", "apisecret", "apiuser", "apiusername",
"api_key", "api-key", "api_secret", "authorization",
+ "db_password",
SECRET, "keystorePassword" };
// extra security options from camel-main properties that are not in
component JSON files