This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch camel-quarkus-main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus-examples.git
The following commit(s) were added to refs/heads/camel-quarkus-main by this
push:
new d8100e17 Avoid logging secrets and use RAW() property placeholders in
the CyberArk Vault example
d8100e17 is described below
commit d8100e170360f43b615f0b3520d325bf6cdfda9a
Author: James Netherton <[email protected]>
AuthorDate: Fri Aug 7 07:11:59 2026 +0100
Avoid logging secrets and use RAW() property placeholders in the CyberArk
Vault example
The example logged retrieved secret values at INFO level, which undercuts
the
point of a vault integration example. The log statements now report the
secret
id and that it resolved, not what it resolved to.
Credentials were interpolated into the endpoint URIs from @ConfigProperty
fields via String.format. They are now referenced with property placeholders
wrapped in RAW(), leaving the secret id as the only interpolated value.
RAW() is not cosmetic here. Camel URI decodes query parameter values, so a
credential containing '+' is silently turned into a space before it reaches
the component. Conjur API keys are base64 encoded and routinely contain '+':
URISupport.parseQuery("apiKey=3ah+x8/dy3==") -> {apiKey=3ah x8/dy3==}
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
cyberark-vault/README.adoc | 5 ++--
.../acme/cyberark/vault/CyberarkVaultRoutes.java | 35 ++++++++--------------
.../cyberark/vault/CyberarkVaultTestResource.java | 3 ++
3 files changed, 18 insertions(+), 25 deletions(-)
diff --git a/cyberark-vault/README.adoc b/cyberark-vault/README.adoc
index 8692f8de..3acb26bd 100644
--- a/cyberark-vault/README.adoc
+++ b/cyberark-vault/README.adoc
@@ -60,8 +60,9 @@ To store a secret, open a new terminal and run:
curl -X POST http://localhost:8080/cyberark-vault/createSecret -d
'my-secret-value'
----
-Following messages will show the resolved secret value. As we run the example
in Quarkus Dev Mode, you can
-edit the source code and have live updates.
+Following messages will show that the secret resolved successfully. The value
itself is deliberately not
+logged, since writing secrets to the log defeats the purpose of storing them
in a vault. As we run the
+example in Quarkus Dev Mode, you can edit the source code and have live
updates.
TIP: Please refer to the Development mode section of
https://camel.apache.org/camel-quarkus/latest/first-steps.html#_development_mode[Camel
Quarkus User guide] for more details.
diff --git
a/cyberark-vault/src/main/java/org/acme/cyberark/vault/CyberarkVaultRoutes.java
b/cyberark-vault/src/main/java/org/acme/cyberark/vault/CyberarkVaultRoutes.java
index a2bef519..05d9a6f1 100644
---
a/cyberark-vault/src/main/java/org/acme/cyberark/vault/CyberarkVaultRoutes.java
+++
b/cyberark-vault/src/main/java/org/acme/cyberark/vault/CyberarkVaultRoutes.java
@@ -19,41 +19,30 @@ package org.acme.cyberark.vault;
import jakarta.enterprise.context.ApplicationScoped;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.PropertiesComponent;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
@ApplicationScoped
public class CyberarkVaultRoutes extends RouteBuilder {
-
- @ConfigProperty(name = "conjur.url")
- String url;
- @ConfigProperty(name = "conjur.account")
- String account;
- @ConfigProperty(name = "conjur.writer.username")
- String writerUsername;
- @ConfigProperty(name = "conjur.writer.apiKey")
- String writerApiKey;
- @ConfigProperty(name = "conjur.reader.username")
- String readerUsername;
- @ConfigProperty(name = "conjur.reader.apiKey")
- String readerApiKey;
+ static final String SECRET_ID = "BotApp/secretVar";
@Override
public void configure() throws Exception {
from("direct:createSecret")
-
.toF("cyberark-vault:secret?operation=createSecret&secretId=BotApp/secretVar&url=%s&account=%s&username=%s&apiKey=%s",
- url, account, writerUsername, writerApiKey)
- .log("Secret created/updated");
+ .toF("cyberark-vault:secret?operation=createSecret&secretId=%s"
+ + "&url={{conjur.url}}&account={{conjur.account}}"
+ +
"&username=RAW({{conjur.writer.username}})&apiKey=RAW({{conjur.writer.apiKey}})",
SECRET_ID)
+ .log("Secret %s created/updated".formatted(SECRET_ID));
from("direct:getSecret")
-
.toF("cyberark-vault:secret?secretId=BotApp/secretVar&url=%s&account=%s&username=%s&apiKey=%s",
- url, account, readerUsername, readerApiKey)
- .log("Retrieved secret: ${body}");
+ .toF("cyberark-vault:secret?secretId=%s"
+ + "&url={{conjur.url}}&account={{conjur.account}}"
+ +
"&username=RAW({{conjur.reader.username}})&apiKey=RAW({{conjur.reader.apiKey}})",
SECRET_ID)
+ .log("Secret %s retrieved successfully".formatted(SECRET_ID));
from("direct:propertyPlaceholder")
.process(exchange -> {
PropertiesComponent component =
exchange.getContext().getPropertiesComponent();
-
component.resolveProperty("cyberark:BotApp/secretVar").ifPresent(value -> {
+ component.resolveProperty("cyberark:" +
SECRET_ID).ifPresent(value -> {
exchange.getMessage().setBody(value);
});
});
@@ -63,11 +52,11 @@ public class CyberarkVaultRoutes extends RouteBuilder {
.doTry()
.process(exchange -> {
PropertiesComponent component =
exchange.getContext().getPropertiesComponent();
-
component.resolveProperty("cyberark:BotApp/secretVar").ifPresent(value -> {
+ component.resolveProperty("cyberark:" +
SECRET_ID).ifPresent(value -> {
exchange.getMessage().setBody(value);
});
})
- .log("Property placeholder cyberark:BotApp/secretVar resolved
to: ${body}")
+ .log("Property placeholder %s resolved
successfully".formatted(SECRET_ID))
.doCatch(Exception.class)
.log("No secret stored yet. Create one with: curl -X POST
http://localhost:8080/cyberark-vault/createSecret -d 'my-secret'")
.end();
diff --git
a/cyberark-vault/src/test/java/org/acme/cyberark/vault/CyberarkVaultTestResource.java
b/cyberark-vault/src/test/java/org/acme/cyberark/vault/CyberarkVaultTestResource.java
index 1f1501d0..8ac6603d 100644
---
a/cyberark-vault/src/test/java/org/acme/cyberark/vault/CyberarkVaultTestResource.java
+++
b/cyberark-vault/src/test/java/org/acme/cyberark/vault/CyberarkVaultTestResource.java
@@ -102,6 +102,9 @@ public class CyberarkVaultTestResource implements
QuarkusTestResourceLifecycleMa
result.put("camel.vault.cyberark.url", conjurUrl);
result.put("camel.vault.cyberark.account", CONJUR_ACCOUNT);
+ // The credentials are generated by the Conjur container at runtime,
so they can only be passed as
+ // plain text here. Camel logs a SECURITY WARNING for each of them at
startup. That is expected for
+ // the test profile only. Outside of tests, application.properties
resolves them from the environment.
result.put("camel.vault.cyberark.username",
result.get("conjur.reader.username"));
result.put("camel.vault.cyberark.apiKey",
result.get("conjur.reader.apiKey"));