Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add override for default region. #88

Merged
merged 9 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,20 @@ The secret being used should be in the JSON format we use for our rotation lambd
...
}
```
### Overriding Default Regions

The default region provider chain is used if no adjustments are made. In order to override this default, use one of the following options listed below.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These provide a way to override the default region and I do like this change for other use cases (so don't revert it), but we also want a way for customers to configure a backup region in order to provide high availability using replicated secrets. There are multiple ways to accomplish this. Some potential options:

  • Allow for a "backupRegion" to be specified via configuration here in the JDBC driver. If present, we can instantiate a second SecretCache with this region. Then in the driver logic, if we can't retrieve the secret in the primary region cache, we can fallback to using the backup SecretCache. There are a couple places where the secret is retrieved from the cache so we would want to split out this logic into a helper function.
  • We can implement the fallback logic in the SecretCache itself. The cache could take a backup region in via configuration and have two different AWSecretsManager clients. If the primary region fails for whatever reason, we can fallback to the backup region.

In both approaches, if a Secret ARN is provided, we probably want to do some automatic region substitution as well.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is spot on with our need. During DR testing, we would like to be able to configure failover secret/region config to be used.


1) Set a PrivateLink DNS endpoint URL and region in the secretsmanager.properties file.
```text
drivers.vpcEndpointUrl= #The endpoint URL
drivers.vpcEndpointRegion= #The endpoint region
```
Both options must be set in order for this option to take effect.

2) Override the region by setting the 'AWS_SECRET_JDBC_REGION' environment variable to the preferred region.

3) Override the region via the secretsmanager.properties file.
```text
drivers.region= #The region to use.
```
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<artifactId>aws-secretsmanager-jdbc</artifactId>
<packaging>jar</packaging>
<name>AWS Secrets Manager SQL Connection Library</name>
<version>1.0.8</version>
<version>1.0.9</version>
<description>The AWS Secrets Manager SQL Connection Library for Java enables Java developers to easily
connect to SQL databases using secrets stored in AWS Secrets Manager.
</description>
Expand All @@ -29,7 +29,7 @@
<jackson.version>2.13.3</jackson.version>
<junit.version>4.13.2</junit.version>
<mockito.version>1.10.19</mockito.version>
<powermock.version>1.6.6</powermock.version>
<powermock.version>1.7.0</powermock.version>
<compiler.plugin.version>3.10.1</compiler.plugin.version>
<javadoc.plugin.version>3.4.0</javadoc.plugin.version>
<source.plugin.version>3.2.1</source.plugin.version>
Expand Down Expand Up @@ -291,4 +291,4 @@
</build>
</profile>
</profiles>
</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
*/
package com.amazonaws.secretsmanager.sql;

import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.secretsmanager.util.Config;
import com.amazonaws.secretsmanager.caching.SecretCache;
import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration;
import com.amazonaws.secretsmanager.util.JDBCSecretCacheBuilderProvider;
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.util.StringUtils;
Expand Down Expand Up @@ -105,13 +105,6 @@ public abstract class AWSSecretsManagerDriver implements Driver {
*/
public static final String INVALID_SECRET_STRING_JSON = "Could not parse SecretString JSON";

/**
* Configuration property to override PrivateLink DNS URL for Secrets Manager
*/
private static final String PROPERTY_VPC_ENDPOINT_URL = "vpcEndpointUrl";

private static final String PROPERTY_VPC_ENDPOINT_REGION = "vpcEndpointRegion";

private SecretCache secretCache;

private String realDriverClass;
Expand All @@ -120,35 +113,25 @@ public abstract class AWSSecretsManagerDriver implements Driver {

private ObjectMapper mapper = new ObjectMapper();



/**
* Constructs the driver setting the properties from the properties file using system properties as defaults.
* Instantiates the secret cache with default options.
*/
protected AWSSecretsManagerDriver() {
this(new SecretCache());
this(new JDBCSecretCacheBuilderProvider().build());
}


/**
* Constructs the driver setting the properties from the properties file using system properties as defaults.
* Sets the secret cache to the cache that was passed in.
*
* @param cache Secret cache to use to retrieve secrets
*/
protected AWSSecretsManagerDriver(SecretCache cache) {

final Config config = Config.loadMainConfig();

String vpcEndpointUrl = config.getStringPropertyWithDefault(PROPERTY_PREFIX+"."+PROPERTY_VPC_ENDPOINT_URL, null);
String vpcEndpointRegion = config.getStringPropertyWithDefault(PROPERTY_PREFIX+"."+PROPERTY_VPC_ENDPOINT_REGION, null);

if (vpcEndpointUrl == null || vpcEndpointUrl.isEmpty() || vpcEndpointRegion == null || vpcEndpointRegion.isEmpty()) {
this.secretCache = cache;
} else {
AWSSecretsManagerClientBuilder builder = AWSSecretsManagerClientBuilder.standard();
builder.setEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(vpcEndpointUrl, vpcEndpointRegion));

this.secretCache = new SecretCache(builder);
}
this.secretCache = cache;

setProperties();
AWSSecretsManagerDriver.register(this);
Expand Down Expand Up @@ -186,8 +169,6 @@ protected AWSSecretsManagerDriver(SecretCacheConfiguration cacheConfig) {

/**
* Sets general configuration properties that are unrelated to the API client.
*
* @param config The main configuration for this driver.
*/
private void setProperties() {
this.config = Config.loadMainConfig().getSubconfig(PROPERTY_PREFIX + "." + getPropertySubprefix());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.amazonaws.secretsmanager.util;

import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.secretsmanager.sql.AWSSecretsManagerDriver;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;


/**
* <p>
* A class for providing JDBC driver the secrets cache builder.
*
* Checks the config file and environment variables for overrides to the default
* region and applies those changes to the provided secret cache builder.
* </p>
*/
public class JDBCSecretCacheBuilderProvider {

/**
* Configuration property to override PrivateLink DNS URL for Secrets Manager
*/
static final String PROPERTY_VPC_ENDPOINT_URL = "vpcEndpointUrl";

static final String PROPERTY_VPC_ENDPOINT_REGION = "vpcEndpointRegion";

/**
* Configuration properties to override the default region
*/
static final String PROPERTY_REGION = "region";

static final String REGION_ENVIRONMENT_VARIABLE = "AWS_SECRET_JDBC_REGION";


private Config configFile;


public JDBCSecretCacheBuilderProvider() {
this(Config.loadMainConfig());
}

public JDBCSecretCacheBuilderProvider(Config config) {
configFile = config;
}

/**
* Provides the secrets cache builder.
*
* 1) If a PrivateLink DNS endpoint URL and region are given in the Config, then they are used to configure the endpoint.
* 2) The AWS_SECRET_JDBC_REGION environment variable is checked. If set, it is used to configure the region.
* 3) The region variable file is checked in the provided Config and, if set, used to configure the region.
* 4) Finally, if none of these are not found, the default region provider chain is used.
*
* @return the built secret cache.
*/
public AWSSecretsManagerClientBuilder build() {

AWSSecretsManagerClientBuilder builder = AWSSecretsManagerClientBuilder.standard();

//Retrieve data from information sources.
String vpcEndpointUrl = configFile.getStringPropertyWithDefault(AWSSecretsManagerDriver.PROPERTY_PREFIX+"."+PROPERTY_VPC_ENDPOINT_URL, null);
String vpcEndpointRegion = configFile.getStringPropertyWithDefault(AWSSecretsManagerDriver.PROPERTY_PREFIX+"."+PROPERTY_VPC_ENDPOINT_REGION, null);
String envRegion = System.getenv(REGION_ENVIRONMENT_VARIABLE);
String configRegion = configFile.getStringPropertyWithDefault(AWSSecretsManagerDriver.PROPERTY_PREFIX+"."+PROPERTY_REGION, null);


//Apply settings to our builder configuration.
if (vpcEndpointUrl != null && !vpcEndpointUrl.isEmpty() && vpcEndpointRegion != null && !vpcEndpointRegion.isEmpty()) {
danmancuso marked this conversation as resolved.
Show resolved Hide resolved
builder.setEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(vpcEndpointUrl, vpcEndpointRegion));
} else if ( envRegion != null && !envRegion.isEmpty() ) {
builder.withRegion(envRegion);
} else if ( configRegion != null && !configRegion.isEmpty() ) {
builder.withRegion(configRegion);
}

return builder;
}
}
Loading