org.apache.camel.component.aws.secretsmanager.SecretsManagerPropertiesFunction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-aws-secrets-manager Show documentation
Show all versions of camel-aws-secrets-manager Show documentation
A Camel Amazon Secrets Manager Web Service Component
The newest version!
/*
* 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.aws.secretsmanager;
import java.net.URI;
import java.util.Base64;
import java.util.HashSet;
import java.util.Set;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.spi.PropertiesFunction;
import org.apache.camel.support.service.ServiceSupport;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.StringHelper;
import org.apache.camel.vault.AwsVaultConfiguration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
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.SecretsManagerException;
/**
* A {@link PropertiesFunction} that lookup the property value from AWS Secrets Manager service.
*
* The credentials to access Secrets Manager is defined using three environment variables representing the static
* credentials:
*
* - CAMEL_VAULT_AWS_ACCESS_KEY
* - CAMEL_VAULT_AWS_SECRET_KEY
* - CAMEL_VAULT_AWS_REGION
* - CAMEL_VAULT_AWS_USE_DEFAULT_CREDENTIALS_PROVIDER
* - CAMEL_VAULT_AWS_USE_PROFILE_CREDENTIALS_PROVIDER
* - CAMEL_AWS_VAULT_PROFILE_NAME
*
*
*
* Otherwise, it is possible to specify the credentials as properties:
*
*
* - camel.vault.aws.accessKey
* - camel.vault.aws.secretKey
* - camel.vault.aws.region
* - camel.vault.aws.defaultCredentialsProvider
* - camel.vault.aws.profileCredentialsProvider
* - camel.vault.aws.profileName
*
*
*
* This implementation is to return the secret value associated with a key. The properties related to this kind of
* Properties Function are all prefixed with aws:. For example asking for aws:token, will return the
* secret value associated to the secret named token on AWS Secrets Manager.
*
* Another way of retrieving a secret value is using the following notation aws:database/username: in this case
* the field username of the secret database will be returned. As a fallback, the user could provide a default value,
* which will be returned in case the secret doesn't exist, the secret has been marked for deletion or, for example, if
* a particular field of the secret doesn't exist. For using this feature, the user could use the following notation
* aws:database/username:admin. The admin value will be returned as default value, if the conditions above were
* all met.
*/
@org.apache.camel.spi.annotations.PropertiesFunction("aws")
public class SecretsManagerPropertiesFunction extends ServiceSupport implements PropertiesFunction, CamelContextAware {
private static final String CAMEL_AWS_VAULT_ACCESS_KEY_ENV = "CAMEL_VAULT_AWS_ACCESS_KEY";
private static final String CAMEL_AWS_VAULT_SECRET_KEY_ENV = "CAMEL_VAULT_AWS_SECRET_KEY";
private static final String CAMEL_AWS_VAULT_REGION_ENV = "CAMEL_VAULT_AWS_REGION";
private static final String CAMEL_AWS_VAULT_USE_DEFAULT_CREDENTIALS_PROVIDER_ENV
= "CAMEL_VAULT_AWS_USE_DEFAULT_CREDENTIALS_PROVIDER";
private static final String CAMEL_AWS_VAULT_USE_PROFILE_CREDENTIALS_PROVIDER_ENV
= "CAMEL_VAULT_AWS_USE_PROFILE_CREDENTIALS_PROVIDER";
private static final String CAMEL_AWS_VAULT_PROFILE_NAME_ENV
= "CAMEL_AWS_VAULT_PROFILE_NAME";
private static final String CAMEL_AWS_VAULT_IS_OVERRIDE_ENDPOINT
= "CAMEL_AWS_VAULT_IS_OVERRIDE_ENDPOINT";
private static final String CAMEL_AWS_VAULT_URI_ENDPOINT_OVERRIDE = "CAMEL_AWS_VAULT_URI_ENDPOINT_OVERRIDE";
private CamelContext camelContext;
private SecretsManagerClient client;
private final Set secrets = new HashSet<>();
private String region;
private boolean defaultCredentialsProvider;
private boolean profleCredentialsProvider;
private String profileName;
private boolean isOverrideEndpoint;
private String uriEndpointOverride;
public SecretsManagerPropertiesFunction() {
super();
}
public SecretsManagerPropertiesFunction(SecretsManagerClient client) {
super();
this.client = client;
}
@Override
protected void doStart() throws Exception {
super.doStart();
String accessKey = System.getenv(CAMEL_AWS_VAULT_ACCESS_KEY_ENV);
String secretKey = System.getenv(CAMEL_AWS_VAULT_SECRET_KEY_ENV);
String region = System.getenv(CAMEL_AWS_VAULT_REGION_ENV);
boolean useDefaultCredentialsProvider
= Boolean.parseBoolean(System.getenv(CAMEL_AWS_VAULT_USE_DEFAULT_CREDENTIALS_PROVIDER_ENV));
boolean useProfileCredentialsProvider
= Boolean.parseBoolean(System.getenv(CAMEL_AWS_VAULT_USE_PROFILE_CREDENTIALS_PROVIDER_ENV));
String profileName = System.getenv(CAMEL_AWS_VAULT_PROFILE_NAME_ENV);
boolean isOverrideEndpoint = Boolean.parseBoolean(System.getenv(CAMEL_AWS_VAULT_IS_OVERRIDE_ENDPOINT));
String uriEndpointOverride = System.getenv(CAMEL_AWS_VAULT_URI_ENDPOINT_OVERRIDE);
if (ObjectHelper.isEmpty(accessKey) && ObjectHelper.isEmpty(secretKey) && ObjectHelper.isEmpty(region)) {
AwsVaultConfiguration awsVaultConfiguration = getCamelContext().getVaultConfiguration().aws();
if (ObjectHelper.isNotEmpty(awsVaultConfiguration)) {
accessKey = awsVaultConfiguration.getAccessKey();
secretKey = awsVaultConfiguration.getSecretKey();
region = awsVaultConfiguration.getRegion();
useDefaultCredentialsProvider = awsVaultConfiguration.isDefaultCredentialsProvider();
useProfileCredentialsProvider = awsVaultConfiguration.isProfileCredentialsProvider();
profileName = awsVaultConfiguration.getProfileName();
isOverrideEndpoint = awsVaultConfiguration.isOverrideEndpoint();
uriEndpointOverride = awsVaultConfiguration.getUriEndpointOverride();
}
}
this.region = region;
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));
if (isOverrideEndpoint) {
if (ObjectHelper.isNotEmpty(uriEndpointOverride)) {
clientBuilder.endpointOverride(URI.create(uriEndpointOverride));
}
}
client = clientBuilder.build();
} else if (useDefaultCredentialsProvider && ObjectHelper.isNotEmpty(region)) {
this.defaultCredentialsProvider = true;
SecretsManagerClientBuilder clientBuilder = SecretsManagerClient.builder();
clientBuilder.region(Region.of(region));
if (isOverrideEndpoint) {
if (ObjectHelper.isNotEmpty(uriEndpointOverride)) {
clientBuilder.endpointOverride(URI.create(uriEndpointOverride));
}
}
client = clientBuilder.build();
} else if (useProfileCredentialsProvider && ObjectHelper.isNotEmpty(profileName)) {
this.profleCredentialsProvider = true;
this.profileName = profileName;
SecretsManagerClientBuilder clientBuilder = SecretsManagerClient.builder();
clientBuilder.credentialsProvider(ProfileCredentialsProvider.create(profileName));
clientBuilder.region(Region.of(region));
if (isOverrideEndpoint) {
if (ObjectHelper.isNotEmpty(uriEndpointOverride)) {
clientBuilder.endpointOverride(URI.create(uriEndpointOverride));
}
}
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
protected void doStop() throws Exception {
if (client != null) {
try {
client.close();
} catch (Exception e) {
// ignore
}
client = null;
}
secrets.clear();
super.doStop();
}
@Override
public String getName() {
return "aws";
}
@Override
public String apply(String remainder) {
String key = remainder;
String subkey = null;
String returnValue = null;
String defaultValue = null;
String version = null;
if (remainder.contains("#")) {
key = StringHelper.before(remainder, "#");
subkey = StringHelper.after(remainder, "#");
defaultValue = StringHelper.after(subkey, ":");
if (ObjectHelper.isNotEmpty(defaultValue)) {
if (defaultValue.contains("@")) {
version = StringHelper.after(defaultValue, "@");
defaultValue = StringHelper.before(defaultValue, "@");
}
}
if (subkey.contains(":")) {
subkey = StringHelper.before(subkey, ":");
}
if (subkey.contains("@")) {
version = StringHelper.after(subkey, "@");
subkey = StringHelper.before(subkey, "@");
}
} else if (remainder.contains(":")) {
key = StringHelper.before(remainder, ":");
defaultValue = StringHelper.after(remainder, ":");
if (remainder.contains("@")) {
version = StringHelper.after(remainder, "@");
defaultValue = StringHelper.before(defaultValue, "@");
}
} else {
if (remainder.contains("@")) {
key = StringHelper.before(remainder, "@");
version = StringHelper.after(remainder, "@");
}
}
if (key != null) {
try {
returnValue = getSecretFromSource(key, subkey, defaultValue, version);
} catch (JsonProcessingException e) {
throw new RuntimeCamelException("Something went wrong while recovering " + key + " from vault");
}
}
return returnValue;
}
private String getSecretFromSource(
String key, String subkey, String defaultValue, String version)
throws JsonProcessingException {
// capture name of secret
secrets.add(key);
String returnValue;
GetSecretValueRequest request;
GetSecretValueRequest.Builder builder = GetSecretValueRequest.builder();
builder.secretId(key);
if (ObjectHelper.isNotEmpty(version)) {
builder.versionId(version);
}
request = builder.build();
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 (SecretsManagerException ex) {
if (ObjectHelper.isNotEmpty(defaultValue)) {
returnValue = defaultValue;
} else {
throw ex;
}
}
return returnValue;
}
@Override
public void setCamelContext(CamelContext camelContext) {
this.camelContext = camelContext;
}
@Override
public CamelContext getCamelContext() {
return camelContext;
}
/**
* Ids of the secrets in use
*/
public Set getSecrets() {
return secrets;
}
/**
* The region in use for connecting to AWS Secrets Manager
*/
public String getRegion() {
return region;
}
/**
* Whether login is using default credentials provider
*/
public boolean isDefaultCredentialsProvider() {
return defaultCredentialsProvider;
}
/**
* Whether login is using default profile credentials provider
*/
public boolean isProfleCredentialsProvider() {
return profleCredentialsProvider;
}
/**
* The profile name to use when using the profile credentials provider
*/
public String getProfileName() {
return profileName;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy