
Aws Sdk Java V2 Secrets Manager
- 1.7k installs
- 318 repo stars
- Updated June 22, 2026
- giuseppe-trisciuoglio/developer-kit
aws-sdk-java-v2-secrets-manager is an agent skill that provides aws secrets manager patterns for aws sdk for java 2.x, including secret retrieval, caching, rotation-aware access, and spring boot integration. use when sto
About
aws-sdk-java-v2-secrets-manager is an agent skill from giuseppe-trisciuoglio/developer-kit that provides aws secrets manager patterns for aws sdk for java 2.x, including secret retrieval, caching, rotation-aware access, and spring boot integration. use when storing or reading secrets in java ser. # AWS SDK for Java 2.x - AWS Secrets Manager ## Overview Use this skill to manage application secrets with AWS Secrets Manager from Java services. It focuses on the operational flow that matters in production: - how to retrieve and deserialize secrets safely - when to add local caching - how to integrate secret access into Spring Boot without le Developers invoke aws-sdk-java-v2-secrets-manager during operate/infra work for cloud & infrastructure tasks. The skill documents triggers, prerequisites, and step-by-step workflows grounded in SKILL.md.
- AWS SDK for Java 2.x - AWS Secrets Manager
- Use this skill to manage application secrets with AWS Secrets Manager from Java services.
- It focuses on the operational flow that matters in production:
- how to retrieve and deserialize secrets safely
- how to integrate secret access into Spring Boot without leaking values into logs or configuration files
Aws Sdk Java V2 Secrets Manager by the numbers
- 1,715 all-time installs (skills.sh)
- +123 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #222 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
aws-sdk-java-v2-secrets-manager capabilities & compatibility
- Capabilities
- aws sdk for java 2.x aws secrets manager · use this skill to manage application secrets wit · it focuses on the operational flow that matters · how to retrieve and deserialize secrets safely · how to integrate secret access into spring boot
- Use cases
- orchestration
What aws-sdk-java-v2-secrets-manager says it does
Use this skill to manage application secrets with AWS Secrets Manager from Java services.
It focuses on the operational flow that matters in production:
- how to retrieve and deserialize secrets safely
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill aws-sdk-java-v2-secrets-managerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.7k |
|---|---|
| repo stars | ★ 318 |
| Security audit | 3 / 3 scanners passed |
| Last updated | June 22, 2026 |
| Repository | giuseppe-trisciuoglio/developer-kit ↗ |
What it does
Provides AWS Secrets Manager patterns for AWS SDK for Java 2.x, including secret retrieval, caching, rotation-aware access, and Spring Boot integration. Use when storing or reading secrets in Java ser
Who is it for?
Developers working on cloud & infrastructure during operate tasks.
Skip if: Tasks outside Cloud & Infrastructure scope described in SKILL.md.
When should I use this skill?
Provides AWS Secrets Manager patterns for AWS SDK for Java 2.x, including secret retrieval, caching, rotation-aware access, and Spring Boot integration. Use when storing or reading secrets in Java ser
What you get
Completed cloud & infrastructure workflow aligned with SKILL.md steps.
- spring configuration class
- secretsmanagerclient bean
- cached secret access
Files
AWS SDK for Java 2.x - AWS Secrets Manager
Overview
Use this skill to manage application secrets with AWS Secrets Manager from Java services.
It focuses on the operational flow that matters in production:
- how to retrieve and deserialize secrets safely
- when to add local caching
- how to integrate secret access into Spring Boot without leaking values into logs or configuration files
Keep large API notes and extended setup details in the bundled references.
When to Use
Use this skill when:
- replacing hardcoded passwords, API keys, or tokens with managed secrets
- loading database credentials or third-party API credentials at runtime
- adding caching to reduce Secrets Manager latency and API cost
- handling secret version stages such as
AWSCURRENTandAWSPENDING - wiring secret access into Spring Boot beans or configuration services
- preparing rotation-aware applications or Lambda rotation workflows
Typical trigger phrases include java secrets manager, spring boot secret, aws secret cache, load db credentials from secrets manager, and rotate secret.
Instructions
1. Model the secret before writing access code
Decide:
- the secret name and path convention
- whether the value is plain text or structured JSON
- which application boundary is allowed to read it
- whether the caller needs the latest value on every request or can tolerate a cache
Prefer JSON secrets for multi-field credentials such as database connection details.
2. Create one reusable client per application configuration
Use a single SecretsManagerClient with explicit region and the default credential provider chain unless the environment requires something more specific.
Keep client creation in configuration code, not in business services.
3. Retrieve and deserialize at the boundary layer
At the integration boundary:
- fetch with
GetSecretValueRequest - deserialize JSON into a typed object or validated map
- convert AWS exceptions into application-level errors
- never log
secretString()or include it in thrown exception messages
4. Add caching only where it solves a real problem
Use caching when:
- the secret is read frequently
- latency matters for startup or request handling
- the cost of repeated lookups is material
Document cache TTL expectations clearly, especially if the secret rotates.
5. Design for rotation and staged versions
If the secret rotates:
- read through a thin service layer so cache invalidation and retry behavior stay centralized
- understand which callers must tolerate
AWSPENDINGduring verification workflows - test how the application behaves during stale cache windows or partial rotation failures
6. Validate end-to-end behavior
Before shipping:
- verify IAM permissions and KMS access
- test missing secret, wrong region, and decryption failure paths
- confirm secrets are not surfaced in logs, metrics, or debug endpoints
- prove database or API clients refresh correctly when credentials rotate
Examples
Example 1: Reusable client and typed secret lookup
@Configuration
public class SecretsConfiguration {
@Bean
SecretsManagerClient secretsManagerClient() {
return SecretsManagerClient.builder()
.region(Region.of("eu-south-2"))
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
}
}
@Service
public class SecretsService {
private final SecretsManagerClient client;
private final ObjectMapper objectMapper;
public SecretsService(SecretsManagerClient client, ObjectMapper objectMapper) {
this.client = client;
this.objectMapper = objectMapper;
}
public DatabaseSecret loadDatabaseSecret(String secretId) throws JsonProcessingException {
GetSecretValueResponse response = client.getSecretValue(
GetSecretValueRequest.builder().secretId(secretId).build()
);
return objectMapper.readValue(response.secretString(), DatabaseSecret.class);
}
}Example 2: Cache a hot-path secret lookup
public class CachedSecretsService {
private final SecretCache cache;
public CachedSecretsService(SecretsManagerClient client) {
this.cache = new SecretCache(client);
}
public String apiToken(String secretId) {
return cache.getSecretString(secretId);
}
}Use this pattern only when the application can tolerate the chosen cache refresh behavior.
Best Practices
- Use hierarchical secret names that match domain and environment boundaries.
- Prefer typed JSON deserialization over string parsing scattered across the codebase.
- Keep secret retrieval in infrastructure services rather than controllers or entities.
- Reuse the SDK client and cache instances.
- Combine least-privilege IAM with KMS permissions and CloudTrail visibility.
- Make rotation behavior explicit in code and operational docs.
Constraints and Warnings
- Do not log secret values, serialized secret objects, or decrypted payload fragments.
- Cached values may remain stale during or after rotation depending on TTL and refresh behavior.
- Secret access can fail because of IAM policy, KMS policy, region mismatch, or deleted versions; handle these cases explicitly.
- Automatic rotation is not available for every secret shape or integration.
- Large or frequently changing secrets may not be good candidates for aggressive in-memory caching.
References
references/api-reference.mdreferences/caching-guide.mdreferences/spring-boot-integration.md
Related Skills
aws-sdk-java-v2-coreaws-sdk-java-v2-kmsspring-boot-dependency-injection
import com.amazonaws.secretsmanager.caching.SecretCache;
import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class {{ConfigClass}} {
@Value("${aws.secrets.region}")
private String region;
@Bean
public SecretsManagerClient secretsManagerClient() {
return SecretsManagerClient.builder()
.region(Region.of(region))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(
"${aws.accessKeyId}",
"${aws.secretKey}"
)
))
.build();
}
@Bean
public SecretCache secretCache(SecretsManagerClient secretsClient) {
SecretCacheConfiguration config = SecretCacheConfiguration.builder()
.maxCacheSize(100)
.cacheItemTTL(3600000) // 1 hour
.build();
return new SecretCache(secretsClient, config);
}
}AWS Secrets Manager API Reference
Overview
AWS Secrets Manager provides a service to enable you to store, manage, and retrieve secrets with API version 2017-10-17.
Core Classes
SecretsManagerClient
- Purpose: Synchronous client for AWS Secrets Manager
- Location:
software.amazon.awssdk.services.secretsmanager.SecretsManagerClient - Builder:
SecretsManagerClient.builder()
SecretsManagerAsyncClient
- Purpose: Asynchronous client for AWS Secrets Manager
- Location:
software.amazon.awssdk.services.secretsmanager.SecretsManagerAsyncClient - Builder:
SecretsManagerAsyncClient.builder()
Configuration Classes
SecretsManagerClientBuilder
- Methods:
region(Region region)- Set AWS regioncredentialsProvider(AwsCredentialsProvider credentialsProvider)- Set credentialsbuild()- Create client instance
SecretsManagerServiceClientConfiguration
- Service client settings and configuration
Request Types
CreateSecretRequest
- Fields:
name(String name)- Secret name (required)secretString(String secretString)- Secret valuesecretBinary(SdkBytes secretBinary)- Binary secret valuedescription(String description)- Secret descriptionkmsKeyId(String kmsKeyId)- KMS key for encryptiontags(List<Tag> tags)- Tags for organization
GetSecretValueRequest
- Fields:
secretId(String secretId)- Secret name or ARNversionId(String versionId)- Specific version IDversionStage(String versionStage)- Version stage (e.g., "AWSCURRENT")
UpdateSecretRequest
- Fields:
secretId(String secretId)- Secret name or ARNsecretString(String secretString)- New secret valuesecretBinary(SdkBytes secretBinary)- New binary secret valuekmsKeyId(String kmsKeyId)- KMS key for encryption
DeleteSecretRequest
- Fields:
secretId(String secretId)- Secret name or ARNrecoveryWindowInDays(Long recoveryWindowInDays)- Recovery periodforceDeleteWithoutRecovery(Boolean forceDeleteWithoutRecovery)- Immediate deletion
RotateSecretRequest
- Fields:
secretId(String secretId)- Secret name or ARNrotationLambdaArn(String rotationLambdaArn)- Lambda ARN for rotationrotationRules(RotationRulesType rotationRules)- Rotation configurationrotationSchedule(RotationScheduleType rotationSchedule)- Schedule configuration
Response Types
CreateSecretResponse
- Fields:
arn()- Secret ARNname()- Secret nameversionId()- Version ID
GetSecretValueResponse
- Fields:
arn()- Secret ARNname()- Secret nameversionId()- Version IDsecretString()- Secret value as stringsecretBinary()- Secret value as binaryversionStages()- Version stages
UpdateSecretResponse
- Fields:
arn()- Secret ARNname()- Secret nameversionId()- New version ID
DeleteSecretResponse
- Fields:
arn()- Secret ARNname()- Secret namedeletionDate()- Deletion date/time
RotateSecretResponse
- Fields:
arn()- Secret ARNname()- Secret nameversionId()- New version ID
Paginated Operations
ListSecretsRequest
- Fields:
maxResults(Integer maxResults)- Maximum results per pagenextToken(String nextToken)- Token for next pagefilter(String filter)- Filter criteria
ListSecretsResponse
- Fields:
secretList()- List of secretsnextToken()- Token for next page
Error Handling
SecretsManagerException
- Common error codes:
ResourceNotFoundException- Secret not foundInvalidParameterException- Invalid parametersMalformedPolicyDocumentException- Invalid policy documentInternalServiceErrorException- Internal service errorInvalidRequestException- Invalid requestDecryptionFailure- Decryption failedResourceExistsException- Resource already existsResourceConflictException- Resource conflictValidationException- Validation failed
AWS Secrets Manager Caching Guide
Overview
The AWS Secrets Manager Java caching client enables in-process caching of secrets for Java applications, reducing API calls and improving performance.
Prerequisites
- Java 8+ development environment
- AWS account with Secrets Manager access
- Appropriate IAM permissions
Installation
Maven Dependency
<dependency>
<groupId>com.amazonaws.secretsmanager</groupId>
<artifactId>aws-secretsmanager-caching-java</artifactId>
<version>2.0.0</version> // Use the latest version compatible with sdk v2
</dependency>Gradle Dependency
implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-caching-java:2.0.0'Basic Usage
Simple Cache Setup
import com.amazonaws.secretsmanager.caching.SecretCache;
public class SimpleCacheExample {
private final SecretCache cache = new SecretCache();
public String getSecret(String secretId) {
return cache.getSecretString(secretId);
}
}Cache with Custom SecretsManagerClient
import com.amazonaws.secretsmanager.caching.SecretCache;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
public class ClientAwareCacheExample {
private final SecretCache cache;
public ClientAwareCacheExample(SecretsManagerClient secretsClient) {
this.cache = new SecretCache(secretsClient);
}
public String getSecret(String secretId) {
return cache.getSecretString(secretId);
}
}Cache Configuration
SecretCacheConfiguration
import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration;
public class ConfiguredCacheExample {
private final SecretCache cache;
public ConfiguredCacheExample(SecretsManagerClient secretsClient) {
SecretCacheConfiguration config = new SecretCacheConfiguration()
.withMaxCacheSize(1000) // Maximum number of cached secrets
.withCacheItemTTL(3600000); // 1 hour TTL in milliseconds
this.cache = new SecretCache(secretsClient, config);
}
}Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
maxCacheSize | Integer | 1000 | Maximum number of cached secrets |
cacheItemTTL | Long | 300000 (5 min) | Cache item TTL in milliseconds |
cacheSizeEvictionPercentage | Integer | 10 | Percentage of items to evict when cache is full |
Advanced Caching Patterns
Multi-Layer Cache
import com.amazonaws.secretsmanager.caching.SecretCache;
import java.util.concurrent.ConcurrentHashMap;
public class MultiLayerCache {
private final SecretCache secretsManagerCache;
private final ConcurrentHashMap<String, String> localCache;
private final long localCacheTtl = 30000; // 30 seconds
public MultiLayerCache(SecretsManagerClient secretsClient) {
this.secretsManagerCache = new SecretCache(secretsClient);
this.localCache = new ConcurrentHashMap<>();
}
public String getSecret(String secretId) {
// Check local cache first
String cached = localCache.get(secretId);
if (cached != null) {
return cached;
}
// Get from Secrets Manager cache
String secret = secretsManagerCache.getSecretString(secretId);
if (secret != null) {
localCache.put(secretId, secret);
}
return secret;
}
}Cache Statistics
import com.amazonaws.secretsmanager.caching.SecretCache;
public class CacheStatsExample {
private final SecretCache cache;
public void demonstrateCacheStats() {
// Get cache statistics
long hitCount = cache.getHitCount();
long missCount = cache.getMissCount();
double hitRatio = cache.getHitRatio();
System.out.println("Cache Hit Ratio: " + hitRatio);
System.out.println("Hits: " + hitCount + ", Misses: " + missCount);
// Clear cache statistics
cache.clearCacheStats();
}
}Error Handling and Cache Management
Cache Refresh Strategy
import com.amazonaws.secretsmanager.caching.SecretCache;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class CacheRefreshManager {
private final SecretCache cache;
private final ScheduledExecutorService scheduler;
public CacheRefreshManager(SecretsManagerClient secretsClient) {
this.cache = new SecretCache(secretsClient);
this.scheduler = Executors.newScheduledThreadPool(1);
}
public void startRefreshSchedule() {
// Refresh cache every hour
scheduler.scheduleAtFixedRate(this::refreshCache, 1, 1, TimeUnit.HOURS);
}
private void refreshCache() {
System.out.println("Refreshing cache...");
cache.refresh();
}
public void shutdown() {
scheduler.shutdown();
}
}Fallback Mechanism
import com.amazonaws.secretsmanager.caching.SecretCache;
public class FallbackCacheExample {
private final SecretCache cache;
private final SecretsManagerClient fallbackClient;
public FallbackCacheExample(SecretsManagerClient primaryClient, SecretsManagerClient fallbackClient) {
this.cache = new SecretCache(primaryClient);
this.fallbackClient = fallbackClient;
}
public String getSecretWithFallback(String secretId) {
try {
// Try cached value first
return cache.getSecretString(secretId);
} catch (Exception e) {
// Fallback to direct API call
return getSecretDirect(secretId);
}
}
private String getSecretDirect(String secretId) {
GetSecretValueRequest request = GetSecretValueRequest.builder()
.secretId(secretId)
.build();
return fallbackClient.getSecretValue(request).secretString();
}
}Performance Optimization
Batch Secret Retrieval
import com.amazonaws.secretsmanager.caching.SecretCache;
import java.util.List;
import java.util.ArrayList;
public class BatchSecretRetrieval {
private final SecretCache cache;
public List<String> getMultipleSecrets(List<String> secretIds) {
List<String> results = new ArrayList<>();
for (String secretId : secretIds) {
String secret = cache.getSecretString(secretId);
results.add(secret != null ? secret : "NOT_FOUND");
}
return results;
}
public Map<String, String> getSecretsAsMap(List<String> secretIds) {
Map<String, String> secretMap = new HashMap<>();
for (String secretId : secretIds) {
String secret = cache.getSecretString(secretId);
if (secret != null) {
secretMap.put(secretId, secret);
}
}
return secretMap;
}
}Monitoring and Debugging
Cache Monitoring
import com.amazonaws.secretsmanager.caching.SecretCache;
public class CacheMonitor {
private final SecretCache cache;
public void monitorCachePerformance() {
// Monitor cache hit rate
double hitRatio = cache.getHitRatio();
System.out.println("Cache Hit Ratio: " + hitRatio);
// Monitor cache size
long currentSize = cache.size();
System.out.println("Current Cache Size: " + currentSize);
// Monitor cache hits and misses
long hits = cache.getHitCount();
long misses = cache.getMissCount();
System.out.println("Cache Hits: " + hits + ", Misses: " + misses);
}
public void printCacheContents() {
// Note: SecretCache doesn't provide direct access to all cached items
// This is a security feature to prevent accidental exposure of secrets
System.out.println("Cache contents are protected and cannot be directly inspected");
}
}Best Practices
1. Cache Size Configuration:
- Adjust
maxCacheSizebased on available memory - Monitor memory usage and adjust accordingly
- Consider using heap analysis tools
2. TTL Configuration:
- Balance between performance and freshness
- Shorter TTL for frequently changing secrets
- Longer TTL for stable secrets
3. Error Handling:
- Implement fallback mechanisms
- Handle cache misses gracefully
- Log errors without exposing sensitive information
4. Security Considerations:
- Never log secret values
- Use appropriate IAM permissions
- Consider encryption at rest for cached data
5. Memory Management:
- Monitor memory usage
- Consider cache eviction strategies
- Implement proper cleanup in shutdown hooks
AWS Secrets Manager Spring Boot Integration
Overview
Integrate AWS Secrets Manager with Spring Boot applications using the caching library for optimal performance and security.
Dependencies
Required Dependencies
<!-- AWS Secrets Manager -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>secretsmanager</artifactId>
</dependency>
<!-- AWS Secrets Manager Caching -->
<dependency>
<groupId>com.amazonaws.secretsmanager</groupId>
<artifactId>aws-secretsmanager-caching-java</artifactId>
<version>2.0.0</version> // Use the latest version compatible with sdk v2
</dependency>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Jackson for JSON processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Connection Pooling -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>Configuration Properties
application.yml
spring:
application:
name: aws-secrets-manager-app
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: ${db.username}
password: ${db.password}
hikari:
maximum-pool-size: 10
minimum-idle: 5
aws:
secrets:
region: us-east-1
# Secret names for different environments
database-credentials: prod/database/credentials
api-keys: prod/external-api/keys
redis-config: prod/redis/config
app:
external-api:
secret-name: prod/external/credentials
base-url: https://api.example.comCore Components
SecretsManager Configuration
import com.amazonaws.secretsmanager.caching.SecretCache;
import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
@Configuration
public class SecretsManagerConfiguration {
@Value("${aws.secrets.region}")
private String region;
@Bean
public SecretsManagerClient secretsManagerClient() {
return SecretsManagerClient.builder()
.region(Region.of(region))
.build();
}
@Bean
public SecretCache secretCache(SecretsManagerClient secretsClient) {
SecretCacheConfiguration config = SecretCacheConfiguration.builder()
.maxCacheSize(100)
.cacheItemTTL(3600000) // 1 hour
.build();
return new SecretCache(secretsClient, config);
}
}Secrets Service
import com.amazonaws.secretsmanager.caching.SecretCache;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class SecretsService {
private final SecretCache secretCache;
private final ObjectMapper objectMapper;
public SecretsService(SecretCache secretCache, ObjectMapper objectMapper) {
this.secretCache = secretCache;
this.objectMapper = objectMapper;
}
/**
* Get secret as string
*/
public String getSecret(String secretName) {
try {
return secretCache.getSecretString(secretName);
} catch (Exception e) {
throw new RuntimeException("Failed to retrieve secret: " + secretName, e);
}
}
/**
* Get secret as object of specified type
*/
public <T> T getSecretAsObject(String secretName, Class<T> type) {
try {
String secretJson = secretCache.getSecretString(secretName);
return objectMapper.readValue(secretJson, type);
} catch (Exception e) {
throw new RuntimeException("Failed to parse secret: " + secretName, e);
}
}
/**
* Get secret as Map
*/
public Map<String, String> getSecretAsMap(String secretName) {
try {
String secretJson = secretCache.getSecretString(secretName);
return objectMapper.readValue(secretJson,
new TypeReference<Map<String, String>>() {});
} catch (Exception e) {
throw new RuntimeException("Failed to parse secret map: " + secretName, e);
}
}
/**
* Get secret with fallback
*/
public String getSecretWithFallback(String secretName, String defaultValue) {
try {
String secret = secretCache.getSecretString(secretName);
return secret != null ? secret : defaultValue;
} catch (Exception e) {
return defaultValue;
}
}
}Database Configuration Integration
Dynamic DataSource Configuration
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DatabaseConfiguration {
private final SecretsService secretsService;
@Value("${aws.secrets.database-credentials}")
private String dbSecretName;
public DatabaseConfiguration(SecretsService secretsService) {
this.secretsService = secretsService;
}
@Bean
public DataSource dataSource() {
Map<String, String> credentials = secretsService.getSecretAsMap(dbSecretName);
HikariConfig config = new HikariConfig();
config.setJdbcUrl(credentials.get("url"));
config.setUsername(credentials.get("username"));
config.setPassword(credentials.get("password"));
config.setMaximumPoolSize(10);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.setLeakDetectionThreshold(15000);
return new HikariDataSource(config);
}
}Configuration Properties with Secrets
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private final SecretsService secretsService;
@Value("${app.external-api.secret-name}")
private String apiSecretName;
public AppProperties(SecretsService secretsService) {
this.secretsService = secretsService;
}
private String apiKey;
public String getApiKey() {
if (apiKey == null) {
apiKey = secretsService.getSecret(apiSecretName);
}
return apiKey;
}
// Additional application properties
private String externalApiBaseUrl;
public String getExternalApiBaseUrl() {
return externalApiBaseUrl;
}
public void setExternalApiBaseUrl(String externalApiBaseUrl) {
this.externalApiBaseUrl = externalApiBaseUrl;
}
}Property Source Integration
Custom Property Source
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@Component
public class SecretsManagerPropertySource extends PropertySource<SecretsService> {
public static final String SECRETS_MANAGER_PROPERTY_SOURCE_NAME = "secretsManagerPropertySource";
private final SecretsService secretsService;
private final Environment environment;
public SecretsManagerPropertySource(SecretsService secretsService, Environment environment) {
super(SECRETS_MANAGER_PROPERTY_SOURCE_NAME, secretsService);
this.secretsService = secretsService;
this.environment = environment;
}
@PostConstruct
public void loadSecrets() {
// Load secrets specified in application.yml
String secretPrefix = "aws.secrets.";
environment.getPropertyNames().forEach(propertyName -> {
if (propertyName.startsWith(secretPrefix)) {
String secretName = environment.getProperty(propertyName);
String secretValue = secretsService.getSecret(secretName);
if (secretValue != null) {
// Add to property source (note: this is simplified)
// In practice, you'd need to work with PropertySources
}
}
});
}
@Override
public Object getProperty(String name) {
if (name.startsWith("aws.secret.")) {
String secretName = name.substring("aws.secret.".length());
return secretsService.getSecret(secretName);
}
return null;
}
}API Integration
REST Client with Secrets
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class ExternalApiClient {
private final SecretsService secretsService;
private final RestTemplate restTemplate;
private final AppProperties appProperties;
public ExternalApiClient(SecretsService secretsService,
RestTemplate restTemplate,
AppProperties appProperties) {
this.secretsService = secretsService;
this.restTemplate = restTemplate;
this.appProperties = appProperties;
}
public String callExternalApi(String endpoint) {
Map<String, String> apiCredentials = secretsService.getSecretAsMap(
appProperties.getExternalApiSecretName());
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + apiCredentials.get("api_token"));
headers.set("X-API-Key", apiCredentials.get("api_key"));
headers.set("Content-Type", "application/json");
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
endpoint,
HttpMethod.GET,
entity,
String.class);
return response.getBody();
}
}Configuration for REST Template
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}Security Configuration
Security Setup
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/secrets/**").hasRole("ADMIN")
.anyRequest().permitAll()
)
.httpBasic()
.and()
.csrf().disable();
return http.build();
}
}Testing Configuration
Test Configuration
import com.amazonaws.secretsmanager.caching.SecretCache;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.mock.env.MockEnvironment;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
import static org.mockito.Mockito.*;
@TestConfiguration
public class TestSecretsConfiguration {
@Bean
@Primary
public SecretsManagerClient secretsManagerClient() {
SecretsManagerClient mockClient = mock(SecretsManagerClient.class);
// Mock successful secret retrieval
when(mockClient.getSecretValue(any()))
.thenReturn(GetSecretValueResponse.builder()
.secretString("{\"username\":\"test\",\"password\":\"testpass\"}")
.build());
return mockClient;
}
@Bean
@Primary
public SecretCache secretCache(SecretsManagerClient mockClient) {
SecretCache mockCache = mock(SecretCache.class);
when(mockCache.getSecretString(anyString()))
.thenReturn("{\"username\":\"test\",\"password\":\"testpass\"}");
return mockCache;
}
@Bean
public MockEnvironment mockEnvironment() {
MockEnvironment env = new MockEnvironment();
env.setProperty("aws.secrets.region", "us-east-1");
env.setProperty("aws.secrets.database-credentials", "test-db-credentials");
return env;
}
}Unit Tests
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class)
class SecretsServiceTest {
@Mock
private SecretCache secretCache;
@InjectMocks
private SecretsService secretsService;
@Test
void shouldGetSecret() {
String secretName = "test-secret";
String expectedValue = "secret-value";
when(secretCache.getSecretString(secretName))
.thenReturn(expectedValue);
String result = secretsService.getSecret(secretName);
assertEquals(expectedValue, result);
verify(secretCache).getSecretString(secretName);
}
@Test
void shouldGetSecretAsMap() throws Exception {
String secretName = "test-secret";
String secretJson = "{\"key\":\"value\"}";
Map<String, String> expectedMap = Map.of("key", "value");
when(secretCache.getSecretString(secretName))
.thenReturn(secretJson);
Map<String, String> result = secretsService.getSecretAsMap(secretName);
assertEquals(expectedMap, result);
}
}Best Practices
1. Environment-Specific Configuration:
- Use different secret names for development, staging, and production
- Implement proper environment variable management
- Use Spring profiles for environment-specific configurations
2. Security Considerations:
- Never log secret values
- Use appropriate IAM roles and policies
- Enable encryption in transit and at rest
- Implement proper access controls
3. Performance Optimization:
- Use caching for frequently accessed secrets
- Configure appropriate TTL values
- Monitor cache hit rates and adjust accordingly
- Use connection pooling for database connections
4. Error Handling:
- Implement fallback mechanisms for critical secrets
- Handle partial secret retrieval gracefully
- Provide meaningful error messages without exposing sensitive information
- Implement circuit breakers for external API calls
5. Monitoring and Logging:
- Monitor secret retrieval performance
- Track cache hit/miss ratios
- Log secret access patterns (without values)
- Set up alerts for abnormal secret access patterns
Related skills
Forks & variants (1)
Aws Sdk Java V2 Secrets Manager has 1 known copy in the catalog totaling 20 installs. They canonicalize to this original listing.
- giuseppe-trisciuoglio - 20 installs
How it compares
Pick aws-sdk-java-v2-secrets-manager for explicit SDK v2 Spring Boot secret caching; use IAM instance roles with Spring Cloud AWS when you want zero client boilerplate.
FAQ
What does aws-sdk-java-v2-secrets-manager do?
Provides AWS Secrets Manager patterns for AWS SDK for Java 2.x, including secret retrieval, caching, rotation-aware access, and Spring Boot integration. Use when storing or reading secrets in Java ser
When should I use aws-sdk-java-v2-secrets-manager?
During operate infra work for cloud & infrastructure.
Is aws-sdk-java-v2-secrets-manager safe to install?
Review the Security Audits panel on this listing before production use.