sst 2.0.13 → 2.0.15

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,5 +1,5 @@
1
1
  import * as ssm from "aws-cdk-lib/aws-ssm";
2
- import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
2
+ import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
3
3
  import { Construct } from "constructs";
4
4
  import { Stack } from "./Stack.js";
5
5
  import { ENVIRONMENT_PLACEHOLDER, getEnvironmentKey, getParameterPath, } from "./util/functionBinding.js";
@@ -45,14 +45,18 @@ export class Auth extends Construct {
45
45
  privatePath: getParameterPath(this, PRIVATE_KEY_PROP),
46
46
  },
47
47
  });
48
- stack.customResourceHandler.role?.addToPrincipalPolicy(new PolicyStatement({
49
- actions: [
50
- "ssm:GetParameter",
51
- "ssm:PutParameter",
52
- "ssm:DeleteParameter",
53
- ],
54
- resources: [
55
- `arn:${stack.partition}:ssm:${stack.region}:${stack.account}:parameter/*`,
48
+ stack.customResourceHandler.role?.attachInlinePolicy(new Policy(this, "CloudFrontInvalidatorPolicy", {
49
+ statements: [
50
+ new PolicyStatement({
51
+ actions: [
52
+ "ssm:GetParameter",
53
+ "ssm:PutParameter",
54
+ "ssm:DeleteParameter",
55
+ ],
56
+ resources: [
57
+ `arn:${stack.partition}:ssm:${stack.region}:${stack.account}:parameter/*`,
58
+ ],
59
+ }),
56
60
  ],
57
61
  }));
58
62
  }
@@ -1,5 +1,5 @@
1
1
  import { Construct, IConstruct } from "constructs";
2
- import * as iam from "aws-cdk-lib/aws-iam";
2
+ import { Role } from "aws-cdk-lib/aws-iam";
3
3
  import * as lambda from "aws-cdk-lib/aws-lambda";
4
4
  import { Size } from "./util/size.js";
5
5
  import { Duration } from "./util/duration.js";
@@ -23,7 +23,7 @@ export interface EdgeFunctionProps {
23
23
  scopeOverride?: IConstruct;
24
24
  }
25
25
  export declare class EdgeFunction extends Construct {
26
- role: iam.Role;
26
+ role: Role;
27
27
  functionArn: string;
28
28
  private scope;
29
29
  private versionId;
@@ -3,7 +3,7 @@ import url from "url";
3
3
  import path from "path";
4
4
  import crypto from "crypto";
5
5
  import { Construct } from "constructs";
6
- import * as iam from "aws-cdk-lib/aws-iam";
6
+ import { Effect, Role, Policy, PolicyStatement, CompositePrincipal, ServicePrincipal, ManagedPolicy, } from "aws-cdk-lib/aws-iam";
7
7
  import * as lambda from "aws-cdk-lib/aws-lambda";
8
8
  import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
9
9
  import { Lazy, Duration as CdkDuration, CustomResource, } from "aws-cdk-lib";
@@ -95,10 +95,10 @@ ${exports}
95
95
  createRole() {
96
96
  const { permissions } = this.props;
97
97
  // Create function role
98
- const role = new iam.Role(this.scope, `ServerLambdaRole`, {
99
- assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal("lambda.amazonaws.com"), new iam.ServicePrincipal("edgelambda.amazonaws.com")),
98
+ const role = new Role(this.scope, `ServerLambdaRole`, {
99
+ assumedBy: new CompositePrincipal(new ServicePrincipal("lambda.amazonaws.com"), new ServicePrincipal("edgelambda.amazonaws.com")),
100
100
  managedPolicies: [
101
- iam.ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy", `arn:${Stack.of(this).partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole`),
101
+ ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy", `arn:${Stack.of(this).partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole`),
102
102
  ],
103
103
  });
104
104
  // Attach permission
@@ -159,10 +159,14 @@ ${exports}
159
159
  replacements: this.getLambdaContentReplaceValues(),
160
160
  },
161
161
  });
162
- stack.customResourceHandler.role?.addToPrincipalPolicy(new iam.PolicyStatement({
163
- effect: iam.Effect.ALLOW,
164
- actions: ["s3:GetObject", "s3:PutObject"],
165
- resources: [`arn:${stack.partition}:s3:::${asset.s3BucketName}/*`],
162
+ stack.customResourceHandler.role?.attachInlinePolicy(new Policy(this, "AssetReplacerPolicy", {
163
+ statements: [
164
+ new PolicyStatement({
165
+ effect: Effect.ALLOW,
166
+ actions: ["s3:GetObject", "s3:PutObject"],
167
+ resources: [`arn:${stack.partition}:s3:::${asset.s3BucketName}/*`],
168
+ }),
169
+ ],
166
170
  }));
167
171
  return resource;
168
172
  }
@@ -183,8 +187,8 @@ ${exports}
183
187
  timeout: CdkDuration.minutes(15),
184
188
  memorySize: 1024,
185
189
  initialPolicy: [
186
- new iam.PolicyStatement({
187
- effect: iam.Effect.ALLOW,
190
+ new PolicyStatement({
191
+ effect: Effect.ALLOW,
188
192
  actions: ["s3:*"],
189
193
  resources: ["*"],
190
194
  }),
@@ -215,8 +219,8 @@ ${exports}
215
219
  timeout: CdkDuration.minutes(15),
216
220
  memorySize: 1024,
217
221
  initialPolicy: [
218
- new iam.PolicyStatement({
219
- effect: iam.Effect.ALLOW,
222
+ new PolicyStatement({
223
+ effect: Effect.ALLOW,
220
224
  actions: ["lambda:*", "s3:*"],
221
225
  resources: ["*"],
222
226
  }),
@@ -253,8 +257,8 @@ ${exports}
253
257
  timeout: CdkDuration.minutes(15),
254
258
  memorySize: 1024,
255
259
  initialPolicy: [
256
- new iam.PolicyStatement({
257
- effect: iam.Effect.ALLOW,
260
+ new PolicyStatement({
261
+ effect: Effect.ALLOW,
258
262
  actions: ["lambda:*"],
259
263
  resources: ["*"],
260
264
  }),
@@ -2,7 +2,7 @@ import url from "url";
2
2
  import path from "path";
3
3
  import spawn from "cross-spawn";
4
4
  import { Construct } from "constructs";
5
- import * as iam from "aws-cdk-lib/aws-iam";
5
+ import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
6
6
  import * as logs from "aws-cdk-lib/aws-logs";
7
7
  import * as lambda from "aws-cdk-lib/aws-lambda";
8
8
  import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
@@ -87,10 +87,14 @@ export class SsrFunction extends Construct {
87
87
  replacements: this.getLambdaContentReplaceValues(),
88
88
  },
89
89
  });
90
- stack.customResourceHandler.role?.addToPrincipalPolicy(new iam.PolicyStatement({
91
- effect: iam.Effect.ALLOW,
92
- actions: ["s3:GetObject", "s3:PutObject"],
93
- resources: [`arn:${stack.partition}:s3:::${asset.s3BucketName}/*`],
90
+ stack.customResourceHandler.role?.attachInlinePolicy(new Policy(this, "AssetReplacerPolicy", {
91
+ statements: [
92
+ new PolicyStatement({
93
+ effect: Effect.ALLOW,
94
+ actions: ["s3:GetObject", "s3:PutObject"],
95
+ resources: [`arn:${stack.partition}:s3:::${asset.s3BucketName}/*`],
96
+ }),
97
+ ],
94
98
  }));
95
99
  return resource;
96
100
  }
@@ -8,7 +8,7 @@ import { execSync } from "child_process";
8
8
  import { Construct } from "constructs";
9
9
  import { Fn, Token, Duration as CdkDuration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
10
10
  import { Bucket } from "aws-cdk-lib/aws-s3";
11
- import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
11
+ import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
12
12
  import { Function, Code, Runtime, FunctionUrlAuthType, } from "aws-cdk-lib/aws-lambda";
13
13
  import { HostedZone, ARecord, AaaaRecord, RecordTarget, } from "aws-cdk-lib/aws-route53";
14
14
  import { Asset } from "aws-cdk-lib/aws-s3-assets";
@@ -100,8 +100,7 @@ export class SsrSite extends Construct {
100
100
  : this.createCloudFrontDistributionForRegional();
101
101
  this.distribution.node.addDependency(s3deployCR);
102
102
  // Invalidate CloudFront
103
- const invalidationCR = this.createCloudFrontInvalidation(cliLayer);
104
- invalidationCR.node.addDependency(this.distribution);
103
+ this.createCloudFrontInvalidation();
105
104
  // Connect Custom Domain to CloudFront Distribution
106
105
  this.createRoute53Records();
107
106
  }
@@ -551,36 +550,33 @@ export class SsrSite extends Construct {
551
550
  comment: "SST server response cache policy",
552
551
  });
553
552
  }
554
- createCloudFrontInvalidation(cliLayer) {
555
- // Create a Lambda function that will be doing the invalidation
556
- const invalidator = new Function(this, "CloudFrontInvalidator", {
557
- code: Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
558
- layers: [cliLayer],
559
- runtime: Runtime.PYTHON_3_7,
560
- handler: "cf-invalidate.handler",
561
- timeout: CdkDuration.minutes(15),
562
- memorySize: 1024,
563
- });
564
- // Grant permissions to invalidate CF Distribution
565
- invalidator.addToRolePolicy(new PolicyStatement({
566
- effect: Effect.ALLOW,
567
- actions: [
568
- "cloudfront:GetInvalidation",
569
- "cloudfront:CreateInvalidation",
570
- ],
571
- resources: ["*"],
572
- }));
573
- return new CustomResource(this, "CloudFrontInvalidation", {
574
- serviceToken: invalidator.functionArn,
575
- resourceType: "Custom::SSTCloudFrontInvalidation",
553
+ createCloudFrontInvalidation() {
554
+ const stack = Stack.of(this);
555
+ const resource = new CustomResource(this, "CloudFrontInvalidator", {
556
+ serviceToken: stack.customResourceHandler.functionArn,
557
+ resourceType: "Custom::CloudFrontInvalidator",
576
558
  properties: {
577
- BuildId: this.generateBuildId(),
578
- DistributionId: this.distribution.distributionId,
579
- // TODO: Ignore the browser build path as it may speed up invalidation
580
- DistributionPaths: ["/*"],
581
- WaitForInvalidation: this.props.waitForInvalidation,
559
+ buildId: this.generateBuildId(),
560
+ distributionId: this.distribution.distributionId,
561
+ paths: ["/*"],
562
+ waitForInvalidation: this.props.waitForInvalidation,
582
563
  },
583
564
  });
565
+ stack.customResourceHandler.role?.attachInlinePolicy(new Policy(this, "CloudFrontInvalidatorPolicy", {
566
+ statements: [
567
+ new PolicyStatement({
568
+ effect: Effect.ALLOW,
569
+ actions: [
570
+ "cloudfront:GetInvalidation",
571
+ "cloudfront:CreateInvalidation",
572
+ ],
573
+ resources: [
574
+ `arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.distribution.distributionId}`,
575
+ ],
576
+ }),
577
+ ],
578
+ }));
579
+ return resource;
584
580
  }
585
581
  /////////////////////
586
582
  // Custom Domain
@@ -1,3 +1,4 @@
1
+ import fs from "fs";
1
2
  import url from "url";
2
3
  import * as path from "path";
3
4
  import * as cdk from "aws-cdk-lib";
@@ -172,9 +173,11 @@ export class Stack extends cdk.Stack {
172
173
  });
173
174
  }
174
175
  createCustomResourceHandler() {
176
+ const dir = path.join(__dirname, "../support/custom-resources/");
175
177
  return new lambda.Function(this, "CustomResourceHandler", {
176
- code: lambda.Code.fromAsset(path.join(__dirname, "../support/custom-resources/"), {
177
- assetHash: this.stackName + "-custom-resources-20230130",
178
+ code: lambda.Code.fromAsset(dir, {
179
+ //assetHash: this.stackName + "-custom-resources-20230130",
180
+ assetHash: this.stackName + fs.readFileSync(dir + "/index.mjs").toString(),
178
181
  }),
179
182
  handler: "index.handler",
180
183
  runtime: lambda.Runtime.NODEJS_16_X,
@@ -7,7 +7,7 @@ import { Construct } from "constructs";
7
7
  import { Token, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
8
8
  import * as s3 from "aws-cdk-lib/aws-s3";
9
9
  import * as s3Assets from "aws-cdk-lib/aws-s3-assets";
10
- import * as iam from "aws-cdk-lib/aws-iam";
10
+ import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
11
11
  import * as lambda from "aws-cdk-lib/aws-lambda";
12
12
  import * as route53 from "aws-cdk-lib/aws-route53";
13
13
  import * as route53Targets from "aws-cdk-lib/aws-route53-targets";
@@ -91,7 +91,7 @@ export class StaticSite extends Construct {
91
91
  this.distribution = this.createCfDistribution();
92
92
  this.distribution.node.addDependency(s3deployCR);
93
93
  // Invalidate CloudFront
94
- const invalidationCR = this.createCloudFrontInvalidation(cliLayer, assets);
94
+ const invalidationCR = this.createCloudFrontInvalidation(assets);
95
95
  invalidationCR.node.addDependency(this.distribution);
96
96
  // Connect Custom Domain to CloudFront Distribution
97
97
  this.createRoute53Records();
@@ -420,41 +420,38 @@ interface ImportMeta {
420
420
  },
421
421
  });
422
422
  }
423
- createCloudFrontInvalidation(cliLayer, assets) {
424
- // Create a Lambda function that will be doing the invalidation
425
- const invalidator = new lambda.Function(this, "CloudFrontInvalidator", {
426
- code: lambda.Code.fromAsset(path.join(__dirname, "../support/base-site-custom-resource")),
427
- layers: [cliLayer],
428
- runtime: lambda.Runtime.PYTHON_3_7,
429
- handler: "cf-invalidate.handler",
430
- timeout: Duration.minutes(15),
431
- memorySize: 1024,
432
- });
433
- // Grant permissions to invalidate CF Distribution
434
- invalidator.addToRolePolicy(new iam.PolicyStatement({
435
- effect: iam.Effect.ALLOW,
436
- actions: [
437
- "cloudfront:GetInvalidation",
438
- "cloudfront:CreateInvalidation",
439
- ],
440
- resources: ["*"],
441
- }));
423
+ createCloudFrontInvalidation(assets) {
424
+ const stack = Stack.of(this);
442
425
  // Need the AssetHash field so the CR gets updated on each deploy
443
426
  const assetsHash = crypto
444
427
  .createHash("md5")
445
428
  .update(assets.map(({ assetHash }) => assetHash).join(""))
446
429
  .digest("hex");
447
- // Create custom resource
448
- return new CustomResource(this, "CloudFrontInvalidation", {
449
- serviceToken: invalidator.functionArn,
450
- resourceType: "Custom::SSTCloudFrontInvalidation",
430
+ const resource = new CustomResource(this, "CloudFrontInvalidator", {
431
+ serviceToken: stack.customResourceHandler.functionArn,
432
+ resourceType: "Custom::CloudFrontInvalidator",
451
433
  properties: {
452
- AssetsHash: assetsHash,
453
- DistributionId: this.distribution.distributionId,
454
- DistributionPaths: ["/*"],
455
- WaitForInvalidation: this.props.waitForInvalidation,
434
+ assetsHash,
435
+ distributionId: this.distribution.distributionId,
436
+ paths: ["/*"],
437
+ waitForInvalidation: this.props.waitForInvalidation,
456
438
  },
457
439
  });
440
+ stack.customResourceHandler.role?.attachInlinePolicy(new Policy(this, "CloudFrontInvalidatorPolicy", {
441
+ statements: [
442
+ new PolicyStatement({
443
+ effect: Effect.ALLOW,
444
+ actions: [
445
+ "cloudfront:GetInvalidation",
446
+ "cloudfront:CreateInvalidation",
447
+ ],
448
+ resources: [
449
+ `arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.distribution.distributionId}`,
450
+ ],
451
+ }),
452
+ ],
453
+ }));
454
+ return resource;
458
455
  }
459
456
  /////////////////////
460
457
  // Custom Domain
@@ -6,7 +6,7 @@ import { execSync } from "child_process";
6
6
  import { Construct } from "constructs";
7
7
  import { Token, Duration, CfnOutput, RemovalPolicy, CustomResource, } from "aws-cdk-lib";
8
8
  import * as s3 from "aws-cdk-lib/aws-s3";
9
- import * as iam from "aws-cdk-lib/aws-iam";
9
+ import { Role, Effect, PolicyStatement, CompositePrincipal, ServicePrincipal, ManagedPolicy, } from "aws-cdk-lib/aws-iam";
10
10
  import * as sqs from "aws-cdk-lib/aws-sqs";
11
11
  import * as logs from "aws-cdk-lib/aws-logs";
12
12
  import * as lambda from "aws-cdk-lib/aws-lambda";
@@ -388,10 +388,10 @@ export class NextjsSite extends Construct {
388
388
  createEdgeFunctionRole() {
389
389
  const { defaults } = this.props;
390
390
  // Create function role
391
- const role = new iam.Role(this, `EdgeLambdaRole`, {
392
- assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal("lambda.amazonaws.com"), new iam.ServicePrincipal("edgelambda.amazonaws.com")),
391
+ const role = new Role(this, `EdgeLambdaRole`, {
392
+ assumedBy: new CompositePrincipal(new ServicePrincipal("lambda.amazonaws.com"), new ServicePrincipal("edgelambda.amazonaws.com")),
393
393
  managedPolicies: [
394
- iam.ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy", `arn:${Stack.of(this).partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole`),
394
+ ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy", `arn:${Stack.of(this).partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole`),
395
395
  ],
396
396
  });
397
397
  // Attach permission
@@ -470,8 +470,8 @@ export class NextjsSite extends Construct {
470
470
  });
471
471
  }
472
472
  // Allow provider to perform search/replace on the asset
473
- provider.role?.addToPrincipalPolicy(new iam.PolicyStatement({
474
- effect: iam.Effect.ALLOW,
473
+ provider.role?.addToPrincipalPolicy(new PolicyStatement({
474
+ effect: Effect.ALLOW,
475
475
  actions: ["s3:*"],
476
476
  resources: [
477
477
  `arn:${Stack.of(this).partition}:s3:::${asset.s3BucketName}/${asset.s3ObjectKey}`,
@@ -813,24 +813,7 @@ export class NextjsSite extends Construct {
813
813
  return new cloudfront.OriginRequestPolicy(this, "ImageOriginRequest", NextjsSite.imageOriginRequestPolicyProps);
814
814
  }
815
815
  createCloudFrontInvalidation() {
816
- // Create a Lambda function that will be doing the invalidation
817
- const invalidator = new lambda.Function(this, "CloudFrontInvalidator", {
818
- code: lambda.Code.fromAsset(path.join(__dirname, "../../support/base-site-custom-resource")),
819
- layers: [this.awsCliLayer],
820
- runtime: lambda.Runtime.PYTHON_3_7,
821
- handler: "cf-invalidate.handler",
822
- timeout: Duration.minutes(15),
823
- memorySize: 1024,
824
- });
825
- // Grant permissions to invalidate CF Distribution
826
- invalidator.addToRolePolicy(new iam.PolicyStatement({
827
- effect: iam.Effect.ALLOW,
828
- actions: [
829
- "cloudfront:GetInvalidation",
830
- "cloudfront:CreateInvalidation",
831
- ],
832
- resources: ["*"],
833
- }));
816
+ const stack = Stack.of(this);
834
817
  // need the BuildId field so this CR gets updated on each deploy
835
818
  let buildId;
836
819
  if (this.isPlaceholder) {
@@ -846,16 +829,27 @@ export class NextjsSite extends Construct {
846
829
  : this.props.waitForInvalidation === false
847
830
  ? false
848
831
  : true;
849
- return new CustomResource(this, "CloudFrontInvalidation", {
850
- serviceToken: invalidator.functionArn,
851
- resourceType: "Custom::SSTCloudFrontInvalidation",
832
+ const resource = new CustomResource(this, "CloudFrontInvalidator", {
833
+ serviceToken: stack.customResourceHandler.functionArn,
834
+ resourceType: "Custom::CloudFrontInvalidator",
852
835
  properties: {
853
- BuildId: buildId,
854
- DistributionId: this.cdk.distribution.distributionId,
855
- DistributionPaths: ["/*"],
856
- WaitForInvalidation: waitForInvalidation,
836
+ buildId,
837
+ distributionId: this.cdk.distribution.distributionId,
838
+ paths: ["/*"],
839
+ waitForInvalidation,
857
840
  },
858
841
  });
842
+ stack.customResourceHandler.role?.addToPrincipalPolicy(new PolicyStatement({
843
+ effect: Effect.ALLOW,
844
+ actions: [
845
+ "cloudfront:GetInvalidation",
846
+ "cloudfront:CreateInvalidation",
847
+ ],
848
+ resources: [
849
+ `arn:${stack.partition}:cloudfront::${stack.account}:distribution/${this.cdk.distribution.distributionId}`,
850
+ ],
851
+ }));
852
+ return resource;
859
853
  }
860
854
  /////////////////////
861
855
  // Custom Domain
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
@@ -30,6 +30,7 @@
30
30
  "@aws-cdk/cx-api": "2.62.2",
31
31
  "@aws-cdk/region-info": "2.62.2",
32
32
  "@aws-sdk/client-cloudformation": "3.208.0",
33
+ "@aws-sdk/client-cloudfront": "3.208.0",
33
34
  "@aws-sdk/client-iot": "3.208.0",
34
35
  "@aws-sdk/client-iot-data-plane": "3.208.0",
35
36
  "@aws-sdk/client-lambda": "3.208.0",