Java client library for AWS Secrets Manager enabling secure storage, management, and retrieval of secrets.
—
Helper functions for enhanced security and compliance including secure random password generation and resource policy validation.
The AWS Secrets Manager service provides a secure random password generator that can create passwords meeting specific complexity requirements. This is useful for automated password rotation and initial secret creation.
class GetRandomPasswordRequest extends AmazonWebServiceRequest {
Long passwordLength; // Password length (4-4096, default: 32)
String excludeCharacters; // Characters to exclude
Boolean excludeNumbers; // Exclude numeric characters (0-9)
Boolean excludePunctuation; // Exclude punctuation (!@#$%^&*()_+-=[]{}|;:,.<>?)
Boolean excludeUppercase; // Exclude uppercase letters (A-Z)
Boolean excludeLowercase; // Exclude lowercase letters (a-z)
Boolean includeSpace; // Include space character
Boolean requireEachIncludedType; // Require at least one character from each enabled type
}class GetRandomPasswordResult {
String randomPassword; // Generated password
}// Generate a basic 32-character password
GetRandomPasswordRequest basicRequest = new GetRandomPasswordRequest();
GetRandomPasswordResult basicResult = client.getRandomPassword(basicRequest);
String basicPassword = basicResult.getRandomPassword();
System.out.println("Generated password: " + basicPassword);
// Generate a 16-character password
GetRandomPasswordRequest shortRequest = new GetRandomPasswordRequest()
.withPasswordLength(16L);
GetRandomPasswordResult shortResult = client.getRandomPassword(shortRequest);
String shortPassword = shortResult.getRandomPassword();// Generate password without special characters
GetRandomPasswordRequest alphanumericRequest = new GetRandomPasswordRequest()
.withPasswordLength(20L)
.withExcludePunctuation(true)
.withRequireEachIncludedType(true);
GetRandomPasswordResult alphanumericResult = client.getRandomPassword(alphanumericRequest);
String alphanumericPassword = alphanumericResult.getRandomPassword();
// Generate password with specific exclusions
GetRandomPasswordRequest customRequest = new GetRandomPasswordRequest()
.withPasswordLength(24L)
.withExcludeCharacters("0O1lI") // Exclude confusing characters
.withRequireEachIncludedType(true);
GetRandomPasswordResult customResult = client.getRandomPassword(customRequest);
String customPassword = customResult.getRandomPassword();
// Generate a simple password (letters and numbers only)
GetRandomPasswordRequest simpleRequest = new GetRandomPasswordRequest()
.withPasswordLength(12L)
.withExcludePunctuation(true)
.withRequireEachIncludedType(true);
GetRandomPasswordResult simpleResult = client.getRandomPassword(simpleRequest);
String simplePassword = simpleResult.getRandomPassword();// Database-friendly password (no special chars that might cause issues)
GetRandomPasswordRequest dbFriendlyRequest = new GetRandomPasswordRequest()
.withPasswordLength(32L)
.withExcludePunctuation(true)
.withExcludeCharacters("'\"\\`") // Exclude SQL problematic characters
.withRequireEachIncludedType(true);
GetRandomPasswordResult dbFriendlyResult = client.getRandomPassword(dbFriendlyRequest);
// URL-safe password (no characters that need URL encoding)
GetRandomPasswordRequest urlSafeRequest = new GetRandomPasswordRequest()
.withPasswordLength(28L)
.withExcludeCharacters("!@#$%^&*()+={}[]|\\:;\"'<>,.?/~`")
.withRequireEachIncludedType(true);
GetRandomPasswordResult urlSafeResult = client.getRandomPassword(urlSafeRequest);
// High entropy password with all character types
GetRandomPasswordRequest highEntropyRequest = new GetRandomPasswordRequest()
.withPasswordLength(40L)
.withIncludeSpace(false) // Avoid spaces for compatibility
.withRequireEachIncludedType(true);
GetRandomPasswordResult highEntropyResult = client.getRandomPassword(highEntropyRequest);public class PasswordGenerator {
private final AWSSecretsManager client;
public PasswordGenerator(AWSSecretsManager client) {
this.client = client;
}
// Generate password for database users
public String generateDatabasePassword() {
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
.withPasswordLength(24L)
.withExcludePunctuation(true)
.withExcludeCharacters("'\"\\`") // Avoid SQL injection issues
.withRequireEachIncludedType(true);
return client.getRandomPassword(request).getRandomPassword();
}
// Generate password for API keys (alphanumeric only)
public String generateAPIPassword() {
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
.withPasswordLength(32L)
.withExcludePunctuation(true)
.withRequireEachIncludedType(true);
return client.getRandomPassword(request).getRandomPassword();
}
// Generate secure password with maximum entropy
public String generateSecurePassword(int length) {
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
.withPasswordLength((long) length)
.withRequireEachIncludedType(true);
return client.getRandomPassword(request).getRandomPassword();
}
// Generate password meeting corporate policy
public String generateCorporatePassword() {
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
.withPasswordLength(16L)
.withRequireEachIncludedType(true)
.withExcludeCharacters("0O1lI5S"); // Exclude confusing characters
return client.getRandomPassword(request).getRandomPassword();
}
// Generate temporary password (shorter, alphanumeric)
public String generateTemporaryPassword() {
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
.withPasswordLength(8L)
.withExcludePunctuation(true)
.withExcludeCharacters("0O1lI")
.withRequireEachIncludedType(true);
return client.getRandomPassword(request).getRandomPassword();
}
}// Create secret with automatically generated password
public String createSecretWithGeneratedPassword(String secretName,
String description,
int passwordLength) {
try {
// Generate secure password
GetRandomPasswordRequest passwordRequest = new GetRandomPasswordRequest()
.withPasswordLength((long) passwordLength)
.withRequireEachIncludedType(true);
GetRandomPasswordResult passwordResult = client.getRandomPassword(passwordRequest);
String generatedPassword = passwordResult.getRandomPassword();
// Create secret with generated password
CreateSecretRequest createRequest = new CreateSecretRequest()
.withName(secretName)
.withSecretString(generatedPassword)
.withDescription(description);
CreateSecretResult createResult = client.createSecret(createRequest);
System.out.println("Created secret: " + createResult.getName());
System.out.println("Secret ARN: " + createResult.getArn());
return generatedPassword;
} catch (Exception e) {
System.err.println("Failed to create secret with generated password: " + e.getMessage());
throw e;
}
}
// Usage
String password = createSecretWithGeneratedPassword(
"prod/database/temp-user",
"Temporary database user password",
24
);public class PasswordComplexityChecker {
public static class ComplexityRequirements {
public int minLength = 8;
public boolean requireUppercase = true;
public boolean requireLowercase = true;
public boolean requireNumbers = true;
public boolean requireSpecialChars = true;
public String forbiddenChars = "";
}
public boolean meetsRequirements(String password, ComplexityRequirements requirements) {
if (password.length() < requirements.minLength) {
return false;
}
boolean hasUpper = password.chars().anyMatch(Character::isUpperCase);
boolean hasLower = password.chars().anyMatch(Character::isLowerCase);
boolean hasDigit = password.chars().anyMatch(Character::isDigit);
boolean hasSpecial = password.chars().anyMatch(ch -> !Character.isLetterOrDigit(ch));
if (requirements.requireUppercase && !hasUpper) return false;
if (requirements.requireLowercase && !hasLower) return false;
if (requirements.requireNumbers && !hasDigit) return false;
if (requirements.requireSpecialChars && !hasSpecial) return false;
// Check forbidden characters
for (char forbidden : requirements.forbiddenChars.toCharArray()) {
if (password.indexOf(forbidden) >= 0) {
return false;
}
}
return true;
}
public String generateCompliantPassword(ComplexityRequirements requirements) {
GetRandomPasswordRequest.Builder requestBuilder = new GetRandomPasswordRequest()
.withPasswordLength((long) Math.max(requirements.minLength, 12))
.withRequireEachIncludedType(true);
if (!requirements.requireUppercase) {
requestBuilder.withExcludeUppercase(true);
}
if (!requirements.requireLowercase) {
requestBuilder.withExcludeLowercase(true);
}
if (!requirements.requireNumbers) {
requestBuilder.withExcludeNumbers(true);
}
if (!requirements.requireSpecialChars) {
requestBuilder.withExcludePunctuation(true);
}
if (!requirements.forbiddenChars.isEmpty()) {
requestBuilder.withExcludeCharacters(requirements.forbiddenChars);
}
GetRandomPasswordResult result = client.getRandomPassword(requestBuilder);
return result.getRandomPassword();
}
}Validate IAM resource policies before applying them to secrets to ensure they follow security best practices and don't introduce vulnerabilities.
class ValidateResourcePolicyRequest extends AmazonWebServiceRequest {
String secretId; // Secret identifier (optional)
String resourcePolicy; // Required: JSON policy document
}class ValidateResourcePolicyResult {
Boolean policyValidationPassed; // Overall validation result
List<ValidationErrorsEntry> validationErrors; // Detailed validation errors
}class ValidationErrorsEntry {
String checkName; // Name of the validation check that failed
String errorMessage; // Detailed error description
}// Validate a resource policy before applying
String policyDocument = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": {\n" +
" \"AWS\": \"arn:aws:iam::123456789012:role/MyRole\"\n" +
" },\n" +
" \"Action\": \"secretsmanager:GetSecretValue\",\n" +
" \"Resource\": \"*\"\n" +
" }\n" +
" ]\n" +
"}";
ValidateResourcePolicyRequest validateRequest = new ValidateResourcePolicyRequest()
.withResourcePolicy(policyDocument);
ValidateResourcePolicyResult validateResult = client.validateResourcePolicy(validateRequest);
if (validateResult.getPolicyValidationPassed()) {
System.out.println("Policy validation passed - safe to apply");
} else {
System.out.println("Policy validation failed:");
for (ValidationErrorsEntry error : validateResult.getValidationErrors()) {
System.out.println(" Check: " + error.getCheckName());
System.out.println(" Error: " + error.getErrorMessage());
}
}public class PolicyValidator {
private final AWSSecretsManager client;
public PolicyValidator(AWSSecretsManager client) {
this.client = client;
}
public ValidationReport validatePolicy(String policyDocument, String secretId) {
ValidateResourcePolicyRequest request = new ValidateResourcePolicyRequest()
.withResourcePolicy(policyDocument)
.withSecretId(secretId);
try {
ValidateResourcePolicyResult result = client.validateResourcePolicy(request);
return new ValidationReport(
result.getPolicyValidationPassed(),
result.getValidationErrors()
);
} catch (Exception e) {
ValidationReport report = new ValidationReport(false, new ArrayList<>());
report.addError("VALIDATION_FAILED", "Policy validation service error: " + e.getMessage());
return report;
}
}
public static class ValidationReport {
private final boolean passed;
private final List<ValidationErrorsEntry> errors;
public ValidationReport(boolean passed, List<ValidationErrorsEntry> errors) {
this.passed = passed;
this.errors = errors != null ? errors : new ArrayList<>();
}
public boolean isPassed() { return passed; }
public List<ValidationErrorsEntry> getErrors() { return errors; }
public void addError(String checkName, String errorMessage) {
ValidationErrorsEntry error = new ValidationErrorsEntry()
.withCheckName(checkName)
.withErrorMessage(errorMessage);
errors.add(error);
}
public void printReport() {
if (passed) {
System.out.println("✓ Policy validation PASSED");
} else {
System.out.println("✗ Policy validation FAILED");
for (ValidationErrorsEntry error : errors) {
System.out.println(" • " + error.getCheckName() + ": " + error.getErrorMessage());
}
}
}
public boolean hasSecurityRisks() {
return errors.stream().anyMatch(error ->
error.getCheckName().toLowerCase().contains("security") ||
error.getCheckName().toLowerCase().contains("public") ||
error.getErrorMessage().toLowerCase().contains("security risk"));
}
}
}public class SecurePolicyManager {
private final AWSSecretsManager client;
private final PolicyValidator validator;
public SecurePolicyManager(AWSSecretsManager client) {
this.client = client;
this.validator = new PolicyValidator(client);
}
public boolean applyPolicyWithValidation(String secretId, String policyDocument) {
// Step 1: Validate the policy
PolicyValidator.ValidationReport report = validator.validatePolicy(policyDocument, secretId);
System.out.println("Policy Validation Report:");
report.printReport();
// Step 2: Check for security risks
if (report.hasSecurityRisks()) {
System.err.println("BLOCKED: Policy contains security risks and will not be applied");
return false;
}
// Step 3: Apply policy if validation passed
if (report.isPassed()) {
try {
PutResourcePolicyRequest putRequest = new PutResourcePolicyRequest()
.withSecretId(secretId)
.withResourcePolicy(policyDocument)
.withBlockPublicPolicy(true);
PutResourcePolicyResult putResult = client.putResourcePolicy(putRequest);
System.out.println("Policy successfully applied to: " + putResult.getName());
return true;
} catch (Exception e) {
System.err.println("Failed to apply policy: " + e.getMessage());
return false;
}
} else {
System.err.println("Policy validation failed - not applying");
return false;
}
}
public void auditExistingPolicies(List<String> secretIds) {
System.out.println("Policy Audit Report");
System.out.println("==================");
for (String secretId : secretIds) {
try {
GetResourcePolicyRequest getRequest = new GetResourcePolicyRequest()
.withSecretId(secretId);
GetResourcePolicyResult getResult = client.getResourcePolicy(getRequest);
String currentPolicy = getResult.getResourcePolicy();
if (currentPolicy != null) {
PolicyValidator.ValidationReport report = validator.validatePolicy(currentPolicy, secretId);
System.out.println("\nSecret: " + secretId);
if (report.isPassed()) {
System.out.println("Status: ✓ COMPLIANT");
} else {
System.out.println("Status: ✗ NON-COMPLIANT");
for (ValidationErrorsEntry error : report.getErrors()) {
System.out.println(" Issue: " + error.getErrorMessage());
}
}
} else {
System.out.println("\nSecret: " + secretId);
System.out.println("Status: No resource policy");
}
} catch (ResourceNotFoundException e) {
System.out.println("\nSecret: " + secretId);
System.out.println("Status: No resource policy");
} catch (Exception e) {
System.out.println("\nSecret: " + secretId);
System.out.println("Status: Error - " + e.getMessage());
}
}
}
}// Test different policy scenarios
public void testPolicyValidationScenarios() {
// 1. Valid restrictive policy
String validPolicy = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": {\n" +
" \"AWS\": \"arn:aws:iam::123456789012:role/MySpecificRole\"\n" +
" },\n" +
" \"Action\": \"secretsmanager:GetSecretValue\",\n" +
" \"Resource\": \"*\",\n" +
" \"Condition\": {\n" +
" \"StringEquals\": {\n" +
" \"aws:userid\": \"AIDACKCEVSQ6C2EXAMPLE\"\n" +
" }\n" +
" }\n" +
" }\n" +
" ]\n" +
"}";
// 2. Potentially problematic policy (public access)
String publicPolicy = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": \"*\",\n" +
" \"Action\": \"secretsmanager:GetSecretValue\",\n" +
" \"Resource\": \"*\"\n" +
" }\n" +
" ]\n" +
"}";
// 3. Malformed policy
String malformedPolicy = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": {\n" +
" \"AWS\": \"invalid-arn\"\n" +
" },\n" +
" \"Action\": \"invalid-action\",\n" +
" \"Resource\": \"*\"\n" +
" }\n" +
" ]\n" +
"}";
String[] policies = {validPolicy, publicPolicy, malformedPolicy};
String[] policyNames = {"Valid Restrictive", "Public Access", "Malformed"};
for (int i = 0; i < policies.length; i++) {
System.out.println("\nTesting: " + policyNames[i]);
System.out.println("----------------------------------------");
ValidateResourcePolicyRequest request = new ValidateResourcePolicyRequest()
.withResourcePolicy(policies[i]);
try {
ValidateResourcePolicyResult result = client.validateResourcePolicy(request);
if (result.getPolicyValidationPassed()) {
System.out.println("✓ Validation PASSED");
} else {
System.out.println("✗ Validation FAILED");
for (ValidationErrorsEntry error : result.getValidationErrors()) {
System.out.println(" " + error.getCheckName() + ": " + error.getErrorMessage());
}
}
} catch (Exception e) {
System.out.println("✗ Validation ERROR: " + e.getMessage());
}
}
}public class SecretNameUtils {
// Generate standardized secret names
public static String generateSecretName(String environment, String service,
String component, String type) {
return String.format("%s/%s/%s/%s",
environment.toLowerCase(),
service.toLowerCase(),
component.toLowerCase(),
type.toLowerCase());
}
// Parse secret name components
public static class SecretNameParts {
public final String environment;
public final String service;
public final String component;
public final String type;
public SecretNameParts(String environment, String service, String component, String type) {
this.environment = environment;
this.service = service;
this.component = component;
this.type = type;
}
}
public static SecretNameParts parseSecretName(String secretName) {
String[] parts = secretName.split("/");
if (parts.length != 4) {
throw new IllegalArgumentException("Secret name must follow pattern: environment/service/component/type");
}
return new SecretNameParts(parts[0], parts[1], parts[2], parts[3]);
}
// Validate secret name format
public static boolean isValidSecretName(String secretName) {
if (secretName == null || secretName.trim().isEmpty()) {
return false;
}
// Check length (1-512 characters)
if (secretName.length() > 512) {
return false;
}
// Check valid characters (alphanumeric, hyphens, underscores, periods, forward slashes)
return secretName.matches("^[a-zA-Z0-9/_.-]+$");
}
}public class SecretsManagerErrorHandler {
public static void handleCommonErrors(Exception e) {
if (e instanceof ResourceNotFoundException) {
System.err.println("Resource not found: " + e.getMessage());
} else if (e instanceof InvalidParameterException) {
System.err.println("Invalid parameter: " + e.getMessage());
} else if (e instanceof LimitExceededException) {
System.err.println("Service limit exceeded: " + e.getMessage());
} else if (e instanceof DecryptionFailureException) {
System.err.println("Decryption failed - check KMS permissions: " + e.getMessage());
} else if (e instanceof EncryptionFailureException) {
System.err.println("Encryption failed - check KMS key: " + e.getMessage());
} else if (e instanceof ResourceExistsException) {
System.err.println("Resource already exists: " + e.getMessage());
} else if (e instanceof AWSSecretsManagerException) {
System.err.println("Secrets Manager service error: " + e.getMessage());
} else {
System.err.println("Unexpected error: " + e.getMessage());
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-amazonaws--aws-java-sdk-secretsmanager