@friggframework/devtools 2.0.0--canary.413.39a9576.0 → 2.0.0--canary.414.451bd3d.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/frigg-cli/deploy-command/index.js +81 -4
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +411 -442
- package/infrastructure/GENERATE-IAM-DOCS.md +66 -91
- package/infrastructure/env-validator.js +73 -0
- package/infrastructure/frigg-deployment-iam-stack.yaml +0 -22
- package/infrastructure/iam-generator.js +232 -207
- package/infrastructure/iam-policy-basic.json +5 -1
- package/infrastructure/iam-policy-full.json +5 -1
- package/infrastructure/serverless-template.js +274 -411
- package/package.json +6 -6
|
@@ -17,39 +17,38 @@ These permissions are required when `aws-discovery.js` runs during the build to
|
|
|
17
17
|
|
|
18
18
|
```json
|
|
19
19
|
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
+
"ec2:DescribeNatGateways",
|
|
32
|
+
"ec2:DescribeAddresses",
|
|
33
|
+
"kms:ListKeys",
|
|
34
|
+
"kms:DescribeKey"
|
|
35
|
+
],
|
|
36
|
+
"Resource": "*"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
### What Each Permission Does:
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- **`kms:DescribeKey`** - Gets details about KMS keys to find customer-managed keys
|
|
43
|
+
- **`sts:GetCallerIdentity`** - Gets your AWS account ID for KMS key ARN construction
|
|
44
|
+
- **`ec2:DescribeVpcs`** - Finds your default VPC or first available VPC
|
|
45
|
+
- **`ec2:DescribeSubnets`** - Identifies private subnets within your VPC
|
|
46
|
+
- **`ec2:DescribeSecurityGroups`** - Locates default security group or Frigg-specific security group
|
|
47
|
+
- **`ec2:DescribeRouteTables`** - Determines which subnets are private (no direct internet gateway route)
|
|
48
|
+
- **`ec2:DescribeNatGateways`** - Finds existing NAT Gateways to reuse (prevents duplicate resource creation)
|
|
49
|
+
- **`ec2:DescribeAddresses`** - Finds available Elastic IPs to reuse (prevents allocation conflicts)
|
|
50
|
+
- **`kms:ListKeys`** - Lists available KMS keys in your account
|
|
51
|
+
- **`kms:DescribeKey`** - Gets details about KMS keys to find customer-managed keys
|
|
53
52
|
|
|
54
53
|
## Core Deployment Permissions
|
|
55
54
|
|
|
@@ -57,236 +56,214 @@ Required for basic Frigg application deployment:
|
|
|
57
56
|
|
|
58
57
|
```json
|
|
59
58
|
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"arn:aws:apigateway:*::/apis/*/stages",
|
|
256
|
-
"arn:aws:apigateway:*::/apis/*/stages/*",
|
|
257
|
-
"arn:aws:apigateway:*::/apis/*/mappings",
|
|
258
|
-
"arn:aws:apigateway:*::/apis/*/mappings/*"
|
|
259
|
-
]
|
|
260
|
-
}
|
|
261
|
-
]
|
|
59
|
+
"Version": "2012-10-17",
|
|
60
|
+
"Statement": [
|
|
61
|
+
{
|
|
62
|
+
"Sid": "CloudFormationFriggStacks",
|
|
63
|
+
"Effect": "Allow",
|
|
64
|
+
"Action": [
|
|
65
|
+
"cloudformation:CreateStack",
|
|
66
|
+
"cloudformation:UpdateStack",
|
|
67
|
+
"cloudformation:DeleteStack",
|
|
68
|
+
"cloudformation:DescribeStacks",
|
|
69
|
+
"cloudformation:DescribeStackEvents",
|
|
70
|
+
"cloudformation:DescribeStackResources",
|
|
71
|
+
"cloudformation:DescribeStackResource",
|
|
72
|
+
"cloudformation:ListStackResources",
|
|
73
|
+
"cloudformation:GetTemplate",
|
|
74
|
+
"cloudformation:ValidateTemplate",
|
|
75
|
+
"cloudformation:DescribeChangeSet",
|
|
76
|
+
"cloudformation:CreateChangeSet",
|
|
77
|
+
"cloudformation:DeleteChangeSet",
|
|
78
|
+
"cloudformation:ExecuteChangeSet"
|
|
79
|
+
],
|
|
80
|
+
"Resource": [
|
|
81
|
+
"arn:aws:cloudformation:*:*:stack/*frigg*/*"
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"Sid": "S3DeploymentBucket",
|
|
86
|
+
"Effect": "Allow",
|
|
87
|
+
"Action": [
|
|
88
|
+
"s3:CreateBucket",
|
|
89
|
+
"s3:PutObject",
|
|
90
|
+
"s3:GetObject",
|
|
91
|
+
"s3:DeleteObject",
|
|
92
|
+
"s3:PutBucketPolicy",
|
|
93
|
+
"s3:PutBucketVersioning",
|
|
94
|
+
"s3:PutBucketPublicAccessBlock",
|
|
95
|
+
"s3:GetBucketLocation",
|
|
96
|
+
"s3:ListBucket",
|
|
97
|
+
"s3:PutBucketTagging",
|
|
98
|
+
"s3:GetBucketTagging"
|
|
99
|
+
],
|
|
100
|
+
"Resource": [
|
|
101
|
+
"arn:aws:s3:::*serverless*",
|
|
102
|
+
"arn:aws:s3:::*serverless*/*"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"Sid": "LambdaFriggFunctions",
|
|
107
|
+
"Effect": "Allow",
|
|
108
|
+
"Action": [
|
|
109
|
+
"lambda:CreateFunction",
|
|
110
|
+
"lambda:UpdateFunctionCode",
|
|
111
|
+
"lambda:UpdateFunctionConfiguration",
|
|
112
|
+
"lambda:DeleteFunction",
|
|
113
|
+
"lambda:GetFunction",
|
|
114
|
+
"lambda:ListFunctions",
|
|
115
|
+
"lambda:PublishVersion",
|
|
116
|
+
"lambda:CreateAlias",
|
|
117
|
+
"lambda:UpdateAlias",
|
|
118
|
+
"lambda:DeleteAlias",
|
|
119
|
+
"lambda:GetAlias",
|
|
120
|
+
"lambda:AddPermission",
|
|
121
|
+
"lambda:RemovePermission",
|
|
122
|
+
"lambda:GetPolicy",
|
|
123
|
+
"lambda:PutProvisionedConcurrencyConfig",
|
|
124
|
+
"lambda:DeleteProvisionedConcurrencyConfig",
|
|
125
|
+
"lambda:PutConcurrency",
|
|
126
|
+
"lambda:DeleteConcurrency",
|
|
127
|
+
"lambda:TagResource",
|
|
128
|
+
"lambda:UntagResource",
|
|
129
|
+
"lambda:ListVersionsByFunction"
|
|
130
|
+
],
|
|
131
|
+
"Resource": [
|
|
132
|
+
"arn:aws:lambda:*:*:function:*frigg*"
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"Sid": "FriggLambdaEventSourceMapping",
|
|
137
|
+
"Effect": "Allow",
|
|
138
|
+
"Action": [
|
|
139
|
+
"lambda:CreateEventSourceMapping",
|
|
140
|
+
"lambda:DeleteEventSourceMapping",
|
|
141
|
+
"lambda:GetEventSourceMapping",
|
|
142
|
+
"lambda:UpdateEventSourceMapping",
|
|
143
|
+
"lambda:ListEventSourceMappings"
|
|
144
|
+
],
|
|
145
|
+
"Resource": [
|
|
146
|
+
"arn:aws:lambda:*:*:event-source-mapping:*"
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"Sid": "IAMRolesForFriggLambda",
|
|
151
|
+
"Effect": "Allow",
|
|
152
|
+
"Action": [
|
|
153
|
+
"iam:CreateRole",
|
|
154
|
+
"iam:DeleteRole",
|
|
155
|
+
"iam:GetRole",
|
|
156
|
+
"iam:PassRole",
|
|
157
|
+
"iam:PutRolePolicy",
|
|
158
|
+
"iam:DeleteRolePolicy",
|
|
159
|
+
"iam:GetRolePolicy",
|
|
160
|
+
"iam:AttachRolePolicy",
|
|
161
|
+
"iam:DetachRolePolicy",
|
|
162
|
+
"iam:TagRole",
|
|
163
|
+
"iam:UntagRole"
|
|
164
|
+
],
|
|
165
|
+
"Resource": [
|
|
166
|
+
"arn:aws:iam::*:role/*frigg*",
|
|
167
|
+
"arn:aws:iam::*:role/*frigg*LambdaRole*"
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"Sid": "IAMPolicyVersionPermissions",
|
|
172
|
+
"Effect": "Allow",
|
|
173
|
+
"Action": [
|
|
174
|
+
"iam:ListPolicyVersions"
|
|
175
|
+
],
|
|
176
|
+
"Resource": [
|
|
177
|
+
"arn:aws:iam::*:policy/*"
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"Sid": "FriggMessagingServices",
|
|
182
|
+
"Effect": "Allow",
|
|
183
|
+
"Action": [
|
|
184
|
+
"sqs:CreateQueue",
|
|
185
|
+
"sqs:DeleteQueue",
|
|
186
|
+
"sqs:GetQueueAttributes",
|
|
187
|
+
"sqs:SetQueueAttributes",
|
|
188
|
+
"sqs:GetQueueUrl",
|
|
189
|
+
"sqs:TagQueue",
|
|
190
|
+
"sqs:UntagQueue"
|
|
191
|
+
],
|
|
192
|
+
"Resource": [
|
|
193
|
+
"arn:aws:sqs:*:*:*frigg*",
|
|
194
|
+
"arn:aws:sqs:*:*:internal-error-queue-*"
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"Sid": "FriggSNSTopics",
|
|
199
|
+
"Effect": "Allow",
|
|
200
|
+
"Action": [
|
|
201
|
+
"sns:CreateTopic",
|
|
202
|
+
"sns:DeleteTopic",
|
|
203
|
+
"sns:GetTopicAttributes",
|
|
204
|
+
"sns:SetTopicAttributes",
|
|
205
|
+
"sns:Subscribe",
|
|
206
|
+
"sns:Unsubscribe",
|
|
207
|
+
"sns:TagResource",
|
|
208
|
+
"sns:UntagResource"
|
|
209
|
+
],
|
|
210
|
+
"Resource": [
|
|
211
|
+
"arn:aws:sns:*:*:*frigg*"
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"Sid": "FriggMonitoringAndLogs",
|
|
216
|
+
"Effect": "Allow",
|
|
217
|
+
"Action": [
|
|
218
|
+
"cloudwatch:PutMetricAlarm",
|
|
219
|
+
"cloudwatch:DeleteAlarms",
|
|
220
|
+
"cloudwatch:DescribeAlarms",
|
|
221
|
+
"logs:CreateLogGroup",
|
|
222
|
+
"logs:CreateLogStream",
|
|
223
|
+
"logs:DeleteLogGroup",
|
|
224
|
+
"logs:DescribeLogGroups",
|
|
225
|
+
"logs:DescribeLogStreams",
|
|
226
|
+
"logs:FilterLogEvents",
|
|
227
|
+
"logs:PutLogEvents",
|
|
228
|
+
"logs:PutRetentionPolicy"
|
|
229
|
+
],
|
|
230
|
+
"Resource": [
|
|
231
|
+
"arn:aws:logs:*:*:log-group:/aws/lambda/*frigg*",
|
|
232
|
+
"arn:aws:logs:*:*:log-group:/aws/lambda/*frigg*:*",
|
|
233
|
+
"arn:aws:cloudwatch:*:*:alarm:*frigg*"
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"Sid": "FriggAPIGateway",
|
|
238
|
+
"Effect": "Allow",
|
|
239
|
+
"Action": [
|
|
240
|
+
"apigateway:POST",
|
|
241
|
+
"apigateway:PUT",
|
|
242
|
+
"apigateway:DELETE",
|
|
243
|
+
"apigateway:GET",
|
|
244
|
+
"apigateway:PATCH"
|
|
245
|
+
],
|
|
246
|
+
"Resource": [
|
|
247
|
+
"arn:aws:apigateway:*::/restapis",
|
|
248
|
+
"arn:aws:apigateway:*::/restapis/*",
|
|
249
|
+
"arn:aws:apigateway:*::/domainnames",
|
|
250
|
+
"arn:aws:apigateway:*::/domainnames/*"
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
]
|
|
262
254
|
}
|
|
263
255
|
```
|
|
264
256
|
|
|
265
|
-
**API Gateway Permissions Security Note:**
|
|
266
|
-
|
|
267
|
-
The API Gateway permissions are intentionally split into two separate policies:
|
|
268
|
-
|
|
269
|
-
- **FriggAPIGateway**: Covers API Gateway v1 (REST APIs) with specific CRUD operations
|
|
270
|
-
- **FriggAPIGatewayV2**: Covers API Gateway v2 (HTTP APIs) with the same specific operations
|
|
271
|
-
|
|
272
|
-
This approach follows the principle of least privilege by:
|
|
273
|
-
|
|
274
|
-
- ✅ **Avoiding wildcards**: Using specific actions instead of `apigateway:*`
|
|
275
|
-
- ✅ **Resource scoping**: Limiting to Frigg-specific API Gateway resources
|
|
276
|
-
- ✅ **Version separation**: Maintaining clear separation between v1 and v2 APIs
|
|
277
|
-
- ✅ **Audit-friendly**: Each permission can be individually tracked and monitored
|
|
278
|
-
|
|
279
257
|
**What the Lambda permissions enable:**
|
|
280
|
-
|
|
281
|
-
-
|
|
282
|
-
-
|
|
283
|
-
-
|
|
284
|
-
-
|
|
285
|
-
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
- Cleaning up event source mappings during stack deletion
|
|
258
|
+
- **Function Management**: Create, update, delete, and configure Lambda functions
|
|
259
|
+
- **Version & Alias Management**: Publish new versions and manage aliases for deployments
|
|
260
|
+
- **Permission Management**: Add/remove function permissions for API Gateway and other services
|
|
261
|
+
- **Concurrency Management**: Configure provisioned and reserved concurrency
|
|
262
|
+
- **EventSourceMapping Management**: Connect Lambda functions to event sources like SQS, SNS, Kinesis, and DynamoDB streams. These permissions are crucial for:
|
|
263
|
+
- Creating mappings between SQS queues and Lambda functions
|
|
264
|
+
- Managing event-driven architectures
|
|
265
|
+
- Handling queue-based processing (e.g., HubSpot integration queues)
|
|
266
|
+
- Cleaning up event source mappings during stack deletion
|
|
290
267
|
|
|
291
268
|
## Feature-Specific Permissions
|
|
292
269
|
|
|
@@ -296,61 +273,58 @@ Additional permissions needed when your app definition includes `vpc: { enable:
|
|
|
296
273
|
|
|
297
274
|
```json
|
|
298
275
|
{
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
"CreateSecurityGroup"
|
|
340
|
-
]
|
|
341
|
-
}
|
|
342
|
-
}
|
|
276
|
+
"Version": "2012-10-17",
|
|
277
|
+
"Statement": [
|
|
278
|
+
{
|
|
279
|
+
"Sid": "FriggVPCEndpointManagement",
|
|
280
|
+
"Effect": "Allow",
|
|
281
|
+
"Action": [
|
|
282
|
+
"ec2:CreateVpcEndpoint",
|
|
283
|
+
"ec2:DeleteVpcEndpoint",
|
|
284
|
+
"ec2:DescribeVpcEndpoints",
|
|
285
|
+
"ec2:ModifyVpcEndpoint",
|
|
286
|
+
"ec2:CreateNatGateway",
|
|
287
|
+
"ec2:DeleteNatGateway",
|
|
288
|
+
"ec2:DescribeNatGateways",
|
|
289
|
+
"ec2:AllocateAddress",
|
|
290
|
+
"ec2:ReleaseAddress",
|
|
291
|
+
"ec2:DescribeAddresses",
|
|
292
|
+
"ec2:CreateRouteTable",
|
|
293
|
+
"ec2:DeleteRouteTable",
|
|
294
|
+
"ec2:DescribeRouteTables",
|
|
295
|
+
"ec2:CreateRoute",
|
|
296
|
+
"ec2:DeleteRoute",
|
|
297
|
+
"ec2:AssociateRouteTable",
|
|
298
|
+
"ec2:DisassociateRouteTable",
|
|
299
|
+
"ec2:CreateSecurityGroup",
|
|
300
|
+
"ec2:DeleteSecurityGroup",
|
|
301
|
+
"ec2:AuthorizeSecurityGroupEgress",
|
|
302
|
+
"ec2:AuthorizeSecurityGroupIngress",
|
|
303
|
+
"ec2:RevokeSecurityGroupEgress",
|
|
304
|
+
"ec2:RevokeSecurityGroupIngress"
|
|
305
|
+
],
|
|
306
|
+
"Resource": "*",
|
|
307
|
+
"Condition": {
|
|
308
|
+
"StringLike": {
|
|
309
|
+
"ec2:CreateAction": [
|
|
310
|
+
"CreateVpcEndpoint",
|
|
311
|
+
"CreateNatGateway",
|
|
312
|
+
"CreateRouteTable",
|
|
313
|
+
"CreateRoute",
|
|
314
|
+
"CreateSecurityGroup"
|
|
315
|
+
]
|
|
343
316
|
}
|
|
344
|
-
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
]
|
|
345
320
|
}
|
|
346
321
|
```
|
|
347
322
|
|
|
348
323
|
**What this enables:**
|
|
349
|
-
|
|
350
|
-
-
|
|
351
|
-
-
|
|
352
|
-
-
|
|
353
|
-
- Automatically configures your Lambda functions to run in your default VPC with full internet access
|
|
324
|
+
- Creates NAT Gateway for Lambda internet access to external APIs (Salesforce, HubSpot, etc.)
|
|
325
|
+
- Creates VPC endpoints for AWS services (S3, DynamoDB, KMS, SSM) to reduce NAT Gateway costs
|
|
326
|
+
- Creates route tables and subnet associations for proper Lambda networking
|
|
327
|
+
- Automatically configures your Lambda functions to run in your default VPC with full internet access
|
|
354
328
|
|
|
355
329
|
### KMS Support
|
|
356
330
|
|
|
@@ -358,31 +332,35 @@ Additional permissions needed when your app definition includes `encryption: { u
|
|
|
358
332
|
|
|
359
333
|
```json
|
|
360
334
|
{
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
335
|
+
"Version": "2012-10-17",
|
|
336
|
+
"Statement": [
|
|
337
|
+
{
|
|
338
|
+
"Sid": "FriggKMSEncryptionRuntime",
|
|
339
|
+
"Effect": "Allow",
|
|
340
|
+
"Action": [
|
|
341
|
+
"kms:GenerateDataKey",
|
|
342
|
+
"kms:Decrypt"
|
|
343
|
+
],
|
|
344
|
+
"Resource": [
|
|
345
|
+
"arn:aws:kms:*:*:key/*"
|
|
346
|
+
],
|
|
347
|
+
"Condition": {
|
|
348
|
+
"StringEquals": {
|
|
349
|
+
"kms:ViaService": [
|
|
350
|
+
"lambda.*.amazonaws.com",
|
|
351
|
+
"s3.*.amazonaws.com"
|
|
352
|
+
]
|
|
376
353
|
}
|
|
377
|
-
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
]
|
|
378
357
|
}
|
|
379
358
|
```
|
|
380
359
|
|
|
381
360
|
**What this enables:**
|
|
382
|
-
|
|
383
|
-
-
|
|
384
|
-
-
|
|
385
|
-
- Fallback to AWS-managed keys if no customer keys are available
|
|
361
|
+
- Lambda functions can encrypt and decrypt data using your default KMS key
|
|
362
|
+
- Automatic discovery and configuration of customer-managed KMS keys
|
|
363
|
+
- Fallback to AWS-managed keys if no customer keys are available
|
|
386
364
|
|
|
387
365
|
### SSM Parameter Store Support
|
|
388
366
|
|
|
@@ -390,30 +368,29 @@ Additional permissions needed when your app definition includes `ssm: { enable:
|
|
|
390
368
|
|
|
391
369
|
```json
|
|
392
370
|
{
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
371
|
+
"Version": "2012-10-17",
|
|
372
|
+
"Statement": [
|
|
373
|
+
{
|
|
374
|
+
"Sid": "FriggSSMParameterAccess",
|
|
375
|
+
"Effect": "Allow",
|
|
376
|
+
"Action": [
|
|
377
|
+
"ssm:GetParameter",
|
|
378
|
+
"ssm:GetParameters",
|
|
379
|
+
"ssm:GetParametersByPath"
|
|
380
|
+
],
|
|
381
|
+
"Resource": [
|
|
382
|
+
"arn:aws:ssm:*:*:parameter/*frigg*",
|
|
383
|
+
"arn:aws:ssm:*:*:parameter/*frigg*/*"
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
]
|
|
409
387
|
}
|
|
410
388
|
```
|
|
411
389
|
|
|
412
390
|
**What this enables:**
|
|
413
|
-
|
|
414
|
-
-
|
|
415
|
-
-
|
|
416
|
-
- Secure environment variable management through SSM
|
|
391
|
+
- Lambda functions can retrieve configuration from SSM Parameter Store
|
|
392
|
+
- Automatic configuration of AWS Parameters and Secrets Lambda Extension layer
|
|
393
|
+
- Secure environment variable management through SSM
|
|
417
394
|
|
|
418
395
|
## Complete Policy Template
|
|
419
396
|
|
|
@@ -421,65 +398,63 @@ For convenience, here's a single IAM policy that includes all permissions needed
|
|
|
421
398
|
|
|
422
399
|
```json
|
|
423
400
|
{
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
}
|
|
482
|
-
]
|
|
401
|
+
"Version": "2012-10-17",
|
|
402
|
+
"Statement": [
|
|
403
|
+
{
|
|
404
|
+
"Sid": "FriggCorePermissions",
|
|
405
|
+
"Effect": "Allow",
|
|
406
|
+
"Action": [
|
|
407
|
+
"sts:GetCallerIdentity",
|
|
408
|
+
"cloudformation:*",
|
|
409
|
+
"lambda:*",
|
|
410
|
+
"apigateway:*",
|
|
411
|
+
"logs:*",
|
|
412
|
+
"sqs:*",
|
|
413
|
+
"sns:*",
|
|
414
|
+
"cloudwatch:*",
|
|
415
|
+
"ec2:Describe*",
|
|
416
|
+
"ec2:CreateVpcEndpoint",
|
|
417
|
+
"ec2:DeleteVpcEndpoint",
|
|
418
|
+
"ec2:ModifyVpcEndpoint",
|
|
419
|
+
"kms:ListKeys",
|
|
420
|
+
"kms:DescribeKey",
|
|
421
|
+
"kms:GenerateDataKey",
|
|
422
|
+
"kms:Decrypt",
|
|
423
|
+
"ssm:GetParameter*"
|
|
424
|
+
],
|
|
425
|
+
"Resource": "*"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"Sid": "S3DeploymentBuckets",
|
|
429
|
+
"Effect": "Allow",
|
|
430
|
+
"Action": [
|
|
431
|
+
"s3:*"
|
|
432
|
+
],
|
|
433
|
+
"Resource": [
|
|
434
|
+
"arn:aws:s3:::*serverless*",
|
|
435
|
+
"arn:aws:s3:::*serverless*/*"
|
|
436
|
+
]
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
"Sid": "IAMRoleManagement",
|
|
440
|
+
"Effect": "Allow",
|
|
441
|
+
"Action": [
|
|
442
|
+
"iam:CreateRole",
|
|
443
|
+
"iam:DeleteRole",
|
|
444
|
+
"iam:GetRole",
|
|
445
|
+
"iam:PassRole",
|
|
446
|
+
"iam:PutRolePolicy",
|
|
447
|
+
"iam:DeleteRolePolicy",
|
|
448
|
+
"iam:GetRolePolicy",
|
|
449
|
+
"iam:AttachRolePolicy",
|
|
450
|
+
"iam:DetachRolePolicy",
|
|
451
|
+
"iam:TagRole",
|
|
452
|
+
"iam:UntagRole",
|
|
453
|
+
"iam:ListPolicyVersions"
|
|
454
|
+
],
|
|
455
|
+
"Resource": "arn:aws:iam::*:role/*"
|
|
456
|
+
}
|
|
457
|
+
]
|
|
483
458
|
}
|
|
484
459
|
```
|
|
485
460
|
|
|
@@ -490,13 +465,11 @@ For convenience, here's a single IAM policy that includes all permissions needed
|
|
|
490
465
|
This policy has been updated to follow the principle of least privilege by scoping permissions to Frigg-specific resources:
|
|
491
466
|
|
|
492
467
|
**Before (Overly Broad):**
|
|
493
|
-
|
|
494
468
|
```json
|
|
495
469
|
"Resource": "*" // ❌ Too permissive
|
|
496
470
|
```
|
|
497
471
|
|
|
498
472
|
**After (Frigg-Specific):**
|
|
499
|
-
|
|
500
473
|
```json
|
|
501
474
|
"Resource": [
|
|
502
475
|
"arn:aws:lambda:*:*:function:*frigg*" // ✅ Only functions containing "frigg"
|
|
@@ -518,17 +491,15 @@ This policy has been updated to follow the principle of least privilege by scopi
|
|
|
518
491
|
For these permissions to work properly, ensure your Frigg applications follow the naming convention of including "frigg" in resource names:
|
|
519
492
|
|
|
520
493
|
✅ **Good Examples:**
|
|
521
|
-
|
|
522
|
-
-
|
|
523
|
-
-
|
|
524
|
-
-
|
|
525
|
-
-
|
|
526
|
-
- `internal-error-queue-dev` (SQS queue - special pattern for error queues)
|
|
494
|
+
- `my-frigg-app-dev` (CloudFormation stack)
|
|
495
|
+
- `integration-frigg-service-auth` (Lambda function)
|
|
496
|
+
- `customer-frigg-platform-prod-auth` (Lambda function)
|
|
497
|
+
- `/my-frigg-app/prod/database-url` (SSM parameter)
|
|
498
|
+
- `internal-error-queue-dev` (SQS queue - special pattern for error queues)
|
|
527
499
|
|
|
528
500
|
❌ **Won't Match:**
|
|
529
|
-
|
|
530
|
-
-
|
|
531
|
-
- `customer-platform-prod` (no "frigg" in name)
|
|
501
|
+
- `my-integration-app-dev` (no "frigg" in name)
|
|
502
|
+
- `customer-platform-prod` (no "frigg" in name)
|
|
532
503
|
|
|
533
504
|
**Note:** The `internal-error-queue-*` pattern is specifically allowed for error handling queues.
|
|
534
505
|
|
|
@@ -548,10 +519,10 @@ You can further restrict permissions by:
|
|
|
548
519
|
|
|
549
520
|
```json
|
|
550
521
|
{
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
522
|
+
"Resource": [
|
|
523
|
+
"arn:aws:cloudformation:us-east-1:YOUR-ACCOUNT-ID:stack/your-app-*/*",
|
|
524
|
+
"arn:aws:lambda:us-east-1:YOUR-ACCOUNT-ID:function:your-app-*"
|
|
525
|
+
]
|
|
555
526
|
}
|
|
556
527
|
```
|
|
557
528
|
|
|
@@ -559,15 +530,15 @@ You can further restrict permissions by:
|
|
|
559
530
|
|
|
560
531
|
The discovery process sets these environment variables during build:
|
|
561
532
|
|
|
562
|
-
-
|
|
563
|
-
-
|
|
564
|
-
-
|
|
565
|
-
-
|
|
566
|
-
-
|
|
567
|
-
-
|
|
568
|
-
-
|
|
569
|
-
-
|
|
570
|
-
-
|
|
533
|
+
- `AWS_DISCOVERY_VPC_ID` - Your default VPC ID
|
|
534
|
+
- `AWS_DISCOVERY_SECURITY_GROUP_ID` - Default security group ID
|
|
535
|
+
- `AWS_DISCOVERY_SUBNET_ID_1` - First private subnet ID (for Lambda functions)
|
|
536
|
+
- `AWS_DISCOVERY_SUBNET_ID_2` - Second private subnet ID (for Lambda functions, or same as first if only one exists)
|
|
537
|
+
- `AWS_DISCOVERY_PUBLIC_SUBNET_ID` - Public subnet ID (for NAT Gateway placement)
|
|
538
|
+
- `AWS_DISCOVERY_ROUTE_TABLE_ID` - Private route table ID for VPC endpoints
|
|
539
|
+
- `AWS_DISCOVERY_KMS_KEY_ID` - Default KMS key ARN
|
|
540
|
+
- `AWS_DISCOVERY_NAT_GATEWAY_ID` - Existing NAT Gateway ID (if found)
|
|
541
|
+
- `AWS_DISCOVERY_ELASTIC_IP_ALLOCATION_ID` - Existing Elastic IP allocation ID (if found)
|
|
571
542
|
|
|
572
543
|
## Troubleshooting
|
|
573
544
|
|
|
@@ -586,19 +557,17 @@ The discovery process sets these environment variables during build:
|
|
|
586
557
|
### Fallback Behavior
|
|
587
558
|
|
|
588
559
|
If AWS discovery fails during build, the framework will:
|
|
589
|
-
|
|
590
|
-
-
|
|
591
|
-
-
|
|
592
|
-
-
|
|
593
|
-
- Not fail the build process
|
|
560
|
+
- Log a warning message
|
|
561
|
+
- Set fallback environment variables
|
|
562
|
+
- Continue with deployment using safe default values
|
|
563
|
+
- Not fail the build process
|
|
594
564
|
|
|
595
565
|
### Regional Considerations
|
|
596
566
|
|
|
597
567
|
Ensure your IAM policy includes permissions for the AWS region where you're deploying:
|
|
598
|
-
|
|
599
|
-
-
|
|
600
|
-
-
|
|
601
|
-
- Some services like IAM are global, others are region-specific
|
|
568
|
+
- Discovery permissions work across all regions (use `*` in resource ARNs)
|
|
569
|
+
- Deployment permissions should match your target region
|
|
570
|
+
- Some services like IAM are global, others are region-specific
|
|
602
571
|
|
|
603
572
|
## Using with CI/CD
|
|
604
573
|
|
|
@@ -615,13 +584,13 @@ Example GitHub Actions configuration:
|
|
|
615
584
|
- name: Configure AWS credentials
|
|
616
585
|
uses: aws-actions/configure-aws-credentials@v1
|
|
617
586
|
with:
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
587
|
+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
588
|
+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
589
|
+
aws-region: us-east-1
|
|
621
590
|
|
|
622
591
|
- name: Deploy Frigg App
|
|
623
592
|
run: |
|
|
624
|
-
|
|
593
|
+
frigg deploy
|
|
625
594
|
```
|
|
626
595
|
|
|
627
|
-
This policy ensures your Frigg application can successfully discover AWS resources during build time and deploy all necessary infrastructure components during deployment.
|
|
596
|
+
This policy ensures your Frigg application can successfully discover AWS resources during build time and deploy all necessary infrastructure components during deployment.
|