sst 2.0.0-rc.8 → 2.0.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/bootstrap.d.ts +2 -4
- package/bootstrap.js +208 -61
- package/bus.d.ts +3 -3
- package/bus.js +1 -1
- package/cache.js +1 -1
- package/cdk/cloudformation-deployments-wrapper.d.ts +3 -0
- package/cdk/cloudformation-deployments-wrapper.js +117 -0
- package/cdk/cloudformation-deployments.d.ts +19 -4
- package/cdk/deploy-stack.d.ts +17 -2
- package/cdk/deploy-stack.js +6 -1
- package/cli/colors.d.ts +28 -0
- package/cli/colors.js +27 -0
- package/cli/commands/bind.d.ts +4 -0
- package/cli/commands/bind.js +10 -7
- package/cli/commands/bootstrap.d.ts +13 -0
- package/cli/commands/bootstrap.js +11 -0
- package/cli/commands/build.d.ts +6 -2
- package/cli/commands/build.js +13 -8
- package/cli/commands/console.d.ts +5 -1
- package/cli/commands/console.js +8 -6
- package/cli/commands/deploy.d.ts +4 -2
- package/cli/commands/deploy.js +71 -29
- package/cli/commands/dev.d.ts +5 -1
- package/cli/commands/dev.js +157 -79
- package/cli/commands/diff.d.ts +15 -0
- package/cli/commands/diff.js +61 -0
- package/cli/commands/env.d.ts +5 -1
- package/cli/commands/env.js +14 -15
- package/cli/commands/plugins/kysely.js +13 -5
- package/cli/commands/plugins/pothos.js +9 -4
- package/cli/commands/remove.d.ts +4 -0
- package/cli/commands/remove.js +26 -18
- package/cli/commands/secrets/get.d.ts +7 -3
- package/cli/commands/secrets/get.js +11 -24
- package/cli/commands/secrets/list.d.ts +6 -2
- package/cli/commands/secrets/list.js +15 -7
- package/cli/commands/secrets/remove.d.ts +8 -4
- package/cli/commands/secrets/remove.js +18 -16
- package/cli/commands/secrets/secrets.js +3 -3
- package/cli/commands/secrets/set.d.ts +8 -6
- package/cli/commands/secrets/set.js +16 -33
- package/cli/commands/telemetry.d.ts +15 -0
- package/cli/commands/telemetry.js +17 -0
- package/cli/commands/transform.d.ts +15 -0
- package/cli/commands/transform.js +55 -0
- package/cli/commands/update.d.ts +6 -2
- package/cli/commands/update.js +41 -33
- package/cli/commands/version.d.ts +13 -0
- package/cli/commands/version.js +7 -0
- package/cli/local/router.d.ts +6 -6
- package/cli/local/router.js +3 -3
- package/cli/local/server.d.ts +5 -3
- package/cli/local/server.js +21 -14
- package/cli/program.d.ts +5 -1
- package/cli/program.js +29 -5
- package/cli/spinner.js +2 -0
- package/cli/sst.js +35 -23
- package/cli/telemetry/environment.d.ts +1 -1
- package/cli/telemetry/environment.js +1 -1
- package/cli/terminal.d.ts +1 -0
- package/cli/terminal.js +8 -0
- package/cli/ui/deploy.d.ts +3 -2
- package/cli/ui/deploy.js +106 -106
- package/cli/ui/functions.d.ts +2 -0
- package/cli/ui/functions.js +132 -0
- package/cli/ui/header.d.ts +5 -0
- package/cli/ui/header.js +16 -0
- package/cli/ui/stack.d.ts +1 -0
- package/cli/ui/stack.js +6 -0
- package/config.d.ts +1 -1
- package/config.js +8 -8
- package/constructs/Api.d.ts +3 -71
- package/constructs/Api.js +3 -42
- package/constructs/ApiGatewayV1Api.d.ts +3 -3
- package/constructs/ApiGatewayV1Api.js +4 -3
- package/constructs/App.d.ts +2 -22
- package/constructs/App.js +12 -25
- package/constructs/AppSyncApi.d.ts +4 -5
- package/constructs/AppSyncApi.js +8 -5
- package/constructs/AstroSite.d.ts +2 -3
- package/constructs/AstroSite.js +43 -53
- package/constructs/Auth.js +27 -16
- package/constructs/BaseSite.d.ts +10 -10
- package/constructs/BaseSite.js +2 -2
- package/constructs/Cognito.js +28 -28
- package/constructs/EdgeFunction.d.ts +6 -4
- package/constructs/EdgeFunction.js +56 -59
- package/constructs/EventBus.js +1 -1
- package/constructs/Function.d.ts +4 -44
- package/constructs/Function.js +14 -50
- package/constructs/FunctionalStack.d.ts +2 -2
- package/constructs/Job.d.ts +23 -63
- package/constructs/Job.js +11 -32
- package/constructs/Metadata.d.ts +18 -20
- package/constructs/NextjsSite.d.ts +21 -5
- package/constructs/NextjsSite.js +67 -101
- package/constructs/Queue.js +10 -10
- package/constructs/RDS.d.ts +1 -1
- package/constructs/RDS.js +1 -1
- package/constructs/RemixSite.d.ts +0 -2
- package/constructs/RemixSite.js +20 -20
- package/constructs/Script.js +1 -1
- package/constructs/Secret.js +5 -3
- package/constructs/SolidStartSite.d.ts +2 -3
- package/constructs/SolidStartSite.js +42 -52
- package/constructs/SsrFunction.d.ts +22 -0
- package/constructs/SsrFunction.js +113 -0
- package/constructs/SsrSite.d.ts +104 -104
- package/constructs/SsrSite.js +196 -217
- package/constructs/Stack.d.ts +1 -20
- package/constructs/Stack.js +3 -65
- package/constructs/StaticSite.d.ts +33 -53
- package/constructs/StaticSite.js +92 -118
- package/constructs/Table.d.ts +1 -1
- package/constructs/Table.js +4 -4
- package/constructs/Topic.js +1 -1
- package/constructs/cdk/certificate-base.d.ts +18 -0
- package/constructs/cdk/certificate-base.js +26 -0
- package/constructs/cdk/dns-validated-certificate.d.ts +77 -0
- package/constructs/cdk/dns-validated-certificate.js +125 -0
- package/constructs/cdk/website-redirect.d.ts +53 -0
- package/constructs/cdk/website-redirect.js +77 -0
- package/constructs/deferred_task.d.ts +1 -1
- package/constructs/deprecated/NextjsSite.js +8 -6
- package/constructs/index.d.ts +0 -6
- package/constructs/index.js +0 -6
- package/constructs/util/apiGatewayV1AccessLog.d.ts +1 -1
- package/constructs/util/apiGatewayV2AccessLog.js +4 -4
- package/constructs/util/apiGatewayV2Domain.js +9 -2
- package/constructs/util/appSyncApiDomain.d.ts +1 -1
- package/constructs/util/appSyncApiDomain.js +9 -15
- package/constructs/util/duration.d.ts +1 -1
- package/constructs/util/functionBinding.js +1 -1
- package/constructs/util/permission.d.ts +3 -3
- package/constructs/util/permission.js +16 -18
- package/constructs/util/size.d.ts +1 -1
- package/constructs/util/warning.js +2 -2
- package/context/context.d.ts +2 -2
- package/context/context.js +4 -4
- package/context/handler.d.ts +1 -1
- package/credentials.d.ts +1 -1
- package/credentials.js +42 -6
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/iot.js +6 -2
- package/logger.js +3 -1
- package/node/api/index.d.ts +4 -3
- package/node/api/index.js +8 -2
- package/node/auth/adapter/adapter.d.ts +1 -1
- package/node/auth/adapter/facebook.js +1 -1
- package/node/auth/adapter/github.js +4 -4
- package/node/auth/adapter/google.d.ts +1 -1
- package/node/auth/adapter/google.js +2 -2
- package/node/auth/adapter/twitch.js +1 -1
- package/node/auth/session.d.ts +1 -1
- package/node/config/index.d.ts +2 -2
- package/node/config/index.js +3 -8
- package/node/job/index.d.ts +2 -2
- package/node/site/index.js +3 -5
- package/package.json +26 -21
- package/pothos.js +1 -0
- package/project.d.ts +47 -0
- package/{app.js → project.js} +60 -53
- package/runtime/handlers/dotnet.d.ts +1 -1
- package/runtime/handlers/dotnet.js +4 -4
- package/runtime/handlers/go.d.ts +1 -1
- package/runtime/handlers/go.js +3 -3
- package/runtime/handlers/java.d.ts +1 -1
- package/runtime/handlers/java.js +4 -4
- package/runtime/handlers/node.d.ts +1 -1
- package/runtime/handlers/node.js +60 -39
- package/runtime/handlers/python.d.ts +1 -1
- package/runtime/handlers/python.js +3 -3
- package/runtime/handlers.js +15 -12
- package/runtime/iot.js +3 -0
- package/runtime/runtime.d.ts +4 -0
- package/runtime/server.d.ts +3 -3
- package/runtime/server.js +11 -5
- package/runtime/workers.d.ts +4 -2
- package/runtime/workers.js +13 -3
- package/site-env.js +2 -1
- package/sst.mjs +6357 -20846
- package/stacks/app-metadata.d.ts +7 -0
- package/stacks/app-metadata.js +78 -0
- package/stacks/assembly.d.ts +1 -0
- package/stacks/assembly.js +4 -0
- package/stacks/build.d.ts +1 -1
- package/stacks/build.js +41 -48
- package/stacks/deploy.d.ts +1 -0
- package/stacks/deploy.js +128 -7
- package/stacks/diff.d.ts +8 -0
- package/stacks/diff.js +62 -0
- package/stacks/index.d.ts +3 -0
- package/stacks/index.js +3 -0
- package/stacks/metadata.d.ts +2 -0
- package/stacks/metadata.js +14 -12
- package/stacks/monitor.d.ts +8 -3
- package/stacks/monitor.js +38 -4
- package/stacks/remove.js +0 -4
- package/stacks/synth.d.ts +1 -0
- package/stacks/synth.js +27 -13
- package/support/base-site-archiver.mjs +1 -1
- package/support/bootstrap-metadata-function/index.mjs +68740 -0
- package/support/bridge/bridge.mjs +28 -28
- package/support/certificate-requestor/index.js +549 -0
- package/support/custom-resources/index.mjs +3824 -26567
- package/support/dotnet6-bootstrap/release/dotnet-bootstrap.deps.json +1 -1
- package/support/dotnet6-bootstrap/release/dotnet-bootstrap.runtimeconfig.json +1 -1
- package/support/edge-function/edge-lambda.mjs +2 -2
- package/support/job-invoker/index.mjs +26 -0
- package/support/nodejs-runtime/index.mjs +75 -72
- package/support/rds-migrator/index.mjs +22 -23
- package/support/remix-site-function/edge-server.js +1 -1
- package/support/script-function/index.mjs +30485 -0
- package/support/{edge-function-code-replacer → sls-nextjs-site-function-code-replacer}/lambda-code-updater.py +0 -0
- package/support/ssr-site-function-archiver.mjs +96 -0
- package/util/process.d.ts +0 -1
- package/watcher.js +1 -1
- package/app.d.ts +0 -36
- package/constructs/DebugApp.d.ts +0 -49
- package/constructs/DebugApp.js +0 -63
- package/constructs/DebugStack.d.ts +0 -34
- package/constructs/DebugStack.js +0 -132
- package/constructs/GraphQLApi.d.ts +0 -98
- package/constructs/GraphQLApi.js +0 -80
- package/constructs/ReactStaticSite.d.ts +0 -20
- package/constructs/ReactStaticSite.js +0 -54
- package/constructs/Script/cfn-response.d.ts +0 -19
- package/constructs/Script/cfn-response.js +0 -77
- package/constructs/Script/index.d.ts +0 -1
- package/constructs/Script/index.js +0 -78
- package/constructs/Script/outbound.d.ts +0 -10
- package/constructs/Script/outbound.js +0 -42
- package/constructs/Script/util.d.ts +0 -2
- package/constructs/Script/util.js +0 -11
- package/constructs/ViteStaticSite.d.ts +0 -32
- package/constructs/ViteStaticSite.js +0 -66
- package/support/astro-site-html-stub/index.html +0 -99
- package/support/base-site-archiver.cjs +0 -116
- package/support/nextjs-site-html-stub/index.html +0 -99
- package/support/remix-site-html-stub/index.html +0 -99
- package/support/solid-start-site-html-stub/index.html +0 -99
- package/support/static-site-stub/index.html +0 -90
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import url from "url";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { Token, TagManager, TagType, Duration, Stack, CustomResource, Lazy, } from "aws-cdk-lib";
|
|
4
|
+
import * as iam from "aws-cdk-lib/aws-iam";
|
|
5
|
+
import * as lambda from "aws-cdk-lib/aws-lambda";
|
|
6
|
+
import { CertificateBase } from "./certificate-base.js";
|
|
7
|
+
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
8
|
+
/**
|
|
9
|
+
* A certificate managed by AWS Certificate Manager. Will be automatically
|
|
10
|
+
* validated using DNS validation against the specified Route 53 hosted zone.
|
|
11
|
+
*
|
|
12
|
+
* @resource AWS::CertificateManager::Certificate
|
|
13
|
+
*/
|
|
14
|
+
export class DnsValidatedCertificate extends CertificateBase {
|
|
15
|
+
certificateArn;
|
|
16
|
+
/**
|
|
17
|
+
* Resource Tags.
|
|
18
|
+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-certificate.html#cfn-certificatemanager-certificate-tags
|
|
19
|
+
*/
|
|
20
|
+
tags;
|
|
21
|
+
region;
|
|
22
|
+
normalizedZoneName;
|
|
23
|
+
hostedZoneId;
|
|
24
|
+
domainName;
|
|
25
|
+
_removalPolicy;
|
|
26
|
+
constructor(scope, id, props) {
|
|
27
|
+
super(scope, id);
|
|
28
|
+
this.region = props.region;
|
|
29
|
+
this.domainName = props.domainName;
|
|
30
|
+
// check if domain name is 64 characters or less
|
|
31
|
+
if (!Token.isUnresolved(props.domainName) && props.domainName.length > 64) {
|
|
32
|
+
throw new Error("Domain name must be 64 characters or less");
|
|
33
|
+
}
|
|
34
|
+
this.normalizedZoneName = props.hostedZone.zoneName;
|
|
35
|
+
// Remove trailing `.` from zone name
|
|
36
|
+
if (this.normalizedZoneName.endsWith(".")) {
|
|
37
|
+
this.normalizedZoneName = this.normalizedZoneName.substring(0, this.normalizedZoneName.length - 1);
|
|
38
|
+
}
|
|
39
|
+
// Remove any `/hostedzone/` prefix from the Hosted Zone ID
|
|
40
|
+
this.hostedZoneId = props.hostedZone.hostedZoneId.replace(/^\/hostedzone\//, "");
|
|
41
|
+
this.tags = new TagManager(TagType.MAP, "AWS::CertificateManager::Certificate");
|
|
42
|
+
let certificateTransparencyLoggingPreference;
|
|
43
|
+
if (props.transparencyLoggingEnabled !== undefined) {
|
|
44
|
+
certificateTransparencyLoggingPreference =
|
|
45
|
+
props.transparencyLoggingEnabled ? "ENABLED" : "DISABLED";
|
|
46
|
+
}
|
|
47
|
+
const requestorFunction = new lambda.Function(this, "CertificateRequestorFunction", {
|
|
48
|
+
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/certificate-requestor")),
|
|
49
|
+
handler: "index.certificateRequestHandler",
|
|
50
|
+
runtime: lambda.Runtime.NODEJS_14_X,
|
|
51
|
+
timeout: Duration.minutes(15),
|
|
52
|
+
role: props.customResourceRole,
|
|
53
|
+
});
|
|
54
|
+
requestorFunction.addToRolePolicy(new iam.PolicyStatement({
|
|
55
|
+
actions: [
|
|
56
|
+
"acm:RequestCertificate",
|
|
57
|
+
"acm:DescribeCertificate",
|
|
58
|
+
"acm:DeleteCertificate",
|
|
59
|
+
"acm:AddTagsToCertificate",
|
|
60
|
+
],
|
|
61
|
+
resources: ["*"],
|
|
62
|
+
}));
|
|
63
|
+
requestorFunction.addToRolePolicy(new iam.PolicyStatement({
|
|
64
|
+
actions: ["route53:GetChange"],
|
|
65
|
+
resources: ["*"],
|
|
66
|
+
}));
|
|
67
|
+
requestorFunction.addToRolePolicy(new iam.PolicyStatement({
|
|
68
|
+
actions: ["route53:changeResourceRecordSets"],
|
|
69
|
+
resources: [
|
|
70
|
+
`arn:${Stack.of(requestorFunction).partition}:route53:::hostedzone/${this.hostedZoneId}`,
|
|
71
|
+
],
|
|
72
|
+
conditions: {
|
|
73
|
+
"ForAllValues:StringEquals": {
|
|
74
|
+
"route53:ChangeResourceRecordSetsRecordTypes": ["CNAME"],
|
|
75
|
+
"route53:ChangeResourceRecordSetsActions": props.cleanupRoute53Records ? ["UPSERT", "DELETE"] : ["UPSERT"],
|
|
76
|
+
},
|
|
77
|
+
"ForAllValues:StringLike": {
|
|
78
|
+
"route53:ChangeResourceRecordSetsNormalizedRecordNames": [
|
|
79
|
+
addWildcard(props.domainName),
|
|
80
|
+
...(props.subjectAlternativeNames ?? []).map((d) => addWildcard(d)),
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
const certificate = new CustomResource(this, "CertificateRequestorResource", {
|
|
86
|
+
serviceToken: requestorFunction.functionArn,
|
|
87
|
+
properties: {
|
|
88
|
+
DomainName: props.domainName,
|
|
89
|
+
SubjectAlternativeNames: Lazy.list({ produce: () => props.subjectAlternativeNames }, { omitEmpty: true }),
|
|
90
|
+
CertificateTransparencyLoggingPreference: certificateTransparencyLoggingPreference,
|
|
91
|
+
HostedZoneId: this.hostedZoneId,
|
|
92
|
+
Region: props.region,
|
|
93
|
+
Route53Endpoint: props.route53Endpoint,
|
|
94
|
+
RemovalPolicy: Lazy.any({ produce: () => this._removalPolicy }),
|
|
95
|
+
// Custom resources properties are always converted to strings; might as well be explict here.
|
|
96
|
+
CleanupRecords: props.cleanupRoute53Records ? "true" : undefined,
|
|
97
|
+
Tags: Lazy.list({ produce: () => this.tags.renderTags() }),
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
this.certificateArn = certificate.getAtt("Arn").toString();
|
|
101
|
+
this.node.addValidation({
|
|
102
|
+
validate: () => this.validateDnsValidatedCertificate(),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
applyRemovalPolicy(policy) {
|
|
106
|
+
this._removalPolicy = policy;
|
|
107
|
+
}
|
|
108
|
+
validateDnsValidatedCertificate() {
|
|
109
|
+
const errors = [];
|
|
110
|
+
// Ensure the zone name is a parent zone of the certificate domain name
|
|
111
|
+
if (!Token.isUnresolved(this.normalizedZoneName) &&
|
|
112
|
+
this.domainName !== this.normalizedZoneName &&
|
|
113
|
+
!this.domainName.endsWith("." + this.normalizedZoneName)) {
|
|
114
|
+
errors.push(`DNS zone ${this.normalizedZoneName} is not authoritative for certificate domain name ${this.domainName}`);
|
|
115
|
+
}
|
|
116
|
+
return errors;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/specifying-rrset-conditions.html
|
|
120
|
+
function addWildcard(domainName) {
|
|
121
|
+
if (domainName.startsWith("*.")) {
|
|
122
|
+
return domainName;
|
|
123
|
+
}
|
|
124
|
+
return `*.${domainName}`;
|
|
125
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
|
|
2
|
+
import { IHostedZone } from "aws-cdk-lib/aws-route53";
|
|
3
|
+
import { Construct } from "constructs";
|
|
4
|
+
/**
|
|
5
|
+
* Properties to configure an HTTPS Redirect
|
|
6
|
+
*/
|
|
7
|
+
export interface HttpsRedirectProps {
|
|
8
|
+
/**
|
|
9
|
+
* Hosted zone of the domain which will be used to create alias record(s) from
|
|
10
|
+
* domain names in the hosted zone to the target domain. The hosted zone must
|
|
11
|
+
* contain entries for the domain name(s) supplied through `recordNames` that
|
|
12
|
+
* will redirect to the target domain.
|
|
13
|
+
*
|
|
14
|
+
* Domain names in the hosted zone can include a specific domain (example.com)
|
|
15
|
+
* and its subdomains (acme.example.com, zenith.example.com).
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
readonly zone: IHostedZone;
|
|
19
|
+
/**
|
|
20
|
+
* The redirect target fully qualified domain name (FQDN). An alias record
|
|
21
|
+
* will be created that points to your CloudFront distribution. Root domain
|
|
22
|
+
* or sub-domain can be supplied.
|
|
23
|
+
*/
|
|
24
|
+
readonly targetDomain: string;
|
|
25
|
+
/**
|
|
26
|
+
* The domain names that will redirect to `targetDomain`
|
|
27
|
+
*
|
|
28
|
+
* @default - the domain name of the hosted zone
|
|
29
|
+
*/
|
|
30
|
+
readonly recordNames?: string[];
|
|
31
|
+
/**
|
|
32
|
+
* The AWS Certificate Manager (ACM) certificate that will be associated with
|
|
33
|
+
* the CloudFront distribution that will be created. If provided, the certificate must be
|
|
34
|
+
* stored in us-east-1 (N. Virginia)
|
|
35
|
+
*
|
|
36
|
+
* @default - A new certificate is created in us-east-1 (N. Virginia)
|
|
37
|
+
*/
|
|
38
|
+
readonly certificate?: ICertificate;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Allows creating a domainA -> domainB redirect using CloudFront and S3.
|
|
42
|
+
* You can specify multiple domains to be redirected.
|
|
43
|
+
*/
|
|
44
|
+
export declare class HttpsRedirect extends Construct {
|
|
45
|
+
constructor(scope: Construct, id: string, props: HttpsRedirectProps);
|
|
46
|
+
/**
|
|
47
|
+
* Creates a certificate.
|
|
48
|
+
*
|
|
49
|
+
* This is also safe to upgrade since the new certificate will be created and updated
|
|
50
|
+
* on the CloudFront distribution before the old one is deleted.
|
|
51
|
+
*/
|
|
52
|
+
private createCertificate;
|
|
53
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { CloudFrontWebDistribution, OriginProtocolPolicy, PriceClass, ViewerCertificate, ViewerProtocolPolicy, } from "aws-cdk-lib/aws-cloudfront";
|
|
2
|
+
import { ARecord, AaaaRecord, RecordTarget, } from "aws-cdk-lib/aws-route53";
|
|
3
|
+
import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
|
|
4
|
+
import { BlockPublicAccess, Bucket, RedirectProtocol, } from "aws-cdk-lib/aws-s3";
|
|
5
|
+
import { ArnFormat, RemovalPolicy, Stack, Token } from "aws-cdk-lib";
|
|
6
|
+
import cdkHelpers from "aws-cdk-lib/core/lib/helpers-internal";
|
|
7
|
+
import { Construct } from "constructs";
|
|
8
|
+
import { DnsValidatedCertificate } from "./dns-validated-certificate.js";
|
|
9
|
+
const { md5hash } = cdkHelpers;
|
|
10
|
+
/**
|
|
11
|
+
* Allows creating a domainA -> domainB redirect using CloudFront and S3.
|
|
12
|
+
* You can specify multiple domains to be redirected.
|
|
13
|
+
*/
|
|
14
|
+
export class HttpsRedirect extends Construct {
|
|
15
|
+
constructor(scope, id, props) {
|
|
16
|
+
super(scope, id);
|
|
17
|
+
const domainNames = props.recordNames ?? [props.zone.zoneName];
|
|
18
|
+
if (props.certificate) {
|
|
19
|
+
const certificateRegion = Stack.of(this).splitArn(props.certificate.certificateArn, ArnFormat.SLASH_RESOURCE_NAME).region;
|
|
20
|
+
if (!Token.isUnresolved(certificateRegion) &&
|
|
21
|
+
certificateRegion !== "us-east-1") {
|
|
22
|
+
throw new Error(`The certificate must be in the us-east-1 region and the certificate you provided is in ${certificateRegion}.`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const redirectCert = props.certificate ?? this.createCertificate(domainNames, props.zone);
|
|
26
|
+
const redirectBucket = new Bucket(this, "RedirectBucket", {
|
|
27
|
+
websiteRedirect: {
|
|
28
|
+
hostName: props.targetDomain,
|
|
29
|
+
protocol: RedirectProtocol.HTTPS,
|
|
30
|
+
},
|
|
31
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
32
|
+
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
|
|
33
|
+
});
|
|
34
|
+
const redirectDist = new CloudFrontWebDistribution(this, "RedirectDistribution", {
|
|
35
|
+
defaultRootObject: "",
|
|
36
|
+
originConfigs: [
|
|
37
|
+
{
|
|
38
|
+
behaviors: [{ isDefaultBehavior: true }],
|
|
39
|
+
customOriginSource: {
|
|
40
|
+
domainName: redirectBucket.bucketWebsiteDomainName,
|
|
41
|
+
originProtocolPolicy: OriginProtocolPolicy.HTTP_ONLY,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
viewerCertificate: ViewerCertificate.fromAcmCertificate(redirectCert, {
|
|
46
|
+
aliases: domainNames,
|
|
47
|
+
}),
|
|
48
|
+
comment: `Redirect to ${props.targetDomain} from ${domainNames.join(", ")}`,
|
|
49
|
+
priceClass: PriceClass.PRICE_CLASS_ALL,
|
|
50
|
+
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
51
|
+
});
|
|
52
|
+
domainNames.forEach((domainName) => {
|
|
53
|
+
const hash = md5hash(domainName).slice(0, 6);
|
|
54
|
+
const aliasProps = {
|
|
55
|
+
recordName: domainName,
|
|
56
|
+
zone: props.zone,
|
|
57
|
+
target: RecordTarget.fromAlias(new CloudFrontTarget(redirectDist)),
|
|
58
|
+
};
|
|
59
|
+
new ARecord(this, `RedirectAliasRecord${hash}`, aliasProps);
|
|
60
|
+
new AaaaRecord(this, `RedirectAliasRecordSix${hash}`, aliasProps);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Creates a certificate.
|
|
65
|
+
*
|
|
66
|
+
* This is also safe to upgrade since the new certificate will be created and updated
|
|
67
|
+
* on the CloudFront distribution before the old one is deleted.
|
|
68
|
+
*/
|
|
69
|
+
createCertificate(domainNames, zone) {
|
|
70
|
+
return new DnsValidatedCertificate(this, "RedirectCertificate", {
|
|
71
|
+
domainName: domainNames[0],
|
|
72
|
+
subjectAlternativeNames: domainNames,
|
|
73
|
+
hostedZone: zone,
|
|
74
|
+
region: "us-east-1",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -28,7 +28,7 @@ import { ENVIRONMENT_PLACEHOLDER, getParameterPath, } from "../util/functionBind
|
|
|
28
28
|
import * as crossRegionHelper from "./cross-region-helper.js";
|
|
29
29
|
import { gray, red } from "colorette";
|
|
30
30
|
import { SiteEnv } from "../../site-env.js";
|
|
31
|
-
import { useProject } from "../../
|
|
31
|
+
import { useProject } from "../../project.js";
|
|
32
32
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
33
33
|
/////////////////////
|
|
34
34
|
// Construct
|
|
@@ -253,7 +253,7 @@ export class NextjsSite extends Construct {
|
|
|
253
253
|
},
|
|
254
254
|
permissions: {
|
|
255
255
|
"ssm:GetParameters": [
|
|
256
|
-
`arn:
|
|
256
|
+
`arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this, "url")}`,
|
|
257
257
|
],
|
|
258
258
|
},
|
|
259
259
|
};
|
|
@@ -265,7 +265,7 @@ export class NextjsSite extends Construct {
|
|
|
265
265
|
throw new Error(`No build output found at "${siteOutputPath}" for the "${this.node.id}" NextjsSite.`);
|
|
266
266
|
}
|
|
267
267
|
// create zip files
|
|
268
|
-
const script = path.join(__dirname, "../../support/base-site-archiver.
|
|
268
|
+
const script = path.join(__dirname, "../../support/base-site-archiver.mjs");
|
|
269
269
|
const zipPath = path.resolve(path.join(this.sstBuildDir, `NextjsSite-${this.node.id}-${this.node.addr}`));
|
|
270
270
|
// clear zip path to ensure no partX.zip remain from previous build
|
|
271
271
|
fs.rmSync(zipPath, {
|
|
@@ -391,7 +391,7 @@ export class NextjsSite extends Construct {
|
|
|
391
391
|
const role = new iam.Role(this, `EdgeLambdaRole`, {
|
|
392
392
|
assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal("lambda.amazonaws.com"), new iam.ServicePrincipal("edgelambda.amazonaws.com")),
|
|
393
393
|
managedPolicies: [
|
|
394
|
-
iam.ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy",
|
|
394
|
+
iam.ManagedPolicy.fromManagedPolicyArn(this, "EdgeLambdaPolicy", `arn:${Stack.of(this).partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole`),
|
|
395
395
|
],
|
|
396
396
|
});
|
|
397
397
|
// Attach permission
|
|
@@ -461,7 +461,7 @@ export class NextjsSite extends Construct {
|
|
|
461
461
|
// Create provider if not already created
|
|
462
462
|
if (!provider) {
|
|
463
463
|
provider = new lambda.Function(stack, providerId, {
|
|
464
|
-
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/
|
|
464
|
+
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/sls-nextjs-site-function-code-replacer")),
|
|
465
465
|
layers: [this.awsCliLayer],
|
|
466
466
|
runtime: lambda.Runtime.PYTHON_3_7,
|
|
467
467
|
handler: "lambda-code-updater.handler",
|
|
@@ -473,7 +473,9 @@ export class NextjsSite extends Construct {
|
|
|
473
473
|
provider.role?.addToPrincipalPolicy(new iam.PolicyStatement({
|
|
474
474
|
effect: iam.Effect.ALLOW,
|
|
475
475
|
actions: ["s3:*"],
|
|
476
|
-
resources: [
|
|
476
|
+
resources: [
|
|
477
|
+
`arn:${Stack.of(this).partition}:s3:::${asset.s3BucketName}/${asset.s3ObjectKey}`,
|
|
478
|
+
],
|
|
477
479
|
}));
|
|
478
480
|
// Create custom resource
|
|
479
481
|
const resource = new CustomResource(this, resId, {
|
package/constructs/index.d.ts
CHANGED
|
@@ -14,9 +14,7 @@ export * from "./Bucket.js";
|
|
|
14
14
|
export * from "./Script.js";
|
|
15
15
|
export * from "./EventBus.js";
|
|
16
16
|
export * from "./Function.js";
|
|
17
|
-
export * from "./GraphQLApi.js";
|
|
18
17
|
export * from "./AppSyncApi.js";
|
|
19
|
-
export * from "./DebugStack.js";
|
|
20
18
|
export * from "./WebSocketApi.js";
|
|
21
19
|
export * from "./KinesisStream.js";
|
|
22
20
|
export * from "./ApiGatewayV1Api.js";
|
|
@@ -24,13 +22,9 @@ export * from "./NextjsSite.js";
|
|
|
24
22
|
export * from "./RemixSite.js";
|
|
25
23
|
export * from "./SolidStartSite.js";
|
|
26
24
|
export * from "./StaticSite.js";
|
|
27
|
-
export * from "./ViteStaticSite.js";
|
|
28
|
-
export * from "./ReactStaticSite.js";
|
|
29
25
|
export * from "./util/size.js";
|
|
30
26
|
export * from "./util/duration.js";
|
|
31
27
|
export * from "./util/permission.js";
|
|
32
28
|
export * as Config from "./Config.js";
|
|
33
29
|
export * as Metadata from "./Metadata.js";
|
|
34
|
-
export * from "./DebugApp.js";
|
|
35
|
-
export * from "./DebugStack.js";
|
|
36
30
|
export { use, dependsOn, getStack, StackContext } from "./FunctionalStack.js";
|
package/constructs/index.js
CHANGED
|
@@ -14,9 +14,7 @@ export * from "./Bucket.js";
|
|
|
14
14
|
export * from "./Script.js";
|
|
15
15
|
export * from "./EventBus.js";
|
|
16
16
|
export * from "./Function.js";
|
|
17
|
-
export * from "./GraphQLApi.js";
|
|
18
17
|
export * from "./AppSyncApi.js";
|
|
19
|
-
export * from "./DebugStack.js";
|
|
20
18
|
export * from "./WebSocketApi.js";
|
|
21
19
|
export * from "./KinesisStream.js";
|
|
22
20
|
export * from "./ApiGatewayV1Api.js";
|
|
@@ -24,13 +22,9 @@ export * from "./NextjsSite.js";
|
|
|
24
22
|
export * from "./RemixSite.js";
|
|
25
23
|
export * from "./SolidStartSite.js";
|
|
26
24
|
export * from "./StaticSite.js";
|
|
27
|
-
export * from "./ViteStaticSite.js";
|
|
28
|
-
export * from "./ReactStaticSite.js";
|
|
29
25
|
export * from "./util/size.js";
|
|
30
26
|
export * from "./util/duration.js";
|
|
31
27
|
export * from "./util/permission.js";
|
|
32
28
|
export * as Config from "./Config.js";
|
|
33
29
|
export * as Metadata from "./Metadata.js";
|
|
34
|
-
export * from "./DebugApp.js";
|
|
35
|
-
export * from "./DebugStack.js";
|
|
36
30
|
export { use, dependsOn, getStack } from "./FunctionalStack.js";
|
|
@@ -6,7 +6,7 @@ export interface AccessLogProps {
|
|
|
6
6
|
destinationArn?: string;
|
|
7
7
|
retention?: Lowercase<keyof typeof logs.RetentionDays>;
|
|
8
8
|
}
|
|
9
|
-
export
|
|
9
|
+
export type AccessLogData = {
|
|
10
10
|
logGroup: logs.LogGroup | undefined;
|
|
11
11
|
format: apig.AccessLogFormat;
|
|
12
12
|
destination: apig.LogGroupLogDestination;
|
|
@@ -17,7 +17,7 @@ const defaultHttpFields = [
|
|
|
17
17
|
// caller info
|
|
18
18
|
`"ip":"$context.identity.sourceIp"`,
|
|
19
19
|
`"userAgent":"$context.identity.userAgent"`,
|
|
20
|
-
`"cognitoIdentityId":"$context.identity.cognitoIdentityId"
|
|
20
|
+
`"cognitoIdentityId":"$context.identity.cognitoIdentityId"`,
|
|
21
21
|
];
|
|
22
22
|
const defaultWebSocketFields = [
|
|
23
23
|
// request info
|
|
@@ -36,7 +36,7 @@ const defaultWebSocketFields = [
|
|
|
36
36
|
`"userAgent":"$context.identity.userAgent"`,
|
|
37
37
|
`"cognitoIdentityId":"$context.identity.cognitoIdentityId"`,
|
|
38
38
|
`"connectedAt":"$context.connectedAt"`,
|
|
39
|
-
`"connectionId":"$context.connectionId"
|
|
39
|
+
`"connectionId":"$context.connectionId"`,
|
|
40
40
|
];
|
|
41
41
|
export function buildAccessLogData(scope, accessLog, apiStage, isDefaultStage) {
|
|
42
42
|
if (accessLog === false) {
|
|
@@ -60,9 +60,9 @@ export function buildAccessLogData(scope, accessLog, apiStage, isDefaultStage) {
|
|
|
60
60
|
logGroupName: [
|
|
61
61
|
`/aws/vendedlogs/apis`,
|
|
62
62
|
`/${cleanupLogGroupName(apiName)}-${apiStage.api.apiId}`,
|
|
63
|
-
`/${cleanupLogGroupName(apiStage.stageName)}
|
|
63
|
+
`/${cleanupLogGroupName(apiStage.stageName)}`,
|
|
64
64
|
].join(""),
|
|
65
|
-
retention: buildLogGroupRetention(accessLog)
|
|
65
|
+
retention: buildLogGroupRetention(accessLog),
|
|
66
66
|
});
|
|
67
67
|
destinationArn = logGroup.logGroupArn;
|
|
68
68
|
}
|
|
@@ -32,7 +32,7 @@ function buildDataForStringInput(scope, customDomain) {
|
|
|
32
32
|
}
|
|
33
33
|
assertDomainNameIsLowerCase(customDomain);
|
|
34
34
|
const domainName = customDomain;
|
|
35
|
-
const hostedZoneDomain = domainName
|
|
35
|
+
const hostedZoneDomain = parseRoute53Domain(domainName);
|
|
36
36
|
const hostedZone = lookupHostedZone(scope, hostedZoneDomain);
|
|
37
37
|
const certificate = createCertificate(scope, domainName, hostedZone);
|
|
38
38
|
const apigDomain = createApigDomain(scope, domainName, certificate);
|
|
@@ -71,7 +71,7 @@ function buildDataForInternalDomainInput(scope, customDomain) {
|
|
|
71
71
|
hostedZone = customDomain.cdk.hostedZone;
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
74
|
-
const hostedZoneDomain = domainName
|
|
74
|
+
const hostedZoneDomain = parseRoute53Domain(domainName);
|
|
75
75
|
hostedZone = lookupHostedZone(scope, hostedZoneDomain);
|
|
76
76
|
}
|
|
77
77
|
// Create certificate
|
|
@@ -199,3 +199,10 @@ function assertDomainNameIsLowerCase(domainName) {
|
|
|
199
199
|
throw new Error(`The domain name needs to be in lowercase`);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
+
function parseRoute53Domain(domainName) {
|
|
203
|
+
const parts = domainName.split(".");
|
|
204
|
+
// If the domain contains subdomain, ie. api.example.com,
|
|
205
|
+
// strip the subdomain and use the root domain, ie. example.com.
|
|
206
|
+
// Otherwise, use the domain as is.
|
|
207
|
+
return parts.length <= 2 ? domainName : parts.slice(1).join(".");
|
|
208
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as route53 from "aws-cdk-lib/aws-route53";
|
|
2
|
-
import * as appsync from "
|
|
2
|
+
import * as appsync from "aws-cdk-lib/aws-appsync";
|
|
3
3
|
import * as acm from "aws-cdk-lib/aws-certificatemanager";
|
|
4
4
|
import { AppSyncApi } from "../AppSyncApi.js";
|
|
5
5
|
export interface CustomDomainProps {
|
|
@@ -26,16 +26,13 @@ function buildDataForStringInput(scope, customDomain) {
|
|
|
26
26
|
}
|
|
27
27
|
assertDomainNameIsLowerCase(customDomain);
|
|
28
28
|
const domainName = customDomain;
|
|
29
|
-
const hostedZoneDomain = domainName
|
|
30
|
-
.split(".")
|
|
31
|
-
.slice(1)
|
|
32
|
-
.join(".");
|
|
29
|
+
const hostedZoneDomain = domainName.split(".").slice(1).join(".");
|
|
33
30
|
const hostedZone = lookupHostedZone(scope, hostedZoneDomain);
|
|
34
31
|
const certificate = createCertificate(scope, domainName, hostedZone);
|
|
35
32
|
createRecord(scope, hostedZone, domainName);
|
|
36
33
|
return {
|
|
37
34
|
certificate,
|
|
38
|
-
domainName
|
|
35
|
+
domainName,
|
|
39
36
|
};
|
|
40
37
|
}
|
|
41
38
|
function buildDataForInternalDomainInput(scope, customDomain) {
|
|
@@ -63,10 +60,7 @@ function buildDataForInternalDomainInput(scope, customDomain) {
|
|
|
63
60
|
hostedZone = customDomain.cdk.hostedZone;
|
|
64
61
|
}
|
|
65
62
|
else {
|
|
66
|
-
const hostedZoneDomain = domainName
|
|
67
|
-
.split(".")
|
|
68
|
-
.slice(1)
|
|
69
|
-
.join(".");
|
|
63
|
+
const hostedZoneDomain = domainName.split(".").slice(1).join(".");
|
|
70
64
|
hostedZone = lookupHostedZone(scope, hostedZoneDomain);
|
|
71
65
|
}
|
|
72
66
|
// Create certificate
|
|
@@ -78,7 +72,7 @@ function buildDataForInternalDomainInput(scope, customDomain) {
|
|
|
78
72
|
createRecord(scope, hostedZone, domainName);
|
|
79
73
|
return {
|
|
80
74
|
certificate,
|
|
81
|
-
domainName
|
|
75
|
+
domainName,
|
|
82
76
|
};
|
|
83
77
|
}
|
|
84
78
|
function buildDataForExternalDomainInput(scope, customDomain) {
|
|
@@ -95,18 +89,18 @@ function buildDataForExternalDomainInput(scope, customDomain) {
|
|
|
95
89
|
const certificate = customDomain.cdk.certificate;
|
|
96
90
|
return {
|
|
97
91
|
certificate,
|
|
98
|
-
domainName
|
|
92
|
+
domainName,
|
|
99
93
|
};
|
|
100
94
|
}
|
|
101
95
|
function lookupHostedZone(scope, hostedZoneDomain) {
|
|
102
96
|
return route53.HostedZone.fromLookup(scope, "HostedZone", {
|
|
103
|
-
domainName: hostedZoneDomain
|
|
97
|
+
domainName: hostedZoneDomain,
|
|
104
98
|
});
|
|
105
99
|
}
|
|
106
100
|
function createCertificate(scope, domainName, hostedZone) {
|
|
107
101
|
return new acm.Certificate(scope, "Certificate", {
|
|
108
102
|
domainName,
|
|
109
|
-
validation: acm.CertificateValidation.fromDns(hostedZone)
|
|
103
|
+
validation: acm.CertificateValidation.fromDns(hostedZone),
|
|
110
104
|
});
|
|
111
105
|
}
|
|
112
106
|
function createRecord(scope, hostedZone, domainName) {
|
|
@@ -117,8 +111,8 @@ function createRecord(scope, hostedZone, domainName) {
|
|
|
117
111
|
domainName: Lazy.string({
|
|
118
112
|
produce() {
|
|
119
113
|
return scope._cfnDomainName.attrAppSyncDomainName;
|
|
120
|
-
}
|
|
121
|
-
})
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
122
116
|
});
|
|
123
117
|
// note: If domainName is a TOKEN string ie. ${TOKEN..}, the route53.ARecord
|
|
124
118
|
// construct will append ".${hostedZoneName}" to the end of the domain.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { Duration as CDKDuration } from "aws-cdk-lib";
|
|
2
|
-
export
|
|
2
|
+
export type Duration = `${number} ${"second" | "seconds" | "minute" | "minutes" | "hour" | "hours" | "day" | "days"}`;
|
|
3
3
|
export declare function toCdkDuration(duration: Duration): CDKDuration;
|
|
@@ -19,7 +19,7 @@ export function bindParameters(c) {
|
|
|
19
19
|
}
|
|
20
20
|
const app = c.node.root;
|
|
21
21
|
Object.entries(binding.variables)
|
|
22
|
-
.filter(([, variable]) => variable.parameter)
|
|
22
|
+
.filter(([, variable]) => variable.parameter !== undefined)
|
|
23
23
|
.forEach(([prop, variable]) => {
|
|
24
24
|
const resId = `Parameter_${prop}`;
|
|
25
25
|
if (!c.node.tryFindChild(resId)) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { IConstruct } from "constructs";
|
|
2
2
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export type Permissions = "*" | Permission[];
|
|
4
|
+
type SupportedPermissions = "execute-api" | "appsync" | "dynamodb" | "sns" | "sqs" | "events" | "kinesis" | "s3" | "rds-data" | "secretsmanager" | "lambda" | "ssm";
|
|
5
|
+
type Permission = SupportedPermissions | Omit<string, SupportedPermissions> | IConstruct | [IConstruct, string] | iam.PolicyStatement;
|
|
6
6
|
export declare function attachPermissionsToRole(role: iam.Role, permissions: Permissions): void;
|
|
7
7
|
export declare function attachPermissionsToPolicy(policy: iam.Policy, permissions: Permissions): void;
|
|
8
8
|
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/ban-ts-comment*/
|
|
2
2
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
3
3
|
import { isCDKConstruct, isCDKConstructOf } from "../Construct.js";
|
|
4
|
-
import { Logger } from "../../logger.js";
|
|
5
4
|
import { Api } from "../Api.js";
|
|
6
5
|
import { ApiGatewayV1Api } from "../ApiGatewayV1Api.js";
|
|
7
6
|
import { Stack } from "../Stack.js";
|
|
@@ -18,8 +17,8 @@ import { RDS } from "../RDS.js";
|
|
|
18
17
|
import { Job } from "../Job.js";
|
|
19
18
|
export function attachPermissionsToRole(role, permissions) {
|
|
20
19
|
const { statements, grants } = permissionsToStatementsAndGrants(permissions);
|
|
21
|
-
statements.forEach(statement => role.addToPolicy(statement));
|
|
22
|
-
grants.forEach(grant => {
|
|
20
|
+
statements.forEach((statement) => role.addToPolicy(statement));
|
|
21
|
+
grants.forEach((grant) => {
|
|
23
22
|
const construct = grant[0];
|
|
24
23
|
const methodName = grant[1];
|
|
25
24
|
construct[methodName](role);
|
|
@@ -27,8 +26,8 @@ export function attachPermissionsToRole(role, permissions) {
|
|
|
27
26
|
}
|
|
28
27
|
export function attachPermissionsToPolicy(policy, permissions) {
|
|
29
28
|
const { statements, grants } = permissionsToStatementsAndGrants(permissions);
|
|
30
|
-
statements.forEach(statement => policy.addStatements(statement));
|
|
31
|
-
grants.forEach(grant => {
|
|
29
|
+
statements.forEach((statement) => policy.addStatements(statement));
|
|
30
|
+
grants.forEach((grant) => {
|
|
32
31
|
throw new Error(`Cannot attach the "${grant[1]}" permission to an IAM policy.`);
|
|
33
32
|
});
|
|
34
33
|
}
|
|
@@ -57,7 +56,7 @@ function permissionsToStatementsAndGrants(permissions) {
|
|
|
57
56
|
if (permissions === "*") {
|
|
58
57
|
return {
|
|
59
58
|
statements: [buildPolicyStatement(permissions, ["*"])],
|
|
60
|
-
grants: []
|
|
59
|
+
grants: [],
|
|
61
60
|
};
|
|
62
61
|
}
|
|
63
62
|
if (!Array.isArray(permissions)) {
|
|
@@ -85,33 +84,33 @@ function permissionsToStatementsAndGrants(permissions) {
|
|
|
85
84
|
////////////////////////////////////
|
|
86
85
|
else if (permission instanceof Api) {
|
|
87
86
|
const httpApi = permission.cdk.httpApi;
|
|
88
|
-
const { account, region } = Stack.of(httpApi);
|
|
87
|
+
const { account, region, partition } = Stack.of(httpApi);
|
|
89
88
|
statements.push(buildPolicyStatement("execute-api:Invoke", [
|
|
90
|
-
`arn:
|
|
89
|
+
`arn:${partition}:execute-api:${region}:${account}:${httpApi.httpApiId}/*`,
|
|
91
90
|
]));
|
|
92
91
|
}
|
|
93
92
|
else if (permission instanceof ApiGatewayV1Api) {
|
|
94
93
|
const restApi = permission.cdk.restApi;
|
|
95
|
-
const { account, region } = Stack.of(restApi);
|
|
94
|
+
const { account, region, partition } = Stack.of(restApi);
|
|
96
95
|
statements.push(buildPolicyStatement("execute-api:Invoke", [
|
|
97
|
-
`arn:
|
|
96
|
+
`arn:${partition}:execute-api:${region}:${account}:${restApi.restApiId}/*`,
|
|
98
97
|
]));
|
|
99
98
|
}
|
|
100
99
|
else if (permission instanceof WebSocketApi) {
|
|
101
100
|
const webSocketApi = permission.cdk.webSocketApi;
|
|
102
|
-
const { account, region } = Stack.of(webSocketApi);
|
|
101
|
+
const { account, region, partition } = Stack.of(webSocketApi);
|
|
103
102
|
statements.push(buildPolicyStatement("execute-api:Invoke", [
|
|
104
|
-
`arn:
|
|
103
|
+
`arn:${partition}:execute-api:${region}:${account}:${webSocketApi.apiId}/*`,
|
|
105
104
|
]));
|
|
106
105
|
statements.push(buildPolicyStatement("execute-api:ManageConnections", [
|
|
107
|
-
permission._connectionsArn
|
|
106
|
+
permission._connectionsArn,
|
|
108
107
|
]));
|
|
109
108
|
}
|
|
110
109
|
else if (permission instanceof AppSyncApi) {
|
|
111
110
|
const graphqlApi = permission.cdk.graphqlApi;
|
|
112
|
-
const { account, region } = Stack.of(graphqlApi);
|
|
111
|
+
const { account, region, partition } = Stack.of(graphqlApi);
|
|
113
112
|
statements.push(buildPolicyStatement("appsync:GraphQL", [
|
|
114
|
-
`arn:
|
|
113
|
+
`arn:${partition}:appsync:${region}:${account}:apis/${graphqlApi.apiId}/*`,
|
|
115
114
|
]));
|
|
116
115
|
}
|
|
117
116
|
else if (permission instanceof Table) {
|
|
@@ -177,7 +176,7 @@ function permissionsToStatementsAndGrants(permissions) {
|
|
|
177
176
|
else if (permission.deliveryStreamArn &&
|
|
178
177
|
permission.deliveryStreamName) {
|
|
179
178
|
statements.push(buildPolicyStatement("firehose:*", [
|
|
180
|
-
permission.deliveryStreamArn
|
|
179
|
+
permission.deliveryStreamArn,
|
|
181
180
|
]));
|
|
182
181
|
}
|
|
183
182
|
else if (permission.bucketArn &&
|
|
@@ -212,7 +211,6 @@ function permissionsToStatementsAndGrants(permissions) {
|
|
|
212
211
|
grants.push(permission);
|
|
213
212
|
}
|
|
214
213
|
else {
|
|
215
|
-
Logger.debug("permission object", permission);
|
|
216
214
|
throw new Error(`The specified permissions are not supported.`);
|
|
217
215
|
}
|
|
218
216
|
});
|
|
@@ -222,6 +220,6 @@ function buildPolicyStatement(actions, resources) {
|
|
|
222
220
|
return new iam.PolicyStatement({
|
|
223
221
|
effect: iam.Effect.ALLOW,
|
|
224
222
|
actions: typeof actions === "string" ? [actions] : actions,
|
|
225
|
-
resources
|
|
223
|
+
resources,
|
|
226
224
|
});
|
|
227
225
|
}
|