@@ -285,6 +285,7 @@ export abstract class DatabaseClusterBase extends Resource implements IDatabaseC
285
285
* Identifier of the cluster
286
286
*/
287
287
public abstract readonly clusterIdentifier : string ;
288
+
288
289
/**
289
290
* Identifiers of the replicas
290
291
*/
@@ -345,9 +346,40 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase {
345
346
protected readonly securityGroups : ec2 . ISecurityGroup [ ] ;
346
347
protected readonly subnetGroup : ISubnetGroup ;
347
348
349
+ /**
350
+ * Secret in SecretsManager to store the database cluster user credentials.
351
+ */
352
+ public abstract readonly secret ?: secretsmanager . ISecret ;
353
+
354
+ /**
355
+ * The VPC network to place the cluster in.
356
+ */
357
+ public readonly vpc : ec2 . IVpc ;
358
+
359
+ /**
360
+ * The cluster's subnets.
361
+ */
362
+ public readonly vpcSubnets ?: ec2 . SubnetSelection ;
363
+
364
+ /**
365
+ * Application for single user rotation of the master password to this cluster.
366
+ */
367
+ public readonly singleUserRotationApplication : secretsmanager . SecretRotationApplication ;
368
+
369
+ /**
370
+ * Application for multi user rotation to this cluster.
371
+ */
372
+ public readonly multiUserRotationApplication : secretsmanager . SecretRotationApplication ;
373
+
348
374
constructor ( scope : Construct , id : string , props : DatabaseClusterBaseProps ) {
349
375
super ( scope , id ) ;
350
376
377
+ this . vpc = props . instanceProps . vpc ;
378
+ this . vpcSubnets = props . instanceProps . vpcSubnets ;
379
+
380
+ this . singleUserRotationApplication = props . engine . singleUserRotationApplication ;
381
+ this . multiUserRotationApplication = props . engine . multiUserRotationApplication ;
382
+
351
383
const { subnetIds } = props . instanceProps . vpc . selectSubnets ( props . instanceProps . vpcSubnets ) ;
352
384
353
385
// Cannot test whether the subnets are in different AZs, but at least we can test the amount.
@@ -436,6 +468,47 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase {
436
468
copyTagsToSnapshot : props . copyTagsToSnapshot ?? true ,
437
469
} ;
438
470
}
471
+
472
+ /**
473
+ * Adds the single user rotation of the master password to this cluster.
474
+ */
475
+ public addRotationSingleUser ( options : RotationSingleUserOptions = { } ) : secretsmanager . SecretRotation {
476
+ if ( ! this . secret ) {
477
+ throw new Error ( 'Cannot add a single user rotation for a cluster without a secret.' ) ;
478
+ }
479
+
480
+ const id = 'RotationSingleUser' ;
481
+ const existing = this . node . tryFindChild ( id ) ;
482
+ if ( existing ) {
483
+ throw new Error ( 'A single user rotation was already added to this cluster.' ) ;
484
+ }
485
+
486
+ return new secretsmanager . SecretRotation ( this , id , {
487
+ ...applyDefaultRotationOptions ( options , this . vpcSubnets ) ,
488
+ secret : this . secret ,
489
+ application : this . singleUserRotationApplication ,
490
+ vpc : this . vpc ,
491
+ target : this ,
492
+ } ) ;
493
+ }
494
+
495
+ /**
496
+ * Adds the multi user rotation to this cluster.
497
+ */
498
+ public addRotationMultiUser ( id : string , options : RotationMultiUserOptions ) : secretsmanager . SecretRotation {
499
+ if ( ! this . secret ) {
500
+ throw new Error ( 'Cannot add a multi user rotation for a cluster without a secret.' ) ;
501
+ }
502
+
503
+ return new secretsmanager . SecretRotation ( this , id , {
504
+ ...applyDefaultRotationOptions ( options , this . vpcSubnets ) ,
505
+ secret : options . secret ,
506
+ masterSecret : this . secret ,
507
+ application : this . multiUserRotationApplication ,
508
+ vpc : this . vpc ,
509
+ target : this ,
510
+ } ) ;
511
+ }
439
512
}
440
513
441
514
/**
@@ -537,21 +610,9 @@ export class DatabaseCluster extends DatabaseClusterNew {
537
610
*/
538
611
public readonly secret ?: secretsmanager . ISecret ;
539
612
540
- private readonly vpc : ec2 . IVpc ;
541
- private readonly vpcSubnets ?: ec2 . SubnetSelection ;
542
-
543
- private readonly singleUserRotationApplication : secretsmanager . SecretRotationApplication ;
544
- private readonly multiUserRotationApplication : secretsmanager . SecretRotationApplication ;
545
-
546
613
constructor ( scope : Construct , id : string , props : DatabaseClusterProps ) {
547
614
super ( scope , id , props ) ;
548
615
549
- this . vpc = props . instanceProps . vpc ;
550
- this . vpcSubnets = props . instanceProps . vpcSubnets ;
551
-
552
- this . singleUserRotationApplication = props . engine . singleUserRotationApplication ;
553
- this . multiUserRotationApplication = props . engine . multiUserRotationApplication ;
554
-
555
616
const credentials = renderCredentials ( this , props . engine , props . credentials ) ;
556
617
const secret = credentials . secret ;
557
618
@@ -564,6 +625,10 @@ export class DatabaseCluster extends DatabaseClusterNew {
564
625
565
626
this . clusterIdentifier = cluster . ref ;
566
627
628
+ if ( secret ) {
629
+ this . secret = secret . attach ( this ) ;
630
+ }
631
+
567
632
// create a number token that represents the port of the cluster
568
633
const portAttribute = Token . asNumber ( cluster . attrEndpointPort ) ;
569
634
this . clusterEndpoint = new Endpoint ( cluster . attrEndpointAddress , portAttribute ) ;
@@ -575,56 +640,11 @@ export class DatabaseCluster extends DatabaseClusterNew {
575
640
576
641
cluster . applyRemovalPolicy ( props . removalPolicy ?? RemovalPolicy . SNAPSHOT ) ;
577
642
578
- if ( secret ) {
579
- this . secret = secret . attach ( this ) ;
580
- }
581
-
582
643
setLogRetention ( this , props ) ;
583
644
const createdInstances = createInstances ( this , props , this . subnetGroup ) ;
584
645
this . instanceIdentifiers = createdInstances . instanceIdentifiers ;
585
646
this . instanceEndpoints = createdInstances . instanceEndpoints ;
586
647
}
587
-
588
- /**
589
- * Adds the single user rotation of the master password to this cluster.
590
- */
591
- public addRotationSingleUser ( options : RotationSingleUserOptions = { } ) : secretsmanager . SecretRotation {
592
- if ( ! this . secret ) {
593
- throw new Error ( 'Cannot add single user rotation for a cluster without secret.' ) ;
594
- }
595
-
596
- const id = 'RotationSingleUser' ;
597
- const existing = this . node . tryFindChild ( id ) ;
598
- if ( existing ) {
599
- throw new Error ( 'A single user rotation was already added to this cluster.' ) ;
600
- }
601
-
602
- return new secretsmanager . SecretRotation ( this , id , {
603
- ...applyDefaultRotationOptions ( options , this . vpcSubnets ) ,
604
- secret : this . secret ,
605
- application : this . singleUserRotationApplication ,
606
- vpc : this . vpc ,
607
- target : this ,
608
- } ) ;
609
- }
610
-
611
- /**
612
- * Adds the multi user rotation to this cluster.
613
- */
614
- public addRotationMultiUser ( id : string , options : RotationMultiUserOptions ) : secretsmanager . SecretRotation {
615
- if ( ! this . secret ) {
616
- throw new Error ( 'Cannot add multi user rotation for a cluster without secret.' ) ;
617
- }
618
-
619
- return new secretsmanager . SecretRotation ( this , id , {
620
- ...applyDefaultRotationOptions ( options , this . vpcSubnets ) ,
621
- secret : options . secret ,
622
- masterSecret : this . secret ,
623
- application : this . multiUserRotationApplication ,
624
- vpc : this . vpc ,
625
- target : this ,
626
- } ) ;
627
- }
628
648
}
629
649
630
650
/**
@@ -637,6 +657,13 @@ export interface DatabaseClusterFromSnapshotProps extends DatabaseClusterBasePro
637
657
* However, you can use only the ARN to specify a DB instance snapshot.
638
658
*/
639
659
readonly snapshotIdentifier : string ;
660
+
661
+ /**
662
+ * Credentials for the administrative user
663
+ *
664
+ * @default - A username of 'admin' (or 'postgres' for PostgreSQL) and SecretsManager-generated password
665
+ */
666
+ readonly credentials ?: Credentials ;
640
667
}
641
668
642
669
/**
@@ -652,16 +679,28 @@ export class DatabaseClusterFromSnapshot extends DatabaseClusterNew {
652
679
public readonly instanceIdentifiers : string [ ] ;
653
680
public readonly instanceEndpoints : Endpoint [ ] ;
654
681
682
+ /**
683
+ * The secret attached to this cluster
684
+ */
685
+ public readonly secret ?: secretsmanager . ISecret ;
686
+
655
687
constructor ( scope : Construct , id : string , props : DatabaseClusterFromSnapshotProps ) {
656
688
super ( scope , id , props ) ;
657
689
690
+ const credentials = renderCredentials ( this , props . engine , props . credentials ) ;
691
+ const secret = credentials . secret ;
692
+
658
693
const cluster = new CfnDBCluster ( this , 'Resource' , {
659
694
...this . newCfnProps ,
660
695
snapshotIdentifier : props . snapshotIdentifier ,
661
696
} ) ;
662
697
663
698
this . clusterIdentifier = cluster . ref ;
664
699
700
+ if ( secret ) {
701
+ this . secret = secret . attach ( this ) ;
702
+ }
703
+
665
704
// create a number token that represents the port of the cluster
666
705
const portAttribute = Token . asNumber ( cluster . attrEndpointPort ) ;
667
706
this . clusterEndpoint = new Endpoint ( cluster . attrEndpointAddress , portAttribute ) ;
0 commit comments