@friggframework/devtools 2.0.0--canary.397.155fecd.0 → 2.0.0--canary.398.e2147f7.0
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.
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +541 -0
- package/infrastructure/README-TESTING.md +332 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +277 -0
- package/infrastructure/aws-discovery.js +395 -0
- package/infrastructure/aws-discovery.test.js +373 -0
- package/infrastructure/build-time-discovery.js +197 -0
- package/infrastructure/build-time-discovery.test.js +375 -0
- package/infrastructure/create-frigg-infrastructure.js +9 -1
- package/infrastructure/integration.test.js +383 -0
- package/infrastructure/serverless-template.js +510 -6
- package/infrastructure/serverless-template.test.js +498 -0
- package/package.json +5 -5
- package/test/mock-integration.js +14 -4
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
# AWS IAM Credential Requirements for Frigg Applications
|
|
2
|
+
|
|
3
|
+
This document outlines the minimum AWS IAM permissions required to build and deploy Frigg applications with VPC, KMS, and SSM support.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Frigg applications require two distinct sets of permissions:
|
|
8
|
+
|
|
9
|
+
1. **Discovery-Time Permissions** - Used during the build process to discover default AWS resources
|
|
10
|
+
2. **Deployment-Time Permissions** - Used during actual deployment to create CloudFormation resources
|
|
11
|
+
|
|
12
|
+
The AWS discovery process runs during the `before:package:initialize` serverless hook to automatically find your default VPC, subnets, security groups, and KMS keys, eliminating the need for manual resource ID lookup.
|
|
13
|
+
|
|
14
|
+
## Discovery-Time Permissions (Build Process)
|
|
15
|
+
|
|
16
|
+
These permissions are required when `aws-discovery.js` runs during the build to find your default AWS resources:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"Version": "2012-10-17",
|
|
21
|
+
"Statement": [
|
|
22
|
+
{
|
|
23
|
+
"Sid": "AWSDiscoveryPermissions",
|
|
24
|
+
"Effect": "Allow",
|
|
25
|
+
"Action": [
|
|
26
|
+
"sts:GetCallerIdentity",
|
|
27
|
+
"ec2:DescribeVpcs",
|
|
28
|
+
"ec2:DescribeSubnets",
|
|
29
|
+
"ec2:DescribeSecurityGroups",
|
|
30
|
+
"ec2:DescribeRouteTables",
|
|
31
|
+
"kms:ListKeys",
|
|
32
|
+
"kms:DescribeKey"
|
|
33
|
+
],
|
|
34
|
+
"Resource": "*"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### What Each Permission Does:
|
|
41
|
+
- **`sts:GetCallerIdentity`** - Gets your AWS account ID for KMS key ARN construction
|
|
42
|
+
- **`ec2:DescribeVpcs`** - Finds your default VPC or first available VPC
|
|
43
|
+
- **`ec2:DescribeSubnets`** - Identifies private subnets within your VPC
|
|
44
|
+
- **`ec2:DescribeSecurityGroups`** - Locates default security group or Frigg-specific security group
|
|
45
|
+
- **`ec2:DescribeRouteTables`** - Determines which subnets are private (no direct internet gateway route)
|
|
46
|
+
- **`kms:ListKeys`** - Lists available KMS keys in your account
|
|
47
|
+
- **`kms:DescribeKey`** - Gets details about KMS keys to find customer-managed keys
|
|
48
|
+
|
|
49
|
+
## Core Deployment Permissions
|
|
50
|
+
|
|
51
|
+
Required for basic Frigg application deployment:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"Version": "2012-10-17",
|
|
56
|
+
"Statement": [
|
|
57
|
+
{
|
|
58
|
+
"Sid": "CloudFormationFriggStacks",
|
|
59
|
+
"Effect": "Allow",
|
|
60
|
+
"Action": [
|
|
61
|
+
"cloudformation:CreateStack",
|
|
62
|
+
"cloudformation:UpdateStack",
|
|
63
|
+
"cloudformation:DeleteStack",
|
|
64
|
+
"cloudformation:DescribeStacks",
|
|
65
|
+
"cloudformation:DescribeStackEvents",
|
|
66
|
+
"cloudformation:DescribeStackResources",
|
|
67
|
+
"cloudformation:DescribeStackResource",
|
|
68
|
+
"cloudformation:GetTemplate",
|
|
69
|
+
"cloudformation:ValidateTemplate",
|
|
70
|
+
"cloudformation:DescribeChangeSet",
|
|
71
|
+
"cloudformation:CreateChangeSet",
|
|
72
|
+
"cloudformation:DeleteChangeSet",
|
|
73
|
+
"cloudformation:ExecuteChangeSet"
|
|
74
|
+
],
|
|
75
|
+
"Resource": [
|
|
76
|
+
"arn:aws:cloudformation:*:*:stack/*frigg*/*"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"Sid": "S3DeploymentBucket",
|
|
81
|
+
"Effect": "Allow",
|
|
82
|
+
"Action": [
|
|
83
|
+
"s3:CreateBucket",
|
|
84
|
+
"s3:PutObject",
|
|
85
|
+
"s3:GetObject",
|
|
86
|
+
"s3:DeleteObject",
|
|
87
|
+
"s3:PutBucketPolicy",
|
|
88
|
+
"s3:PutBucketVersioning",
|
|
89
|
+
"s3:PutBucketPublicAccessBlock",
|
|
90
|
+
"s3:GetBucketLocation",
|
|
91
|
+
"s3:ListBucket"
|
|
92
|
+
],
|
|
93
|
+
"Resource": [
|
|
94
|
+
"arn:aws:s3:::*serverless*",
|
|
95
|
+
"arn:aws:s3:::*serverless*/*"
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"Sid": "LambdaFriggFunctions",
|
|
100
|
+
"Effect": "Allow",
|
|
101
|
+
"Action": [
|
|
102
|
+
"lambda:CreateFunction",
|
|
103
|
+
"lambda:UpdateFunctionCode",
|
|
104
|
+
"lambda:UpdateFunctionConfiguration",
|
|
105
|
+
"lambda:DeleteFunction",
|
|
106
|
+
"lambda:GetFunction",
|
|
107
|
+
"lambda:ListFunctions",
|
|
108
|
+
"lambda:PublishVersion",
|
|
109
|
+
"lambda:CreateAlias",
|
|
110
|
+
"lambda:UpdateAlias",
|
|
111
|
+
"lambda:DeleteAlias",
|
|
112
|
+
"lambda:GetAlias",
|
|
113
|
+
"lambda:AddPermission",
|
|
114
|
+
"lambda:RemovePermission",
|
|
115
|
+
"lambda:GetPolicy",
|
|
116
|
+
"lambda:PutProvisionedConcurrencyConfig",
|
|
117
|
+
"lambda:DeleteProvisionedConcurrencyConfig",
|
|
118
|
+
"lambda:PutConcurrency",
|
|
119
|
+
"lambda:DeleteConcurrency",
|
|
120
|
+
"lambda:TagResource",
|
|
121
|
+
"lambda:UntagResource"
|
|
122
|
+
],
|
|
123
|
+
"Resource": [
|
|
124
|
+
"arn:aws:lambda:*:*:function:*frigg*"
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"Sid": "IAMRolesForFriggLambda",
|
|
129
|
+
"Effect": "Allow",
|
|
130
|
+
"Action": [
|
|
131
|
+
"iam:CreateRole",
|
|
132
|
+
"iam:DeleteRole",
|
|
133
|
+
"iam:GetRole",
|
|
134
|
+
"iam:PassRole",
|
|
135
|
+
"iam:PutRolePolicy",
|
|
136
|
+
"iam:DeleteRolePolicy",
|
|
137
|
+
"iam:GetRolePolicy",
|
|
138
|
+
"iam:AttachRolePolicy",
|
|
139
|
+
"iam:DetachRolePolicy",
|
|
140
|
+
"iam:TagRole",
|
|
141
|
+
"iam:UntagRole"
|
|
142
|
+
],
|
|
143
|
+
"Resource": [
|
|
144
|
+
"arn:aws:iam::*:role/*frigg*",
|
|
145
|
+
"arn:aws:iam::*:role/*frigg*LambdaRole*"
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"Sid": "FriggMessagingServices",
|
|
150
|
+
"Effect": "Allow",
|
|
151
|
+
"Action": [
|
|
152
|
+
"sqs:CreateQueue",
|
|
153
|
+
"sqs:DeleteQueue",
|
|
154
|
+
"sqs:GetQueueAttributes",
|
|
155
|
+
"sqs:SetQueueAttributes",
|
|
156
|
+
"sqs:GetQueueUrl",
|
|
157
|
+
"sqs:TagQueue",
|
|
158
|
+
"sqs:UntagQueue"
|
|
159
|
+
],
|
|
160
|
+
"Resource": [
|
|
161
|
+
"arn:aws:sqs:*:*:*frigg*"
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"Sid": "FriggSNSTopics",
|
|
166
|
+
"Effect": "Allow",
|
|
167
|
+
"Action": [
|
|
168
|
+
"sns:CreateTopic",
|
|
169
|
+
"sns:DeleteTopic",
|
|
170
|
+
"sns:GetTopicAttributes",
|
|
171
|
+
"sns:SetTopicAttributes",
|
|
172
|
+
"sns:Subscribe",
|
|
173
|
+
"sns:Unsubscribe",
|
|
174
|
+
"sns:TagResource",
|
|
175
|
+
"sns:UntagResource"
|
|
176
|
+
],
|
|
177
|
+
"Resource": [
|
|
178
|
+
"arn:aws:sns:*:*:*frigg*"
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"Sid": "FriggMonitoringAndLogs",
|
|
183
|
+
"Effect": "Allow",
|
|
184
|
+
"Action": [
|
|
185
|
+
"cloudwatch:PutMetricAlarm",
|
|
186
|
+
"cloudwatch:DeleteAlarms",
|
|
187
|
+
"cloudwatch:DescribeAlarms",
|
|
188
|
+
"logs:CreateLogGroup",
|
|
189
|
+
"logs:CreateLogStream",
|
|
190
|
+
"logs:DeleteLogGroup",
|
|
191
|
+
"logs:DescribeLogGroups",
|
|
192
|
+
"logs:DescribeLogStreams",
|
|
193
|
+
"logs:FilterLogEvents",
|
|
194
|
+
"logs:PutLogEvents",
|
|
195
|
+
"logs:PutRetentionPolicy"
|
|
196
|
+
],
|
|
197
|
+
"Resource": [
|
|
198
|
+
"arn:aws:logs:*:*:log-group:/aws/lambda/*frigg*",
|
|
199
|
+
"arn:aws:logs:*:*:log-group:/aws/lambda/*frigg*:*",
|
|
200
|
+
"arn:aws:cloudwatch:*:*:alarm:*frigg*"
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"Sid": "FriggAPIGateway",
|
|
205
|
+
"Effect": "Allow",
|
|
206
|
+
"Action": [
|
|
207
|
+
"apigateway:POST",
|
|
208
|
+
"apigateway:PUT",
|
|
209
|
+
"apigateway:DELETE",
|
|
210
|
+
"apigateway:GET",
|
|
211
|
+
"apigateway:PATCH"
|
|
212
|
+
],
|
|
213
|
+
"Resource": [
|
|
214
|
+
"arn:aws:apigateway:*::/restapis",
|
|
215
|
+
"arn:aws:apigateway:*::/restapis/*",
|
|
216
|
+
"arn:aws:apigateway:*::/domainnames",
|
|
217
|
+
"arn:aws:apigateway:*::/domainnames/*"
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Feature-Specific Permissions
|
|
225
|
+
|
|
226
|
+
### VPC Support
|
|
227
|
+
|
|
228
|
+
Additional permissions needed when your app definition includes `vpc: { enable: true }`:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"Version": "2012-10-17",
|
|
233
|
+
"Statement": [
|
|
234
|
+
{
|
|
235
|
+
"Sid": "FriggVPCEndpointManagement",
|
|
236
|
+
"Effect": "Allow",
|
|
237
|
+
"Action": [
|
|
238
|
+
"ec2:CreateVpcEndpoint",
|
|
239
|
+
"ec2:DeleteVpcEndpoint",
|
|
240
|
+
"ec2:DescribeVpcEndpoints",
|
|
241
|
+
"ec2:ModifyVpcEndpoint",
|
|
242
|
+
"ec2:CreateNatGateway",
|
|
243
|
+
"ec2:DeleteNatGateway",
|
|
244
|
+
"ec2:DescribeNatGateways",
|
|
245
|
+
"ec2:AllocateAddress",
|
|
246
|
+
"ec2:ReleaseAddress",
|
|
247
|
+
"ec2:DescribeAddresses",
|
|
248
|
+
"ec2:CreateRouteTable",
|
|
249
|
+
"ec2:DeleteRouteTable",
|
|
250
|
+
"ec2:DescribeRouteTables",
|
|
251
|
+
"ec2:CreateRoute",
|
|
252
|
+
"ec2:DeleteRoute",
|
|
253
|
+
"ec2:AssociateRouteTable",
|
|
254
|
+
"ec2:DisassociateRouteTable",
|
|
255
|
+
"ec2:CreateSecurityGroup",
|
|
256
|
+
"ec2:DeleteSecurityGroup",
|
|
257
|
+
"ec2:AuthorizeSecurityGroupEgress",
|
|
258
|
+
"ec2:AuthorizeSecurityGroupIngress",
|
|
259
|
+
"ec2:RevokeSecurityGroupEgress",
|
|
260
|
+
"ec2:RevokeSecurityGroupIngress"
|
|
261
|
+
],
|
|
262
|
+
"Resource": "*",
|
|
263
|
+
"Condition": {
|
|
264
|
+
"StringLike": {
|
|
265
|
+
"ec2:CreateAction": [
|
|
266
|
+
"CreateVpcEndpoint",
|
|
267
|
+
"CreateNatGateway",
|
|
268
|
+
"CreateRouteTable",
|
|
269
|
+
"CreateRoute",
|
|
270
|
+
"CreateSecurityGroup"
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**What this enables:**
|
|
280
|
+
- Creates NAT Gateway for Lambda internet access to external APIs (Salesforce, HubSpot, etc.)
|
|
281
|
+
- Creates VPC endpoints for AWS services (S3, DynamoDB, KMS, SSM) to reduce NAT Gateway costs
|
|
282
|
+
- Creates route tables and subnet associations for proper Lambda networking
|
|
283
|
+
- Automatically configures your Lambda functions to run in your default VPC with full internet access
|
|
284
|
+
|
|
285
|
+
### KMS Support
|
|
286
|
+
|
|
287
|
+
Additional permissions needed when your app definition includes `encryption: { useDefaultKMSForFieldLevelEncryption: true }`:
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
{
|
|
291
|
+
"Version": "2012-10-17",
|
|
292
|
+
"Statement": [
|
|
293
|
+
{
|
|
294
|
+
"Sid": "FriggKMSEncryptionRuntime",
|
|
295
|
+
"Effect": "Allow",
|
|
296
|
+
"Action": [
|
|
297
|
+
"kms:GenerateDataKey",
|
|
298
|
+
"kms:Decrypt"
|
|
299
|
+
],
|
|
300
|
+
"Resource": [
|
|
301
|
+
"arn:aws:kms:*:*:key/*"
|
|
302
|
+
],
|
|
303
|
+
"Condition": {
|
|
304
|
+
"StringEquals": {
|
|
305
|
+
"kms:ViaService": [
|
|
306
|
+
"lambda.*.amazonaws.com",
|
|
307
|
+
"s3.*.amazonaws.com"
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**What this enables:**
|
|
317
|
+
- Lambda functions can encrypt and decrypt data using your default KMS key
|
|
318
|
+
- Automatic discovery and configuration of customer-managed KMS keys
|
|
319
|
+
- Fallback to AWS-managed keys if no customer keys are available
|
|
320
|
+
|
|
321
|
+
### SSM Parameter Store Support
|
|
322
|
+
|
|
323
|
+
Additional permissions needed when your app definition includes `ssm: { enable: true }`:
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"Version": "2012-10-17",
|
|
328
|
+
"Statement": [
|
|
329
|
+
{
|
|
330
|
+
"Sid": "FriggSSMParameterAccess",
|
|
331
|
+
"Effect": "Allow",
|
|
332
|
+
"Action": [
|
|
333
|
+
"ssm:GetParameter",
|
|
334
|
+
"ssm:GetParameters",
|
|
335
|
+
"ssm:GetParametersByPath"
|
|
336
|
+
],
|
|
337
|
+
"Resource": [
|
|
338
|
+
"arn:aws:ssm:*:*:parameter/*frigg*",
|
|
339
|
+
"arn:aws:ssm:*:*:parameter/*frigg*/*"
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**What this enables:**
|
|
347
|
+
- Lambda functions can retrieve configuration from SSM Parameter Store
|
|
348
|
+
- Automatic configuration of AWS Parameters and Secrets Lambda Extension layer
|
|
349
|
+
- Secure environment variable management through SSM
|
|
350
|
+
|
|
351
|
+
## Complete Policy Template
|
|
352
|
+
|
|
353
|
+
For convenience, here's a single IAM policy that includes all permissions needed for full Frigg functionality:
|
|
354
|
+
|
|
355
|
+
```json
|
|
356
|
+
{
|
|
357
|
+
"Version": "2012-10-17",
|
|
358
|
+
"Statement": [
|
|
359
|
+
{
|
|
360
|
+
"Sid": "FriggCorePermissions",
|
|
361
|
+
"Effect": "Allow",
|
|
362
|
+
"Action": [
|
|
363
|
+
"sts:GetCallerIdentity",
|
|
364
|
+
"cloudformation:*",
|
|
365
|
+
"lambda:*",
|
|
366
|
+
"apigateway:*",
|
|
367
|
+
"logs:*",
|
|
368
|
+
"sqs:*",
|
|
369
|
+
"sns:*",
|
|
370
|
+
"cloudwatch:*",
|
|
371
|
+
"ec2:Describe*",
|
|
372
|
+
"ec2:CreateVpcEndpoint",
|
|
373
|
+
"ec2:DeleteVpcEndpoint",
|
|
374
|
+
"ec2:ModifyVpcEndpoint",
|
|
375
|
+
"kms:ListKeys",
|
|
376
|
+
"kms:DescribeKey",
|
|
377
|
+
"kms:GenerateDataKey",
|
|
378
|
+
"kms:Decrypt",
|
|
379
|
+
"ssm:GetParameter*"
|
|
380
|
+
],
|
|
381
|
+
"Resource": "*"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
"Sid": "S3DeploymentBuckets",
|
|
385
|
+
"Effect": "Allow",
|
|
386
|
+
"Action": [
|
|
387
|
+
"s3:*"
|
|
388
|
+
],
|
|
389
|
+
"Resource": [
|
|
390
|
+
"arn:aws:s3:::*serverless*",
|
|
391
|
+
"arn:aws:s3:::*serverless*/*"
|
|
392
|
+
]
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"Sid": "IAMRoleManagement",
|
|
396
|
+
"Effect": "Allow",
|
|
397
|
+
"Action": [
|
|
398
|
+
"iam:CreateRole",
|
|
399
|
+
"iam:DeleteRole",
|
|
400
|
+
"iam:GetRole",
|
|
401
|
+
"iam:PassRole",
|
|
402
|
+
"iam:PutRolePolicy",
|
|
403
|
+
"iam:DeleteRolePolicy",
|
|
404
|
+
"iam:GetRolePolicy",
|
|
405
|
+
"iam:AttachRolePolicy",
|
|
406
|
+
"iam:DetachRolePolicy",
|
|
407
|
+
"iam:TagRole",
|
|
408
|
+
"iam:UntagRole"
|
|
409
|
+
],
|
|
410
|
+
"Resource": "arn:aws:iam::*:role/*"
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Security Improvements (Updated)
|
|
417
|
+
|
|
418
|
+
### Scoped Resource Permissions
|
|
419
|
+
|
|
420
|
+
This policy has been updated to follow the principle of least privilege by scoping permissions to Frigg-specific resources:
|
|
421
|
+
|
|
422
|
+
**Before (Overly Broad):**
|
|
423
|
+
```json
|
|
424
|
+
"Resource": "*" // ❌ Too permissive
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**After (Frigg-Specific):**
|
|
428
|
+
```json
|
|
429
|
+
"Resource": [
|
|
430
|
+
"arn:aws:lambda:*:*:function:*frigg*" // ✅ Only functions containing "frigg"
|
|
431
|
+
]
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Key Security Enhancements
|
|
435
|
+
|
|
436
|
+
1. **CloudFormation Stacks**: Limited to stacks containing "frigg" in the name
|
|
437
|
+
2. **Lambda Functions**: Scoped to functions containing "frigg" in the name
|
|
438
|
+
3. **IAM Roles**: Restricted to roles containing "frigg" (including Lambda execution roles)
|
|
439
|
+
4. **SQS/SNS**: Limited to queues and topics containing "frigg" in the name
|
|
440
|
+
5. **Logs & Monitoring**: Scoped to Lambda log groups for Frigg functions and CloudWatch alarms containing "frigg"
|
|
441
|
+
6. **KMS**: Added ViaService condition to restrict usage to Lambda and S3 services only
|
|
442
|
+
7. **SSM Parameters**: Limited to parameter paths containing "frigg" in the path structure
|
|
443
|
+
|
|
444
|
+
### Naming Convention Requirements
|
|
445
|
+
|
|
446
|
+
For these permissions to work properly, ensure your Frigg applications follow the naming convention of including "frigg" in resource names:
|
|
447
|
+
|
|
448
|
+
✅ **Good Examples:**
|
|
449
|
+
- `my-frigg-app-dev` (CloudFormation stack)
|
|
450
|
+
- `integration-frigg-service-auth` (Lambda function)
|
|
451
|
+
- `customer-frigg-platform-prod-auth` (Lambda function)
|
|
452
|
+
- `/my-frigg-app/prod/database-url` (SSM parameter)
|
|
453
|
+
|
|
454
|
+
❌ **Won't Match:**
|
|
455
|
+
- `my-integration-app-dev` (no "frigg" in name)
|
|
456
|
+
- `customer-platform-prod` (no "frigg" in name)
|
|
457
|
+
|
|
458
|
+
## Security Best Practices
|
|
459
|
+
|
|
460
|
+
### Principle of Least Privilege
|
|
461
|
+
|
|
462
|
+
For production deployments, consider creating separate policies for different environments:
|
|
463
|
+
|
|
464
|
+
1. **Development Policy** - Includes all permissions for full feature testing
|
|
465
|
+
2. **Production Policy** - Only includes permissions for features actually used in production
|
|
466
|
+
3. **CI/CD Policy** - Includes discovery and deployment permissions but restricts sensitive operations
|
|
467
|
+
|
|
468
|
+
### Resource-Specific Restrictions
|
|
469
|
+
|
|
470
|
+
You can further restrict permissions by:
|
|
471
|
+
|
|
472
|
+
```json
|
|
473
|
+
{
|
|
474
|
+
"Resource": [
|
|
475
|
+
"arn:aws:cloudformation:us-east-1:YOUR-ACCOUNT-ID:stack/your-app-*/*",
|
|
476
|
+
"arn:aws:lambda:us-east-1:YOUR-ACCOUNT-ID:function:your-app-*"
|
|
477
|
+
]
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Environment Variables for Discovery
|
|
482
|
+
|
|
483
|
+
The discovery process sets these environment variables during build:
|
|
484
|
+
|
|
485
|
+
- `AWS_DISCOVERY_VPC_ID` - Your default VPC ID
|
|
486
|
+
- `AWS_DISCOVERY_SECURITY_GROUP_ID` - Default security group ID
|
|
487
|
+
- `AWS_DISCOVERY_SUBNET_ID_1` - First private subnet ID (for Lambda functions)
|
|
488
|
+
- `AWS_DISCOVERY_SUBNET_ID_2` - Second private subnet ID (for Lambda functions, or same as first if only one exists)
|
|
489
|
+
- `AWS_DISCOVERY_PUBLIC_SUBNET_ID` - Public subnet ID (for NAT Gateway placement)
|
|
490
|
+
- `AWS_DISCOVERY_ROUTE_TABLE_ID` - Private route table ID for VPC endpoints
|
|
491
|
+
- `AWS_DISCOVERY_KMS_KEY_ID` - Default KMS key ARN
|
|
492
|
+
|
|
493
|
+
## Troubleshooting
|
|
494
|
+
|
|
495
|
+
### Common Permission Issues
|
|
496
|
+
|
|
497
|
+
1. **Discovery Fails** - Check that you have the discovery-time permissions
|
|
498
|
+
2. **VPC Endpoint Creation Fails** - Ensure you have `ec2:CreateVpcEndpoint` permission
|
|
499
|
+
3. **KMS Operations Fail** - Verify KMS key permissions and that the key exists
|
|
500
|
+
4. **SSM Parameter Access Fails** - Check SSM parameter path permissions
|
|
501
|
+
|
|
502
|
+
### Fallback Behavior
|
|
503
|
+
|
|
504
|
+
If AWS discovery fails during build, the framework will:
|
|
505
|
+
- Log a warning message
|
|
506
|
+
- Set fallback environment variables
|
|
507
|
+
- Continue with deployment using safe default values
|
|
508
|
+
- Not fail the build process
|
|
509
|
+
|
|
510
|
+
### Regional Considerations
|
|
511
|
+
|
|
512
|
+
Ensure your IAM policy includes permissions for the AWS region where you're deploying:
|
|
513
|
+
- Discovery permissions work across all regions (use `*` in resource ARNs)
|
|
514
|
+
- Deployment permissions should match your target region
|
|
515
|
+
- Some services like IAM are global, others are region-specific
|
|
516
|
+
|
|
517
|
+
## Using with CI/CD
|
|
518
|
+
|
|
519
|
+
For automated deployments, ensure your CI/CD system has:
|
|
520
|
+
|
|
521
|
+
1. **AWS Credentials** configured (access key or IAM role)
|
|
522
|
+
2. **Region** set via `AWS_REGION` environment variable
|
|
523
|
+
3. **This IAM policy** attached to the deployment user/role
|
|
524
|
+
4. **Proper build order** - discovery runs before packaging
|
|
525
|
+
|
|
526
|
+
Example GitHub Actions configuration:
|
|
527
|
+
|
|
528
|
+
```yaml
|
|
529
|
+
- name: Configure AWS credentials
|
|
530
|
+
uses: aws-actions/configure-aws-credentials@v1
|
|
531
|
+
with:
|
|
532
|
+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
533
|
+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
534
|
+
aws-region: us-east-1
|
|
535
|
+
|
|
536
|
+
- name: Deploy Frigg App
|
|
537
|
+
run: |
|
|
538
|
+
frigg deploy
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
This policy ensures your Frigg application can successfully discover AWS resources during build time and deploy all necessary infrastructure components during deployment.
|