diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bb436fe..0d669f8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,6 +11,12 @@ updates: update-types: - minor - patch + dev-dependencies: + applies-to: version-updates + dependency-type: development + update-types: + - minor + - patch - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 648e92a..a158e0f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [ "master" ] + branches: [ "master", "v2" ] pull_request: # The branches below must be a subset of the branches above - branches: [ "master" ] + branches: [ "master", "v2" ] schedule: - cron: '17 12 * * 1' @@ -36,11 +36,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v5 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,7 +54,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -67,4 +67,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0c80932..871cf8b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,24 +5,32 @@ name: Java CI with Maven on: push: - branches: [ "master" ] + branches: ["master", "v2"] pull_request: - branches: [ "master" ] + branches: ["master", "v2"] + +permissions: + contents: read + id-token: write jobs: build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v3 - with: - java-version: '11' - distribution: 'temurin' - cache: maven - - name: Build with Maven - run: mvn -B package --file pom.xml - - name: Codecov - uses: codecov/codecov-action@v3.1.0 + - uses: actions/checkout@v5 + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: "21" + distribution: "corretto" + cache: maven + - name: Maven version + run: mvn --version + - name: Build with Maven + run: mvn clean package + - name: Codecov + uses: codecov/codecov-action@v5 + with: + fail_ci_if_error: true + use_oidc: true diff --git a/pom.xml b/pom.xml index 166f3b0..eb5410b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.amazonaws.secretsmanager aws-secretsmanager-caching-java - 1.0.2 + 1.1.0 jar @@ -35,41 +35,43 @@ - 1.8 - 1.8 UTF-8 - 3.1.2 - 3.0.5 com.amazonaws aws-java-sdk-secretsmanager - 1.12.264 + 1.12.793 org.testng testng - 7.7.0 + 7.11.0 test org.mockito - mockito-all - 1.10.19 + mockito-core + 5.20.0 test + + com.github.spotbugs + spotbugs-annotations + 4.9.8 + compile + + org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.13.0 - 1.8 - 1.8 + 8 -Xlint:all true true @@ -78,7 +80,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 attach-sources @@ -91,7 +93,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.0 + 3.12.0 attach-javadocs @@ -103,10 +105,9 @@ maven-checkstyle-plugin - ${checkstyle.plugin.version} + 3.6.0 ${basedir}/config/checkstyle/checkstyle.xml - ${project.build.sourceEncoding} true true false @@ -124,9 +125,9 @@ - org.codehaus.mojo - findbugs-maven-plugin - ${findbugs.plugin.version} + com.github.spotbugs + spotbugs-maven-plugin + 4.9.8.1 Max Low @@ -146,7 +147,7 @@ org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.14 prepare-agent @@ -174,7 +175,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.2.8 sign-artifacts @@ -186,14 +187,12 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 + org.sonatype.central + central-publishing-maven-plugin + 0.9.0 true - sonatype-nexus-staging - https://aws.oss.sonatype.org - true + central diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java index 9b796b3..cd15617 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java @@ -14,6 +14,7 @@ package com.amazonaws.secretsmanager.caching; import com.amazonaws.services.secretsmanager.AWSSecretsManager; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.concurrent.TimeUnit; @@ -71,6 +72,7 @@ public SecretCacheConfiguration() { * * @return The AWS Secrets Manager client. */ + @SuppressFBWarnings("EI_EXPOSE_REP") public AWSSecretsManager getClient() { return client; } @@ -83,6 +85,7 @@ public AWSSecretsManager getClient() { * @param client * The AWS Secrets Manager client. */ + @SuppressFBWarnings("EI_EXPOSE_REP2") public void setClient(AWSSecretsManager client) { this.client = client; } @@ -106,6 +109,7 @@ public SecretCacheConfiguration withClient(AWSSecretsManager client) { * * @return The object used to hook in-memory cache updates. */ + @SuppressFBWarnings("EI_EXPOSE_REP") public SecretCacheHook getCacheHook() { return cacheHook; } @@ -117,6 +121,7 @@ public SecretCacheHook getCacheHook() { * @param cacheHook * The interface used to hook the in-memory cache. */ + @SuppressFBWarnings("EI_EXPOSE_REP2") public void setCacheHook(SecretCacheHook cacheHook) { this.cacheHook = cacheHook; } 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..af66a1f 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java @@ -16,6 +16,7 @@ import com.amazonaws.AmazonWebServiceRequest; import com.amazonaws.services.secretsmanager.AWSSecretsManager; import com.amazonaws.services.secretsmanager.model.GetSecretValueResult; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; @@ -23,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicBoolean; /** * Basic secret caching object. @@ -61,7 +63,7 @@ public abstract class SecretCacheObject { protected final SecretCacheConfiguration config; /** A flag to indicate a refresh is needed. */ - private boolean refreshNeeded = true; + private AtomicBoolean refreshNeeded = new AtomicBoolean(true); /** The result of the last AWS Secrets Manager request for this item. */ private Object data = null; @@ -96,6 +98,7 @@ public abstract class SecretCacheObject { * @param config * The secret cache configuration. */ + @SuppressFBWarnings("EI_EXPOSE_REP2") public SecretCacheObject(final String secretId, final AWSSecretsManager client, final SecretCacheConfiguration config) { @@ -160,7 +163,7 @@ private void setResult(T result) { * @return True if the secret item should be refreshed. */ protected boolean isRefreshNeeded() { - if (this.refreshNeeded) { return true; } + if (this.refreshNeeded.get()) { return true; } if (null != this.exception) { // If we encountered an exception on the last attempt // we do not want to keep retrying without a pause between @@ -183,7 +186,7 @@ protected boolean isRefreshNeeded() { */ private void refresh() { if (!this.isRefreshNeeded()) { return; } - this.refreshNeeded = false; + this.refreshNeeded.set(false); try { this.setResult(this.executeRefresh()); this.exception = null; @@ -255,7 +258,7 @@ private ByteBuffer clone(ByteBuffer b) { * If the thread is interrupted while waiting for the refresh. */ public boolean refreshNow() throws InterruptedException { - this.refreshNeeded = true; + this.refreshNeeded.set(true); // When forcing a refresh, always sleep with a random jitter // to prevent coding errors that could be calling refreshNow // in a loop. @@ -285,6 +288,7 @@ public boolean refreshNow() throws InterruptedException { * * @return The cached GetSecretValue result. */ + @SuppressFBWarnings("THROWS_METHOD_THROWS_RUNTIMEEXCEPTION") public GetSecretValueResult getSecretValue() { synchronized (lock) { refresh(); 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..46bedc3 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,20 @@ 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 { - // 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"; - // 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 - + "." + BUGFIX_REVISION_NUM; + /** + * Library version number + */ + public static final String RELEASE_VERSION = "1.1.0"; + /** + * User agent for AWS Secrets Manager API calls. + */ public static final String USER_AGENT = "AwsSecretCache/" + RELEASE_VERSION; - private VersionInfo(){} -} \ No newline at end of file + private VersionInfo() { + } +} diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java index 24b3f54..fe66110 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java @@ -53,7 +53,7 @@ public class SecretCacheTest { @BeforeMethod public void setUp() { getSecretValueResult = new GetSecretValueResult().withVersionStages(Arrays.asList("v1")); - MockitoAnnotations.initMocks(this); + MockitoAnnotations.openMocks(this); Mockito.when(asm.describeSecret(Mockito.any())).thenReturn(describeSecretResult); Mockito.when(asm.getSecretValue(Mockito.any())).thenReturn(getSecretValueResult); } @@ -276,6 +276,7 @@ public void basicSecretCacheRefreshTest() throws Throwable { // 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()); + sc.close(); } @Test @@ -305,6 +306,7 @@ public void secretCacheRefreshAfterVersionChangeTest() throws Throwable { // 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()); + sc.close(); } @Test