@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.
@@ -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 { deploymentUserName = 'frigg-deployment-user', mode = 'auto' } =
14
- options;
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
- appDefinition.name || 'Frigg'
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
- 'Enable SSM Parameter Store permissions for Frigg applications',
78
- },
72
+ Description: 'Enable SSM Parameter Store permissions for Frigg applications'
73
+ }
79
74
  },
80
75
 
81
76
  Conditions: {
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
- },
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
- 'Fn::If': [
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
- 'Fn::If': [
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
- 'Fn::If': [
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
- 'Fn::Sub':
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
- 'Fn::Sub':
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
- 'Fn::Sub':
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
- 'Fn::Sub':
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
- '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
- ],
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
- 'arn:aws:apigateway:*::/domainnames/*/apimappings',
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: ['kms:GenerateDataKey', 'kms:Decrypt'],
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
- '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
- },
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
- '${FriggDeploymentAccessKey.SecretAccessKey}',
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
- 'aws secretsmanager get-secret-value --secret-id frigg-deployment-credentials --query SecretString --output text | jq -r .SecretAccessKey',
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
+ };