dbt-platform-helper 11.3.0__py3-none-any.whl → 12.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dbt-platform-helper might be problematic. Click here for more details.
- dbt_platform_helper/COMMANDS.md +3 -252
- dbt_platform_helper/addons-template-map.yml +7 -33
- dbt_platform_helper/commands/application.py +8 -7
- dbt_platform_helper/commands/conduit.py +1 -4
- dbt_platform_helper/commands/copilot.py +14 -110
- dbt_platform_helper/commands/environment.py +0 -5
- dbt_platform_helper/commands/pipeline.py +1 -13
- dbt_platform_helper/domain/database_copy.py +2 -2
- dbt_platform_helper/domain/maintenance_page.py +0 -3
- dbt_platform_helper/templates/addon-instructions.txt +1 -1
- dbt_platform_helper/templates/addons/svc/s3-policy.yml +0 -8
- dbt_platform_helper/utils/aws.py +3 -1
- dbt_platform_helper/utils/platform_config.py +2 -7
- dbt_platform_helper/utils/validation.py +3 -78
- {dbt_platform_helper-11.3.0.dist-info → dbt_platform_helper-12.0.0.dist-info}/METADATA +1 -1
- {dbt_platform_helper-11.3.0.dist-info → dbt_platform_helper-12.0.0.dist-info}/RECORD +20 -33
- platform_helper.py +0 -8
- dbt_platform_helper/commands/check_cloudformation.py +0 -87
- dbt_platform_helper/commands/dns.py +0 -952
- dbt_platform_helper/custom_resources/__init__.py +0 -0
- dbt_platform_helper/custom_resources/s3_object.py +0 -85
- dbt_platform_helper/templates/addons/env/addons.parameters.yml +0 -19
- dbt_platform_helper/templates/addons/env/aurora-postgres.yml +0 -604
- dbt_platform_helper/templates/addons/env/monitoring.yml +0 -121
- dbt_platform_helper/templates/addons/env/opensearch.yml +0 -257
- dbt_platform_helper/templates/addons/env/rds-postgres.yml +0 -603
- dbt_platform_helper/templates/addons/env/redis-cluster.yml +0 -171
- dbt_platform_helper/templates/addons/env/s3.yml +0 -219
- dbt_platform_helper/templates/addons/env/vpc.yml +0 -120
- dbt_platform_helper/utils/cloudformation.py +0 -34
- {dbt_platform_helper-11.3.0.dist-info → dbt_platform_helper-12.0.0.dist-info}/LICENSE +0 -0
- {dbt_platform_helper-11.3.0.dist-info → dbt_platform_helper-12.0.0.dist-info}/WHEEL +0 -0
- {dbt_platform_helper-11.3.0.dist-info → dbt_platform_helper-12.0.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,604 +0,0 @@
|
|
|
1
|
-
# {% extra_header %}
|
|
2
|
-
# {% version_info %}
|
|
3
|
-
|
|
4
|
-
Parameters:
|
|
5
|
-
# Copilot required Parameters...
|
|
6
|
-
App:
|
|
7
|
-
Type: String
|
|
8
|
-
Description: Your application's name.
|
|
9
|
-
Env:
|
|
10
|
-
Type: String
|
|
11
|
-
Description: The environment name your service, job, or workflow is being deployed to.
|
|
12
|
-
|
|
13
|
-
# Parameters from the parent stack brought in via addons.parameters.yml...
|
|
14
|
-
EnvironmentSecurityGroup:
|
|
15
|
-
Type: String
|
|
16
|
-
DefaultPublicRoute:
|
|
17
|
-
Type: String
|
|
18
|
-
InternetGateway:
|
|
19
|
-
Type: String
|
|
20
|
-
InternetGatewayAttachment:
|
|
21
|
-
Type: String
|
|
22
|
-
PrivateSubnets:
|
|
23
|
-
Type: String
|
|
24
|
-
PublicRouteTable:
|
|
25
|
-
Type: String
|
|
26
|
-
PublicSubnet1RouteTableAssociation:
|
|
27
|
-
Type: String
|
|
28
|
-
PublicSubnet2RouteTableAssociation:
|
|
29
|
-
Type: String
|
|
30
|
-
VpcId:
|
|
31
|
-
Type: String
|
|
32
|
-
|
|
33
|
-
# Other parameters...
|
|
34
|
-
# Customize your Aurora Postgres cluster by setting the default value of the following parameters.
|
|
35
|
-
{{ addon_config.prefix }}DBName:
|
|
36
|
-
Type: String
|
|
37
|
-
Description: The name of the initial database to be created in the Aurora Serverless v2 cluster.
|
|
38
|
-
Default: main
|
|
39
|
-
# Cannot have special characters
|
|
40
|
-
# Naming constraints: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints
|
|
41
|
-
|
|
42
|
-
Mappings:
|
|
43
|
-
{{ addon_config.prefix }}EnvironmentConfigMap:
|
|
44
|
-
{%- for environment_name, config in addon_config.environments.items() %}
|
|
45
|
-
{{ environment_name }}:
|
|
46
|
-
DBMinCapacity: {{ config.min_capacity }}
|
|
47
|
-
DBMaxCapacity: {{ config.max_capacity }}
|
|
48
|
-
DeletionPolicy: {{ config.deletion_policy }}
|
|
49
|
-
SnapshotIdentifier: {{ config.snapshot_id if config.snapshot_id else '""' }}
|
|
50
|
-
DeletionProtection: {{ config.deletion_protection if config.deletion_protection else false }}
|
|
51
|
-
{%- endfor %}
|
|
52
|
-
|
|
53
|
-
Conditions:
|
|
54
|
-
{{ addon_config.prefix }}CreateProdSubFilter: !Or [!Equals [!Ref Env, prod], !Equals [!Ref Env, production], !Equals [!Ref Env, PROD], !Equals [!Ref Env, PRODUCTION]]
|
|
55
|
-
{{ addon_config.prefix }}UseSnapshot: !Not [!Equals [!FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, SnapshotIdentifier], ""]]
|
|
56
|
-
|
|
57
|
-
Resources:
|
|
58
|
-
{{ addon_config.prefix }}DBSubnetGroup:
|
|
59
|
-
Type: 'AWS::RDS::DBSubnetGroup'
|
|
60
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
61
|
-
UpdateReplacePolicy: Retain
|
|
62
|
-
Properties:
|
|
63
|
-
DBSubnetGroupDescription: Group of Copilot private subnets for Aurora Serverless v2 cluster.
|
|
64
|
-
SubnetIds: !Split [ ",", !Ref PrivateSubnets ]
|
|
65
|
-
|
|
66
|
-
{{ addon_config.prefix }}SecurityGroup:
|
|
67
|
-
Metadata:
|
|
68
|
-
'aws:copilot:description': 'A security group for your workload to access the Aurora Serverless v2 cluster {{ addon_config.prefix }}'
|
|
69
|
-
Type: 'AWS::EC2::SecurityGroup'
|
|
70
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
71
|
-
UpdateReplacePolicy: Retain
|
|
72
|
-
Properties:
|
|
73
|
-
GroupDescription: 'The Security Group for {{ addon_config.name }} to access Aurora Serverless v2 cluster {{ addon_config.prefix }}.'
|
|
74
|
-
VpcId: !Ref VpcId
|
|
75
|
-
Tags:
|
|
76
|
-
- Key: Name
|
|
77
|
-
Value: !Sub 'copilot-${App}-${Env}-{{ addon_config.name }}-Aurora'
|
|
78
|
-
|
|
79
|
-
{{ addon_config.prefix }}DBClusterSecurityGroup:
|
|
80
|
-
Metadata:
|
|
81
|
-
'aws:copilot:description': 'A security group for your Aurora Serverless v2 cluster {{ addon_config.prefix }}'
|
|
82
|
-
Type: AWS::EC2::SecurityGroup
|
|
83
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
84
|
-
UpdateReplacePolicy: Retain
|
|
85
|
-
Properties:
|
|
86
|
-
GroupDescription: The Security Group for the Aurora Serverless v2 cluster.
|
|
87
|
-
SecurityGroupIngress:
|
|
88
|
-
- ToPort: 5432
|
|
89
|
-
FromPort: 5432
|
|
90
|
-
IpProtocol: tcp
|
|
91
|
-
Description: 'From the Aurora Security Group of the workload {{ addon_config.name }}.'
|
|
92
|
-
SourceSecurityGroupId: !Ref {{ addon_config.prefix }}SecurityGroup
|
|
93
|
-
VpcId: !Ref VpcId
|
|
94
|
-
|
|
95
|
-
{{ addon_config.prefix }}AuroraSecret:
|
|
96
|
-
Metadata:
|
|
97
|
-
'aws:copilot:description': 'A Secrets Manager secret to store your DB credentials'
|
|
98
|
-
Type: AWS::SecretsManager::Secret
|
|
99
|
-
Properties:
|
|
100
|
-
Name: !Sub '/copilot/${App}/${Env}/secrets/{{ addon_config.name|upper|replace("-", "_") }}'
|
|
101
|
-
Description: !Sub Aurora main user secret for ${AWS::StackName}
|
|
102
|
-
GenerateSecretString:
|
|
103
|
-
SecretStringTemplate: '{"username": "postgres"}'
|
|
104
|
-
GenerateStringKey: "password"
|
|
105
|
-
ExcludePunctuation: true
|
|
106
|
-
IncludeSpace: false
|
|
107
|
-
PasswordLength: 16
|
|
108
|
-
ExcludeCharacters: '[]{}()"@/\;=?&`><:|#'
|
|
109
|
-
|
|
110
|
-
{{ addon_config.prefix }}DBClusterParameterGroup:
|
|
111
|
-
Metadata:
|
|
112
|
-
'aws:copilot:description': 'A DB parameter group for engine configuration values'
|
|
113
|
-
Type: 'AWS::RDS::DBClusterParameterGroup'
|
|
114
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
115
|
-
UpdateReplacePolicy: Retain
|
|
116
|
-
Properties:
|
|
117
|
-
Description: !Ref 'AWS::StackName'
|
|
118
|
-
Family: 'aurora-postgresql{{ addon_config.version|round(0, "floor")|int }}'
|
|
119
|
-
Parameters:
|
|
120
|
-
client_encoding: 'UTF8'
|
|
121
|
-
log_statement: ddl
|
|
122
|
-
log_statement_sample_rate: '1.0'
|
|
123
|
-
|
|
124
|
-
{{ addon_config.prefix }}KMSKey:
|
|
125
|
-
Type: "AWS::KMS::Key"
|
|
126
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
127
|
-
UpdateReplacePolicy: Retain
|
|
128
|
-
Properties:
|
|
129
|
-
Description: "KMS Key for Aurora encryption"
|
|
130
|
-
KeyPolicy:
|
|
131
|
-
Version: '2012-10-17'
|
|
132
|
-
Id: !Sub '${App}-${Env}-{{ addon_config.prefix }}-cluster-key'
|
|
133
|
-
Statement:
|
|
134
|
-
- Sid: Enable IAM User Permissions
|
|
135
|
-
Effect: Allow
|
|
136
|
-
Principal:
|
|
137
|
-
AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
|
|
138
|
-
Action: kms:*
|
|
139
|
-
Resource: '*'
|
|
140
|
-
|
|
141
|
-
{{ addon_config.prefix }}KeyAlias:
|
|
142
|
-
Type: 'AWS::KMS::Alias'
|
|
143
|
-
Properties:
|
|
144
|
-
AliasName: !Sub 'alias/${App}-${Env}-{{ addon_config.prefix }}-cluster-key'
|
|
145
|
-
TargetKeyId: !Ref {{ addon_config.prefix }}KMSKey
|
|
146
|
-
|
|
147
|
-
{{ addon_config.prefix }}DBCluster:
|
|
148
|
-
Metadata:
|
|
149
|
-
'aws:copilot:description': 'The {{ addon_config.prefix }} Aurora Serverless v2 database cluster'
|
|
150
|
-
Type: 'AWS::RDS::DBCluster'
|
|
151
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
152
|
-
UpdateReplacePolicy: Retain
|
|
153
|
-
Properties:
|
|
154
|
-
AutoMinorVersionUpgrade: true
|
|
155
|
-
BackupRetentionPeriod: 8
|
|
156
|
-
MasterUsername:
|
|
157
|
-
!If [
|
|
158
|
-
{{ addon_config.prefix }}UseSnapshot,
|
|
159
|
-
!Ref AWS::NoValue,
|
|
160
|
-
!Join [ "", [ '{% raw %}{{{% endraw %}resolve:secretsmanager:', !Ref {{ addon_config.prefix }}AuroraSecret, ":SecretString:username{% raw %}}}{% endraw %}" ]]
|
|
161
|
-
]
|
|
162
|
-
MasterUserPassword:
|
|
163
|
-
!If [
|
|
164
|
-
{{ addon_config.prefix }}UseSnapshot,
|
|
165
|
-
!Ref AWS::NoValue,
|
|
166
|
-
!Join [ "", [ '{% raw %}{{{% endraw %}resolve:secretsmanager:', !Ref {{ addon_config.prefix }}AuroraSecret, ":SecretString:password{% raw %}}}{% endraw %}" ]]
|
|
167
|
-
]
|
|
168
|
-
DatabaseName: !Ref {{ addon_config.prefix }}DBName
|
|
169
|
-
Engine: 'aurora-postgresql'
|
|
170
|
-
EngineVersion: '{{ addon_config.version }}'
|
|
171
|
-
EnableCloudwatchLogsExports:
|
|
172
|
-
- postgresql
|
|
173
|
-
DBClusterParameterGroupName: !Ref {{ addon_config.prefix }}DBClusterParameterGroup
|
|
174
|
-
DBSubnetGroupName: !Ref {{ addon_config.prefix }}DBSubnetGroup
|
|
175
|
-
KmsKeyId: !Ref {{ addon_config.prefix }}KMSKey
|
|
176
|
-
Port: 5432
|
|
177
|
-
VpcSecurityGroupIds:
|
|
178
|
-
- !Ref {{ addon_config.prefix }}DBClusterSecurityGroup
|
|
179
|
-
ServerlessV2ScalingConfiguration:
|
|
180
|
-
MinCapacity: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DBMinCapacity]
|
|
181
|
-
MaxCapacity: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DBMaxCapacity]
|
|
182
|
-
SnapshotIdentifier: !If [{{ addon_config.prefix }}UseSnapshot, !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, SnapshotIdentifier], !Ref AWS::NoValue]
|
|
183
|
-
StorageEncrypted: true
|
|
184
|
-
DeletionProtection: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionProtection]
|
|
185
|
-
|
|
186
|
-
{{ addon_config.prefix }}DBWriterInstance:
|
|
187
|
-
Metadata:
|
|
188
|
-
'aws:copilot:description': 'The {{ addon_config.prefix }} Aurora Serverless v2 writer instance'
|
|
189
|
-
Type: 'AWS::RDS::DBInstance'
|
|
190
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
191
|
-
UpdateReplacePolicy: Retain
|
|
192
|
-
Properties:
|
|
193
|
-
DBClusterIdentifier: !Ref {{ addon_config.prefix }}DBCluster
|
|
194
|
-
DBInstanceClass: db.serverless
|
|
195
|
-
EnablePerformanceInsights: true
|
|
196
|
-
Engine: 'aurora-postgresql'
|
|
197
|
-
PromotionTier: 1
|
|
198
|
-
AvailabilityZone: !Select
|
|
199
|
-
- 0
|
|
200
|
-
- !GetAZs
|
|
201
|
-
Ref: AWS::Region
|
|
202
|
-
|
|
203
|
-
{{ addon_config.prefix }}SecretAuroraClusterAttachment:
|
|
204
|
-
Type: AWS::SecretsManager::SecretTargetAttachment
|
|
205
|
-
Properties:
|
|
206
|
-
SecretId: !Ref {{ addon_config.prefix }}AuroraSecret
|
|
207
|
-
TargetId: !Ref {{ addon_config.prefix }}DBCluster
|
|
208
|
-
TargetType: AWS::RDS::DBCluster
|
|
209
|
-
|
|
210
|
-
# Enable ingress from other ECS services created within the environment.
|
|
211
|
-
{{ addon_config.prefix }}EnvironmentIngress:
|
|
212
|
-
Metadata:
|
|
213
|
-
'aws:copilot:description': 'Allow ingress from containers in my application to the OpenSearch cluster'
|
|
214
|
-
Type: AWS::EC2::SecurityGroupIngress
|
|
215
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
216
|
-
UpdateReplacePolicy: Retain
|
|
217
|
-
Properties:
|
|
218
|
-
Description: Ingress Security Group from Fargate containers
|
|
219
|
-
GroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
220
|
-
IpProtocol: tcp
|
|
221
|
-
FromPort: 5432
|
|
222
|
-
ToPort: 5432
|
|
223
|
-
SourceSecurityGroupId: !Ref EnvironmentSecurityGroup
|
|
224
|
-
|
|
225
|
-
{{ addon_config.prefix }}LambdaIngress:
|
|
226
|
-
Metadata:
|
|
227
|
-
'aws:copilot:description': 'Allow ingress from Lambda Functions in my application to the DB cluster'
|
|
228
|
-
Type: AWS::EC2::SecurityGroupIngress
|
|
229
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
230
|
-
UpdateReplacePolicy: Retain
|
|
231
|
-
Properties:
|
|
232
|
-
Description: Ingress from Lambda Functions to DB
|
|
233
|
-
GroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
234
|
-
IpProtocol: tcp
|
|
235
|
-
FromPort: 5432
|
|
236
|
-
ToPort: 5432
|
|
237
|
-
SourceSecurityGroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
238
|
-
|
|
239
|
-
{{ addon_config.prefix }}SecretsManagerIngress:
|
|
240
|
-
Metadata:
|
|
241
|
-
'aws:copilot:description': 'Allow ingress from Lambda Functions in my application to the Secrets Manager'
|
|
242
|
-
Type: AWS::EC2::SecurityGroupIngress
|
|
243
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
244
|
-
UpdateReplacePolicy: Retain
|
|
245
|
-
Properties:
|
|
246
|
-
Description: Ingress from Lambda Functions to Secrets Manager
|
|
247
|
-
GroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
248
|
-
IpProtocol: tcp
|
|
249
|
-
FromPort: 443
|
|
250
|
-
ToPort: 443
|
|
251
|
-
SourceSecurityGroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
252
|
-
|
|
253
|
-
{{ addon_config.prefix }}LambdaEgress:
|
|
254
|
-
Metadata:
|
|
255
|
-
'aws:copilot:description': 'Allow egress from DB cluster in my application to the Lambda Function'
|
|
256
|
-
Type: AWS::EC2::SecurityGroupEgress
|
|
257
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
258
|
-
UpdateReplacePolicy: Retain
|
|
259
|
-
Properties:
|
|
260
|
-
Description: Egress from DB to Lambda Functions
|
|
261
|
-
GroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
262
|
-
IpProtocol: tcp
|
|
263
|
-
FromPort: 5432
|
|
264
|
-
ToPort: 5432
|
|
265
|
-
DestinationSecurityGroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
266
|
-
|
|
267
|
-
{{ addon_config.prefix }}SecretsManagerEgress:
|
|
268
|
-
Metadata:
|
|
269
|
-
'aws:copilot:description': 'Allow egress from Secrets Manager in my application to the Lambda Function'
|
|
270
|
-
Type: AWS::EC2::SecurityGroupEgress
|
|
271
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
272
|
-
UpdateReplacePolicy: Retain
|
|
273
|
-
Properties:
|
|
274
|
-
Description: Egress from Secrets Manager to Lambda Functions
|
|
275
|
-
GroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
276
|
-
IpProtocol: tcp
|
|
277
|
-
FromPort: 443
|
|
278
|
-
ToPort: 443
|
|
279
|
-
DestinationSecurityGroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
280
|
-
|
|
281
|
-
{{ addon_config.prefix }}HTTPSEgress:
|
|
282
|
-
Metadata:
|
|
283
|
-
'aws:copilot:description': 'Allow egress for HTTPS (so the Lambda Function can post a success response back to the Custom Resource)'
|
|
284
|
-
Type: AWS::EC2::SecurityGroupEgress
|
|
285
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
286
|
-
UpdateReplacePolicy: Retain
|
|
287
|
-
Properties:
|
|
288
|
-
CidrIp: 0.0.0.0/0
|
|
289
|
-
Description: Egress for HTTPS
|
|
290
|
-
GroupId: !Ref '{{ addon_config.prefix }}DBClusterSecurityGroup'
|
|
291
|
-
IpProtocol: tcp
|
|
292
|
-
FromPort: 443
|
|
293
|
-
ToPort: 443
|
|
294
|
-
|
|
295
|
-
{{ addon_config.prefix }}LambdaFunction:
|
|
296
|
-
Type: AWS::Lambda::Function
|
|
297
|
-
Properties:
|
|
298
|
-
FunctionName: !Sub "${App}-${Env}-{{ addon_config.prefix }}-aurora-create-user"
|
|
299
|
-
Handler: index.handler
|
|
300
|
-
Runtime: python3.11
|
|
301
|
-
Layers:
|
|
302
|
-
- arn:aws:lambda:eu-west-2:763451185160:layer:python-postgres:1
|
|
303
|
-
MemorySize: 128
|
|
304
|
-
Timeout: 10
|
|
305
|
-
Role: !GetAtt {{ addon_config.prefix }}LambdaFunctionExecutionRole.Arn
|
|
306
|
-
VpcConfig:
|
|
307
|
-
SecurityGroupIds:
|
|
308
|
-
- !Ref {{ addon_config.prefix }}DBClusterSecurityGroup
|
|
309
|
-
SubnetIds: !Split [ ",", !Ref PrivateSubnets ]
|
|
310
|
-
Code:
|
|
311
|
-
ZipFile: |
|
|
312
|
-
import json
|
|
313
|
-
import boto3
|
|
314
|
-
import cfnresponse
|
|
315
|
-
import psycopg2
|
|
316
|
-
from botocore.exceptions import ClientError
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
def drop_user(cursor, username):
|
|
320
|
-
cursor.execute(f"SELECT * FROM pg_catalog.pg_user WHERE usename = '{username}'")
|
|
321
|
-
|
|
322
|
-
if cursor.fetchone() is not None:
|
|
323
|
-
cursor.execute(f"GRANT {username} TO postgres")
|
|
324
|
-
cursor.execute(f"DROP OWNED BY {username}")
|
|
325
|
-
cursor.execute(f"DROP USER {username}")
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
def create_db_user(conn, cursor, username, password, permissions):
|
|
329
|
-
drop_user(cursor, username)
|
|
330
|
-
|
|
331
|
-
cursor.execute(f"CREATE USER {username} WITH ENCRYPTED PASSWORD '%s'" % password)
|
|
332
|
-
cursor.execute(f"GRANT {username} to postgres;")
|
|
333
|
-
cursor.execute(f"GRANT {', '.join(permissions)} ON ALL TABLES IN SCHEMA public TO {username};")
|
|
334
|
-
cursor.execute(f"ALTER DEFAULT PRIVILEGES FOR USER {username} IN SCHEMA public GRANT {', '.join(permissions)} ON TABLES TO {username};")
|
|
335
|
-
conn.commit()
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
def create_or_update_user_secret(ssm, user_secret_name, user_secret_string, event):
|
|
339
|
-
user_secret_description = event['ResourceProperties']['SecretDescription']
|
|
340
|
-
copilot_application = event['ResourceProperties']['CopilotApplication']
|
|
341
|
-
copilot_environment = event['ResourceProperties']['CopilotEnvironment']
|
|
342
|
-
|
|
343
|
-
user_secret = None
|
|
344
|
-
|
|
345
|
-
try:
|
|
346
|
-
user_secret = ssm.put_parameter(
|
|
347
|
-
Name=user_secret_name,
|
|
348
|
-
Description=user_secret_description,
|
|
349
|
-
Value=json.dumps(user_secret_string),
|
|
350
|
-
Tags=[
|
|
351
|
-
{'Key': 'custom:cloudformation:stack-name', 'Value': event["StackId"].split('/')[1]},
|
|
352
|
-
{'Key': 'custom:cloudformation:logical-id', 'Value': event["LogicalResourceId"]},
|
|
353
|
-
{'Key': 'custom:cloudformation:stack-id', 'Value': event["StackId"]},
|
|
354
|
-
{'Key': 'copilot-application', 'Value': copilot_application},
|
|
355
|
-
{'Key': 'copilot-environment', 'Value': copilot_environment},
|
|
356
|
-
],
|
|
357
|
-
Type="String",
|
|
358
|
-
)
|
|
359
|
-
except ClientError as error:
|
|
360
|
-
if error.response["Error"]["Code"] == "ParameterAlreadyExists":
|
|
361
|
-
user_secret = ssm.put_parameter(
|
|
362
|
-
Name=user_secret_name,
|
|
363
|
-
Description=user_secret_description,
|
|
364
|
-
Value=json.dumps(user_secret_string),
|
|
365
|
-
Overwrite=True,
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
return user_secret
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
def handler(event, context):
|
|
372
|
-
print("REQUEST RECEIVED:\n" + json.dumps(event))
|
|
373
|
-
|
|
374
|
-
db_master_user_secret = event['ResourceProperties']['MasterUserSecret']
|
|
375
|
-
user_secret_name = event['ResourceProperties']['SecretName']
|
|
376
|
-
username = event['ResourceProperties']['Username']
|
|
377
|
-
user_permissions = event['ResourceProperties']['Permissions']
|
|
378
|
-
|
|
379
|
-
secrets_manager = boto3.client("secretsmanager")
|
|
380
|
-
ssm = boto3.client("ssm")
|
|
381
|
-
|
|
382
|
-
master_user = json.loads(secrets_manager.get_secret_value(SecretId=db_master_user_secret)["SecretString"])
|
|
383
|
-
|
|
384
|
-
user_password = secrets_manager.get_random_password(
|
|
385
|
-
PasswordLength=16,
|
|
386
|
-
ExcludeCharacters='[]{}()"@/\;=?&`><:|#',
|
|
387
|
-
ExcludePunctuation=True,
|
|
388
|
-
IncludeSpace=False,
|
|
389
|
-
)["RandomPassword"]
|
|
390
|
-
|
|
391
|
-
user_secret_string = {
|
|
392
|
-
"username": username,
|
|
393
|
-
"password": user_password,
|
|
394
|
-
"engine": master_user["engine"],
|
|
395
|
-
"port": master_user["port"],
|
|
396
|
-
"dbname": master_user["dbname"],
|
|
397
|
-
"host": master_user["host"],
|
|
398
|
-
"dbClusterIdentifier": master_user["dbClusterIdentifier"]
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
conn = psycopg2.connect(
|
|
402
|
-
dbname=master_user["dbname"],
|
|
403
|
-
user=master_user["username"],
|
|
404
|
-
password=master_user["password"],
|
|
405
|
-
host=master_user["host"],
|
|
406
|
-
port=master_user["port"]
|
|
407
|
-
)
|
|
408
|
-
|
|
409
|
-
cursor = conn.cursor()
|
|
410
|
-
|
|
411
|
-
response = {"Status": "SUCCESS"}
|
|
412
|
-
|
|
413
|
-
try:
|
|
414
|
-
match event["RequestType"]:
|
|
415
|
-
case "Create":
|
|
416
|
-
create_db_user(conn, cursor, username, user_password, user_permissions)
|
|
417
|
-
|
|
418
|
-
response = {
|
|
419
|
-
**response,
|
|
420
|
-
"Data": create_or_update_user_secret(ssm, user_secret_name, user_secret_string, event)
|
|
421
|
-
}
|
|
422
|
-
case "Update":
|
|
423
|
-
create_db_user(conn, cursor, username, user_password, user_permissions)
|
|
424
|
-
|
|
425
|
-
response = {
|
|
426
|
-
**response,
|
|
427
|
-
"Data": create_or_update_user_secret(ssm, user_secret_name, user_secret_string, event)
|
|
428
|
-
}
|
|
429
|
-
case "Delete":
|
|
430
|
-
drop_user(cursor, username)
|
|
431
|
-
|
|
432
|
-
response = {
|
|
433
|
-
**response,
|
|
434
|
-
"Data": ssm.delete_parameter(Name=user_secret_name)
|
|
435
|
-
}
|
|
436
|
-
case _:
|
|
437
|
-
response = {"Status": "FAILED",
|
|
438
|
-
"Data": {"Error": f"""Invalid requestType of '${event["RequestType"]}'"""}}
|
|
439
|
-
except Exception as e:
|
|
440
|
-
response = {"Status": "FAILED", "Data": {"Error": str(e)}}
|
|
441
|
-
|
|
442
|
-
cursor.close()
|
|
443
|
-
conn.close()
|
|
444
|
-
|
|
445
|
-
print(json.dumps(response, default=str))
|
|
446
|
-
cfnresponse.send(event, context, response["Status"], response["Data"], event["LogicalResourceId"])
|
|
447
|
-
|
|
448
|
-
{{ addon_config.prefix }}ApplicationUser:
|
|
449
|
-
Type: 'Custom::{{ addon_config.prefix }}ApplicationUser'
|
|
450
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
451
|
-
UpdateReplacePolicy: Retain
|
|
452
|
-
Properties:
|
|
453
|
-
ServiceToken: !GetAtt '{{ addon_config.prefix }}LambdaFunction.Arn'
|
|
454
|
-
CopilotApplication: !Sub "${App}"
|
|
455
|
-
CopilotEnvironment: !Sub "${Env}"
|
|
456
|
-
MasterUserSecret: !Ref {{ addon_config.prefix }}AuroraSecret
|
|
457
|
-
SecretDescription: !Sub Aurora application user secret for ${AWS::StackName}
|
|
458
|
-
SecretName: !Sub '/copilot/${App}/${Env}/secrets/{{ addon_config.name|upper|replace("-", "_") }}_APPLICATION_USER'
|
|
459
|
-
DefaultPublicRoute: !Ref DefaultPublicRoute
|
|
460
|
-
InternetGateway: !Ref InternetGateway
|
|
461
|
-
InternetGatewayAttachment: !Ref InternetGatewayAttachment
|
|
462
|
-
PublicRouteTable: !Ref PublicRouteTable
|
|
463
|
-
PublicSubnet1RouteTableAssociation: !Ref PublicSubnet1RouteTableAssociation
|
|
464
|
-
PublicSubnet2RouteTableAssociation: !Ref PublicSubnet2RouteTableAssociation
|
|
465
|
-
Snapshot: !If [{{ addon_config.prefix }}UseSnapshot, !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, SnapshotIdentifier], ""]
|
|
466
|
-
Username: 'application_user'
|
|
467
|
-
Permissions:
|
|
468
|
-
- 'SELECT'
|
|
469
|
-
- 'INSERT'
|
|
470
|
-
- 'UPDATE'
|
|
471
|
-
- 'DELETE'
|
|
472
|
-
- 'TRIGGER'
|
|
473
|
-
# Resource based metadata block to ignore reference to resources in other addon templates. Do not remove.
|
|
474
|
-
Metadata:
|
|
475
|
-
cfn-lint:
|
|
476
|
-
config:
|
|
477
|
-
ignore_checks:
|
|
478
|
-
# https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md
|
|
479
|
-
- E3005
|
|
480
|
-
DependsOn:
|
|
481
|
-
- VpcEndpoint
|
|
482
|
-
- {{ addon_config.prefix }}DBWriterInstance
|
|
483
|
-
- AdditionalNatGateway1
|
|
484
|
-
- AdditionalNatGateway2
|
|
485
|
-
- AdditionalPrivateRoute1
|
|
486
|
-
- AdditionalPrivateRouteTable1
|
|
487
|
-
- AdditionalPrivateRouteTable1Association
|
|
488
|
-
- AdditionalPrivateRoute2
|
|
489
|
-
- AdditionalPrivateRouteTable2
|
|
490
|
-
- AdditionalPrivateRouteTable2Association
|
|
491
|
-
- {{ addon_config.prefix }}SecretAuroraClusterAttachment
|
|
492
|
-
- {{ addon_config.prefix }}EnvironmentIngress
|
|
493
|
-
- {{ addon_config.prefix }}SecretsManagerIngress
|
|
494
|
-
- {{ addon_config.prefix }}LambdaIngress
|
|
495
|
-
- {{ addon_config.prefix }}SecretsManagerEgress
|
|
496
|
-
- {{ addon_config.prefix }}LambdaEgress
|
|
497
|
-
- {{ addon_config.prefix }}HTTPSEgress
|
|
498
|
-
- {{ addon_config.prefix }}KeyAlias
|
|
499
|
-
|
|
500
|
-
{{ addon_config.prefix }}ReadOnlyUser:
|
|
501
|
-
Type: 'Custom::{{ addon_config.prefix }}ReadOnlyUser'
|
|
502
|
-
DeletionPolicy: !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, DeletionPolicy]
|
|
503
|
-
UpdateReplacePolicy: Retain
|
|
504
|
-
Properties:
|
|
505
|
-
ServiceToken: !GetAtt '{{ addon_config.prefix }}LambdaFunction.Arn'
|
|
506
|
-
CopilotApplication: !Sub "${App}"
|
|
507
|
-
CopilotEnvironment: !Sub "${Env}"
|
|
508
|
-
MasterUserSecret: !Ref {{ addon_config.prefix }}AuroraSecret
|
|
509
|
-
SecretDescription: !Sub Aurora read only user secret for ${AWS::StackName}
|
|
510
|
-
SecretName: !Sub '/copilot/${App}/${Env}/secrets/{{ addon_config.name|upper|replace("-", "_") }}_READ_ONLY_USER'
|
|
511
|
-
DefaultPublicRoute: !Ref DefaultPublicRoute
|
|
512
|
-
InternetGateway: !Ref InternetGateway
|
|
513
|
-
InternetGatewayAttachment: !Ref InternetGatewayAttachment
|
|
514
|
-
PublicRouteTable: !Ref PublicRouteTable
|
|
515
|
-
PublicSubnet1RouteTableAssociation: !Ref PublicSubnet1RouteTableAssociation
|
|
516
|
-
PublicSubnet2RouteTableAssociation: !Ref PublicSubnet2RouteTableAssociation
|
|
517
|
-
Snapshot: !If [{{ addon_config.prefix }}UseSnapshot, !FindInMap [{{ addon_config.prefix }}EnvironmentConfigMap, !Ref Env, SnapshotIdentifier], ""]
|
|
518
|
-
Username: 'read_only_user'
|
|
519
|
-
Permissions:
|
|
520
|
-
- 'SELECT'
|
|
521
|
-
# Resource based metadata block to ignore reference to resources in other addon templates. Do not remove.
|
|
522
|
-
Metadata:
|
|
523
|
-
cfn-lint:
|
|
524
|
-
config:
|
|
525
|
-
ignore_checks:
|
|
526
|
-
# https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/rules.md
|
|
527
|
-
- E3005
|
|
528
|
-
DependsOn:
|
|
529
|
-
- VpcEndpoint
|
|
530
|
-
- {{ addon_config.prefix }}DBWriterInstance
|
|
531
|
-
- AdditionalNatGateway1
|
|
532
|
-
- AdditionalNatGateway2
|
|
533
|
-
- AdditionalPrivateRoute1
|
|
534
|
-
- AdditionalPrivateRouteTable1
|
|
535
|
-
- AdditionalPrivateRouteTable1Association
|
|
536
|
-
- AdditionalPrivateRoute2
|
|
537
|
-
- AdditionalPrivateRouteTable2
|
|
538
|
-
- AdditionalPrivateRouteTable2Association
|
|
539
|
-
- {{ addon_config.prefix }}SecretAuroraClusterAttachment
|
|
540
|
-
- {{ addon_config.prefix }}EnvironmentIngress
|
|
541
|
-
- {{ addon_config.prefix }}SecretsManagerIngress
|
|
542
|
-
- {{ addon_config.prefix }}LambdaIngress
|
|
543
|
-
- {{ addon_config.prefix }}SecretsManagerEgress
|
|
544
|
-
- {{ addon_config.prefix }}LambdaEgress
|
|
545
|
-
- {{ addon_config.prefix }}HTTPSEgress
|
|
546
|
-
- {{ addon_config.prefix }}KeyAlias
|
|
547
|
-
|
|
548
|
-
{{ addon_config.prefix }}LambdaFunctionExecutionRole:
|
|
549
|
-
Type: AWS::IAM::Role
|
|
550
|
-
Properties:
|
|
551
|
-
RoleName: !Sub "${App}-${Env}-{{ addon_config.prefix }}-aurora-user"
|
|
552
|
-
AssumeRolePolicyDocument:
|
|
553
|
-
Version: 2012-10-17
|
|
554
|
-
Statement:
|
|
555
|
-
- Effect: Allow
|
|
556
|
-
Action:
|
|
557
|
-
- 'sts:AssumeRole'
|
|
558
|
-
Principal:
|
|
559
|
-
Service:
|
|
560
|
-
- lambda.amazonaws.com
|
|
561
|
-
Policies:
|
|
562
|
-
- PolicyName: !Sub "${App}-${Env}-aurora-user"
|
|
563
|
-
PolicyDocument:
|
|
564
|
-
Version: '2012-10-17'
|
|
565
|
-
Statement:
|
|
566
|
-
- Effect: Allow
|
|
567
|
-
Action:
|
|
568
|
-
- 'ec2:CreateNetworkInterface'
|
|
569
|
-
- 'ec2:DescribeNetworkInterfaces'
|
|
570
|
-
- 'ec2:DeleteNetworkInterface'
|
|
571
|
-
Resource:
|
|
572
|
-
- '*'
|
|
573
|
-
- Effect: Allow
|
|
574
|
-
Action:
|
|
575
|
-
- 'ssm:DeleteParameter'
|
|
576
|
-
- 'ssm:PutParameter'
|
|
577
|
-
- 'ssm:AddTagsToResource'
|
|
578
|
-
- 'kms:Decrypt'
|
|
579
|
-
Resource:
|
|
580
|
-
- '*'
|
|
581
|
-
- Effect: Allow
|
|
582
|
-
Action:
|
|
583
|
-
- 'secretsmanager:DescribeSecret'
|
|
584
|
-
- 'secretsmanager:GetRandomPassword'
|
|
585
|
-
- 'secretsmanager:GetSecretValue'
|
|
586
|
-
Resource:
|
|
587
|
-
- '*'
|
|
588
|
-
- Effect: Allow
|
|
589
|
-
Action:
|
|
590
|
-
- 'logs:CreateLogGroup'
|
|
591
|
-
- 'logs:CreateLogStream'
|
|
592
|
-
- 'logs:PutLogEvents'
|
|
593
|
-
Resource: 'arn:aws:logs:*:*:*'
|
|
594
|
-
|
|
595
|
-
{{ addon_config.prefix }}SubscriptionFilter:
|
|
596
|
-
Type: AWS::Logs::SubscriptionFilter
|
|
597
|
-
DependsOn:
|
|
598
|
-
- {{ addon_config.prefix }}DBWriterInstance
|
|
599
|
-
Properties:
|
|
600
|
-
RoleArn: !Sub 'arn:aws:iam::${AWS::AccountId}:role/CWLtoSubscriptionFilterRole'
|
|
601
|
-
LogGroupName: !Sub '/aws/rds/cluster/${{ '{' }}{{ addon_config.prefix }}DBCluster}/postgresql'
|
|
602
|
-
FilterName: !Sub '/aws/rds/cluster/${App}/${Env}/${{ '{' }}{{ addon_config.prefix }}DBCluster}/postgresql'
|
|
603
|
-
FilterPattern: ''
|
|
604
|
-
DestinationArn: !If [{{ addon_config.prefix }}CreateProdSubFilter, '{{ log_destination.prod }}', '{{ log_destination.dev }}']
|