0
# Utility Operations
1
2
Helper functions for enhanced security and compliance including secure random password generation and resource policy validation.
3
4
## Random Password Generation
5
6
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.
7
8
### GetRandomPasswordRequest
9
10
```java { .api }
11
class GetRandomPasswordRequest extends AmazonWebServiceRequest {
12
Long passwordLength; // Password length (4-4096, default: 32)
13
String excludeCharacters; // Characters to exclude
14
Boolean excludeNumbers; // Exclude numeric characters (0-9)
15
Boolean excludePunctuation; // Exclude punctuation (!@#$%^&*()_+-=[]{}|;:,.<>?)
16
Boolean excludeUppercase; // Exclude uppercase letters (A-Z)
17
Boolean excludeLowercase; // Exclude lowercase letters (a-z)
18
Boolean includeSpace; // Include space character
19
Boolean requireEachIncludedType; // Require at least one character from each enabled type
20
}
21
```
22
23
### GetRandomPasswordResult
24
25
```java { .api }
26
class GetRandomPasswordResult {
27
String randomPassword; // Generated password
28
}
29
```
30
31
### Basic Password Generation
32
33
```java { .api }
34
// Generate a basic 32-character password
35
GetRandomPasswordRequest basicRequest = new GetRandomPasswordRequest();
36
37
GetRandomPasswordResult basicResult = client.getRandomPassword(basicRequest);
38
String basicPassword = basicResult.getRandomPassword();
39
System.out.println("Generated password: " + basicPassword);
40
41
// Generate a 16-character password
42
GetRandomPasswordRequest shortRequest = new GetRandomPasswordRequest()
43
.withPasswordLength(16L);
44
45
GetRandomPasswordResult shortResult = client.getRandomPassword(shortRequest);
46
String shortPassword = shortResult.getRandomPassword();
47
```
48
49
### Custom Password Requirements
50
51
```java { .api }
52
// Generate password without special characters
53
GetRandomPasswordRequest alphanumericRequest = new GetRandomPasswordRequest()
54
.withPasswordLength(20L)
55
.withExcludePunctuation(true)
56
.withRequireEachIncludedType(true);
57
58
GetRandomPasswordResult alphanumericResult = client.getRandomPassword(alphanumericRequest);
59
String alphanumericPassword = alphanumericResult.getRandomPassword();
60
61
// Generate password with specific exclusions
62
GetRandomPasswordRequest customRequest = new GetRandomPasswordRequest()
63
.withPasswordLength(24L)
64
.withExcludeCharacters("0O1lI") // Exclude confusing characters
65
.withRequireEachIncludedType(true);
66
67
GetRandomPasswordResult customResult = client.getRandomPassword(customRequest);
68
String customPassword = customResult.getRandomPassword();
69
70
// Generate a simple password (letters and numbers only)
71
GetRandomPasswordRequest simpleRequest = new GetRandomPasswordRequest()
72
.withPasswordLength(12L)
73
.withExcludePunctuation(true)
74
.withRequireEachIncludedType(true);
75
76
GetRandomPasswordResult simpleResult = client.getRandomPassword(simpleRequest);
77
String simplePassword = simpleResult.getRandomPassword();
78
```
79
80
### Advanced Password Generation
81
82
```java { .api }
83
// Database-friendly password (no special chars that might cause issues)
84
GetRandomPasswordRequest dbFriendlyRequest = new GetRandomPasswordRequest()
85
.withPasswordLength(32L)
86
.withExcludePunctuation(true)
87
.withExcludeCharacters("'\"\\`") // Exclude SQL problematic characters
88
.withRequireEachIncludedType(true);
89
90
GetRandomPasswordResult dbFriendlyResult = client.getRandomPassword(dbFriendlyRequest);
91
92
// URL-safe password (no characters that need URL encoding)
93
GetRandomPasswordRequest urlSafeRequest = new GetRandomPasswordRequest()
94
.withPasswordLength(28L)
95
.withExcludeCharacters("!@#$%^&*()+={}[]|\\:;\"'<>,.?/~`")
96
.withRequireEachIncludedType(true);
97
98
GetRandomPasswordResult urlSafeResult = client.getRandomPassword(urlSafeRequest);
99
100
// High entropy password with all character types
101
GetRandomPasswordRequest highEntropyRequest = new GetRandomPasswordRequest()
102
.withPasswordLength(40L)
103
.withIncludeSpace(false) // Avoid spaces for compatibility
104
.withRequireEachIncludedType(true);
105
106
GetRandomPasswordResult highEntropyResult = client.getRandomPassword(highEntropyRequest);
107
```
108
109
### Password Generation Patterns
110
111
```java { .api }
112
public class PasswordGenerator {
113
114
private final AWSSecretsManager client;
115
116
public PasswordGenerator(AWSSecretsManager client) {
117
this.client = client;
118
}
119
120
// Generate password for database users
121
public String generateDatabasePassword() {
122
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
123
.withPasswordLength(24L)
124
.withExcludePunctuation(true)
125
.withExcludeCharacters("'\"\\`") // Avoid SQL injection issues
126
.withRequireEachIncludedType(true);
127
128
return client.getRandomPassword(request).getRandomPassword();
129
}
130
131
// Generate password for API keys (alphanumeric only)
132
public String generateAPIPassword() {
133
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
134
.withPasswordLength(32L)
135
.withExcludePunctuation(true)
136
.withRequireEachIncludedType(true);
137
138
return client.getRandomPassword(request).getRandomPassword();
139
}
140
141
// Generate secure password with maximum entropy
142
public String generateSecurePassword(int length) {
143
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
144
.withPasswordLength((long) length)
145
.withRequireEachIncludedType(true);
146
147
return client.getRandomPassword(request).getRandomPassword();
148
}
149
150
// Generate password meeting corporate policy
151
public String generateCorporatePassword() {
152
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
153
.withPasswordLength(16L)
154
.withRequireEachIncludedType(true)
155
.withExcludeCharacters("0O1lI5S"); // Exclude confusing characters
156
157
return client.getRandomPassword(request).getRandomPassword();
158
}
159
160
// Generate temporary password (shorter, alphanumeric)
161
public String generateTemporaryPassword() {
162
GetRandomPasswordRequest request = new GetRandomPasswordRequest()
163
.withPasswordLength(8L)
164
.withExcludePunctuation(true)
165
.withExcludeCharacters("0O1lI")
166
.withRequireEachIncludedType(true);
167
168
return client.getRandomPassword(request).getRandomPassword();
169
}
170
}
171
```
172
173
### Automated Secret Creation with Generated Passwords
174
175
```java { .api }
176
// Create secret with automatically generated password
177
public String createSecretWithGeneratedPassword(String secretName,
178
String description,
179
int passwordLength) {
180
try {
181
// Generate secure password
182
GetRandomPasswordRequest passwordRequest = new GetRandomPasswordRequest()
183
.withPasswordLength((long) passwordLength)
184
.withRequireEachIncludedType(true);
185
186
GetRandomPasswordResult passwordResult = client.getRandomPassword(passwordRequest);
187
String generatedPassword = passwordResult.getRandomPassword();
188
189
// Create secret with generated password
190
CreateSecretRequest createRequest = new CreateSecretRequest()
191
.withName(secretName)
192
.withSecretString(generatedPassword)
193
.withDescription(description);
194
195
CreateSecretResult createResult = client.createSecret(createRequest);
196
197
System.out.println("Created secret: " + createResult.getName());
198
System.out.println("Secret ARN: " + createResult.getArn());
199
200
return generatedPassword;
201
202
} catch (Exception e) {
203
System.err.println("Failed to create secret with generated password: " + e.getMessage());
204
throw e;
205
}
206
}
207
208
// Usage
209
String password = createSecretWithGeneratedPassword(
210
"prod/database/temp-user",
211
"Temporary database user password",
212
24
213
);
214
```
215
216
### Password Complexity Validation
217
218
```java { .api }
219
public class PasswordComplexityChecker {
220
221
public static class ComplexityRequirements {
222
public int minLength = 8;
223
public boolean requireUppercase = true;
224
public boolean requireLowercase = true;
225
public boolean requireNumbers = true;
226
public boolean requireSpecialChars = true;
227
public String forbiddenChars = "";
228
}
229
230
public boolean meetsRequirements(String password, ComplexityRequirements requirements) {
231
if (password.length() < requirements.minLength) {
232
return false;
233
}
234
235
boolean hasUpper = password.chars().anyMatch(Character::isUpperCase);
236
boolean hasLower = password.chars().anyMatch(Character::isLowerCase);
237
boolean hasDigit = password.chars().anyMatch(Character::isDigit);
238
boolean hasSpecial = password.chars().anyMatch(ch -> !Character.isLetterOrDigit(ch));
239
240
if (requirements.requireUppercase && !hasUpper) return false;
241
if (requirements.requireLowercase && !hasLower) return false;
242
if (requirements.requireNumbers && !hasDigit) return false;
243
if (requirements.requireSpecialChars && !hasSpecial) return false;
244
245
// Check forbidden characters
246
for (char forbidden : requirements.forbiddenChars.toCharArray()) {
247
if (password.indexOf(forbidden) >= 0) {
248
return false;
249
}
250
}
251
252
return true;
253
}
254
255
public String generateCompliantPassword(ComplexityRequirements requirements) {
256
GetRandomPasswordRequest.Builder requestBuilder = new GetRandomPasswordRequest()
257
.withPasswordLength((long) Math.max(requirements.minLength, 12))
258
.withRequireEachIncludedType(true);
259
260
if (!requirements.requireUppercase) {
261
requestBuilder.withExcludeUppercase(true);
262
}
263
if (!requirements.requireLowercase) {
264
requestBuilder.withExcludeLowercase(true);
265
}
266
if (!requirements.requireNumbers) {
267
requestBuilder.withExcludeNumbers(true);
268
}
269
if (!requirements.requireSpecialChars) {
270
requestBuilder.withExcludePunctuation(true);
271
}
272
if (!requirements.forbiddenChars.isEmpty()) {
273
requestBuilder.withExcludeCharacters(requirements.forbiddenChars);
274
}
275
276
GetRandomPasswordResult result = client.getRandomPassword(requestBuilder);
277
return result.getRandomPassword();
278
}
279
}
280
```
281
282
## Resource Policy Validation
283
284
Validate IAM resource policies before applying them to secrets to ensure they follow security best practices and don't introduce vulnerabilities.
285
286
### ValidateResourcePolicyRequest
287
288
```java { .api }
289
class ValidateResourcePolicyRequest extends AmazonWebServiceRequest {
290
String secretId; // Secret identifier (optional)
291
String resourcePolicy; // Required: JSON policy document
292
}
293
```
294
295
### ValidateResourcePolicyResult
296
297
```java { .api }
298
class ValidateResourcePolicyResult {
299
Boolean policyValidationPassed; // Overall validation result
300
List<ValidationErrorsEntry> validationErrors; // Detailed validation errors
301
}
302
```
303
304
### ValidationErrorsEntry
305
306
```java { .api }
307
class ValidationErrorsEntry {
308
String checkName; // Name of the validation check that failed
309
String errorMessage; // Detailed error description
310
}
311
```
312
313
### Basic Policy Validation
314
315
```java { .api }
316
// Validate a resource policy before applying
317
String policyDocument = "{\n" +
318
" \"Version\": \"2012-10-17\",\n" +
319
" \"Statement\": [\n" +
320
" {\n" +
321
" \"Effect\": \"Allow\",\n" +
322
" \"Principal\": {\n" +
323
" \"AWS\": \"arn:aws:iam::123456789012:role/MyRole\"\n" +
324
" },\n" +
325
" \"Action\": \"secretsmanager:GetSecretValue\",\n" +
326
" \"Resource\": \"*\"\n" +
327
" }\n" +
328
" ]\n" +
329
"}";
330
331
ValidateResourcePolicyRequest validateRequest = new ValidateResourcePolicyRequest()
332
.withResourcePolicy(policyDocument);
333
334
ValidateResourcePolicyResult validateResult = client.validateResourcePolicy(validateRequest);
335
336
if (validateResult.getPolicyValidationPassed()) {
337
System.out.println("Policy validation passed - safe to apply");
338
} else {
339
System.out.println("Policy validation failed:");
340
for (ValidationErrorsEntry error : validateResult.getValidationErrors()) {
341
System.out.println(" Check: " + error.getCheckName());
342
System.out.println(" Error: " + error.getErrorMessage());
343
}
344
}
345
```
346
347
### Advanced Policy Validation
348
349
```java { .api }
350
public class PolicyValidator {
351
352
private final AWSSecretsManager client;
353
354
public PolicyValidator(AWSSecretsManager client) {
355
this.client = client;
356
}
357
358
public ValidationReport validatePolicy(String policyDocument, String secretId) {
359
ValidateResourcePolicyRequest request = new ValidateResourcePolicyRequest()
360
.withResourcePolicy(policyDocument)
361
.withSecretId(secretId);
362
363
try {
364
ValidateResourcePolicyResult result = client.validateResourcePolicy(request);
365
366
return new ValidationReport(
367
result.getPolicyValidationPassed(),
368
result.getValidationErrors()
369
);
370
371
} catch (Exception e) {
372
ValidationReport report = new ValidationReport(false, new ArrayList<>());
373
report.addError("VALIDATION_FAILED", "Policy validation service error: " + e.getMessage());
374
return report;
375
}
376
}
377
378
public static class ValidationReport {
379
private final boolean passed;
380
private final List<ValidationErrorsEntry> errors;
381
382
public ValidationReport(boolean passed, List<ValidationErrorsEntry> errors) {
383
this.passed = passed;
384
this.errors = errors != null ? errors : new ArrayList<>();
385
}
386
387
public boolean isPassed() { return passed; }
388
public List<ValidationErrorsEntry> getErrors() { return errors; }
389
390
public void addError(String checkName, String errorMessage) {
391
ValidationErrorsEntry error = new ValidationErrorsEntry()
392
.withCheckName(checkName)
393
.withErrorMessage(errorMessage);
394
errors.add(error);
395
}
396
397
public void printReport() {
398
if (passed) {
399
System.out.println("✓ Policy validation PASSED");
400
} else {
401
System.out.println("✗ Policy validation FAILED");
402
for (ValidationErrorsEntry error : errors) {
403
System.out.println(" • " + error.getCheckName() + ": " + error.getErrorMessage());
404
}
405
}
406
}
407
408
public boolean hasSecurityRisks() {
409
return errors.stream().anyMatch(error ->
410
error.getCheckName().toLowerCase().contains("security") ||
411
error.getCheckName().toLowerCase().contains("public") ||
412
error.getErrorMessage().toLowerCase().contains("security risk"));
413
}
414
}
415
}
416
```
417
418
### Policy Validation Workflow
419
420
```java { .api }
421
public class SecurePolicyManager {
422
423
private final AWSSecretsManager client;
424
private final PolicyValidator validator;
425
426
public SecurePolicyManager(AWSSecretsManager client) {
427
this.client = client;
428
this.validator = new PolicyValidator(client);
429
}
430
431
public boolean applyPolicyWithValidation(String secretId, String policyDocument) {
432
// Step 1: Validate the policy
433
PolicyValidator.ValidationReport report = validator.validatePolicy(policyDocument, secretId);
434
435
System.out.println("Policy Validation Report:");
436
report.printReport();
437
438
// Step 2: Check for security risks
439
if (report.hasSecurityRisks()) {
440
System.err.println("BLOCKED: Policy contains security risks and will not be applied");
441
return false;
442
}
443
444
// Step 3: Apply policy if validation passed
445
if (report.isPassed()) {
446
try {
447
PutResourcePolicyRequest putRequest = new PutResourcePolicyRequest()
448
.withSecretId(secretId)
449
.withResourcePolicy(policyDocument)
450
.withBlockPublicPolicy(true);
451
452
PutResourcePolicyResult putResult = client.putResourcePolicy(putRequest);
453
System.out.println("Policy successfully applied to: " + putResult.getName());
454
return true;
455
456
} catch (Exception e) {
457
System.err.println("Failed to apply policy: " + e.getMessage());
458
return false;
459
}
460
} else {
461
System.err.println("Policy validation failed - not applying");
462
return false;
463
}
464
}
465
466
public void auditExistingPolicies(List<String> secretIds) {
467
System.out.println("Policy Audit Report");
468
System.out.println("==================");
469
470
for (String secretId : secretIds) {
471
try {
472
GetResourcePolicyRequest getRequest = new GetResourcePolicyRequest()
473
.withSecretId(secretId);
474
475
GetResourcePolicyResult getResult = client.getResourcePolicy(getRequest);
476
String currentPolicy = getResult.getResourcePolicy();
477
478
if (currentPolicy != null) {
479
PolicyValidator.ValidationReport report = validator.validatePolicy(currentPolicy, secretId);
480
481
System.out.println("\nSecret: " + secretId);
482
if (report.isPassed()) {
483
System.out.println("Status: ✓ COMPLIANT");
484
} else {
485
System.out.println("Status: ✗ NON-COMPLIANT");
486
for (ValidationErrorsEntry error : report.getErrors()) {
487
System.out.println(" Issue: " + error.getErrorMessage());
488
}
489
}
490
} else {
491
System.out.println("\nSecret: " + secretId);
492
System.out.println("Status: No resource policy");
493
}
494
495
} catch (ResourceNotFoundException e) {
496
System.out.println("\nSecret: " + secretId);
497
System.out.println("Status: No resource policy");
498
} catch (Exception e) {
499
System.out.println("\nSecret: " + secretId);
500
System.out.println("Status: Error - " + e.getMessage());
501
}
502
}
503
}
504
}
505
```
506
507
### Common Validation Scenarios
508
509
```java { .api }
510
// Test different policy scenarios
511
public void testPolicyValidationScenarios() {
512
513
// 1. Valid restrictive policy
514
String validPolicy = "{\n" +
515
" \"Version\": \"2012-10-17\",\n" +
516
" \"Statement\": [\n" +
517
" {\n" +
518
" \"Effect\": \"Allow\",\n" +
519
" \"Principal\": {\n" +
520
" \"AWS\": \"arn:aws:iam::123456789012:role/MySpecificRole\"\n" +
521
" },\n" +
522
" \"Action\": \"secretsmanager:GetSecretValue\",\n" +
523
" \"Resource\": \"*\",\n" +
524
" \"Condition\": {\n" +
525
" \"StringEquals\": {\n" +
526
" \"aws:userid\": \"AIDACKCEVSQ6C2EXAMPLE\"\n" +
527
" }\n" +
528
" }\n" +
529
" }\n" +
530
" ]\n" +
531
"}";
532
533
// 2. Potentially problematic policy (public access)
534
String publicPolicy = "{\n" +
535
" \"Version\": \"2012-10-17\",\n" +
536
" \"Statement\": [\n" +
537
" {\n" +
538
" \"Effect\": \"Allow\",\n" +
539
" \"Principal\": \"*\",\n" +
540
" \"Action\": \"secretsmanager:GetSecretValue\",\n" +
541
" \"Resource\": \"*\"\n" +
542
" }\n" +
543
" ]\n" +
544
"}";
545
546
// 3. Malformed policy
547
String malformedPolicy = "{\n" +
548
" \"Version\": \"2012-10-17\",\n" +
549
" \"Statement\": [\n" +
550
" {\n" +
551
" \"Effect\": \"Allow\",\n" +
552
" \"Principal\": {\n" +
553
" \"AWS\": \"invalid-arn\"\n" +
554
" },\n" +
555
" \"Action\": \"invalid-action\",\n" +
556
" \"Resource\": \"*\"\n" +
557
" }\n" +
558
" ]\n" +
559
"}";
560
561
String[] policies = {validPolicy, publicPolicy, malformedPolicy};
562
String[] policyNames = {"Valid Restrictive", "Public Access", "Malformed"};
563
564
for (int i = 0; i < policies.length; i++) {
565
System.out.println("\nTesting: " + policyNames[i]);
566
System.out.println("----------------------------------------");
567
568
ValidateResourcePolicyRequest request = new ValidateResourcePolicyRequest()
569
.withResourcePolicy(policies[i]);
570
571
try {
572
ValidateResourcePolicyResult result = client.validateResourcePolicy(request);
573
574
if (result.getPolicyValidationPassed()) {
575
System.out.println("✓ Validation PASSED");
576
} else {
577
System.out.println("✗ Validation FAILED");
578
for (ValidationErrorsEntry error : result.getValidationErrors()) {
579
System.out.println(" " + error.getCheckName() + ": " + error.getErrorMessage());
580
}
581
}
582
} catch (Exception e) {
583
System.out.println("✗ Validation ERROR: " + e.getMessage());
584
}
585
}
586
}
587
```
588
589
## Utility Helpers
590
591
### Secret Name Utilities
592
593
```java { .api }
594
public class SecretNameUtils {
595
596
// Generate standardized secret names
597
public static String generateSecretName(String environment, String service,
598
String component, String type) {
599
return String.format("%s/%s/%s/%s",
600
environment.toLowerCase(),
601
service.toLowerCase(),
602
component.toLowerCase(),
603
type.toLowerCase());
604
}
605
606
// Parse secret name components
607
public static class SecretNameParts {
608
public final String environment;
609
public final String service;
610
public final String component;
611
public final String type;
612
613
public SecretNameParts(String environment, String service, String component, String type) {
614
this.environment = environment;
615
this.service = service;
616
this.component = component;
617
this.type = type;
618
}
619
}
620
621
public static SecretNameParts parseSecretName(String secretName) {
622
String[] parts = secretName.split("/");
623
if (parts.length != 4) {
624
throw new IllegalArgumentException("Secret name must follow pattern: environment/service/component/type");
625
}
626
return new SecretNameParts(parts[0], parts[1], parts[2], parts[3]);
627
}
628
629
// Validate secret name format
630
public static boolean isValidSecretName(String secretName) {
631
if (secretName == null || secretName.trim().isEmpty()) {
632
return false;
633
}
634
635
// Check length (1-512 characters)
636
if (secretName.length() > 512) {
637
return false;
638
}
639
640
// Check valid characters (alphanumeric, hyphens, underscores, periods, forward slashes)
641
return secretName.matches("^[a-zA-Z0-9/_.-]+$");
642
}
643
}
644
```
645
646
### Error Handling Utilities
647
648
```java { .api }
649
public class SecretsManagerErrorHandler {
650
651
public static void handleCommonErrors(Exception e) {
652
if (e instanceof ResourceNotFoundException) {
653
System.err.println("Resource not found: " + e.getMessage());
654
} else if (e instanceof InvalidParameterException) {
655
System.err.println("Invalid parameter: " + e.getMessage());
656
} else if (e instanceof LimitExceededException) {
657
System.err.println("Service limit exceeded: " + e.getMessage());
658
} else if (e instanceof DecryptionFailureException) {
659
System.err.println("Decryption failed - check KMS permissions: " + e.getMessage());
660
} else if (e instanceof EncryptionFailureException) {
661
System.err.println("Encryption failed - check KMS key: " + e.getMessage());
662
} else if (e instanceof ResourceExistsException) {
663
System.err.println("Resource already exists: " + e.getMessage());
664
} else if (e instanceof AWSSecretsManagerException) {
665
System.err.println("Secrets Manager service error: " + e.getMessage());
666
} else {
667
System.err.println("Unexpected error: " + e.getMessage());
668
}
669
}
670
}
671
```
672
673
## Best Practices
674
675
### Password Generation
676
1. **Appropriate Length**: Use sufficient length for security (minimum 12 characters)
677
2. **Character Diversity**: Include multiple character types unless restricted
678
3. **Avoid Confusing Characters**: Exclude similar-looking characters (0O1lI) for human-readable passwords
679
4. **Context-Specific**: Adapt requirements to the target system's capabilities
680
5. **Entropy**: Prefer longer passwords over complex requirements when possible
681
682
### Policy Validation
683
1. **Pre-Validation**: Always validate policies before applying to production
684
2. **Least Privilege**: Ensure policies grant minimal necessary permissions
685
3. **Regular Audits**: Periodically validate existing policies for compliance
686
4. **Security Scanning**: Check for potential security risks in policy statements
687
5. **Documentation**: Document policy purpose and any special conditions
688
6. **Testing**: Test policies in development environments first
689
690
### General Utilities
691
1. **Error Handling**: Implement comprehensive error handling for all operations
692
2. **Logging**: Log utility operations for audit and debugging purposes
693
3. **Validation**: Validate inputs before making API calls
694
4. **Retries**: Implement appropriate retry logic for transient failures
695
5. **Monitoring**: Monitor utility usage patterns and performance