This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit 368cbf505e12a9cfb49e6235e73764c56604ce0c Author: Andrea Cosentino <[email protected]> AuthorDate: Wed Feb 23 10:42:19 2022 +0100 CAMEL-17700 - AWS Secret Manager Properties Source: Provide a fallback default value --- .../SecretsManagerPropertiesFunction.java | 68 +++++++++----- .../SecretsManagerPropertiesSourceTestIT.java | 101 ++++++++++++++++++++- 2 files changed, 140 insertions(+), 29 deletions(-) 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 2144be8..93d2a89 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 @@ -37,6 +37,7 @@ import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; +import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException; /** * A {@link PropertiesFunction} that lookup the property value from AWS Secrets Manager service. @@ -87,11 +88,16 @@ public class SecretsManagerPropertiesFunction extends ServiceSupport implements region = awsVaultConfiguration.getRegion(); } } - SecretsManagerClientBuilder clientBuilder = SecretsManagerClient.builder(); - AwsBasicCredentials cred = AwsBasicCredentials.create(accessKey, secretKey); - clientBuilder = clientBuilder.credentialsProvider(StaticCredentialsProvider.create(cred)); - clientBuilder.region(Region.of(region)); - client = clientBuilder.build(); + if (ObjectHelper.isNotEmpty(accessKey) && ObjectHelper.isNotEmpty(secretKey) && ObjectHelper.isNotEmpty(region)) { + SecretsManagerClientBuilder clientBuilder = SecretsManagerClient.builder(); + AwsBasicCredentials cred = AwsBasicCredentials.create(accessKey, secretKey); + clientBuilder = clientBuilder.credentialsProvider(StaticCredentialsProvider.create(cred)); + clientBuilder.region(Region.of(region)); + client = clientBuilder.build(); + } else { + throw new RuntimeCamelException( + "Using the AWS Secrets Manager Properties Function requires setting AWS credentials as application properties or environment variables"); + } } @Override @@ -112,15 +118,19 @@ public class SecretsManagerPropertiesFunction extends ServiceSupport implements String key = remainder; String subkey = null; String returnValue = null; - - if (remainder.contains(":")) { + String defaultValue = null; + if (remainder.contains("/")) { + key = StringHelper.before(remainder, "/"); + subkey = StringHelper.after(remainder, "/"); + defaultValue = StringHelper.after(subkey, ":"); + } else if (remainder.contains(":")) { key = StringHelper.before(remainder, ":"); - subkey = StringHelper.after(remainder, ":"); + defaultValue = StringHelper.after(remainder, ":"); } if (key != null) { try { - returnValue = getSecretFromSource(key, subkey); + returnValue = getSecretFromSource(key, subkey, defaultValue); } catch (JsonProcessingException e) { throw new RuntimeCamelException("Something went wrong while recovering " + key + " from vault"); } @@ -130,28 +140,38 @@ public class SecretsManagerPropertiesFunction extends ServiceSupport implements } private String getSecretFromSource( - String key, String subkey) + String key, String subkey, String defaultValue) throws JsonProcessingException { String returnValue; GetSecretValueRequest request; GetSecretValueRequest.Builder builder = GetSecretValueRequest.builder(); builder.secretId(key); request = builder.build(); - GetSecretValueResponse secret = client.getSecretValue(request); - returnValue = secret.secretString(); - if (secret.secretString() != null) { - returnValue = secret.secretString(); - } else { - returnValue = new String(Base64.getDecoder().decode(secret.secretBinary().asByteBuffer()).array()); - } - if (subkey != null) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode actualObj = mapper.readTree(returnValue); - JsonNode field = actualObj.get(subkey); - if (ObjectHelper.isNotEmpty(field)) { - returnValue = field.textValue(); + try { + GetSecretValueResponse secret = client.getSecretValue(request); + if (ObjectHelper.isNotEmpty(secret.secretString())) { + returnValue = secret.secretString(); + } else { + returnValue = new String(Base64.getDecoder().decode(secret.secretBinary().asByteBuffer()).array()); + } + if (ObjectHelper.isNotEmpty(subkey)) { + ObjectMapper mapper = new ObjectMapper(); + JsonNode actualObj = mapper.readTree(returnValue); + JsonNode field = actualObj.get(subkey); + if (ObjectHelper.isNotEmpty(field)) { + returnValue = field.textValue(); + } else { + returnValue = null; + } + } + if (ObjectHelper.isEmpty(returnValue)) { + returnValue = defaultValue; + } + } catch (ResourceNotFoundException ex) { + if (ObjectHelper.isNotEmpty(defaultValue)) { + returnValue = defaultValue; } else { - returnValue = null; + throw ex; } } return returnValue; diff --git a/components/camel-aws/camel-aws-secrets-manager/src/test/java/org/apache/camel/component/aws/secretsmanager/integration/SecretsManagerPropertiesSourceTestIT.java b/components/camel-aws/camel-aws-secrets-manager/src/test/java/org/apache/camel/component/aws/secretsmanager/integration/SecretsManagerPropertiesSourceTestIT.java index 3416c47..b8b928e 100644 --- a/components/camel-aws/camel-aws-secrets-manager/src/test/java/org/apache/camel/component/aws/secretsmanager/integration/SecretsManagerPropertiesSourceTestIT.java +++ b/components/camel-aws/camel-aws-secrets-manager/src/test/java/org/apache/camel/component/aws/secretsmanager/integration/SecretsManagerPropertiesSourceTestIT.java @@ -51,8 +51,8 @@ public class SecretsManagerPropertiesSourceTestIT extends CamelTestSupport { context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:username").setBody(simple("{{aws:database_sample:username}}")).to("mock:bar"); - from("direct:password").setBody(simple("{{aws:database_sample:password}}")).to("mock:bar"); + from("direct:username").setBody(simple("{{aws:database_sample/username}}")).to("mock:bar"); + from("direct:password").setBody(simple("{{aws:database_sample/password}}")).to("mock:bar"); } }); context.start(); @@ -69,8 +69,8 @@ public class SecretsManagerPropertiesSourceTestIT extends CamelTestSupport { context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:username").setBody(simple("{{aws:normalkey:username}}")).to("mock:bar"); - from("direct:password").setBody(simple("{{aws:normalkey:password}}")).to("mock:bar"); + from("direct:username").setBody(simple("{{aws:normalkey/username}}")).to("mock:bar"); + from("direct:password").setBody(simple("{{aws:normalkey/password}}")).to("mock:bar"); } }); context.start(); @@ -107,7 +107,7 @@ public class SecretsManagerPropertiesSourceTestIT extends CamelTestSupport { context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:username").setBody(simple("{{aws:database_sample:not_existent}}")).to("mock:bar"); + from("direct:username").setBody(simple("{{aws:database_sample/not_existent}}")).to("mock:bar"); } }); context.start(); @@ -119,4 +119,95 @@ public class SecretsManagerPropertiesSourceTestIT extends CamelTestSupport { }); } + @Test + public void testComplexCustomPropertiesDefaultValueFunction() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:username").setBody(simple("{{aws:postgresql/additional1:admin}}")).to("mock:bar"); + from("direct:password").setBody(simple("{{aws:postgresql/additional2:secret}}")).to("mock:bar"); + } + }); + context.start(); + + getMockEndpoint("mock:bar").expectedBodiesReceived("admin", "secret"); + + template.sendBody("direct:username", "Hello World"); + template.sendBody("direct:password", "Hello World"); + assertMockEndpointsSatisfied(); + } + + @Test + public void testComplexCustomPropertiesDefaultValueExceptionFunction() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:username").setBody(simple("{{aws:test-3/additional1:admin}}")).to("mock:bar"); + from("direct:password").setBody(simple("{{aws:test-3/additional2:secret}}")).to("mock:bar"); + } + }); + context.start(); + + getMockEndpoint("mock:bar").expectedBodiesReceived("admin", "secret"); + + template.sendBody("direct:username", "Hello World"); + template.sendBody("direct:password", "Hello World"); + assertMockEndpointsSatisfied(); + } + + @Test + public void testComplexCustomPropertiesExceptionFunction() throws Exception { + Exception exception = assertThrows(FailedToCreateRouteException.class, () -> { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:username").setBody(simple("{{aws:test-3/additional1}}")).to("mock:bar"); + from("direct:password").setBody(simple("{{aws:test-3/additional2}}")).to("mock:bar"); + } + }); + context.start(); + + getMockEndpoint("mock:bar").expectedBodiesReceived("admin", "secret"); + + template.sendBody("direct:username", "Hello World"); + template.sendBody("direct:password", "Hello World"); + assertMockEndpointsSatisfied(); + }); + } + + @Test + public void testComplexSimpleDefaultValueExceptionFunction() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:username").setBody(simple("{{aws:test-3:admin}}")).to("mock:bar"); + from("direct:password").setBody(simple("{{aws:test-1:secret}}")).to("mock:bar"); + } + }); + context.start(); + + getMockEndpoint("mock:bar").expectedBodiesReceived("admin", "secret"); + + template.sendBody("direct:username", "Hello World"); + template.sendBody("direct:password", "Hello World"); + assertMockEndpointsSatisfied(); + } + + @Test + public void testComplexSimpleNoDefaultValueExceptionFunction() throws Exception { + Exception exception = assertThrows(FailedToCreateRouteException.class, () -> { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:username").setBody(simple("{{aws:secretsuper}}")).to("mock:bar"); + } + }); + context.start(); + + getMockEndpoint("mock:bar").expectedBodiesReceived("admin"); + + template.sendBody("direct:username", "Hello World"); + assertMockEndpointsSatisfied(); + }); + } }
