---
AWSTemplateFormatVersion: 2010-09-09
Description: Aurora PostgreSQL Cluster
Metadata:
repository: >-
https://pramerica-bitbucket.prudential.com/projects/GBTSCLOUDENG/repos/deployer-patterns/browse
cfn-lint:
config:
regions:
- us-east-1
- us-east-2
- us-west-2
- sa-east-1
- ap-northeast-1
- ap-northeast-3
- ap-south-1
ignore_checks:
# Returns false positives on DependsOn.
- W3005
# GlobalDBCluster is unsupported in sa-east-1
- E3001
Parameters:
# #############################################
# Tags
# #############################################
ApplicationIDName:
Type: String
Description: >-
The name of the application this cluster supports, as stored in CMDB.
Default: ''
APMNumber:
Type: String
Description:
cmdb:businessapp:number for your application.
AllowedPattern: ^APM\d+
ConstraintDescription: Must start with APM followed by numbers
ProjectName:
Type: String
Description: Bitbucket Project Key where your application code is stored.
AllowedPattern: ".+"
ConstraintDescription: Must be populated.
CostCenter:
Type: String
Description: The cost center associated with this cluster.
AllowedPattern: '^[1-9][0-9]{5}$'
MinLength: 5
ConstraintDescription: >-
Must be a valid 6 digit cost center. Cost centers never start with 0.
RSMs:
Type: String
Description: The Responsible System Managers of this cluster.
AllowedPattern: >-
^([a-z][0-9]{6} ?){0,2}([a-z][0-9]{6})$
MinLength: 7
ConstraintDescription: >-
Must be a domain ID starting with a lowercase letter. Separate RSMs with
a single space. Up to three RSMs are permitted.
DataClassification:
Type: String
Description: The classification of the data stored in this database.
AllowedValues:
- Internal
- Public
- Restricted
- Confidential
Default: Internal
BusinessUnit:
Type: String
Description: The name of the business unit requesting this cluster.
Default: GT
MinLength: 2
Tier:
Type: String
Default: np
AllowedValues:
- bc
- cont
- dr
- dev
- np
- prod
- qa
- stage
- uat
- perf
Description: >-
The function this table will serve. This is used in its name.
SnapshotRetention:
Type: String
Default: None
AllowedValues:
- None
- 1M
- 2M
- 3M
Description: >-
The value of the SnapshotRetention, i.e. AWS Backup tag. For more
information on AWS Backup tags, visit Storage Solutions' Confluence page:
https://confluence.prudential.com/display/SS/AWS+Backup
CopyTagsToSnapshot:
Type: String
AllowedValues:
- 'True'
- 'False'
Default: 'True'
Description: >-
A value that indicates whether to copy all tags from the DB cluster
to snapshots of the DB cluster. The default is not to copy them.
# #############################################
# Networking
# #############################################
IP1:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
IP1Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP1`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP1` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
IP2:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
IP2Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP2`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP2` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
IP3:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
IP3Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP3`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP3` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
IP4:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
IP4Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP4`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP4` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
IP5:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
IP5Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP5`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP5` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
EgressIP1:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
EgressIP1Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP1`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP1` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
EgressIP2:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
EgressIP2Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP2`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP2` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
EgressIP3:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
EgressIP3Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP3`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP3` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
EgressIP4:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
EgressIP4Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP4`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP4` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
EgressIP5:
Type: String
Description: >-
An additional IP address to add to this security group's ingress rules.
AllowedPattern: '^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$'
ConstraintDescription: >-
Must be a valid IP, like "192.0.2.243". If you do not want to add an
additional ingress rule, supply 127.0.0.1 as the IP here.
Default: 127.0.0.1
EgressIP5Mask:
Type: Number
Description: >-
The netmask for the range specified in `IP5`. This is used to determine
a full CIDR; for example, supplying "32" here when `IP5` is "192.0.2.243"
will add an ingress rule that allows access from 192.0.2.243/32.
MinValue: 8
MaxValue: 128
Default: 32
SubnetCategory:
AllowedValues:
- Native
- PruRouted
Default: Native
Description: >-
The subnet category to place this cluster in.
Type: String
# #############################################
# Cluster
# #############################################
ClusterName:
Type: String
Description: The name of the cluster to create.
MinLength: 1
CertificateAuthority:
Type: String
Description: The CA to use
Default: ''
DatabaseName:
Description: >-
The name of the initial database to provision.
MinLength: 1
Type: String
MachineType:
AllowedValues:
- db.t3.medium
- db.t4g.medium
- db.r5.large
- db.r5.xlarge
- db.r5.2xlarge
- db.r5.4xlarge
- db.r5.8xlarge
- db.r5.12xlarge
- db.r5.24xlarge
- db.r6g.large
- db.r6g.xlarge
- db.r6g.2xlarge
- db.r6g.4xlarge
- db.r6g.8xlarge
- db.r6g.12xlarge
- db.r6g.16xlarge
- db.r6i.large
- db.r6i.xlarge
- db.r6i.2xlarge
- db.r6i.4xlarge
- db.r6i.8xlarge
- db.r6i.12xlarge
- db.r6i.16xlarge
- db.r7g.large
- db.r7g.xlarge
- db.r7g.2xlarge
- db.r7g.4xlarge
- db.r7g.8xlarge
- db.r7g.12xlarge
- db.r7g.16xlarge
- db.x2g.large
- db.x2g.xlarge
- db.x2g.2xlarge
- db.x2g.4xlarge
- db.x2g.8xlarge
- db.x2g.12xlarge
- db.x2g.16xlarge
Description: >-
The size of the machines to provision for the initial instance and any
replica instances. When choosing a machine size, consider the CPU,
memory, and networking requirements for your application.
Type: String
PostgresEngineMode:
AllowedValues:
- 'global'
- 'provisioned'
Default: 'provisioned'
Description: >-
Whether this cluster should run in "provisioned" or "global" mode.
Running a cluster in "global" mode is not required on Aurora PostgreSQL.
Type: String
PreferredBackupWindow:
Default: 06:00-08:00
Description: >-
The daily time range (UTC) during which automated backups are created if
automated backups are enabled using the BackupRetentionPeriod parameter.
Must be in the format
hh24:mi-hh24:mi.
MaxLength: 11
MinLength: 11
Type: String
PreferredMaintenanceWindow:
Default:
Sun:03:00-Sun:05:00
Description: >-
The time range each week during which system maintenance can occur,
in UTC. Must be in the format
ddd:hh24:mi-ddd:hh24:mi.
MaxLength: 19
MinLength: 19
Type: String
MinorVersionUpgrade:
AllowedValues:
- 'Yes'
- 'No'
Default: 'Yes'
Description: >-
Whether to allow AWS to patch this system to a newer minor version during
the specified maintenance window.
Type: String
TerminationProtection:
AllowedValues:
- 'True'
- 'False'
Default: 'True'
Description: >-
Protects clusters from being accidentally deleted. If enabled, the
cluster cannot be deleted unless it is modified and DeletionProtection
is disabled.
Type: String
PrimaryRegion:
AllowedValues:
- 'Primary'
- 'Secondary'
Default: 'Primary'
Description: >-
The region this cluster is being deployed in. If this is a GLOBAL cluster
this should be set to "Primary" in the cluster's primary region; and
"Secondary" otherwise. If this is a SINGLE-REGION cluster, this should
always be set to "Primary".
Type: String
GlobalClusterIdentifier:
Default: ''
Description: >-
The identifier of the global cluster, if any. If this template is being
deployed in the global cluster's primary region, a new global cluster
will be created and a local cluster will be added to it. If this template
is being deployed in a secondary region, the local cluster that is
deployed will be added to a global cluster with this ID. If this field is
left blank, no global cluster will be created, and no local cluster will
be added to any global cluster.
Type: String
KMSMasterKeyID:
Type: String
Default: ""
Description: >-
The ARN of a custom KMS key to use for encryption on the RDS cluster. If
no KMS key is provided, the default GBTS keychain will be used.
BackupRetentionPeriod:
Type: Number
Description: >-
The number of days (1-35) for which automated backups are retained.
Default: 21
ConstraintDescription: Must be a value from 1 to 35.
MinValue: 1
MaxValue: 35
InstanceCount:
Type: Number
Default: 1
MinValue: 1
MaxValue: 6
Description: >-
The number of instances to provision as part of this cluster. Specifying
one instance will create only a primary instance and no additional
replicas.
SupportGroup:
Type: String
Default: Automatic
AllowedValues:
- GT
- PSJL
- Automatic
Description: >-
The support group of this cluster. This parameter sets who gets access to
the master password. If this is set to "Automatic", the support group
will be determined by the deployment region, i.e. the PSJL DBA team will
get access to the master password if the deployment occurs in
ap-northeast-1 or ap-northeast-3.
DBSnapshotName:
Description: >-
Optional. DB Snapshot ID to restore database.Leave this blank if you are
not restoring from a snapshot. Be aware that this parameter can only be set
at stack creating. If you once specify this parameter, this value should not
be updated further until delete this stack. After restored from snapshot, you
should update rds master password manually using secret created in secret
manager. This parameter is ignored for secondaries in a global cluster. Restore
the global cluster from the defined snapshot first and then join the secondary
to the global cluster in order to achieve the same effect.
Type: String
Default: ""
EnableGlueConnection:
Type: String
Default: "False"
AllowedValues:
- "True"
- "False"
Description: >-
Optional. To determine whether to allow AWS Glue to connect to the DB Cluster
Set to 'True' to enable the connection, or 'False' to disable it.
EnableDevelopers:
Type: String
Default: "False"
AllowedValues:
- "True"
- "False"
Description: >-
Optional. Run SQL commands to grant developers full access. Applies to tier=dev only.
Set to 'True' to add developers, or 'False' to not add developers.
EnablePerformanceInsights:
Type: String
Default: "False"
AllowedValues:
- "True"
- "False"
Description: >-
Optional. Set 'True' to enable Performance Insights for all instances, or 'False' to disable
PerformanceInsights for all instances.
PerformanceInsightsRetentionPeriod:
Type: Number
Default: 7
MinValue: 7
Description: >-
The number of days to retain Performance Insights data. Only 7 and month * 31 is valid.
The number of month from 1-23. If you specify a retention period that isn't valid,
such as 94, Amazon RDS returns an error. If this value set to one month or longer,
additional charges will apply.
MonitoringInterval:
Default: 0
Type: Number
AllowedValues:
- 0
- 1
- 5
- 10
- 15
- 30
- 60
Description: >-
Optional: The interval, in seconds, between points when Enhanced
Monitoring metrics are collected for the DB cluster. To turn off
collecting Enhanced Monitoring metrics, specify 0.
PermBoundaryName:
Type: AWS::SSM::Parameter::Value
Default: "/prucloud/boundaries/app-infra"
Description: Enter the path for the permissions boundary SSM Parameter
AdditionalSharedPreloadLibraries:
Type: String
Default: ""
Description: >-
Additional items to add to the beginning of shared_preload_libraries, e.g.,
"rdsutils,pgvector". Separate each item with a comma and no space.
EnableIPv6:
Type: String
Default: "False"
AllowedValues:
- "True"
- "False"
Description: >-
Whether to run this cluster in dual-stack IPv4 and IPv6 modes. This may be needed for some
container environments, e.g. EKS.
Timezone:
Type: String
Default: ""
Description: >-
The timezone to use for this cluster, e.g. America/New_York or UTC. If this value is omitted,
the cluster will run in the Japan timezone (if deployed in Japan) or EST timezone.
# The business accepts the risk of adding import/export roles to the cluster and as such must
# supply their own role ARNs.
S3ImportRole:
Type: String
Default: ""
Description: >-
Optional: the role ARN to attach to this RDS cluster as the data import role. This IAM role
must already exist, is managed by the application team, and cannot be associated with another
cluster or have a different function on the same cluster.
S3ExportRole:
Type: String
Default: ""
Description: >-
Optional: the role ARN to attach to this RDS cluster as the data export role. This IAM role
must already exist, is managed by the application team, and cannot be associated with another
cluster or have a different function on the same cluster.
LambdaRole:
Type: String
Default: ""
Description: >-
Optional: the role ARN to attach to this RDS cluster as the lambda exec role. This IAM role
must already exist, is managed by the application team, and cannot be associated with another
cluster or have a different function on the same cluster.
SecretNameOverride:
# Great for new builds.
# Existing builds using this will cause replacement of resource and reset of rdsmaster password
Type: String
Default: "Original"
AllowedValues:
- "Original"
- "PSJL"
Description: >-
Optional. Using PSJL will use the PSJL convention that includes StackName in secretname
PostgresVersion: # When adding new version, also update Mapping EngineMap below
AllowedValues:
- 12.15
- 12.16
- 13.9
- 13.10
- 13.11
- 13.12
- 13.18
- 14.6
- 14.8
- 14.9
- 15.3
- 15.4
- 15.5
- 15.6
- 15.7
- "15.10"
- 15.12
- 15.13
- 16.1
- 16.2
- 16.3
- 16.6
- 16.8
- 16.9
Description: >-
Specify the version of Aurora PostgreSQL to use. The Database Engineering
Group only supports the versions of Aurora PostgreSQL provided here.
Type: String
Mappings:
EngineMap:
'12.15':
family: aurora-postgresql12
'12.16':
family: aurora-postgresql12
'13.9':
family: aurora-postgresql13
'13.10':
family: aurora-postgresql13
'13.11':
family: aurora-postgresql13
'13.12':
family: aurora-postgresql13
'13.18':
family: aurora-postgresql13
'14.6':
family: aurora-postgresql14
'14.7':
family: aurora-postgresql14
'14.8':
family: aurora-postgresql14
'14.9':
family: aurora-postgresql14
'15.3':
family: aurora-postgresql15
'15.4':
family: aurora-postgresql15
'15.5':
family: aurora-postgresql15
'15.6':
family: aurora-postgresql15
'15.7':
family: aurora-postgresql15
'15.10':
family: aurora-postgresql15
'15.12':
family: aurora-postgresql15
'15.13':
family: aurora-postgresql15
'16.1':
family: aurora-postgresql16
'16.2':
family: aurora-postgresql16
'16.3':
family: aurora-postgresql16
'16.6':
family: aurora-postgresql16
'16.8':
family: aurora-postgresql16
'16.9':
family: aurora-postgresql16
MinorUpdateMap:
'No':
value: false
'Yes':
value: true
S3PrefixListMap:
us-east-1:
S3PrefixListId: 'pl-63a5400a'
us-east-2:
S3PrefixListId: 'pl-7ba54012'
us-west-2:
S3PrefixListId: 'pl-68a54001'
sa-east-1:
S3PrefixListId: 'pl-6aa54003'
ap-south-1:
S3PrefixListId: 'pl-78a54011'
ap-northeast-1:
S3PrefixListId: 'pl-61a54008'
ap-northeast-3:
S3PrefixListId: 'pl-a4a540cd'
Conditions:
CheckIP1: !Not [!Equals [!Ref IP1, 127.0.0.1]]
CheckIP2: !Not [!Equals [!Ref IP2, 127.0.0.1]]
CheckIP3: !Not [!Equals [!Ref IP3, 127.0.0.1]]
CheckIP4: !Not [!Equals [!Ref IP4, 127.0.0.1]]
CheckIP5: !Not [!Equals [!Ref IP5, 127.0.0.1]]
CheckEgressIP1: !Not [!Equals [!Ref EgressIP1, 127.0.0.1]]
CheckEgressIP2: !Not [!Equals [!Ref EgressIP2, 127.0.0.1]]
CheckEgressIP3: !Not [!Equals [!Ref EgressIP3, 127.0.0.1]]
CheckEgressIP4: !Not [!Equals [!Ref EgressIP4, 127.0.0.1]]
CheckEgressIP5: !Not [!Equals [!Ref EgressIP5, 127.0.0.1]]
UseNative: !Equals [!Ref SubnetCategory, Native]
IsGlobalCluster: !Not [!Equals [!Ref GlobalClusterIdentifier, '']]
IsPrimaryRegion: !Equals [!Ref PrimaryRegion, 'Primary']
IsSecondaryRegion: !Not [Condition: IsPrimaryRegion]
IsPrimaryGlobal: !And
- Condition: IsGlobalCluster
- Condition: IsPrimaryRegion
IsSecondaryGlobal: !And
- Condition: IsGlobalCluster
- Condition: IsSecondaryRegion
UseGBTSKeychain: !Equals [!Ref KMSMasterKeyID, ""]
IsPerformanceInsightsEnabled: !Equals [!Ref EnablePerformanceInsights, "True"]
# Define the number of instances to provision using conditions.
#
# This makes things easier for the user, but unfortunately the template gets
# a little messier because of that as each instance needs to be a separate
# resource and we need to have a separate condition.
#
# In theory we can have up to 15 instances attached to a cluster, but 5 (1
# primary + 4 replicas) is a good start.
ShouldCreateInstanceB:
Fn::Or:
- !Equals [!Ref InstanceCount, 2]
- !Equals [!Ref InstanceCount, 3]
- !Equals [!Ref InstanceCount, 4]
- !Equals [!Ref InstanceCount, 5]
ShouldCreateInstanceC:
Fn::Or:
- !Equals [!Ref InstanceCount, 3]
- !Equals [!Ref InstanceCount, 4]
- !Equals [!Ref InstanceCount, 5]
ShouldCreateInstanceD:
Fn::Or:
- !Equals [!Ref InstanceCount, 4]
- !Equals [!Ref InstanceCount, 5]
ShouldCreateInstanceE: !Equals [!Ref InstanceCount, 5]
ShouldEnableSnapshotRetention: !Not [!Equals [!Ref SnapshotRetention, None]]
# The Japanese DBA team manages their own deployments.
PSJL:
Fn::Or:
- !Equals [!Ref SupportGroup, PSJL]
- Fn::And:
- !Equals [!Ref SupportGroup, Automatic]
- Fn::Or:
- !Equals [!Ref AWS::Region, ap-northeast-1]
- !Equals [!Ref AWS::Region, ap-northeast-3]
IsUseDBSnapshot: !And
- !Not [!Equals [!Ref DBSnapshotName, ""]]
- !Not [Condition: IsSecondaryGlobal]
IsSecondaryOrRestore: !Or [Condition: IsSecondaryGlobal, Condition: IsUseDBSnapshot]
IsPrimaryRegionAndNotRestore: !And
- Condition: IsPrimaryRegion
- !Equals [!Ref DBSnapshotName, ""]
IsEnabledGlueConnection: !Equals [!Ref EnableGlueConnection, "True"]
# IsDev is used to determine whether or not to call the IAM CustomResource Lambda
# Using AccountTier would be better but needs to be passed to the template first
# And call only once in primary region
IsDev: !Equals [!Ref Tier, dev]
IsDevAndPrimaryRegionAndNotRestore: !And
- Condition: IsDev
- Condition: IsPrimaryRegionAndNotRestore
IsDevAndEnableDevelopers: !And
- Condition: IsDevAndPrimaryRegionAndNotRestore
- !Equals [!Ref EnableDevelopers, "True"]
IsCertAuthorityParamNotBlank: !Not [!Equals [!Ref CertificateAuthority, ""]]
HasAdditionalSharedPreloadLibraries: !Not [!Equals [!Ref AdditionalSharedPreloadLibraries, ""]]
ShouldEnableIPv6: !Equals [!Ref EnableIPv6, "True"]
ShouldUseCustomTimezone: !Not [!Equals [!Ref Timezone, ""]]
ShouldEnableImportRole: !Not [!Equals [!Ref S3ImportRole, ""]]
ShouldEnableExportRole: !Not [!Equals [!Ref S3ExportRole, ""]]
ShouldEnableLambdaRole: !Not [!Equals [!Ref LambdaRole, ""]]
ShouldEnableEnhancedMonitoring: !Not [!Equals [!Ref MonitoringInterval, 0]]
PSJLorSecretNameOverride:
Fn::Or:
- Condition: PSJL
- !Equals [!Ref SecretNameOverride, "PSJL"]
Resources:
# #############################################
# Secret
#
# DEG is given access, but RSMs are *not*
# #############################################
AuroraDBCreateSecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: !Sub "${Tier} AuroraDB AuthToken"
KmsKeyId: !ImportValue "secretsmanagerkms-cmk"
# DEG implicitly has access to secrets in the /deg/
# namespace. DEGSupportRole.yaml@1abb4970789#94
Name: !If
- PSJLorSecretNameOverride
- !Sub "/deg/${AWS::StackName}/deg/aurora/authtoken"
- !Sub "/deg/${BusinessUnit}/${ApplicationIDName}\
/${Tier}/deg/aurora/authtoken"
GenerateSecretString:
SecretStringTemplate: '{"username": "rdsmaster"}'
GenerateStringKey: "password"
PasswordLength: "20"
ExcludeCharacters: '"@/\:`^$,?|%'
Tags:
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: CostCenter
Value: !Ref CostCenter
- Key: RSMs
Value: !Ref RSMs
- Key: DataClassification
Value: !Ref DataClassification
- Key: BusinessUnit
Value: !Ref BusinessUnit
AuroraDBSecretPolicy:
Type: AWS::SecretsManager::ResourcePolicy
Properties:
SecretId: !Ref AuroraDBCreateSecret
ResourcePolicy:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
# We only allow the devops tool and support group using the
# Condition below
AWS: "*"
Action:
-
secretsmanager:DescribeSecret
-
secretsmanager:ListSecrets
-
secretsmanager:GetSecretValue
Resource: !Ref AuroraDBCreateSecret
Condition:
ForAnyValue:StringLike:
aws:PrincipalArn:
# Allow support group access
# The Japanese DBA team manages their own deployments.
- !If
- PSJL
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/psjl-???-database_engineering
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt-???-database_engineering
# Allow devops tool in local account
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*
# Allow devops tool in shared services
- "
arn:aws:iam::527083916834:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*"
- !If
- PSJL
# This will need to be updated if and when PSJL starts using "SSO"
- !Ref AWS::NoValue
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_database-administrator_*
# Hard deny secret value access from non-support group. Internal
# database accounts must be provisioned by the support group to
# access database resources, if and as necessary.
- Effect: "Deny"
Principal:
AWS: "*"
Action:
-
secretsmanager:GetSecretValue
Resource: !Ref AuroraDBCreateSecret
Condition:
ForAnyValue:StringNotLike:
aws:PrincipalArn:
- !If
- PSJL
# The Japanese DBA team manages their own deployments.
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/psjl-???-database_engineering
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt-???-database_engineering
# Allow devops tool in local account
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*
# Allow devops tool in shared services
- "
arn:aws:iam::527083916834:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*"
# Allow lambda that runs commands inside the database
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/deg/GT-DEG-Postgres-Install-Auto-PostgresLambdaRole-*
# Allow lambda that runs commands inside the database
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/deg/GT-DEG-Postgres-Install-Auto-IAMLambdaRole-*
- !If
- PSJL
# This will need to be updated if and when PSJL starts using "SSO"
- !Ref AWS::NoValue
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_database-administrator_*
FlywayCreateSecret:
Type: AWS::SecretsManager::Secret
Condition: IsPrimaryRegion
Properties:
Description: !Sub "${Tier} dbacd Flyway account"
KmsKeyId: !ImportValue "secretsmanagerkms-cmk"
Name: !Sub "/deg/${AWS::StackName}/dbacd"
GenerateSecretString:
SecretStringTemplate: '{"username": "dbacd"}'
GenerateStringKey: "password"
PasswordLength: "20"
ExcludeCharacters: '"@/\:`^$,?|%''' # To escape single quote, use 2 of them
Tags:
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: CostCenter
Value: !Ref CostCenter
- Key: RSMs
Value: !Ref RSMs
- Key: DataClassification
Value: !Ref DataClassification
- Key: BusinessUnit
Value: !Ref BusinessUnit
FlywaySecretPolicy:
Type: AWS::SecretsManager::ResourcePolicy
Condition: IsPrimaryRegion
Properties:
SecretId: !Ref FlywayCreateSecret
ResourcePolicy:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
# We only allow the devops tool and support group using the
# Condition below
AWS: "*"
Action:
-
secretsmanager:DescribeSecret
-
secretsmanager:ListSecrets
-
secretsmanager:GetSecretValue
Resource: !Ref FlywayCreateSecret
Condition:
ForAnyValue:StringLike:
aws:PrincipalArn:
# Allow support group access
# The Japanese DBA team manages their own deployments.
- !If
- PSJL
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/psjl-???-database_engineering
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt-???-database_engineering
- !If
- PSJL
# This will need to be updated if and when PSJL starts using "SSO"
- !Ref AWS::NoValue
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_database-administrator_*
# Allow devops tool in local account
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*
# Allow devops tool in shared services
- "
arn:aws:iam::527083916834:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*"
# Hard deny secret value access from non-support group. Internal
# database accounts must be provisioned by the support group to
# access database resources, if and as necessary.
- Effect: "Deny"
Principal:
AWS: "*"
Action:
-
secretsmanager:GetSecretValue
Resource: !Ref FlywayCreateSecret
Condition:
ForAnyValue:StringNotLike:
aws:PrincipalArn:
- !If
- PSJL
# The Japanese DBA team manages their own deployments.
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/psjl-???-database_engineering
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt-???-database_engineering
- !If
- PSJL
# This will need to be updated if and when PSJL starts using "SSO"
- !Ref AWS::NoValue
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_database-administrator_*
# Allow devops tool in local account
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*
# Allow devops tool in shared services
- "
arn:aws:iam::527083916834:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*"
# Allow lambda that runs commands inside the database
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/deg/GT-DEG-Postgres-Install-Auto-PostgresLambdaRole-*
FoglightCreateSecret:
Type: AWS::SecretsManager::Secret
Condition: IsPrimaryRegion
Properties:
Description: !Sub "${Tier} fglmon Foglight account"
KmsKeyId: !ImportValue "secretsmanagerkms-cmk"
Name: !Sub "/deg/${AWS::StackName}/fglmon"
GenerateSecretString:
SecretStringTemplate: '{"username": "fglmon"}'
GenerateStringKey: "password"
PasswordLength: "20"
ExcludeCharacters: '"@/\:`^$,?|%''' # To escape single quote, use 2 of them
Tags:
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: CostCenter
Value: !Ref CostCenter
- Key: DataClassification
Value: !Ref DataClassification
- Key: BusinessUnit
Value: !Ref BusinessUnit
FoglightSecretPolicy:
Type: AWS::SecretsManager::ResourcePolicy
Condition: IsPrimaryRegion
Properties:
SecretId: !Ref FoglightCreateSecret
ResourcePolicy:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
# We only allow the devops tool and support group using the
# Condition below
AWS: "*"
Action:
-
secretsmanager:DescribeSecret
-
secretsmanager:ListSecrets
-
secretsmanager:GetSecretValue
Resource: !Ref FoglightCreateSecret
Condition:
ForAnyValue:StringLike:
aws:PrincipalArn:
# Allow DEG
- !Sub
arn:aws:iam::${AWS::AccountId}:role/gt-???-database_engineering
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_database-administrator_*
# Allow devops tool in local account
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*
# Allow devops tool in shared services
- "
arn:aws:iam::527083916834:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*"
# Hard deny secret value access from non-support group. Internal
# database accounts must be provisioned by the support group to
# access database resources, if and as necessary.
- Effect: "Deny"
Principal:
AWS: "*"
Action:
-
secretsmanager:GetSecretValue
Resource: !Ref FoglightCreateSecret
Condition:
ForAnyValue:StringNotLike:
aws:PrincipalArn:
# DEG
- !Sub
arn:aws:iam::${AWS::AccountId}:role/gt-???-database_engineering
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_database-administrator_*
# Allow devops tool in local account
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*
# Allow devops tool in shared services
- "
arn:aws:iam::527083916834:role/gt/devops/backend/GT-ENG-RES-DevOpsBackend-DefaultEntityRole*"
# Allow lambda that runs commands inside the database
- !Sub >-
arn:aws:iam::${AWS::AccountId}:role/deg/GT-DEG-Postgres-Install-Auto-PostgresLambdaRole-*
# #############################################
# Networking
#
# - A base security group is created, and then each ingress rule based on the
# values of IP[1..5]
# - A subnet group is created
# #############################################
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Metadata:
cfn_nag:
rules_to_suppress:
- id: W9 # Security Groups found with ingress cidr that is not /32
reason: We want to allow some access to the RDS
Properties:
GroupDescription: !Sub >-
I am the security group for the Aurora Postgres Server Deploy via
${AWS::StackName}.
Tags:
- Key: __SupportProvider
Value: GT
- Key: __StackName
Value: !Ref AWS::StackName
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
VpcId: !ImportValue gt-vpc-v3
SecurityGroupEgress:
# To have a default egress rule allow the network loopback address.
- CidrIp: 127.0.0.1/32
Description: Allow self.
FromPort: 5432
IpProtocol: tcp
ToPort: 5432
SecurityGroupIngressGroup:
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Allow inbound access on port 5432
SourceSecurityGroupId: !GetAtt SecurityGroup.GroupId
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
SecurityGroupIngressGroupForGlue:
Condition: IsEnabledGlueConnection
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Allow inbound access on all ports for AWS Glue
SourceSecurityGroupId: !GetAtt SecurityGroup.GroupId
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
SecurityGroupEgressGroup:
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: Allow outbound access on port 5432
DestinationSecurityGroupId: !GetAtt SecurityGroup.GroupId
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
SecurityGroupEgressGroupForGlue:
Condition: IsEnabledGlueConnection
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: Allow outbound access on all ports for AWS Glue
DestinationSecurityGroupId: !GetAtt SecurityGroup.GroupId
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
SecurityGroupEgressGroupForGlue2:
Condition: IsEnabledGlueConnection
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: Allow outbound access on 443 ports for AWS Glue
DestinationPrefixListId: !FindInMap [S3PrefixListMap, !Ref 'AWS::Region', S3PrefixListId]
FromPort: 443
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 443
# IP1
SecurityGroupIngress1:
Condition: CheckIP1
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: !Sub Allow ingress from ${IP1}
CidrIp: !Sub ${IP1}/${IP1Mask}
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
# IP2
SecurityGroupIngress2:
Condition: CheckIP2
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: !Sub Allow ingress from ${IP2}
CidrIp: !Sub ${IP2}/${IP2Mask}
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
# IP3
SecurityGroupIngress3:
Condition: CheckIP3
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: !Sub Allow ingress from ${IP3}
CidrIp: !Sub ${IP3}/${IP3Mask}
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
# IP4
SecurityGroupIngress4:
Condition: CheckIP4
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: !Sub Allow ingress from ${IP4}
CidrIp: !Sub ${IP4}/${IP4Mask}
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
# IP5
SecurityGroupIngress5:
Condition: CheckIP5
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: !Sub Allow ingress from ${IP5}
CidrIp: !Sub ${IP5}/${IP5Mask}
FromPort: 5432
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 5432
# IP1
SecurityGroupEgress1:
Condition: CheckEgressIP1
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: !Sub Allow egress to ${EgressIP1}
CidrIp: !Sub ${EgressIP1}/${EgressIP1Mask}
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
# IP2
SecurityGroupEgress2:
Condition: CheckEgressIP2
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: !Sub Allow egress to ${EgressIP2}
CidrIp: !Sub ${EgressIP2}/${EgressIP2Mask}
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
# IP3
SecurityGroupEgress3:
Condition: CheckEgressIP3
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: !Sub Allow egress to ${EgressIP3}
CidrIp: !Sub ${EgressIP3}/${EgressIP3Mask}
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
# IP4
SecurityGroupEgress4:
Condition: CheckEgressIP4
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: !Sub Allow egress to ${EgressIP4}
CidrIp: !Sub ${EgressIP4}/${EgressIP4Mask}
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
# IP5
SecurityGroupEgress5:
Condition: CheckEgressIP5
DependsOn: SecurityGroup
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: !Sub Allow egress to ${EgressIP5}
CidrIp: !Sub ${EgressIP5}/${EgressIP5Mask}
FromPort: 0
GroupId: !GetAtt SecurityGroup.GroupId
IpProtocol: tcp
ToPort: 65535
SubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: !Sub Aurora SubnetGroup for ${AWS::StackName}
SubnetIds: !If
- UseNative
- - !ImportValue VpcV3-Native-1
- !ImportValue VpcV3-Native-2
- !ImportValue VpcV3-Native-3
- - !ImportValue VpcV3-PruRouted-1
- !ImportValue VpcV3-PruRouted-2
- !ImportValue VpcV3-PruRouted-3
Tags:
- Key: __StackName
Value: !Ref AWS::StackName
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
# #############################################
# Single-region cluster
#
# Created regardless of whether the current region is the primary. If the
# consumer wants a global cluster, this local cluster is joined to the
# provisioned global cluster.
# #############################################
# Cluster parameter group
DBClusterParameterGroup:
Type: AWS::RDS::DBClusterParameterGroup
Properties:
Description: !Ref AWS::StackName
Family: !FindInMap [EngineMap, !Ref PostgresVersion, family]
Parameters:
client_encoding: UTF8
timezone: !If
- ShouldUseCustomTimezone
- !Ref Timezone
- !If [PSJL, Japan, EST]
rds.force_ssl: '1'
pgaudit.log: ddl, role
pgaudit.role: rds_pgaudit
shared_preload_libraries: !Join
- ""
- - !If
- HasAdditionalSharedPreloadLibraries
- !Sub >-
${AdditionalSharedPreloadLibraries},
- ""
- "pgaudit,pg_stat_statements" # Default: pg_stat_statements
pgaudit.log_parameter: '1'
log_rotation_age: 720 # 12hrs. Default was 60/1hr.
log_connections: '1'
log_disconnections: '1'
log_destination: 'csvlog'
# Role for Enhanced Monitoring
RDSMonitoringRole:
Type: AWS::IAM::Role
Condition: ShouldEnableEnhancedMonitoring
Properties:
PermissionsBoundary: !Ref PermBoundaryName
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: monitoring.rds.amazonaws.com
Action:
sts:AssumeRole
ManagedPolicyArns:
-
arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole
Tags:
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: CostCenter
Value: !Ref CostCenter
- Key: RSMs
Value: !Ref RSMs
- Key: DataClassification
Value: !Ref DataClassification
- Key: BusinessUnit
Value: !Ref BusinessUnit
# Cluster
DBCluster:
DependsOn:
- DBClusterParameterGroup
- SecurityGroup
- SubnetGroup
Type: AWS::RDS::DBCluster
Properties:
# Join secondary region's cluster to Primary region's global cluster ID
# This property is not needed for Primary region's Cluster
GlobalClusterIdentifier:
!If
- IsSecondaryOrRestore
- !Ref GlobalClusterIdentifier
- !Ref 'AWS::NoValue'
BackupRetentionPeriod: !Ref BackupRetentionPeriod
DBClusterIdentifier: !If
- PSJL
- !Sub "${ClusterName}"
- !Sub "${ClusterName}-${ApplicationIDName}-${Tier}"
DBClusterParameterGroupName: !Ref DBClusterParameterGroup
DBInstanceParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref SubnetGroup
DeletionProtection: !Ref TerminationProtection
EnableCloudwatchLogsExports:
- postgresql
EnableIAMDatabaseAuthentication: true
Engine: aurora-postgresql
EngineVersion: !Ref PostgresVersion
EngineMode: !Ref PostgresEngineMode
KmsKeyId: !If
- UseGBTSKeychain
- !If [PSJL, !ImportValue pru-default-keychain, !ImportValue gbtskeychain]
- !Ref KMSMasterKeyID
# These three properties are not needed for Secondary region's Cluster
# of Global DB Cluster
DatabaseName:
!If
- IsSecondaryOrRestore
- !Ref 'AWS::NoValue'
- !Ref DatabaseName
# MasterUsername and MasterUserPassword are restored as part of restores
# AWS lint rule E2520 advises against setting this during restore build.
# AWS Case # 171381426300076 opened on 023. Answer is unclear.
# Needs regression testing to change this and confirm older dbs built using restore are ok.
MasterUsername: !If
- IsSecondaryOrRestore
- !Ref 'AWS::NoValue'
- !Sub "{{
resolve:secretsmanager:${AuroraDBCreateSecret}:\
SecretString:username}}"
MasterUserPassword: !If
- IsSecondaryOrRestore
- !Ref 'AWS::NoValue'
- !Sub "{{
resolve:secretsmanager:${AuroraDBCreateSecret}:\
SecretString:password}}"
Port: 5432
PreferredBackupWindow: !Ref PreferredBackupWindow
PreferredMaintenanceWindow: !Ref PreferredMaintenanceWindow
MonitoringInterval:
!If
- ShouldEnableEnhancedMonitoring
- !Ref MonitoringInterval
- !Ref AWS::NoValue
MonitoringRoleArn:
!If
- ShouldEnableEnhancedMonitoring
- !GetAtt RDSMonitoringRole.Arn
- !Ref AWS::NoValue
StorageEncrypted: !If [IsUseDBSnapshot, !Ref 'AWS::NoValue', true]
SnapshotIdentifier: !If [IsUseDBSnapshot, !Ref DBSnapshotName, !Ref "AWS::NoValue"]
CopyTagsToSnapshot: !Ref CopyTagsToSnapshot
Tags:
- Key: __SupportProvider
Value: GT
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: DataClassification
Value: !Ref DataClassification
- Key: BusinessUnit
Value: !Ref BusinessUnit
# secret arn. secret name is not available
- Key:
deg:database-secret
Value: !Ref AuroraDBCreateSecret
- Key:
deg:EnableDevelopers
Value: !If
- IsDevAndEnableDevelopers
- !Ref EnableDevelopers
- "False"
- !If
- IsPrimaryRegion
- Key:
deg:dbacd
Value: !Ref FlywayCreateSecret
- !Ref AWS::NoValue
- !If
- IsPrimaryRegion
- Key:
deg:fglmon
Value: !Ref FoglightCreateSecret
- !Ref AWS::NoValue
# Snapshot retention is enabled on the cluster level, according to
#
https://confluence.prudential.com/display/SS/AWS+Backup
#
# Normally we would just conditionally create the tag, but cfn-lint
# E9361 can't parse that for whatever reason (I tried suppressing it
# but no dice). So we'll just create it with a blank value if the user
# doesn't want snapshot retention.
- Key: SnapshotRetention
Value: !If
- ShouldEnableSnapshotRetention
- !Ref SnapshotRetention
- !Ref AWS::NoValue
VpcSecurityGroupIds:
- !Ref SecurityGroup
NetworkType: !If
- ShouldEnableIPv6
- DUAL
- IPV4
AssociatedRoles:
- Fn::If:
- ShouldEnableImportRole
- FeatureName: s3Import
RoleArn: !Ref S3ImportRole
- !Ref AWS::NoValue
- Fn::If:
- ShouldEnableExportRole
- FeatureName: s3Export
RoleArn: !Ref S3ExportRole
- !Ref AWS::NoValue
- Fn::If:
- ShouldEnableLambdaRole
- FeatureName: Lambda
RoleArn: !Ref LambdaRole
- !Ref AWS::NoValue
# #############################################
# Individual DB instances
#
# These are joined to the local DB cluster.
# #############################################
# The instances all rely on this ParameterGroup
DBParameterGroup:
Type: AWS::RDS::DBParameterGroup
Properties:
Description: !Ref AWS::StackName
Family: !FindInMap [EngineMap, !Ref PostgresVersion, family]
Parameters:
pgaudit.log: ddl, role
# Always created, clusters must have at least 1
DBInstanceA:
DependsOn:
- DBParameterGroup
- DBCluster
Metadata:
cfn_nag:
rules_to_suppress:
- id: F22
reason: bad check splat required as
the only action for PutMetricData
Type: AWS::RDS::DBInstance
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: !FindInMap
- MinorUpdateMap
- !Ref MinorVersionUpgrade
- value
CACertificateIdentifier: !If
- IsCertAuthorityParamNotBlank
- !Ref CertificateAuthority
- 'rds-ca-rsa4096-g1'
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref MachineType
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref SubnetGroup
Engine: aurora-postgresql
PubliclyAccessible: false
EnablePerformanceInsights: !Ref EnablePerformanceInsights
PerformanceInsightsKMSKeyId: !If
- IsPerformanceInsightsEnabled
- !If
- UseGBTSKeychain
- !If [PSJL, !ImportValue pru-default-keychain, !ImportValue gbtskeychain]
- !Ref KMSMasterKeyID
- !Ref 'AWS::NoValue'
PerformanceInsightsRetentionPeriod: !If
- IsPerformanceInsightsEnabled
- !Ref PerformanceInsightsRetentionPeriod
- !Ref 'AWS::NoValue'
Tags:
- Key: __SupportProvider
Value: GT
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: DataClassification
Value: !Ref DataClassification
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
DBInstanceB:
Type: AWS::RDS::DBInstance
DependsOn:
# Force separation into different AZs at the cost of time
- DBInstanceA
- DBParameterGroup
- DBCluster
Condition: ShouldCreateInstanceB
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: !FindInMap
- MinorUpdateMap
- !Ref MinorVersionUpgrade
- value
CACertificateIdentifier: !If
- IsCertAuthorityParamNotBlank
- !Ref CertificateAuthority
- 'rds-ca-rsa4096-g1'
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref MachineType
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref SubnetGroup
Engine: aurora-postgresql
PubliclyAccessible: false
EnablePerformanceInsights: !Ref EnablePerformanceInsights
PerformanceInsightsKMSKeyId: !If
- UseGBTSKeychain
- !If [PSJL, !ImportValue pru-default-keychain, !ImportValue gbtskeychain]
- !Ref KMSMasterKeyID
Tags:
- Key: __SupportProvider
Value: GT
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: DataClassification
Value: !Ref DataClassification
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
DBInstanceC:
Type: AWS::RDS::DBInstance
DependsOn:
# Force separation into different AZs at the cost of time
- DBInstanceB
- DBParameterGroup
- DBCluster
Condition: ShouldCreateInstanceC
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: !FindInMap
- MinorUpdateMap
- !Ref MinorVersionUpgrade
- value
CACertificateIdentifier: !If
- IsCertAuthorityParamNotBlank
- !Ref CertificateAuthority
- 'rds-ca-rsa4096-g1'
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref MachineType
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref SubnetGroup
Engine: aurora-postgresql
PubliclyAccessible: false
EnablePerformanceInsights: !Ref EnablePerformanceInsights
PerformanceInsightsKMSKeyId: !If
- UseGBTSKeychain
- !If [PSJL, !ImportValue pru-default-keychain, !ImportValue gbtskeychain]
- !Ref KMSMasterKeyID
Tags:
- Key: __SupportProvider
Value: GT
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: DataClassification
Value: !Ref DataClassification
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
DBInstanceD:
Type: AWS::RDS::DBInstance
DependsOn:
# Force separation into different AZs at the cost of time
- DBInstanceC
- DBParameterGroup
- DBCluster
Condition: ShouldCreateInstanceD
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: !FindInMap
- MinorUpdateMap
- !Ref MinorVersionUpgrade
- value
CACertificateIdentifier: !If
- IsCertAuthorityParamNotBlank
- !Ref CertificateAuthority
- 'rds-ca-rsa4096-g1'
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref MachineType
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref SubnetGroup
Engine: aurora-postgresql
PubliclyAccessible: false
EnablePerformanceInsights: !Ref EnablePerformanceInsights
PerformanceInsightsKMSKeyId: !If
- UseGBTSKeychain
- !If [PSJL, !ImportValue pru-default-keychain, !ImportValue gbtskeychain]
- !Ref KMSMasterKeyID
Tags:
- Key: __SupportProvider
Value: GT
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: DataClassification
Value: !Ref DataClassification
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
DBInstanceE:
Type: AWS::RDS::DBInstance
DependsOn:
# Force separation into different AZs at the cost of time
- DBInstanceD
- DBParameterGroup
- DBCluster
Condition: ShouldCreateInstanceE
Properties:
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: !FindInMap
- MinorUpdateMap
- !Ref MinorVersionUpgrade
- value
CACertificateIdentifier: !If
- IsCertAuthorityParamNotBlank
- !Ref CertificateAuthority
- 'rds-ca-rsa4096-g1'
DBClusterIdentifier: !Ref DBCluster
DBInstanceClass: !Ref MachineType
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref SubnetGroup
Engine: aurora-postgresql
PubliclyAccessible: false
EnablePerformanceInsights: !Ref EnablePerformanceInsights
PerformanceInsightsKMSKeyId: !If
- UseGBTSKeychain
- !If [PSJL, !ImportValue pru-default-keychain, !ImportValue gbtskeychain]
- !Ref KMSMasterKeyID
Tags:
- Key: __SupportProvider
Value: GT
- Key: ApplicationIDName
Value: !Ref ApplicationIDName
- Key:
cmdb:businessapp:number
Value: !Ref APMNumber
- Key:
pruaws:CE_PROJECT_NAME
Value: !Ref ProjectName
- Key: DataClassification
Value: !Ref DataClassification
- Key: RSMs
Value: !Ref RSMs
- Key: CostCenter
Value: !Ref CostCenter
- Key: BusinessUnit
Value: !Ref BusinessUnit
# #############################################
# Global cluster
#
# Created when this is the primary region, as indicated by the PrimaryRegion
# parameter. Created AFTER the local cluster. The local cluster is considered
# the "source".
# ######################################