@@ -285,6 +285,7 @@ export abstract class DatabaseClusterBase extends Resource implements IDatabaseC
285285   * Identifier of the cluster 
286286   */ 
287287  public  abstract  readonly  clusterIdentifier : string ; 
288+ 
288289  /** 
289290   * Identifiers of the replicas 
290291   */ 
@@ -345,9 +346,40 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase {
345346  protected  readonly  securityGroups : ec2 . ISecurityGroup [ ] ; 
346347  protected  readonly  subnetGroup : ISubnetGroup ; 
347348
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+ 
348374  constructor ( scope : Construct ,  id : string ,  props : DatabaseClusterBaseProps )  { 
349375    super ( scope ,  id ) ; 
350376
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+ 
351383    const  {  subnetIds }  =  props . instanceProps . vpc . selectSubnets ( props . instanceProps . vpcSubnets ) ; 
352384
353385    // 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 {
436468      copyTagsToSnapshot : props . copyTagsToSnapshot  ??  true , 
437469    } ; 
438470  } 
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+   } 
439512} 
440513
441514/** 
@@ -537,21 +610,9 @@ export class DatabaseCluster extends DatabaseClusterNew {
537610   */ 
538611  public  readonly  secret ?: secretsmanager . ISecret ; 
539612
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- 
546613  constructor ( scope : Construct ,  id : string ,  props : DatabaseClusterProps )  { 
547614    super ( scope ,  id ,  props ) ; 
548615
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- 
555616    const  credentials  =  renderCredentials ( this ,  props . engine ,  props . credentials ) ; 
556617    const  secret  =  credentials . secret ; 
557618
@@ -564,6 +625,10 @@ export class DatabaseCluster extends DatabaseClusterNew {
564625
565626    this . clusterIdentifier  =  cluster . ref ; 
566627
628+     if  ( secret )  { 
629+       this . secret  =  secret . attach ( this ) ; 
630+     } 
631+ 
567632    // create a number token that represents the port of the cluster 
568633    const  portAttribute  =  Token . asNumber ( cluster . attrEndpointPort ) ; 
569634    this . clusterEndpoint  =  new  Endpoint ( cluster . attrEndpointAddress ,  portAttribute ) ; 
@@ -575,56 +640,11 @@ export class DatabaseCluster extends DatabaseClusterNew {
575640
576641    cluster . applyRemovalPolicy ( props . removalPolicy  ??  RemovalPolicy . SNAPSHOT ) ; 
577642
578-     if  ( secret )  { 
579-       this . secret  =  secret . attach ( this ) ; 
580-     } 
581- 
582643    setLogRetention ( this ,  props ) ; 
583644    const  createdInstances  =  createInstances ( this ,  props ,  this . subnetGroup ) ; 
584645    this . instanceIdentifiers  =  createdInstances . instanceIdentifiers ; 
585646    this . instanceEndpoints  =  createdInstances . instanceEndpoints ; 
586647  } 
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-   } 
628648} 
629649
630650/** 
@@ -637,6 +657,13 @@ export interface DatabaseClusterFromSnapshotProps extends DatabaseClusterBasePro
637657   * However, you can use only the ARN to specify a DB instance snapshot. 
638658   */ 
639659  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 ; 
640667} 
641668
642669/** 
@@ -652,16 +679,28 @@ export class DatabaseClusterFromSnapshot extends DatabaseClusterNew {
652679  public  readonly  instanceIdentifiers : string [ ] ; 
653680  public  readonly  instanceEndpoints : Endpoint [ ] ; 
654681
682+   /** 
683+    * The secret attached to this cluster 
684+    */ 
685+   public  readonly  secret ?: secretsmanager . ISecret ; 
686+ 
655687  constructor ( scope : Construct ,  id : string ,  props : DatabaseClusterFromSnapshotProps )  { 
656688    super ( scope ,  id ,  props ) ; 
657689
690+     const  credentials  =  renderCredentials ( this ,  props . engine ,  props . credentials ) ; 
691+     const  secret  =  credentials . secret ; 
692+ 
658693    const  cluster  =  new  CfnDBCluster ( this ,  'Resource' ,  { 
659694      ...this . newCfnProps , 
660695      snapshotIdentifier : props . snapshotIdentifier , 
661696    } ) ; 
662697
663698    this . clusterIdentifier  =  cluster . ref ; 
664699
700+     if  ( secret )  { 
701+       this . secret  =  secret . attach ( this ) ; 
702+     } 
703+ 
665704    // create a number token that represents the port of the cluster 
666705    const  portAttribute  =  Token . asNumber ( cluster . attrEndpointPort ) ; 
667706    this . clusterEndpoint  =  new  Endpoint ( cluster . attrEndpointAddress ,  portAttribute ) ; 
0 commit comments