diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3e6907b..880d548 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -25,4 +25,4 @@ jobs: - name: Build with Maven run: mvn -B package --file pom.xml - name: Codecov - uses: codecov/codecov-action@v3.1.0 + uses: codecov/codecov-action@v3.1.1 diff --git a/README.md b/README.md index 9737f30..03745d9 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ You can get the latest release from Maven: com.amazonaws.secretsmanager aws-secretsmanager-caching-java - 1.0.2 + 2.0.0 ``` diff --git a/pom.xml b/pom.xml index 166f3b0..80e00d1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.amazonaws.secretsmanager aws-secretsmanager-caching-java - 1.0.2 + 2.0.0 jar @@ -38,26 +38,24 @@ 1.8 1.8 UTF-8 - 3.1.2 - 3.0.5 - com.amazonaws - aws-java-sdk-secretsmanager - 1.12.264 + software.amazon.awssdk + secretsmanager + 2.20.93 org.testng testng - 7.7.0 + 7.8.0 test org.mockito - mockito-all - 1.10.19 + mockito-core + 5.4.0 test @@ -66,7 +64,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.11.0 1.8 1.8 @@ -78,7 +76,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources @@ -91,7 +89,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.0 + 3.5.0 attach-javadocs @@ -103,10 +101,9 @@ maven-checkstyle-plugin - ${checkstyle.plugin.version} + 3.3.0 ${basedir}/config/checkstyle/checkstyle.xml - ${project.build.sourceEncoding} true true false @@ -126,7 +123,7 @@ org.codehaus.mojo findbugs-maven-plugin - ${findbugs.plugin.version} + 3.0.5 Max Low @@ -146,7 +143,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.10 prepare-agent @@ -174,7 +171,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 sign-artifacts diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java index fcd62a5..d0c2672 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java @@ -12,13 +12,17 @@ */ package com.amazonaws.secretsmanager.caching; +import java.nio.ByteBuffer; + import com.amazonaws.secretsmanager.caching.cache.LRUCache; import com.amazonaws.secretsmanager.caching.cache.SecretCacheItem; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; -import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder; -import com.amazonaws.services.secretsmanager.model.GetSecretValueResult; +import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; -import java.nio.ByteBuffer; +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; /** * Provides the primary entry-point to the AWS Secrets Manager client cache SDK. @@ -47,58 +51,64 @@ public class SecretCache implements AutoCloseable { private final SecretCacheConfiguration config; /** The AWS Secrets Manager client to use when requesting secrets. */ - private final AWSSecretsManager client; + private final SecretsManagerClient client; /** - * Constructs a new secret cache using the standard AWS Secrets Manager client with default options. + * Constructs a new secret cache using the standard AWS Secrets Manager client + * with default options. */ public SecretCache() { - this(AWSSecretsManagerClientBuilder.standard()); + this(SecretsManagerClient.builder()); } - /** - * Constructs a new secret cache using an AWS Secrets Manager client created using the + * Constructs a new secret cache using an AWS Secrets Manager client created + * using the * provided builder. * - * @param builder - * The builder to use for creating the AWS Secrets Manager client. + * @param builder The builder to use for creating the AWS Secrets Manager + * client. */ - public SecretCache(AWSSecretsManagerClientBuilder builder) { - this(null == builder ? - AWSSecretsManagerClientBuilder.standard().build() : - builder.build()); + public SecretCache(SecretsManagerClientBuilder builder) { + this(new SecretCacheConfiguration().withClient(builder + .overrideConfiguration( + builder.overrideConfiguration().toBuilder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, VersionInfo.USER_AGENT) + .build()) + .build())); } /** * Constructs a new secret cache using the provided AWS Secrets Manager client. * - * @param client - * The AWS Secrets Manager client to use for requesting secret values. + * @param client The AWS Secrets Manager client to use for requesting secret + * values. */ - public SecretCache(AWSSecretsManager client) { + public SecretCache(SecretsManagerClient client) { this(new SecretCacheConfiguration().withClient(client)); } /** * Constructs a new secret cache using the provided cache configuration. * - * @param config - * The secret cache configuration. + * @param config The secret cache configuration. */ public SecretCache(SecretCacheConfiguration config) { - if (null == config) { config = new SecretCacheConfiguration(); } + if (null == config) { + config = new SecretCacheConfiguration(); + } this.cache = new LRUCache(config.getMaxCacheSize()); this.config = config; - this.client = config.getClient() != null ? config.getClient() : - AWSSecretsManagerClientBuilder.standard().build(); + 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(); } /** * Method to retrieve the cached secret item. * - * @param secretId - * The identifier for the secret being requested. + * @param secretId The identifier for the secret being requested. * @return The cached secret item */ private SecretCacheItem getCachedSecret(final String secretId) { @@ -114,39 +124,40 @@ private SecretCacheItem getCachedSecret(final String secretId) { /** * Method to retrieve a string secret from AWS Secrets Manager. * - * @param secretId - * The identifier for the secret being requested. + * @param secretId The identifier for the secret being requested. * @return The string secret */ public String getSecretString(final String secretId) { SecretCacheItem secret = this.getCachedSecret(secretId); - GetSecretValueResult gsv = secret.getSecretValue(); - if (null == gsv) { return null; } - return gsv.getSecretString(); + GetSecretValueResponse gsv = secret.getSecretValue(); + if (null == gsv) { + return null; + } + return gsv.secretString(); } /** * Method to retrieve a binary secret from AWS Secrets Manager. * - * @param secretId - * The identifier for the secret being requested. + * @param secretId The identifier for the secret being requested. * @return The binary secret */ public ByteBuffer getSecretBinary(final String secretId) { SecretCacheItem secret = this.getCachedSecret(secretId); - GetSecretValueResult gsv = secret.getSecretValue(); - if (null == gsv) { return null; } - return gsv.getSecretBinary(); + GetSecretValueResponse gsv = secret.getSecretValue(); + if (null == gsv) { + return null; + } + return gsv.secretBinary().asByteBuffer(); } /** * Method to force the refresh of a cached secret state. * - * @param secretId - * The identifier for the secret being refreshed. + * @param secretId The identifier for the secret being refreshed. * @return True if the refresh completed without error. - * @throws InterruptedException - * If the thread is interrupted while waiting for the refresh. + * @throws InterruptedException If the thread is interrupted while waiting for + * the refresh. */ public boolean refreshNow(final String secretId) throws InterruptedException { SecretCacheItem secret = this.getCachedSecret(secretId); diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java index 9b796b3..f5e6821 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java @@ -13,10 +13,10 @@ package com.amazonaws.secretsmanager.caching; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; - import java.util.concurrent.TimeUnit; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; + /** * Cache configuration options such as max cache size, ttl for cached items, etc. @@ -34,7 +34,7 @@ public class SecretCacheConfiguration { public static final String DEFAULT_VERSION_STAGE = "AWSCURRENT"; /** The client this cache instance will use for accessing AWS Secrets Manager. */ - private AWSSecretsManager client = null; + private SecretsManagerClient client = null; /** Used to hook in-memory cache updates. */ private SecretCacheHook cacheHook = null; @@ -71,7 +71,7 @@ public SecretCacheConfiguration() { * * @return The AWS Secrets Manager client. */ - public AWSSecretsManager getClient() { + public SecretsManagerClient getClient() { return client; } @@ -83,7 +83,7 @@ public AWSSecretsManager getClient() { * @param client * The AWS Secrets Manager client. */ - public void setClient(AWSSecretsManager client) { + public void setClient(SecretsManagerClient client) { this.client = client; } @@ -95,7 +95,7 @@ public void setClient(AWSSecretsManager client) { * The AWS Secrets Manager client. * @return The updated ClientConfiguration object with the new client setting. */ - public SecretCacheConfiguration withClient(AWSSecretsManager client) { + public SecretCacheConfiguration withClient(SecretsManagerClient client) { this.setClient(client); return this; } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java index a53615b..9c0ed78 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java @@ -13,23 +13,24 @@ package com.amazonaws.secretsmanager.caching.cache; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; -import com.amazonaws.services.secretsmanager.model.DescribeSecretRequest; -import com.amazonaws.services.secretsmanager.model.DescribeSecretResult; -import com.amazonaws.services.secretsmanager.model.GetSecretValueResult; -import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; - import java.util.Objects; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; +import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; + +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest; +import software.amazon.awssdk.services.secretsmanager.model.DescribeSecretResponse; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; + /** * The cached secret item which contains information from the DescribeSecret * request to AWS Secrets Manager along with any associated GetSecretValue * results. * */ -public class SecretCacheItem extends SecretCacheObject { +public class SecretCacheItem extends SecretCacheObject { /** The cached secret value versions for this cached secret. */ private LRUCache versions = new LRUCache(10); @@ -52,7 +53,7 @@ public class SecretCacheItem extends SecretCacheObject { * Cache configuration. */ public SecretCacheItem(final String secretId, - final AWSSecretsManager client, + final SecretsManagerClient client, final SecretCacheConfiguration config) { super(secretId, client, config); } @@ -98,28 +99,26 @@ protected boolean isRefreshNeeded() { * @return The result from AWS Secrets Manager for the refresh. */ @Override - protected DescribeSecretResult executeRefresh() { - DescribeSecretResult describeSecretResult = client.describeSecret( - updateUserAgent(new DescribeSecretRequest() - .withSecretId(this.secretId))); + protected DescribeSecretResponse executeRefresh() { + DescribeSecretResponse describeSecretResponse = client.describeSecret(DescribeSecretRequest.builder().secretId(this.secretId).build()); long ttl = this.config.getCacheItemTTL(); this.nextRefreshTime = System.currentTimeMillis() + ThreadLocalRandom.current().nextLong(ttl / 2,ttl + 1) ; - return describeSecretResult; + return describeSecretResponse; } /** * Return the secret version based on the current state of the secret. * - * @param describeResult + * @param describeResponse * The result of the Describe Secret request to AWS Secrets Manager. * @return The cached secret version. */ - private SecretCacheVersion getVersion(DescribeSecretResult describeResult) { - if (null == describeResult) { return null; } - if (null == describeResult.getVersionIdsToStages()) { return null; } - Optional currentVersionId = describeResult.getVersionIdsToStages().entrySet() + private SecretCacheVersion getVersion(DescribeSecretResponse describeResponse) { + if (null == describeResponse) { return null; } + if (null == describeResponse.versionIdsToStages()) { return null; } + Optional currentVersionId = describeResponse.versionIdsToStages().entrySet() .stream() .filter(Objects::nonNull) .filter(x -> x.getValue() != null) @@ -141,13 +140,13 @@ private SecretCacheVersion getVersion(DescribeSecretResult describeResult) { /** * Return the cached result from AWS Secrets Manager for GetSecretValue. * - * @param describeResult + * @param describeResponse * The result of the Describe Secret request to AWS Secrets Manager. * @return The cached GetSecretValue result. */ @Override - protected GetSecretValueResult getSecretValue(DescribeSecretResult describeResult) { - SecretCacheVersion version = getVersion(describeResult); + protected GetSecretValueResponse getSecretValue(DescribeSecretResponse describeResponse) { + SecretCacheVersion version = getVersion(describeResponse); if (null == version) { return null; } return version.getSecretValue(); } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java index 7fe473a..b1eee46 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java @@ -13,16 +13,12 @@ package com.amazonaws.secretsmanager.caching.cache; -import com.amazonaws.AmazonWebServiceRequest; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; -import com.amazonaws.services.secretsmanager.model.GetSecretValueResult; -import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; +import java.util.concurrent.ThreadLocalRandom; + import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; /** * Basic secret caching object. @@ -55,7 +51,7 @@ public abstract class SecretCacheObject { protected final Object lock = new Object(); /** The AWS Secrets Manager client to use for requesting secrets. */ - protected final AWSSecretsManager client; + protected final SecretsManagerClient client; /** The Secret Cache Configuration. */ protected final SecretCacheConfiguration config; @@ -97,7 +93,7 @@ public abstract class SecretCacheObject { * The secret cache configuration. */ public SecretCacheObject(final String secretId, - final AWSSecretsManager client, + final SecretsManagerClient client, final SecretCacheConfiguration config) { this.secretId = secretId; this.client = client; @@ -119,17 +115,12 @@ public SecretCacheObject(final String secretId, * @return The cached GetSecretValue result based on the current * cached state. */ - protected abstract GetSecretValueResult getSecretValue(T result); + protected abstract GetSecretValueResponse getSecretValue(T result); public abstract boolean equals(Object obj); public abstract int hashCode(); public abstract String toString(); - protected U updateUserAgent(U request) { - request.getRequestClientOptions().appendUserAgent(VersionInfo.USER_AGENT); - return request; - } - /** * Return the typed result object * @@ -211,42 +202,6 @@ private void refresh() { } } - /** - * Method to clone a List of String - * - * @param l - * The List of String - * @return The cloned List of String. - */ - private List clone(List l) { - if (null == l) { return null; } - return new ArrayList<>(l); - } - - /** - * Method to clone a ByteBuffer - * - * @param b - * The ByteBuffer to be cloned. - * @return The cloned ByteBuffer. - */ - private ByteBuffer clone(ByteBuffer b) { - // Nothing to clone, return null. - if (null == b) { return null; } - b.rewind(); - ByteBuffer clone = ByteBuffer.allocate(b.remaining()); - - if (b.hasArray()) { - System.arraycopy(b.array(), 0, clone.array(), 0, b.remaining()); - } - else { - clone.put(b.duplicate()); - clone.flip(); - } - - return clone; - } - /** * Method to force the refresh of a cached secret state. * @@ -285,25 +240,14 @@ public boolean refreshNow() throws InterruptedException { * * @return The cached GetSecretValue result. */ - public GetSecretValueResult getSecretValue() { + public GetSecretValueResponse getSecretValue() { synchronized (lock) { refresh(); if (null == this.data) { if (null != this.exception) { throw this.exception; } } - GetSecretValueResult gsv = this.getSecretValue(this.getResult()); - - // If there is no cached result, return null. - if (null == gsv) { return null; } - - // We want to clone the result to prevent callers from modifying - // the cached data. - gsv = gsv.clone(); - // The prior clone did not perform a deep clone of all objects. - // Handle cloning the byte buffer it one exists. - gsv.setSecretBinary(clone(gsv.getSecretBinary())); - gsv.setVersionStages(clone(gsv.getVersionStages())); - return gsv; + + return this.getSecretValue(this.getResult()); } } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java index f8e7ab8..ec98dbf 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java @@ -13,18 +13,19 @@ package com.amazonaws.secretsmanager.caching.cache; +import java.util.Objects; + import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; -import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest; -import com.amazonaws.services.secretsmanager.model.GetSecretValueResult; -import java.util.Objects; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; /** * The cached secret version item which contains information from the * GetSecretValue AWS Secrets Manager request. */ -public class SecretCacheVersion extends SecretCacheObject { +public class SecretCacheVersion extends SecretCacheObject { /** The version identifier to use when requesting the secret value. */ private final String versionId; @@ -48,7 +49,7 @@ public class SecretCacheVersion extends SecretCacheObject */ public SecretCacheVersion(final String secretId, final String versionId, - final AWSSecretsManager client, + final SecretsManagerClient client, final SecretCacheConfiguration config) { super(secretId, client, config); this.versionId = versionId; @@ -80,10 +81,9 @@ public String toString() { * @return The result from AWS Secrets Manager for the refresh. */ @Override - protected GetSecretValueResult executeRefresh() { + protected GetSecretValueResponse executeRefresh() { return client.getSecretValue( - updateUserAgent(new GetSecretValueRequest() - .withSecretId(this.secretId).withVersionId(this.versionId))); + GetSecretValueRequest.builder().secretId(this.secretId).versionId(this.versionId).build()); } /** @@ -94,7 +94,7 @@ protected GetSecretValueResult executeRefresh() { * @return The cached GetSecretValue result. */ @Override - protected GetSecretValueResult getSecretValue(GetSecretValueResult gsvResult) { + protected GetSecretValueResponse getSecretValue(GetSecretValueResponse gsvResult) { return gsvResult; } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/internal/VersionInfo.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/internal/VersionInfo.java index aa212ad..d0fa0a9 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/internal/VersionInfo.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/internal/VersionInfo.java @@ -14,22 +14,23 @@ package com.amazonaws.secretsmanager.caching.cache.internal; /** - * This class specifies the versioning system for the AWS SecretsManager caching client. + * This class specifies the versioning system for the AWS SecretsManager caching + * client. */ public class VersionInfo { + public static final String VERSION_NUM = "2"; // incremented for design changes that break backward compatibility. - public static final String VERSION_NUM = "1"; - // incremented for major changes to the implementation - public static final String MAJOR_REVISION_NUM = "1"; + public static final String MAJOR_REVISION_NUM = VERSION_NUM; // incremented for minor changes to the implementation public static final String MINOR_REVISION_NUM = "0"; // incremented for releases containing an immediate bug fix. public static final String BUGFIX_REVISION_NUM = "0"; - public static final String RELEASE_VERSION = VERSION_NUM + "." + MAJOR_REVISION_NUM + "." + MINOR_REVISION_NUM + public static final String RELEASE_VERSION = MAJOR_REVISION_NUM + "." + MINOR_REVISION_NUM + "." + BUGFIX_REVISION_NUM; public static final String USER_AGENT = "AwsSecretCache/" + RELEASE_VERSION; - private VersionInfo(){} + private VersionInfo() { + } } \ No newline at end of file diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java index 24b3f54..40e64fa 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java @@ -13,49 +13,52 @@ package com.amazonaws.secretsmanager.caching; -import com.amazonaws.services.secretsmanager.AWSSecretsManager; -import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder; -import com.amazonaws.services.secretsmanager.model.DescribeSecretResult; -import com.amazonaws.services.secretsmanager.model.GetSecretValueResult; -import com.amazonaws.SdkClientException; - -import org.testng.annotations.Test; -import org.testng.annotations.BeforeMethod; -import org.testng.Assert; - -import org.mockito.MockitoAnnotations; -import org.mockito.Mockito; -import org.mockito.Mock; - import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.IntConsumer; +import org.mockito.ArgumentMatcher; +import org.mockito.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; +import software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest; +import software.amazon.awssdk.services.secretsmanager.model.DescribeSecretResponse; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; + /** - * SecretCacheTest. + * SecretCacheTest. */ public class SecretCacheTest { @Mock - private AWSSecretsManager asm; + private SecretsManagerClient asm; @Mock - private DescribeSecretResult describeSecretResult; + private DescribeSecretResponse describeSecretResponse; - private GetSecretValueResult getSecretValueResult = new GetSecretValueResult(); + private GetSecretValueResponse getSecretValueResponse = GetSecretValueResponse.builder() + .versionStages(Arrays.asList("v1")).build(); @Mock private SecretCacheConfiguration secretCacheConfiguration; @BeforeMethod public void setUp() { - getSecretValueResult = new GetSecretValueResult().withVersionStages(Arrays.asList("v1")); - MockitoAnnotations.initMocks(this); - Mockito.when(asm.describeSecret(Mockito.any())).thenReturn(describeSecretResult); - Mockito.when(asm.getSecretValue(Mockito.any())).thenReturn(getSecretValueResult); + MockitoAnnotations.openMocks(this); } private static void repeat(int number, IntConsumer c) { @@ -64,36 +67,21 @@ private static void repeat(int number, IntConsumer c) { } } - @Test(expectedExceptions = {SdkClientException.class}) - public void exceptionSecretCacheTest() { - SecretCache sc = new SecretCache(); - sc.getSecretString(""); - sc.close(); - } - - @Test(expectedExceptions = {SdkClientException.class}) - public void exceptionSecretCacheConfigTest() { - try (SecretCache sc = new SecretCache(new SecretCacheConfiguration() - .withCacheItemTTL(SecretCacheConfiguration.DEFAULT_CACHE_ITEM_TTL) - .withMaxCacheSize(SecretCacheConfiguration.DEFAULT_MAX_CACHE_SIZE) - .withVersionStage(SecretCacheConfiguration.DEFAULT_VERSION_STAGE))) { - sc.getSecretString(""); - } - } - @Test public void secretCacheConstructorTest() { // coverage for null parameters to constructor SecretCache sc1 = null; SecretCache sc2 = null; try { - sc1 = new SecretCache((SecretCacheConfiguration)null); + sc1 = new SecretCache((SecretCacheConfiguration) null); sc1.close(); - } catch (Exception e) {} + } catch (Exception e) { + } try { - sc2 = new SecretCache((AWSSecretsManagerClientBuilder)null); + sc2 = new SecretCache((SecretsManagerClientBuilder) null); sc2.close(); - } catch (Exception e) {} + } catch (Exception e) { + } } @Test @@ -101,17 +89,22 @@ public void basicSecretCacheTest() { final String secret = "basicSecretCacheTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); - getSecretValueResult.setSecretBinary(ByteBuffer.wrap(secret.getBytes())); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + .secretBinary(SdkBytes.fromByteArray(secret.getBytes())); + getSecretValueResponse = resBuilder.build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes()))); @@ -123,20 +116,30 @@ public void hookSecretCacheTest() { final String secret = "hookSecretCacheTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); - getSecretValueResult.setSecretBinary(ByteBuffer.wrap(secret.getBytes())); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + .secretBinary(SdkBytes.fromByteArray(secret.getBytes())); + getSecretValueResponse = resBuilder.build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); class Hook implements SecretCacheHook { private HashMap map = new HashMap(); + public Object put(final Object o) { Integer key = map.size(); map.put(key, o); return key; } + public Object get(final Object o) { - return map.get((Integer)o); + return map.get((Integer) o); + } + + public int getCount() { + return map.size(); } - public int getCount() { return map.size(); } } Hook hook = new Hook(); SecretCache sc = new SecretCache(new SecretCacheConfiguration() @@ -147,8 +150,8 @@ public Object get(final Object o) { repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes()))); @@ -161,18 +164,21 @@ public void secretCacheNullStagesTest() { final String secret = "basicSecretCacheTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); - getSecretValueResult.setSecretBinary(ByteBuffer.wrap(secret.getBytes())); - getSecretValueResult.setVersionStages(null); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + .secretBinary(SdkBytes.fromByteArray(secret.getBytes())).versionStages((Collection) null); + getSecretValueResponse = resBuilder.build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes()))); @@ -184,25 +190,30 @@ public void basicSecretCacheRefreshNowTest() throws Throwable { final String secret = "basicSecretCacheRefreshNowTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); - getSecretValueResult.setSecretBinary(ByteBuffer.wrap(secret.getBytes())); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + .secretBinary(SdkBytes.fromByteArray(secret.getBytes())); + getSecretValueResponse = resBuilder.build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); sc.refreshNow(""); - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); sc.close(); } @@ -210,23 +221,28 @@ public void basicSecretCacheRefreshNowTest() throws Throwable { public void basicSecretCacheByteBufferTest() { final String secret = "basicSecretCacheByteBufferTest"; Map> versionMap = new HashMap>(); - ByteBuffer buffer = ByteBuffer.allocateDirect(secret.getBytes().length); - buffer.put(secret.getBytes()); + ByteBuffer buffer = ByteBuffer.allocate(secret.getBytes(StandardCharsets.UTF_8).length); + + buffer.put(secret.getBytes(StandardCharsets.UTF_8)).rewind(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); - getSecretValueResult.setSecretBinary(buffer); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + + GetSecretValueResponse diff = GetSecretValueResponse.builder().secretBinary(SdkBytes.fromByteBuffer(buffer)) + .build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(diff); + SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result - repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); + repeat(10, n -> Assert.assertEquals(StandardCharsets.UTF_8.decode(sc.getSecretBinary("")).toString(), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); - repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), - ByteBuffer.wrap(secret.getBytes()))); + Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes())); sc.close(); } @@ -236,19 +252,42 @@ public void basicSecretCacheMultipleTest() { final String secretB = "basicSecretCacheMultipleTestB"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secretA); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + getSecretValueResponse = GetSecretValueResponse.builder().secretString(secretA).build(); + + GetSecretValueResponse res2 = GetSecretValueResponse.builder().secretString(secretB).build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + + Mockito.when(asm.getSecretValue(ArgumentMatchers.argThat(new ArgumentMatcher() { + @Override + public boolean matches(GetSecretValueRequest argument) { + if (argument == null) { + return false; + } + return argument.secretId().equals("SecretA"); + } + }))).thenReturn(getSecretValueResponse); + + Mockito.when(asm.getSecretValue(ArgumentMatchers.argThat(new ArgumentMatcher() { + @Override + public boolean matches(GetSecretValueRequest argument) { + if (argument == null) { + return false; + } + return argument.secretId().equals("SecretB"); + } + }))).thenReturn(res2); + SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString("SecretA"), secretA)); - - getSecretValueResult.setSecretString(secretB); repeat(10, n -> Assert.assertEquals(sc.getSecretString("SecretB"), secretB)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(2)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(2)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); sc.close(); } @@ -257,8 +296,12 @@ public void basicSecretCacheRefreshTest() throws Throwable { final String secret = "basicSecretCacheRefreshTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + SecretCache sc = new SecretCache(new SecretCacheConfiguration() .withClient(asm) .withCacheItemTTL(500)); @@ -267,15 +310,15 @@ public void basicSecretCacheRefreshTest() throws Throwable { repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); // Wait long enough to expire the TTL on the cached item. Thread.sleep(600); repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that the refresh occurred after the ttl - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); } @Test @@ -283,8 +326,12 @@ public void secretCacheRefreshAfterVersionChangeTest() throws Throwable { final String secret = "secretCacheRefreshAfterVersionChangeTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + + getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(new SecretCacheConfiguration() .withClient(asm) .withCacheItemTTL(500)); @@ -293,8 +340,8 @@ public void secretCacheRefreshAfterVersionChangeTest() throws Throwable { repeat(5, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); // Wait long enough to expire the TTL on the cached item. Thread.sleep(600); @@ -303,29 +350,33 @@ public void secretCacheRefreshAfterVersionChangeTest() throws Throwable { versionMap.put("versionIdNew", Arrays.asList("AWSCURRENT")); repeat(5, n -> Assert.assertEquals(sc.getSecretString(""), secret)); // Verify that the refresh occurred after the ttl - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(2)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(2)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); } @Test public void basicSecretCacheTestNoVersions() { final String secret = "basicSecretCacheTestNoVersion"; - getSecretValueResult.setSecretString(secret); + + getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result - repeat(10, m -> Assert.assertEquals(sc.getSecretString(""), null)); - repeat(10, m -> Assert.assertEquals(sc.getSecretBinary(""), null)); + repeat(10, m -> Assert.assertNull(sc.getSecretString(""))); + repeat(10, m -> Assert.assertNull(sc.getSecretBinary(""))); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(0)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(0)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); sc.close(); } - @Test(expectedExceptions = {RuntimeException.class}) + @Test(expectedExceptions = { RuntimeException.class }) public void basicSecretCacheExceptionTest() { - Mockito.when(asm.describeSecret(Mockito.any())).thenThrow(new RuntimeException()); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenThrow(new RuntimeException()); SecretCache sc = new SecretCache(asm); sc.getSecretString(""); sc.close(); @@ -333,19 +384,19 @@ public void basicSecretCacheExceptionTest() { @Test public void basicSecretCacheExceptionRefreshNowTest() throws Throwable { - Mockito.when(asm.describeSecret(Mockito.any())).thenThrow(new RuntimeException()); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenThrow(new RuntimeException()); SecretCache sc = new SecretCache(asm); Assert.assertFalse(sc.refreshNow("")); - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); Assert.assertFalse(sc.refreshNow("")); - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); sc.close(); } @Test public void basicSecretCacheExceptionRetryTest() throws Throwable { final int retryCount = 10; - Mockito.when(asm.describeSecret(Mockito.any())).thenThrow(new RuntimeException()); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenThrow(new RuntimeException()); SecretCache sc = new SecretCache(asm); for (int n = 0; n < retryCount; ++n) { try { @@ -354,7 +405,7 @@ public void basicSecretCacheExceptionRetryTest() throws Throwable { } catch (RuntimeException ex) { } } - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); // Wait the backoff interval before retrying failed requests to verify // a retry will be performed. @@ -362,15 +413,16 @@ public void basicSecretCacheExceptionRetryTest() throws Throwable { try { sc.getSecretString(""); Assert.fail("Exception should have been thrown!"); - } catch (RuntimeException ex) {} + } catch (RuntimeException ex) { + } // The api call should have been retried after the delay. - Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any()); + Mockito.verify(asm, Mockito.times(2)).describeSecret(Mockito.any(DescribeSecretRequest.class)); sc.close(); } @Test public void basicSecretCacheNullTest() { - Mockito.when(asm.describeSecret(Mockito.any())).thenReturn(null); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(null); SecretCache sc = new SecretCache(asm); Assert.assertNull(sc.getSecretString("")); sc.close(); @@ -378,7 +430,7 @@ public void basicSecretCacheNullTest() { @Test public void basicSecretCacheNullStagesTest() { - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(null); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(null); SecretCache sc = new SecretCache(asm); Assert.assertNull(sc.getSecretString("")); sc.close(); @@ -389,16 +441,20 @@ public void basicSecretCacheVersionWithNullStageTest() { final String secret = "basicSecretCacheTest"; Map> versionMap = new HashMap>(); versionMap.put("versionId", null); - Mockito.when(describeSecretResult.getVersionIdsToStages()).thenReturn(versionMap); - getSecretValueResult.setSecretString(secret); + Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); + + getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), null)); // Verify that multiple requests did not call the API - Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any()); - Mockito.verify(asm, Mockito.times(0)).getSecretValue(Mockito.any()); + Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); + Mockito.verify(asm, Mockito.times(0)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); sc.close(); } diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItemTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItemTest.java index 166d759..4d25c04 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItemTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItemTest.java @@ -13,8 +13,8 @@ package com.amazonaws.secretsmanager.caching.cache; -import org.testng.annotations.Test; import org.testng.Assert; +import org.testng.annotations.Test; public class SecretCacheItemTest { @Test diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java new file mode 100644 index 0000000..d28b555 --- /dev/null +++ b/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java @@ -0,0 +1,18 @@ +package com.amazonaws.secretsmanager.caching.internal; + +import java.util.regex.Pattern; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; + +public class VersionInfoTest { + @Test + public void versionInfoIsValid() { + String ua = VersionInfo.USER_AGENT; + Pattern p = Pattern.compile("AwsSecretCache/\\d+.\\d+.\\d+"); + + Assert.assertTrue(p.matcher(ua).matches(), "User agent " + ua + " is not valid"); + } +}