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