diff --git a/README.md b/README.md index 03745d9..90c8211 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,22 @@ public class SampleClass implements RequestHandler { } ``` +### Enabling Post-Quantum TLS + +To enable Post-Quantum TLS for enhanced security: + +```java +import com.amazonaws.secretsmanager.caching.SecretCache; +import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; + +SecretCache cache = new SecretCache( + new SecretCacheConfiguration() + .withPostQuantumTlsEnabled(true) +); + +String secret = cache.getSecretString("my-secret-id"); +``` + ## License This library is licensed under the Apache 2.0 License. diff --git a/pom.xml b/pom.xml index 34c71b2..9565d34 100644 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,11 @@ secretsmanager 2.41.3 + + software.amazon.awssdk + aws-crt-client + 2.41.3 + org.testng testng diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java index d0c2672..ad79122 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java @@ -18,11 +18,13 @@ import com.amazonaws.secretsmanager.caching.cache.SecretCacheItem; import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; +import software.amazon.awssdk.http.crt.AwsCrtHttpClient; /** * Provides the primary entry-point to the AWS Secrets Manager client cache SDK. @@ -69,6 +71,8 @@ public SecretCache() { * @param builder The builder to use for creating the AWS Secrets Manager * client. */ + @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", + justification = "Delegates to constructor that validates before field initialization") public SecretCache(SecretsManagerClientBuilder builder) { this(new SecretCacheConfiguration().withClient(builder .overrideConfiguration( @@ -84,6 +88,8 @@ public SecretCache(SecretsManagerClientBuilder builder) { * @param client The AWS Secrets Manager client to use for requesting secret * values. */ + @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", + justification = "Delegates to constructor that validates before field initialization") public SecretCache(SecretsManagerClient client) { this(new SecretCacheConfiguration().withClient(client)); } @@ -92,17 +98,40 @@ public SecretCache(SecretsManagerClient client) { * Constructs a new secret cache using the provided cache configuration. * * @param config The secret cache configuration. + * @throws IllegalArgumentException if both a custom client and postQuantumTlsEnabled + * are specified in the configuration. */ + @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", + justification = "Validation occurs before any field initialization") public SecretCache(SecretCacheConfiguration config) { if (null == config) { config = new SecretCacheConfiguration(); } + + if (config.getClient() != null && config.isPostQuantumTlsEnabled()) { + throw new IllegalArgumentException( + "Cannot specify both a custom client and postQuantumTlsEnabled. " + + "To use PQTLS, omit the custom client or configure your client with PQTLS support."); + } + this.cache = new LRUCache(config.getMaxCacheSize()); this.config = config; ClientOverrideConfiguration defaultOverride = ClientOverrideConfiguration.builder() .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, VersionInfo.USER_AGENT).build(); - this.client = config.getClient() != null ? config.getClient() - : SecretsManagerClient.builder().overrideConfiguration(defaultOverride).build(); + + if (config.getClient() != null) { + this.client = config.getClient(); + } else { + SecretsManagerClientBuilder builder = SecretsManagerClient.builder(); + + if (config.isPostQuantumTlsEnabled()) { + builder.httpClient(AwsCrtHttpClient.builder() + .postQuantumTlsEnabled(true) + .build()); + } + + this.client = builder.overrideConfiguration(defaultOverride).build(); + } } /** diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java index 744ebbd..325be90 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java @@ -18,7 +18,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; - /** * Cache configuration options such as max cache size, ttl for cached items, etc. * @@ -73,6 +72,11 @@ public class SecretCacheConfiguration { */ private long forceRefreshJitterMillis = DEFAULT_FORCE_REFRESH_JITTER; + /** + * Whether to enable Post-Quantum TLS. + * */ + private boolean postQuantumTlsEnabled = false; + /** * Default constructor for the SecretCacheConfiguration object. * @@ -291,4 +295,42 @@ public SecretCacheConfiguration withForceRefreshJitterMillis(long forceRefreshJi return this; } + /** + * Returns whether Post-Quantum TLS is enabled. + * + * @return true if Post-Quantum TLS is enabled, false otherwise. + */ + public boolean isPostQuantumTlsEnabled() { + return this.postQuantumTlsEnabled; + } + + /** + * Sets whether to enable Post-Quantum TLS. + * + *

Note: This setting is mutually exclusive with providing a custom client via + * {@link #withClient(SecretsManagerClient)}. If both are specified, an + * {@link IllegalArgumentException} will be thrown. + * + * @param postQuantumTlsEnabled + * Whether to enable Post-Quantum TLS. + */ + public void setPostQuantumTlsEnabled(boolean postQuantumTlsEnabled) { + this.postQuantumTlsEnabled = postQuantumTlsEnabled; + } + + /** + * Sets whether to enable Post-Quantum TLS. + * + *

Note: This setting is mutually exclusive with providing a custom client via + * {@link #withClient(SecretsManagerClient)}. If both are specified, an + * {@link IllegalArgumentException} will be thrown. + * + * @param postQuantumTlsEnabled + * Whether to enable Post-Quantum TLS. + * @return The updated SecretCacheConfiguration object with the new PQTLS setting. + */ + public SecretCacheConfiguration withPostQuantumTlsEnabled(boolean postQuantumTlsEnabled) { + this.setPostQuantumTlsEnabled(postQuantumTlsEnabled); + return this; + } } diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java index 4f4e93b..3e96373 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java @@ -482,4 +482,48 @@ public void basicSecretCacheVersionWithNullStageTest() { sc.close(); } + @Test + public void testPostQuantumTlsConfiguration() { + // Test default is false + SecretCacheConfiguration config = new SecretCacheConfiguration(); + Assert.assertFalse(config.isPostQuantumTlsEnabled()); + + // Test setter + config.setPostQuantumTlsEnabled(true); + Assert.assertTrue(config.isPostQuantumTlsEnabled()); + + // Test fluent method + SecretCacheConfiguration config2 = new SecretCacheConfiguration() + .withPostQuantumTlsEnabled(true); + Assert.assertTrue(config2.isPostQuantumTlsEnabled()); + } + + @Test(expectedExceptions = { IllegalArgumentException.class }) + public void testSecretCacheWithPQTLSEnabled() { + // Verify that providing both client and PQTLS flag throws exception + SecretCacheConfiguration config = new SecretCacheConfiguration() + .withClient(asm) + .withPostQuantumTlsEnabled(true); + + new SecretCache(config); + } + + @Test + public void testSecretCacheWithPQTLSEnabledNoClient() { + String originalRegion = System.getProperty("aws.region"); + try { + System.setProperty("aws.region", "us-east-1"); + SecretCacheConfiguration config = new SecretCacheConfiguration() + .withPostQuantumTlsEnabled(true); // No .withClient() call + SecretCache cache = new SecretCache(config); + Assert.assertNotNull(cache); + cache.close(); + } finally { + if (originalRegion != null) { + System.setProperty("aws.region", originalRegion); + } else { + System.clearProperty("aws.region"); + } + } + } }