or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdpolicies-tags.mdreplication.mdrotation.mdsecret-management.mdutilities.md

replication.mddocs/

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