@friggframework/devtools 2.0.0-next.32 → 2.0.0-next.34
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 +6 -3
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +442 -411
- package/infrastructure/GENERATE-IAM-DOCS.md +91 -66
- package/infrastructure/frigg-deployment-iam-stack.yaml +22 -0
- package/infrastructure/iam-generator.js +212 -229
- package/infrastructure/iam-policy-basic.json +2 -0
- package/infrastructure/iam-policy-full.json +2 -0
- package/infrastructure/serverless-template.js +412 -243
- package/package.json +6 -6
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
1
|
const path = require('path');
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -11,11 +10,8 @@ const path = require('path');
|
|
|
11
10
|
* @returns {string} CloudFormation YAML template
|
|
12
11
|
*/
|
|
13
12
|
function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
14
|
-
const {
|
|
15
|
-
|
|
16
|
-
stackName = 'frigg-deployment-iam',
|
|
17
|
-
mode = 'auto'
|
|
18
|
-
} = options;
|
|
13
|
+
const { deploymentUserName = 'frigg-deployment-user', mode = 'auto' } =
|
|
14
|
+
options;
|
|
19
15
|
|
|
20
16
|
// Determine which features are enabled based on mode
|
|
21
17
|
let features;
|
|
@@ -24,62 +20,77 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
24
20
|
vpc: false,
|
|
25
21
|
kms: false,
|
|
26
22
|
ssm: false,
|
|
27
|
-
websockets: appDefinition.websockets?.enable === true
|
|
23
|
+
websockets: appDefinition.websockets?.enable === true,
|
|
28
24
|
};
|
|
29
25
|
} else if (mode === 'full') {
|
|
30
26
|
features = {
|
|
31
27
|
vpc: true,
|
|
32
28
|
kms: true,
|
|
33
29
|
ssm: true,
|
|
34
|
-
websockets: appDefinition.websockets?.enable === true
|
|
30
|
+
websockets: appDefinition.websockets?.enable === true,
|
|
35
31
|
};
|
|
36
|
-
} else {
|
|
32
|
+
} else {
|
|
33
|
+
// mode === 'auto'
|
|
37
34
|
features = {
|
|
38
35
|
vpc: appDefinition.vpc?.enable === true,
|
|
39
|
-
kms:
|
|
36
|
+
kms:
|
|
37
|
+
appDefinition.encryption
|
|
38
|
+
?.useDefaultKMSForFieldLevelEncryption === true,
|
|
40
39
|
ssm: appDefinition.ssm?.enable === true,
|
|
41
|
-
websockets: appDefinition.websockets?.enable === true
|
|
40
|
+
websockets: appDefinition.websockets?.enable === true,
|
|
42
41
|
};
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
// Build the CloudFormation template
|
|
46
45
|
const template = {
|
|
47
46
|
AWSTemplateFormatVersion: '2010-09-09',
|
|
48
|
-
Description: `IAM roles and policies for ${
|
|
49
|
-
|
|
47
|
+
Description: `IAM roles and policies for ${
|
|
48
|
+
appDefinition.name || 'Frigg'
|
|
49
|
+
} application deployment pipeline`,
|
|
50
|
+
|
|
50
51
|
Parameters: {
|
|
51
52
|
DeploymentUserName: {
|
|
52
53
|
Type: 'String',
|
|
53
54
|
Default: deploymentUserName,
|
|
54
|
-
Description:
|
|
55
|
+
Description:
|
|
56
|
+
'Name for the IAM user that will deploy Frigg applications',
|
|
55
57
|
},
|
|
56
58
|
EnableVPCSupport: {
|
|
57
59
|
Type: 'String',
|
|
58
60
|
Default: features.vpc ? 'true' : 'false',
|
|
59
61
|
AllowedValues: ['true', 'false'],
|
|
60
|
-
Description:
|
|
62
|
+
Description:
|
|
63
|
+
'Enable VPC-related permissions for Frigg applications',
|
|
61
64
|
},
|
|
62
65
|
EnableKMSSupport: {
|
|
63
66
|
Type: 'String',
|
|
64
67
|
Default: features.kms ? 'true' : 'false',
|
|
65
68
|
AllowedValues: ['true', 'false'],
|
|
66
|
-
Description:
|
|
69
|
+
Description:
|
|
70
|
+
'Enable KMS encryption permissions for Frigg applications',
|
|
67
71
|
},
|
|
68
72
|
EnableSSMSupport: {
|
|
69
73
|
Type: 'String',
|
|
70
74
|
Default: features.ssm ? 'true' : 'false',
|
|
71
75
|
AllowedValues: ['true', 'false'],
|
|
72
|
-
Description:
|
|
73
|
-
|
|
76
|
+
Description:
|
|
77
|
+
'Enable SSM Parameter Store permissions for Frigg applications',
|
|
78
|
+
},
|
|
74
79
|
},
|
|
75
80
|
|
|
76
81
|
Conditions: {
|
|
77
|
-
CreateVPCPermissions: {
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
CreateVPCPermissions: {
|
|
83
|
+
'Fn::Equals': [{ Ref: 'EnableVPCSupport' }, 'true'],
|
|
84
|
+
},
|
|
85
|
+
CreateKMSPermissions: {
|
|
86
|
+
'Fn::Equals': [{ Ref: 'EnableKMSSupport' }, 'true'],
|
|
87
|
+
},
|
|
88
|
+
CreateSSMPermissions: {
|
|
89
|
+
'Fn::Equals': [{ Ref: 'EnableSSMSupport' }, 'true'],
|
|
90
|
+
},
|
|
80
91
|
},
|
|
81
92
|
|
|
82
|
-
Resources: {}
|
|
93
|
+
Resources: {},
|
|
83
94
|
};
|
|
84
95
|
|
|
85
96
|
// Add IAM User
|
|
@@ -89,34 +100,52 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
89
100
|
UserName: { Ref: 'DeploymentUserName' },
|
|
90
101
|
ManagedPolicyArns: [
|
|
91
102
|
{ Ref: 'FriggDiscoveryPolicy' },
|
|
92
|
-
{ Ref: 'FriggCoreDeploymentPolicy' }
|
|
93
|
-
]
|
|
94
|
-
}
|
|
103
|
+
{ Ref: 'FriggCoreDeploymentPolicy' },
|
|
104
|
+
],
|
|
105
|
+
},
|
|
95
106
|
};
|
|
96
107
|
|
|
97
108
|
// Conditionally add feature-specific policies
|
|
98
109
|
if (features.vpc) {
|
|
99
|
-
template.Resources.FriggDeploymentUser.Properties.ManagedPolicyArns.push(
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
template.Resources.FriggDeploymentUser.Properties.ManagedPolicyArns.push(
|
|
111
|
+
{
|
|
112
|
+
'Fn::If': [
|
|
113
|
+
'CreateVPCPermissions',
|
|
114
|
+
{ Ref: 'FriggVPCPolicy' },
|
|
115
|
+
{ Ref: 'AWS::NoValue' },
|
|
116
|
+
],
|
|
117
|
+
}
|
|
118
|
+
);
|
|
102
119
|
}
|
|
103
120
|
if (features.kms) {
|
|
104
|
-
template.Resources.FriggDeploymentUser.Properties.ManagedPolicyArns.push(
|
|
105
|
-
|
|
106
|
-
|
|
121
|
+
template.Resources.FriggDeploymentUser.Properties.ManagedPolicyArns.push(
|
|
122
|
+
{
|
|
123
|
+
'Fn::If': [
|
|
124
|
+
'CreateKMSPermissions',
|
|
125
|
+
{ Ref: 'FriggKMSPolicy' },
|
|
126
|
+
{ Ref: 'AWS::NoValue' },
|
|
127
|
+
],
|
|
128
|
+
}
|
|
129
|
+
);
|
|
107
130
|
}
|
|
108
131
|
if (features.ssm) {
|
|
109
|
-
template.Resources.FriggDeploymentUser.Properties.ManagedPolicyArns.push(
|
|
110
|
-
|
|
111
|
-
|
|
132
|
+
template.Resources.FriggDeploymentUser.Properties.ManagedPolicyArns.push(
|
|
133
|
+
{
|
|
134
|
+
'Fn::If': [
|
|
135
|
+
'CreateSSMPermissions',
|
|
136
|
+
{ Ref: 'FriggSSMPolicy' },
|
|
137
|
+
{ Ref: 'AWS::NoValue' },
|
|
138
|
+
],
|
|
139
|
+
}
|
|
140
|
+
);
|
|
112
141
|
}
|
|
113
142
|
|
|
114
143
|
// Add Access Key
|
|
115
144
|
template.Resources.FriggDeploymentAccessKey = {
|
|
116
145
|
Type: 'AWS::IAM::AccessKey',
|
|
117
146
|
Properties: {
|
|
118
|
-
UserName: { Ref: 'FriggDeploymentUser' }
|
|
119
|
-
}
|
|
147
|
+
UserName: { Ref: 'FriggDeploymentUser' },
|
|
148
|
+
},
|
|
120
149
|
};
|
|
121
150
|
|
|
122
151
|
// Add Discovery Policy (always needed)
|
|
@@ -124,7 +153,8 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
124
153
|
Type: 'AWS::IAM::ManagedPolicy',
|
|
125
154
|
Properties: {
|
|
126
155
|
ManagedPolicyName: 'FriggDiscoveryPolicy',
|
|
127
|
-
Description:
|
|
156
|
+
Description:
|
|
157
|
+
'Permissions for AWS resource discovery during Frigg build process',
|
|
128
158
|
PolicyDocument: {
|
|
129
159
|
Version: '2012-10-17',
|
|
130
160
|
Statement: [
|
|
@@ -140,122 +170,16 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
140
170
|
'ec2:DescribeNatGateways',
|
|
141
171
|
'ec2:DescribeAddresses',
|
|
142
172
|
'kms:ListKeys',
|
|
143
|
-
'kms:DescribeKey'
|
|
173
|
+
'kms:DescribeKey',
|
|
144
174
|
],
|
|
145
|
-
Resource: '*'
|
|
146
|
-
}
|
|
147
|
-
]
|
|
148
|
-
}
|
|
149
|
-
}
|
|
175
|
+
Resource: '*',
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
150
180
|
};
|
|
151
181
|
|
|
152
182
|
// Add Core Deployment Policy (always needed)
|
|
153
|
-
const coreActions = [
|
|
154
|
-
// CloudFormation permissions
|
|
155
|
-
'cloudformation:CreateStack',
|
|
156
|
-
'cloudformation:UpdateStack',
|
|
157
|
-
'cloudformation:DeleteStack',
|
|
158
|
-
'cloudformation:DescribeStacks',
|
|
159
|
-
'cloudformation:DescribeStackEvents',
|
|
160
|
-
'cloudformation:DescribeStackResources',
|
|
161
|
-
'cloudformation:DescribeStackResource',
|
|
162
|
-
'cloudformation:ListStackResources',
|
|
163
|
-
'cloudformation:GetTemplate',
|
|
164
|
-
'cloudformation:DescribeChangeSet',
|
|
165
|
-
'cloudformation:CreateChangeSet',
|
|
166
|
-
'cloudformation:DeleteChangeSet',
|
|
167
|
-
'cloudformation:ExecuteChangeSet',
|
|
168
|
-
'cloudformation:ValidateTemplate',
|
|
169
|
-
|
|
170
|
-
// Lambda permissions
|
|
171
|
-
'lambda:CreateFunction',
|
|
172
|
-
'lambda:UpdateFunctionCode',
|
|
173
|
-
'lambda:UpdateFunctionConfiguration',
|
|
174
|
-
'lambda:DeleteFunction',
|
|
175
|
-
'lambda:GetFunction',
|
|
176
|
-
'lambda:ListFunctions',
|
|
177
|
-
'lambda:PublishVersion',
|
|
178
|
-
'lambda:CreateAlias',
|
|
179
|
-
'lambda:UpdateAlias',
|
|
180
|
-
'lambda:DeleteAlias',
|
|
181
|
-
'lambda:GetAlias',
|
|
182
|
-
'lambda:AddPermission',
|
|
183
|
-
'lambda:RemovePermission',
|
|
184
|
-
'lambda:GetPolicy',
|
|
185
|
-
'lambda:PutProvisionedConcurrencyConfig',
|
|
186
|
-
'lambda:DeleteProvisionedConcurrencyConfig',
|
|
187
|
-
'lambda:PutConcurrency',
|
|
188
|
-
'lambda:DeleteConcurrency',
|
|
189
|
-
'lambda:TagResource',
|
|
190
|
-
'lambda:UntagResource',
|
|
191
|
-
'lambda:ListVersionsByFunction',
|
|
192
|
-
|
|
193
|
-
// IAM permissions
|
|
194
|
-
'iam:CreateRole',
|
|
195
|
-
'iam:DeleteRole',
|
|
196
|
-
'iam:GetRole',
|
|
197
|
-
'iam:PassRole',
|
|
198
|
-
'iam:PutRolePolicy',
|
|
199
|
-
'iam:DeleteRolePolicy',
|
|
200
|
-
'iam:GetRolePolicy',
|
|
201
|
-
'iam:AttachRolePolicy',
|
|
202
|
-
'iam:DetachRolePolicy',
|
|
203
|
-
'iam:TagRole',
|
|
204
|
-
'iam:UntagRole',
|
|
205
|
-
'iam:ListPolicyVersions',
|
|
206
|
-
|
|
207
|
-
// S3 permissions
|
|
208
|
-
's3:CreateBucket',
|
|
209
|
-
's3:PutObject',
|
|
210
|
-
's3:GetObject',
|
|
211
|
-
's3:DeleteObject',
|
|
212
|
-
's3:PutBucketPolicy',
|
|
213
|
-
's3:PutBucketVersioning',
|
|
214
|
-
's3:PutBucketPublicAccessBlock',
|
|
215
|
-
's3:GetBucketLocation',
|
|
216
|
-
's3:ListBucket',
|
|
217
|
-
|
|
218
|
-
// SQS permissions
|
|
219
|
-
'sqs:CreateQueue',
|
|
220
|
-
'sqs:DeleteQueue',
|
|
221
|
-
'sqs:GetQueueAttributes',
|
|
222
|
-
'sqs:SetQueueAttributes',
|
|
223
|
-
'sqs:GetQueueUrl',
|
|
224
|
-
'sqs:TagQueue',
|
|
225
|
-
'sqs:UntagQueue',
|
|
226
|
-
|
|
227
|
-
// SNS permissions
|
|
228
|
-
'sns:CreateTopic',
|
|
229
|
-
'sns:DeleteTopic',
|
|
230
|
-
'sns:GetTopicAttributes',
|
|
231
|
-
'sns:SetTopicAttributes',
|
|
232
|
-
'sns:Subscribe',
|
|
233
|
-
'sns:Unsubscribe',
|
|
234
|
-
'sns:ListSubscriptionsByTopic',
|
|
235
|
-
'sns:TagResource',
|
|
236
|
-
'sns:UntagResource',
|
|
237
|
-
|
|
238
|
-
// CloudWatch and Logs permissions
|
|
239
|
-
'cloudwatch:PutMetricAlarm',
|
|
240
|
-
'cloudwatch:DeleteAlarms',
|
|
241
|
-
'cloudwatch:DescribeAlarms',
|
|
242
|
-
'logs:CreateLogGroup',
|
|
243
|
-
'logs:CreateLogStream',
|
|
244
|
-
'logs:DeleteLogGroup',
|
|
245
|
-
'logs:DescribeLogGroups',
|
|
246
|
-
'logs:DescribeLogStreams',
|
|
247
|
-
'logs:FilterLogEvents',
|
|
248
|
-
'logs:PutLogEvents',
|
|
249
|
-
'logs:PutRetentionPolicy',
|
|
250
|
-
|
|
251
|
-
// API Gateway permissions
|
|
252
|
-
'apigateway:POST',
|
|
253
|
-
'apigateway:PUT',
|
|
254
|
-
'apigateway:DELETE',
|
|
255
|
-
'apigateway:GET',
|
|
256
|
-
'apigateway:PATCH'
|
|
257
|
-
];
|
|
258
|
-
|
|
259
183
|
const coreStatements = [
|
|
260
184
|
{
|
|
261
185
|
Sid: 'CloudFormationFriggStacks',
|
|
@@ -273,17 +197,20 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
273
197
|
'cloudformation:DescribeChangeSet',
|
|
274
198
|
'cloudformation:CreateChangeSet',
|
|
275
199
|
'cloudformation:DeleteChangeSet',
|
|
276
|
-
'cloudformation:ExecuteChangeSet'
|
|
200
|
+
'cloudformation:ExecuteChangeSet',
|
|
277
201
|
],
|
|
278
202
|
Resource: [
|
|
279
|
-
{
|
|
280
|
-
|
|
203
|
+
{
|
|
204
|
+
'Fn::Sub':
|
|
205
|
+
'arn:aws:cloudformation:*:${AWS::AccountId}:stack/*frigg*/*',
|
|
206
|
+
},
|
|
207
|
+
],
|
|
281
208
|
},
|
|
282
209
|
{
|
|
283
210
|
Sid: 'CloudFormationValidateTemplate',
|
|
284
211
|
Effect: 'Allow',
|
|
285
212
|
Action: ['cloudformation:ValidateTemplate'],
|
|
286
|
-
Resource: '*'
|
|
213
|
+
Resource: '*',
|
|
287
214
|
},
|
|
288
215
|
{
|
|
289
216
|
Sid: 'S3DeploymentBucket',
|
|
@@ -297,12 +224,12 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
297
224
|
's3:PutBucketVersioning',
|
|
298
225
|
's3:PutBucketPublicAccessBlock',
|
|
299
226
|
's3:GetBucketLocation',
|
|
300
|
-
's3:ListBucket'
|
|
227
|
+
's3:ListBucket',
|
|
301
228
|
],
|
|
302
229
|
Resource: [
|
|
303
230
|
'arn:aws:s3:::*serverless*',
|
|
304
|
-
'arn:aws:s3:::*serverless*/*'
|
|
305
|
-
]
|
|
231
|
+
'arn:aws:s3:::*serverless*/*',
|
|
232
|
+
],
|
|
306
233
|
},
|
|
307
234
|
{
|
|
308
235
|
Sid: 'LambdaFriggFunctions',
|
|
@@ -328,11 +255,14 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
328
255
|
'lambda:DeleteConcurrency',
|
|
329
256
|
'lambda:TagResource',
|
|
330
257
|
'lambda:UntagResource',
|
|
331
|
-
'lambda:ListVersionsByFunction'
|
|
258
|
+
'lambda:ListVersionsByFunction',
|
|
332
259
|
],
|
|
333
260
|
Resource: [
|
|
334
|
-
{
|
|
335
|
-
|
|
261
|
+
{
|
|
262
|
+
'Fn::Sub':
|
|
263
|
+
'arn:aws:lambda:*:${AWS::AccountId}:function:*frigg*',
|
|
264
|
+
},
|
|
265
|
+
],
|
|
336
266
|
},
|
|
337
267
|
{
|
|
338
268
|
Sid: 'IAMRolesForFriggLambda',
|
|
@@ -348,18 +278,23 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
348
278
|
'iam:AttachRolePolicy',
|
|
349
279
|
'iam:DetachRolePolicy',
|
|
350
280
|
'iam:TagRole',
|
|
351
|
-
'iam:UntagRole'
|
|
281
|
+
'iam:UntagRole',
|
|
352
282
|
],
|
|
353
283
|
Resource: [
|
|
354
284
|
{ 'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:role/*frigg*' },
|
|
355
|
-
{
|
|
356
|
-
|
|
285
|
+
{
|
|
286
|
+
'Fn::Sub':
|
|
287
|
+
'arn:aws:iam::${AWS::AccountId}:role/*frigg*LambdaRole*',
|
|
288
|
+
},
|
|
289
|
+
],
|
|
357
290
|
},
|
|
358
291
|
{
|
|
359
292
|
Sid: 'IAMPolicyVersionPermissions',
|
|
360
293
|
Effect: 'Allow',
|
|
361
294
|
Action: ['iam:ListPolicyVersions'],
|
|
362
|
-
Resource: [
|
|
295
|
+
Resource: [
|
|
296
|
+
{ 'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:policy/*' },
|
|
297
|
+
],
|
|
363
298
|
},
|
|
364
299
|
{
|
|
365
300
|
Sid: 'FriggMessagingServices',
|
|
@@ -371,12 +306,15 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
371
306
|
'sqs:SetQueueAttributes',
|
|
372
307
|
'sqs:GetQueueUrl',
|
|
373
308
|
'sqs:TagQueue',
|
|
374
|
-
'sqs:UntagQueue'
|
|
309
|
+
'sqs:UntagQueue',
|
|
375
310
|
],
|
|
376
311
|
Resource: [
|
|
377
312
|
{ 'Fn::Sub': 'arn:aws:sqs:*:${AWS::AccountId}:*frigg*' },
|
|
378
|
-
{
|
|
379
|
-
|
|
313
|
+
{
|
|
314
|
+
'Fn::Sub':
|
|
315
|
+
'arn:aws:sqs:*:${AWS::AccountId}:internal-error-queue-*',
|
|
316
|
+
},
|
|
317
|
+
],
|
|
380
318
|
},
|
|
381
319
|
{
|
|
382
320
|
Sid: 'FriggSNSTopics',
|
|
@@ -390,11 +328,11 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
390
328
|
'sns:Unsubscribe',
|
|
391
329
|
'sns:ListSubscriptionsByTopic',
|
|
392
330
|
'sns:TagResource',
|
|
393
|
-
'sns:UntagResource'
|
|
331
|
+
'sns:UntagResource',
|
|
394
332
|
],
|
|
395
333
|
Resource: [
|
|
396
|
-
{ 'Fn::Sub': 'arn:aws:sns:*:${AWS::AccountId}:*frigg*' }
|
|
397
|
-
]
|
|
334
|
+
{ 'Fn::Sub': 'arn:aws:sns:*:${AWS::AccountId}:*frigg*' },
|
|
335
|
+
],
|
|
398
336
|
},
|
|
399
337
|
{
|
|
400
338
|
Sid: 'FriggMonitoringAndLogs',
|
|
@@ -410,13 +348,22 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
410
348
|
'logs:DescribeLogStreams',
|
|
411
349
|
'logs:FilterLogEvents',
|
|
412
350
|
'logs:PutLogEvents',
|
|
413
|
-
'logs:PutRetentionPolicy'
|
|
351
|
+
'logs:PutRetentionPolicy',
|
|
414
352
|
],
|
|
415
353
|
Resource: [
|
|
416
|
-
{
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
354
|
+
{
|
|
355
|
+
'Fn::Sub':
|
|
356
|
+
'arn:aws:logs:*:${AWS::AccountId}:log-group:/aws/lambda/*frigg*',
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
'Fn::Sub':
|
|
360
|
+
'arn:aws:logs:*:${AWS::AccountId}:log-group:/aws/lambda/*frigg*:*',
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
'Fn::Sub':
|
|
364
|
+
'arn:aws:cloudwatch:*:${AWS::AccountId}:alarm:*frigg*',
|
|
365
|
+
},
|
|
366
|
+
],
|
|
420
367
|
},
|
|
421
368
|
{
|
|
422
369
|
Sid: 'FriggAPIGateway',
|
|
@@ -426,15 +373,37 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
426
373
|
'apigateway:PUT',
|
|
427
374
|
'apigateway:DELETE',
|
|
428
375
|
'apigateway:GET',
|
|
429
|
-
'apigateway:PATCH'
|
|
376
|
+
'apigateway:PATCH',
|
|
430
377
|
],
|
|
431
378
|
Resource: [
|
|
432
379
|
'arn:aws:apigateway:*::/restapis',
|
|
433
380
|
'arn:aws:apigateway:*::/restapis/*',
|
|
434
381
|
'arn:aws:apigateway:*::/domainnames',
|
|
435
|
-
'arn:aws:apigateway:*::/domainnames/*'
|
|
436
|
-
]
|
|
437
|
-
}
|
|
382
|
+
'arn:aws:apigateway:*::/domainnames/*',
|
|
383
|
+
],
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
Sid: 'FriggAPIGatewayV2',
|
|
387
|
+
Effect: 'Allow',
|
|
388
|
+
Action: [
|
|
389
|
+
'apigateway:GET',
|
|
390
|
+
'apigateway:DELETE',
|
|
391
|
+
'apigateway:PATCH',
|
|
392
|
+
'apigateway:POST',
|
|
393
|
+
'apigateway:PUT',
|
|
394
|
+
],
|
|
395
|
+
Resource: [
|
|
396
|
+
'arn:aws:apigateway:*::/apis',
|
|
397
|
+
'arn:aws:apigateway:*::/apis/*',
|
|
398
|
+
'arn:aws:apigateway:*::/apis/*/stages',
|
|
399
|
+
'arn:aws:apigateway:*::/apis/*/stages/*',
|
|
400
|
+
'arn:aws:apigateway:*::/apis/*/mappings',
|
|
401
|
+
'arn:aws:apigateway:*::/apis/*/mappings/*',
|
|
402
|
+
'arn:aws:apigateway:*::/domainnames',
|
|
403
|
+
'arn:aws:apigateway:*::/domainnames/*',
|
|
404
|
+
'arn:aws:apigateway:*::/domainnames/*/apimappings',
|
|
405
|
+
],
|
|
406
|
+
},
|
|
438
407
|
];
|
|
439
408
|
|
|
440
409
|
template.Resources.FriggCoreDeploymentPolicy = {
|
|
@@ -444,9 +413,9 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
444
413
|
Description: 'Core permissions for deploying Frigg applications',
|
|
445
414
|
PolicyDocument: {
|
|
446
415
|
Version: '2012-10-17',
|
|
447
|
-
Statement: coreStatements
|
|
448
|
-
}
|
|
449
|
-
}
|
|
416
|
+
Statement: coreStatements,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
450
419
|
};
|
|
451
420
|
|
|
452
421
|
// Add feature-specific policies only if needed
|
|
@@ -486,13 +455,15 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
486
455
|
'ec2:AuthorizeSecurityGroupEgress',
|
|
487
456
|
'ec2:AuthorizeSecurityGroupIngress',
|
|
488
457
|
'ec2:RevokeSecurityGroupEgress',
|
|
489
|
-
'ec2:RevokeSecurityGroupIngress'
|
|
458
|
+
'ec2:RevokeSecurityGroupIngress',
|
|
459
|
+
'ec2:DetachInternetGateway',
|
|
460
|
+
'ec2:DeleteSubnet',
|
|
490
461
|
],
|
|
491
|
-
Resource: '*'
|
|
492
|
-
}
|
|
493
|
-
]
|
|
494
|
-
}
|
|
495
|
-
}
|
|
462
|
+
Resource: '*',
|
|
463
|
+
},
|
|
464
|
+
],
|
|
465
|
+
},
|
|
466
|
+
},
|
|
496
467
|
};
|
|
497
468
|
}
|
|
498
469
|
|
|
@@ -502,32 +473,33 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
502
473
|
Condition: 'CreateKMSPermissions',
|
|
503
474
|
Properties: {
|
|
504
475
|
ManagedPolicyName: 'FriggKMSPolicy',
|
|
505
|
-
Description:
|
|
476
|
+
Description:
|
|
477
|
+
'KMS encryption permissions for Frigg applications',
|
|
506
478
|
PolicyDocument: {
|
|
507
479
|
Version: '2012-10-17',
|
|
508
480
|
Statement: [
|
|
509
481
|
{
|
|
510
482
|
Sid: 'FriggKMSEncryptionRuntime',
|
|
511
483
|
Effect: 'Allow',
|
|
512
|
-
Action: [
|
|
513
|
-
'kms:GenerateDataKey',
|
|
514
|
-
'kms:Decrypt'
|
|
515
|
-
],
|
|
484
|
+
Action: ['kms:GenerateDataKey', 'kms:Decrypt'],
|
|
516
485
|
Resource: [
|
|
517
|
-
{
|
|
486
|
+
{
|
|
487
|
+
'Fn::Sub':
|
|
488
|
+
'arn:aws:kms:*:${AWS::AccountId}:key/*',
|
|
489
|
+
},
|
|
518
490
|
],
|
|
519
491
|
Condition: {
|
|
520
492
|
StringEquals: {
|
|
521
493
|
'kms:ViaService': [
|
|
522
494
|
'lambda.*.amazonaws.com',
|
|
523
|
-
's3.*.amazonaws.com'
|
|
524
|
-
]
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
]
|
|
529
|
-
}
|
|
530
|
-
}
|
|
495
|
+
's3.*.amazonaws.com',
|
|
496
|
+
],
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
},
|
|
502
|
+
},
|
|
531
503
|
};
|
|
532
504
|
}
|
|
533
505
|
|
|
@@ -537,7 +509,8 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
537
509
|
Condition: 'CreateSSMPermissions',
|
|
538
510
|
Properties: {
|
|
539
511
|
ManagedPolicyName: 'FriggSSMPolicy',
|
|
540
|
-
Description:
|
|
512
|
+
Description:
|
|
513
|
+
'SSM Parameter Store permissions for Frigg applications',
|
|
541
514
|
PolicyDocument: {
|
|
542
515
|
Version: '2012-10-17',
|
|
543
516
|
Statement: [
|
|
@@ -547,16 +520,22 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
547
520
|
Action: [
|
|
548
521
|
'ssm:GetParameter',
|
|
549
522
|
'ssm:GetParameters',
|
|
550
|
-
'ssm:GetParametersByPath'
|
|
523
|
+
'ssm:GetParametersByPath',
|
|
551
524
|
],
|
|
552
525
|
Resource: [
|
|
553
|
-
{
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
526
|
+
{
|
|
527
|
+
'Fn::Sub':
|
|
528
|
+
'arn:aws:ssm:*:${AWS::AccountId}:parameter/*frigg*',
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
'Fn::Sub':
|
|
532
|
+
'arn:aws:ssm:*:${AWS::AccountId}:parameter/*frigg*/*',
|
|
533
|
+
},
|
|
534
|
+
],
|
|
535
|
+
},
|
|
536
|
+
],
|
|
537
|
+
},
|
|
538
|
+
},
|
|
560
539
|
};
|
|
561
540
|
}
|
|
562
541
|
|
|
@@ -569,10 +548,11 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
569
548
|
SecretString: {
|
|
570
549
|
'Fn::Sub': JSON.stringify({
|
|
571
550
|
AccessKeyId: '${FriggDeploymentAccessKey}',
|
|
572
|
-
SecretAccessKey:
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
551
|
+
SecretAccessKey:
|
|
552
|
+
'${FriggDeploymentAccessKey.SecretAccessKey}',
|
|
553
|
+
}),
|
|
554
|
+
},
|
|
555
|
+
},
|
|
576
556
|
};
|
|
577
557
|
|
|
578
558
|
// Add Outputs
|
|
@@ -581,29 +561,30 @@ function generateIAMCloudFormation(appDefinition, options = {}) {
|
|
|
581
561
|
Description: 'ARN of the Frigg deployment user',
|
|
582
562
|
Value: { 'Fn::GetAtt': ['FriggDeploymentUser', 'Arn'] },
|
|
583
563
|
Export: {
|
|
584
|
-
Name: { 'Fn::Sub': '${AWS::StackName}-UserArn' }
|
|
585
|
-
}
|
|
564
|
+
Name: { 'Fn::Sub': '${AWS::StackName}-UserArn' },
|
|
565
|
+
},
|
|
586
566
|
},
|
|
587
567
|
AccessKeyId: {
|
|
588
568
|
Description: 'Access Key ID for the deployment user',
|
|
589
569
|
Value: { Ref: 'FriggDeploymentAccessKey' },
|
|
590
570
|
Export: {
|
|
591
|
-
Name: { 'Fn::Sub': '${AWS::StackName}-AccessKeyId' }
|
|
592
|
-
}
|
|
571
|
+
Name: { 'Fn::Sub': '${AWS::StackName}-AccessKeyId' },
|
|
572
|
+
},
|
|
593
573
|
},
|
|
594
574
|
SecretAccessKeyCommand: {
|
|
595
575
|
Description: 'Command to retrieve the secret access key',
|
|
596
576
|
Value: {
|
|
597
|
-
'Fn::Sub':
|
|
598
|
-
|
|
577
|
+
'Fn::Sub':
|
|
578
|
+
'aws secretsmanager get-secret-value --secret-id frigg-deployment-credentials --query SecretString --output text | jq -r .SecretAccessKey',
|
|
579
|
+
},
|
|
599
580
|
},
|
|
600
581
|
CredentialsSecretArn: {
|
|
601
582
|
Description: 'ARN of the secret containing deployment credentials',
|
|
602
583
|
Value: { Ref: 'FriggDeploymentCredentials' },
|
|
603
584
|
Export: {
|
|
604
|
-
Name: { 'Fn::Sub': '${AWS::StackName}-CredentialsSecretArn' }
|
|
605
|
-
}
|
|
606
|
-
}
|
|
585
|
+
Name: { 'Fn::Sub': '${AWS::StackName}-CredentialsSecretArn' },
|
|
586
|
+
},
|
|
587
|
+
},
|
|
607
588
|
};
|
|
608
589
|
|
|
609
590
|
// Convert to YAML
|
|
@@ -621,7 +602,7 @@ function convertToYAML(obj) {
|
|
|
621
602
|
indent: 2,
|
|
622
603
|
lineWidth: 120,
|
|
623
604
|
noRefs: true,
|
|
624
|
-
sortKeys: false
|
|
605
|
+
sortKeys: false,
|
|
625
606
|
});
|
|
626
607
|
}
|
|
627
608
|
|
|
@@ -634,9 +615,11 @@ function getFeatureSummary(appDefinition) {
|
|
|
634
615
|
const features = {
|
|
635
616
|
core: true, // Always enabled
|
|
636
617
|
vpc: appDefinition.vpc?.enable === true,
|
|
637
|
-
kms:
|
|
618
|
+
kms:
|
|
619
|
+
appDefinition.encryption?.useDefaultKMSForFieldLevelEncryption ===
|
|
620
|
+
true,
|
|
638
621
|
ssm: appDefinition.ssm?.enable === true,
|
|
639
|
-
websockets: appDefinition.websockets?.enable === true
|
|
622
|
+
websockets: appDefinition.websockets?.enable === true,
|
|
640
623
|
};
|
|
641
624
|
|
|
642
625
|
const integrationCount = appDefinition.integrations?.length || 0;
|
|
@@ -644,7 +627,7 @@ function getFeatureSummary(appDefinition) {
|
|
|
644
627
|
return {
|
|
645
628
|
features,
|
|
646
629
|
integrationCount,
|
|
647
|
-
appName: appDefinition.name || 'Unnamed Frigg App'
|
|
630
|
+
appName: appDefinition.name || 'Unnamed Frigg App',
|
|
648
631
|
};
|
|
649
632
|
}
|
|
650
633
|
|
|
@@ -683,5 +666,5 @@ module.exports = {
|
|
|
683
666
|
getFeatureSummary,
|
|
684
667
|
generateBasicIAMPolicy,
|
|
685
668
|
generateFullIAMPolicy,
|
|
686
|
-
generateIAMPolicy
|
|
687
|
-
};
|
|
669
|
+
generateIAMPolicy,
|
|
670
|
+
};
|