0
# Replication Management
1
2
Multi-region secret replication for high availability, disaster recovery, and global application deployment. AWS Secrets Manager supports cross-region replication to ensure secrets are available where your applications need them.
3
4
## Replication Concepts
5
6
- **Primary Region**: The original region where the secret was created
7
- **Replica Regions**: Additional regions where the secret is replicated
8
- **Replication Status**: Current state of replication per region
9
- **KMS Key Management**: Each region can use different KMS keys for encryption
10
11
## Core Replication Operations
12
13
### Setting Up Replication
14
15
#### ReplicateSecretToRegionsRequest
16
17
```java { .api }
18
class ReplicateSecretToRegionsRequest extends AmazonWebServiceRequest {
19
String secretId; // Required: Secret identifier
20
List<ReplicaRegionType> addReplicaRegions; // Required: Regions to replicate to
21
Boolean forceOverwriteReplicaSecret; // Overwrite existing replica secrets
22
}
23
```
24
25
#### ReplicateSecretToRegionsResult
26
27
```java { .api }
28
class ReplicateSecretToRegionsResult {
29
String arn; // Primary secret ARN
30
List<ReplicationStatusType> replicationStatus; // Replication status per region
31
}
32
```
33
34
#### ReplicaRegionType
35
36
```java { .api }
37
class ReplicaRegionType {
38
String region; // Required: AWS region code
39
String kmsKeyId; // KMS key ID for encryption in this region
40
}
41
```
42
43
#### ReplicationStatusType
44
45
```java { .api }
46
class ReplicationStatusType {
47
String region; // AWS region
48
String kmsKeyId; // KMS key ID used
49
String status; // Replication status (InSync, Failed, InProgress)
50
String statusMessage; // Detailed status message
51
Date lastAccessedDate; // Last access date in this region
52
}
53
```
54
55
#### Usage Example
56
57
```java { .api }
58
// Replicate secret to multiple regions
59
List<ReplicaRegionType> replicaRegions = new ArrayList<>();
60
61
// Replicate to us-east-1 with default KMS key
62
replicaRegions.add(new ReplicaRegionType()
63
.withRegion("us-east-1"));
64
65
// Replicate to eu-west-1 with specific KMS key
66
replicaRegions.add(new ReplicaRegionType()
67
.withRegion("eu-west-1")
68
.withKmsKeyId("arn:aws:kms:eu-west-1:123456789012:key/12345678-1234-1234-1234-123456789012"));
69
70
ReplicateSecretToRegionsRequest replicateRequest = new ReplicateSecretToRegionsRequest()
71
.withSecretId("prod/database/credentials")
72
.withAddReplicaRegions(replicaRegions)
73
.withForceOverwriteReplicaSecret(false);
74
75
ReplicateSecretToRegionsResult replicateResult = client.replicateSecretToRegions(replicateRequest);
76
77
// Check replication status
78
for (ReplicationStatusType status : replicateResult.getReplicationStatus()) {
79
System.out.println("Region: " + status.getRegion() +
80
" Status: " + status.getStatus());
81
}
82
```
83
84
### Creating Secrets with Replication
85
86
```java { .api }
87
// Create secret with immediate replication
88
List<ReplicaRegionType> initialReplicas = new ArrayList<>();
89
initialReplicas.add(new ReplicaRegionType().withRegion("us-east-1"));
90
initialReplicas.add(new ReplicaRegionType().withRegion("ap-southeast-1"));
91
92
CreateSecretRequest createWithReplication = new CreateSecretRequest()
93
.withName("global/api/key")
94
.withSecretString("api-key-value")
95
.withDescription("Global API key with multi-region replication")
96
.withAddReplicaRegions(initialReplicas);
97
98
CreateSecretResult createResult = client.createSecret(createWithReplication);
99
100
// Check initial replication status
101
for (ReplicationStatusType status : createResult.getReplicationStatus()) {
102
System.out.println("Initial replication to " + status.getRegion() +
103
": " + status.getStatus());
104
}
105
```
106
107
## Managing Existing Replication
108
109
### Adding New Replica Regions
110
111
```java { .api }
112
// Add additional regions to existing replication
113
List<ReplicaRegionType> newRegions = new ArrayList<>();
114
newRegions.add(new ReplicaRegionType()
115
.withRegion("ap-northeast-1")
116
.withKmsKeyId("arn:aws:kms:ap-northeast-1:123456789012:key/asia-key-id"));
117
118
ReplicateSecretToRegionsRequest addRegionsRequest = new ReplicateSecretToRegionsRequest()
119
.withSecretId("global/api/key")
120
.withAddReplicaRegions(newRegions);
121
122
ReplicateSecretToRegionsResult addResult = client.replicateSecretToRegions(addRegionsRequest);
123
System.out.println("Added replication to new regions");
124
```
125
126
### Removing Replica Regions
127
128
#### RemoveRegionsFromReplicationRequest
129
130
```java { .api }
131
class RemoveRegionsFromReplicationRequest extends AmazonWebServiceRequest {
132
String secretId; // Required: Secret identifier
133
List<String> removeReplicaRegions; // Required: Region codes to remove
134
}
135
```
136
137
#### RemoveRegionsFromReplicationResult
138
139
```java { .api }
140
class RemoveRegionsFromReplicationResult {
141
String arn; // Primary secret ARN
142
List<ReplicationStatusType> replicationStatus; // Updated replication status
143
}
144
```
145
146
#### Usage Example
147
148
```java { .api }
149
// Remove replication from specific regions
150
List<String> regionsToRemove = Arrays.asList("us-east-1", "ap-southeast-1");
151
152
RemoveRegionsFromReplicationRequest removeRequest = new RemoveRegionsFromReplicationRequest()
153
.withSecretId("global/api/key")
154
.withRemoveReplicaRegions(regionsToRemove);
155
156
RemoveRegionsFromReplicationResult removeResult = client.removeRegionsFromReplication(removeRequest);
157
158
// Check remaining replications
159
for (ReplicationStatusType status : removeResult.getReplicationStatus()) {
160
System.out.println("Remaining replica in: " + status.getRegion());
161
}
162
```
163
164
### Stopping Replication to Replica
165
166
#### StopReplicationToReplicaRequest
167
168
```java { .api }
169
class StopReplicationToReplicaRequest extends AmazonWebServiceRequest {
170
String secretId; // Required: Secret identifier (from replica region)
171
}
172
```
173
174
#### StopReplicationToReplicaResult
175
176
```java { .api }
177
class StopReplicationToReplicaResult {
178
String arn; // Replica secret ARN
179
}
180
```
181
182
#### Usage Example
183
184
```java { .api }
185
// Stop replication when called from the replica region
186
// This promotes the replica to a standalone secret
187
StopReplicationToReplicaRequest stopRequest = new StopReplicationToReplicaRequest()
188
.withSecretId("global/api/key");
189
190
// This call must be made from the replica region you want to stop
191
StopReplicationToReplicaResult stopResult = replicaRegionClient.stopReplicationToReplica(stopRequest);
192
System.out.println("Stopped replication for: " + stopResult.getArn());
193
```
194
195
## Replication Monitoring and Status
196
197
### Checking Replication Status
198
199
```java { .api }
200
// Get detailed replication status
201
DescribeSecretRequest statusRequest = new DescribeSecretRequest()
202
.withSecretId("global/api/key");
203
204
DescribeSecretResult statusResult = client.describeSecret(statusRequest);
205
206
System.out.println("Primary Region: " + statusResult.getPrimaryRegion());
207
208
if (statusResult.getReplicationStatus() != null) {
209
for (ReplicationStatusType status : statusResult.getReplicationStatus()) {
210
System.out.println("Region: " + status.getRegion());
211
System.out.println(" Status: " + status.getStatus());
212
System.out.println(" KMS Key: " + status.getKmsKeyId());
213
System.out.println(" Message: " + status.getStatusMessage());
214
System.out.println(" Last Accessed: " + status.getLastAccessedDate());
215
}
216
} else {
217
System.out.println("No replication configured");
218
}
219
```
220
221
### Replication Status Values
222
223
```java { .api }
224
enum StatusType {
225
InSync, // Replication is current and healthy
226
Failed, // Replication failed
227
InProgress // Replication is in progress
228
}
229
```
230
231
### Monitoring Replication Health
232
233
```java { .api }
234
public class ReplicationMonitor {
235
236
public void checkReplicationHealth(AWSSecretsManager client, String secretId) {
237
try {
238
DescribeSecretResult result = client.describeSecret(
239
new DescribeSecretRequest().withSecretId(secretId));
240
241
List<ReplicationStatusType> statuses = result.getReplicationStatus();
242
if (statuses == null || statuses.isEmpty()) {
243
System.out.println("No replication configured");
244
return;
245
}
246
247
boolean allHealthy = true;
248
for (ReplicationStatusType status : statuses) {
249
String region = status.getRegion();
250
String statusValue = status.getStatus();
251
252
switch (statusValue) {
253
case "InSync":
254
System.out.println("✓ " + region + ": Healthy");
255
break;
256
case "InProgress":
257
System.out.println("⏳ " + region + ": Syncing...");
258
allHealthy = false;
259
break;
260
case "Failed":
261
System.err.println("✗ " + region + ": FAILED - " +
262
status.getStatusMessage());
263
allHealthy = false;
264
break;
265
default:
266
System.out.println("? " + region + ": Unknown status - " + statusValue);
267
allHealthy = false;
268
}
269
}
270
271
if (allHealthy) {
272
System.out.println("All replications are healthy");
273
} else {
274
System.out.println("Some replications need attention");
275
}
276
277
} catch (Exception e) {
278
System.err.println("Error checking replication health: " + e.getMessage());
279
}
280
}
281
}
282
```
283
284
## Advanced Replication Scenarios
285
286
### Cross-Region Disaster Recovery
287
288
```java { .api }
289
// Set up disaster recovery replication
290
public void setupDisasterRecovery(String primarySecretId, String drRegion) {
291
List<ReplicaRegionType> drReplicas = new ArrayList<>();
292
293
// Use region-specific KMS key for DR region
294
drReplicas.add(new ReplicaRegionType()
295
.withRegion(drRegion)
296
.withKmsKeyId("arn:aws:kms:" + drRegion + ":123456789012:key/dr-key-id"));
297
298
ReplicateSecretToRegionsRequest drRequest = new ReplicateSecretToRegionsRequest()
299
.withSecretId(primarySecretId)
300
.withAddReplicaRegions(drReplicas);
301
302
try {
303
ReplicateSecretToRegionsResult result = client.replicateSecretToRegions(drRequest);
304
System.out.println("DR replication configured for region: " + drRegion);
305
306
// Wait for initial sync
307
waitForReplicationSync(primarySecretId, drRegion);
308
309
} catch (Exception e) {
310
System.err.println("DR setup failed: " + e.getMessage());
311
}
312
}
313
314
private void waitForReplicationSync(String secretId, String targetRegion) {
315
int maxWaitMinutes = 10;
316
int waitIntervalSeconds = 15;
317
318
for (int i = 0; i < (maxWaitMinutes * 60 / waitIntervalSeconds); i++) {
319
try {
320
DescribeSecretResult result = client.describeSecret(
321
new DescribeSecretRequest().withSecretId(secretId));
322
323
List<ReplicationStatusType> statuses = result.getReplicationStatus();
324
for (ReplicationStatusType status : statuses) {
325
if (targetRegion.equals(status.getRegion())) {
326
if ("InSync".equals(status.getStatus())) {
327
System.out.println("Replication sync completed for " + targetRegion);
328
return;
329
} else if ("Failed".equals(status.getStatus())) {
330
System.err.println("Replication failed: " + status.getStatusMessage());
331
return;
332
}
333
}
334
}
335
336
Thread.sleep(waitIntervalSeconds * 1000);
337
338
} catch (InterruptedException e) {
339
Thread.currentThread().interrupt();
340
break;
341
} catch (Exception e) {
342
System.err.println("Error waiting for sync: " + e.getMessage());
343
}
344
}
345
346
System.err.println("Replication sync did not complete within expected time");
347
}
348
```
349
350
### Global Application Deployment
351
352
```java { .api }
353
// Configure replication for global application
354
public void configureGlobalReplication(String secretId) {
355
List<ReplicaRegionType> globalRegions = new ArrayList<>();
356
357
// North America
358
globalRegions.add(new ReplicaRegionType().withRegion("us-east-1"));
359
globalRegions.add(new ReplicaRegionType().withRegion("us-west-2"));
360
361
// Europe
362
globalRegions.add(new ReplicaRegionType().withRegion("eu-west-1"));
363
globalRegions.add(new ReplicaRegionType().withRegion("eu-central-1"));
364
365
// Asia Pacific
366
globalRegions.add(new ReplicaRegionType().withRegion("ap-southeast-1"));
367
globalRegions.add(new ReplicaRegionType().withRegion("ap-northeast-1"));
368
369
ReplicateSecretToRegionsRequest globalRequest = new ReplicateSecretToRegionsRequest()
370
.withSecretId(secretId)
371
.withAddReplicaRegions(globalRegions);
372
373
try {
374
ReplicateSecretToRegionsResult result = client.replicateSecretToRegions(globalRequest);
375
System.out.println("Global replication configured");
376
377
// Monitor all regions
378
monitorGlobalReplication(secretId);
379
380
} catch (Exception e) {
381
System.err.println("Global replication setup failed: " + e.getMessage());
382
}
383
}
384
385
private void monitorGlobalReplication(String secretId) {
386
DescribeSecretResult result = client.describeSecret(
387
new DescribeSecretRequest().withSecretId(secretId));
388
389
Map<String, Integer> statusCounts = new HashMap<>();
390
391
for (ReplicationStatusType status : result.getReplicationStatus()) {
392
String statusValue = status.getStatus();
393
statusCounts.put(statusValue, statusCounts.getOrDefault(statusValue, 0) + 1);
394
}
395
396
System.out.println("Global Replication Status Summary:");
397
for (Map.Entry<String, Integer> entry : statusCounts.entrySet()) {
398
System.out.println(" " + entry.getKey() + ": " + entry.getValue() + " regions");
399
}
400
}
401
```
402
403
### Updating KMS Keys for Replicas
404
405
```java { .api }
406
// Update KMS key for specific replica regions
407
public void updateReplicaKMSKeys(String secretId, Map<String, String> regionKeyMap) {
408
// Remove existing replicas
409
List<String> regionsToUpdate = new ArrayList<>(regionKeyMap.keySet());
410
411
RemoveRegionsFromReplicationRequest removeRequest = new RemoveRegionsFromReplicationRequest()
412
.withSecretId(secretId)
413
.withRemoveReplicaRegions(regionsToUpdate);
414
415
try {
416
client.removeRegionsFromReplication(removeRequest);
417
418
// Wait a moment for cleanup
419
Thread.sleep(5000);
420
421
// Re-add with new KMS keys
422
List<ReplicaRegionType> updatedReplicas = new ArrayList<>();
423
for (Map.Entry<String, String> entry : regionKeyMap.entrySet()) {
424
updatedReplicas.add(new ReplicaRegionType()
425
.withRegion(entry.getKey())
426
.withKmsKeyId(entry.getValue()));
427
}
428
429
ReplicateSecretToRegionsRequest addRequest = new ReplicateSecretToRegionsRequest()
430
.withSecretId(secretId)
431
.withAddReplicaRegions(updatedReplicas);
432
433
ReplicateSecretToRegionsResult result = client.replicateSecretToRegions(addRequest);
434
System.out.println("Updated KMS keys for replica regions");
435
436
} catch (Exception e) {
437
System.err.println("KMS key update failed: " + e.getMessage());
438
}
439
}
440
```
441
442
## Cross-Region Client Management
443
444
### Multi-Region Secret Access
445
446
```java { .api }
447
// Access secrets from different regions
448
public class CrossRegionSecretAccess {
449
450
private Map<String, AWSSecretsManager> regionClients = new HashMap<>();
451
452
public CrossRegionSecretAccess(List<String> regions) {
453
for (String region : regions) {
454
regionClients.put(region, AWSSecretsManagerClientBuilder.standard()
455
.withRegion(region)
456
.build());
457
}
458
}
459
460
public GetSecretValueResult getSecretFromClosestRegion(String secretName,
461
List<String> preferredRegions) {
462
for (String region : preferredRegions) {
463
AWSSecretsManager client = regionClients.get(region);
464
if (client != null) {
465
try {
466
GetSecretValueRequest request = new GetSecretValueRequest()
467
.withSecretId(secretName);
468
469
return client.getSecretValue(request);
470
471
} catch (ResourceNotFoundException e) {
472
// Try next region
473
continue;
474
} catch (Exception e) {
475
System.err.println("Error accessing secret in " + region + ": " + e.getMessage());
476
continue;
477
}
478
}
479
}
480
481
throw new RuntimeException("Secret not accessible from any preferred region");
482
}
483
484
public void shutdown() {
485
for (AWSSecretsManager client : regionClients.values()) {
486
client.shutdown();
487
}
488
}
489
}
490
```
491
492
### Failover Strategy
493
494
```java { .api }
495
public class SecretFailoverManager {
496
497
public String getSecretWithFailover(String secretName, String primaryRegion,
498
List<String> backupRegions) {
499
500
// Try primary region first
501
try {
502
AWSSecretsManager primaryClient = AWSSecretsManagerClientBuilder.standard()
503
.withRegion(primaryRegion)
504
.build();
505
506
GetSecretValueResult result = primaryClient.getSecretValue(
507
new GetSecretValueRequest().withSecretId(secretName));
508
509
primaryClient.shutdown();
510
return result.getSecretString();
511
512
} catch (Exception e) {
513
System.err.println("Primary region failed: " + e.getMessage());
514
}
515
516
// Try backup regions
517
for (String backupRegion : backupRegions) {
518
try {
519
AWSSecretsManager backupClient = AWSSecretsManagerClientBuilder.standard()
520
.withRegion(backupRegion)
521
.build();
522
523
GetSecretValueResult result = backupClient.getSecretValue(
524
new GetSecretValueRequest().withSecretId(secretName));
525
526
System.out.println("Retrieved secret from backup region: " + backupRegion);
527
backupClient.shutdown();
528
return result.getSecretString();
529
530
} catch (Exception e) {
531
System.err.println("Backup region " + backupRegion + " failed: " + e.getMessage());
532
}
533
}
534
535
throw new RuntimeException("Secret not accessible from any region");
536
}
537
}
538
```
539
540
## Error Handling
541
542
Common replication-related exceptions:
543
544
```java { .api }
545
try {
546
ReplicateSecretToRegionsResult result = client.replicateSecretToRegions(request);
547
} catch (ResourceNotFoundException e) {
548
System.err.println("Secret not found: " + e.getMessage());
549
} catch (InvalidParameterException e) {
550
System.err.println("Invalid region or KMS key: " + e.getMessage());
551
} catch (LimitExceededException e) {
552
System.err.println("Replication limit exceeded: " + e.getMessage());
553
} catch (ResourceExistsException e) {
554
// Use forceOverwriteReplicaSecret if intentional
555
System.err.println("Replica already exists: " + e.getMessage());
556
} catch (EncryptionFailureException e) {
557
System.err.println("KMS encryption failed: " + e.getMessage());
558
} catch (AWSSecretsManagerException e) {
559
System.err.println("Replication service error: " + e.getMessage());
560
}
561
```
562
563
## Best Practices
564
565
1. **Region Selection**: Choose regions close to your application deployments
566
2. **KMS Key Management**: Use region-specific KMS keys for compliance
567
3. **Network Latency**: Consider latency when accessing replicated secrets
568
4. **Cost Management**: Monitor cross-region data transfer costs
569
5. **Failover Testing**: Regularly test cross-region failover scenarios
570
6. **Monitoring**: Set up CloudWatch alarms for replication failures
571
7. **Cleanup**: Remove unnecessary replicas to reduce costs
572
8. **Security**: Ensure IAM policies work across regions
573
9. **Consistency**: Understand eventual consistency for cross-region updates
574
10. **Disaster Recovery**: Plan for complete region failures