This is an automated email from the ASF dual-hosted git repository. JiriOndrusek pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus-examples.git
commit 915ac8b848acf1e09f85c871956f6d257fff4535 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"));
