@webiny/pulumi-aws 0.0.0-ee-vpcs.549378cf03
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/LICENSE +21 -0
- package/README.md +328 -0
- package/apps/admin/createAdminPulumiApp.d.ts +24 -0
- package/apps/admin/createAdminPulumiApp.js +21 -0
- package/apps/admin/createAdminPulumiApp.js.map +1 -0
- package/apps/admin/index.d.ts +1 -0
- package/apps/admin/index.js +18 -0
- package/apps/admin/index.js.map +1 -0
- package/apps/api/ApiApwScheduler.d.ts +20 -0
- package/apps/api/ApiApwScheduler.js +246 -0
- package/apps/api/ApiApwScheduler.js.map +1 -0
- package/apps/api/ApiCloudfront.d.ts +3 -0
- package/apps/api/ApiCloudfront.js +101 -0
- package/apps/api/ApiCloudfront.js.map +1 -0
- package/apps/api/ApiFileManager.d.ts +10 -0
- package/apps/api/ApiFileManager.js +166 -0
- package/apps/api/ApiFileManager.js.map +1 -0
- package/apps/api/ApiGateway.d.ts +18 -0
- package/apps/api/ApiGateway.js +88 -0
- package/apps/api/ApiGateway.js.map +1 -0
- package/apps/api/ApiGraphql.d.ts +26 -0
- package/apps/api/ApiGraphql.js +167 -0
- package/apps/api/ApiGraphql.js.map +1 -0
- package/apps/api/ApiHeadlessCMS.d.ts +13 -0
- package/apps/api/ApiHeadlessCMS.js +94 -0
- package/apps/api/ApiHeadlessCMS.js.map +1 -0
- package/apps/api/ApiOutput.d.ts +15 -0
- package/apps/api/ApiOutput.js +43 -0
- package/apps/api/ApiOutput.js.map +1 -0
- package/apps/api/ApiPageBuilder.d.ts +24 -0
- package/apps/api/ApiPageBuilder.js +248 -0
- package/apps/api/ApiPageBuilder.js.map +1 -0
- package/apps/api/createApiPulumiApp.d.ts +71 -0
- package/apps/api/createApiPulumiApp.js +188 -0
- package/apps/api/createApiPulumiApp.js.map +1 -0
- package/apps/api/index.d.ts +9 -0
- package/apps/api/index.js +122 -0
- package/apps/api/index.js.map +1 -0
- package/apps/awsUtils.d.ts +3 -0
- package/apps/awsUtils.js +23 -0
- package/apps/awsUtils.js.map +1 -0
- package/apps/common/CoreOutput.d.ts +21 -0
- package/apps/common/CoreOutput.js +50 -0
- package/apps/common/CoreOutput.js.map +1 -0
- package/apps/common/VpcConfig.d.ts +8 -0
- package/apps/common/VpcConfig.js +37 -0
- package/apps/common/VpcConfig.js.map +1 -0
- package/apps/common/index.d.ts +2 -0
- package/apps/common/index.js +31 -0
- package/apps/common/index.js.map +1 -0
- package/apps/core/CoreCognito.d.ts +10 -0
- package/apps/core/CoreCognito.js +100 -0
- package/apps/core/CoreCognito.js.map +1 -0
- package/apps/core/CoreDynamo.d.ts +5 -0
- package/apps/core/CoreDynamo.js +51 -0
- package/apps/core/CoreDynamo.js.map +1 -0
- package/apps/core/CoreElasticSearch.d.ts +16 -0
- package/apps/core/CoreElasticSearch.js +286 -0
- package/apps/core/CoreElasticSearch.js.map +1 -0
- package/apps/core/CoreEventBus.d.ts +1 -0
- package/apps/core/CoreEventBus.js +25 -0
- package/apps/core/CoreEventBus.js.map +1 -0
- package/apps/core/CoreFileManager.d.ts +8 -0
- package/apps/core/CoreFileManager.js +55 -0
- package/apps/core/CoreFileManager.js.map +1 -0
- package/apps/core/CoreVpc.d.ts +13 -0
- package/apps/core/CoreVpc.js +148 -0
- package/apps/core/CoreVpc.js.map +1 -0
- package/apps/core/createCorePulumiApp.d.ts +64 -0
- package/apps/core/createCorePulumiApp.js +104 -0
- package/apps/core/createCorePulumiApp.js.map +1 -0
- package/apps/core/index.d.ts +6 -0
- package/apps/core/index.js +83 -0
- package/apps/core/index.js.map +1 -0
- package/apps/createAppBucket.d.ts +13 -0
- package/apps/createAppBucket.js +106 -0
- package/apps/createAppBucket.js.map +1 -0
- package/apps/customDomain.d.ts +9 -0
- package/apps/customDomain.js +14 -0
- package/apps/customDomain.js.map +1 -0
- package/apps/index.d.ts +7 -0
- package/apps/index.js +100 -0
- package/apps/index.js.map +1 -0
- package/apps/lambdaUtils.d.ts +10 -0
- package/apps/lambdaUtils.js +82 -0
- package/apps/lambdaUtils.js.map +1 -0
- package/apps/react/createReactPulumiApp.d.ts +33 -0
- package/apps/react/createReactPulumiApp.js +144 -0
- package/apps/react/createReactPulumiApp.js.map +1 -0
- package/apps/react/index.d.ts +1 -0
- package/apps/react/index.js +18 -0
- package/apps/react/index.js.map +1 -0
- package/apps/tenantRouter.d.ts +3 -0
- package/apps/tenantRouter.js +115 -0
- package/apps/tenantRouter.js.map +1 -0
- package/apps/website/WebsitePrerendering.d.ts +39 -0
- package/apps/website/WebsitePrerendering.js +300 -0
- package/apps/website/WebsitePrerendering.js.map +1 -0
- package/apps/website/createWebsitePulumiApp.d.ts +74 -0
- package/apps/website/createWebsitePulumiApp.js +246 -0
- package/apps/website/createWebsitePulumiApp.js.map +1 -0
- package/apps/website/deliveryViewerRequest.d.ts +2 -0
- package/apps/website/deliveryViewerRequest.js +32 -0
- package/apps/website/deliveryViewerRequest.js.map +1 -0
- package/apps/website/index.d.ts +1 -0
- package/apps/website/index.js +18 -0
- package/apps/website/index.js.map +1 -0
- package/components/tenantRouter/WebsiteTenantRouter.d.ts +11 -0
- package/components/tenantRouter/WebsiteTenantRouter.js +98 -0
- package/components/tenantRouter/WebsiteTenantRouter.js.map +1 -0
- package/components/tenantRouter/functions/origin/request.d.ts +1 -0
- package/components/tenantRouter/functions/origin/request.js +129 -0
- package/components/tenantRouter/functions/origin/request.js.map +1 -0
- package/enterprise/createAdminPulumiApp.d.ts +1 -0
- package/enterprise/createAdminPulumiApp.js +25 -0
- package/enterprise/createAdminPulumiApp.js.map +1 -0
- package/enterprise/createApiPulumiApp.d.ts +61 -0
- package/enterprise/createApiPulumiApp.js +68 -0
- package/enterprise/createApiPulumiApp.js.map +1 -0
- package/enterprise/createCorePulumiApp.d.ts +42 -0
- package/enterprise/createCorePulumiApp.js +137 -0
- package/enterprise/createCorePulumiApp.js.map +1 -0
- package/enterprise/createWebsitePulumiApp.d.ts +56 -0
- package/enterprise/createWebsitePulumiApp.js +68 -0
- package/enterprise/createWebsitePulumiApp.js.map +1 -0
- package/enterprise/index.d.ts +4 -0
- package/enterprise/index.js +57 -0
- package/enterprise/index.js.map +1 -0
- package/index.d.ts +3 -0
- package/index.js +44 -0
- package/index.js.map +1 -0
- package/package.json +53 -0
- package/utils/crawlDirectory.d.ts +1 -0
- package/utils/crawlDirectory.js +33 -0
- package/utils/crawlDirectory.js.map +1 -0
- package/utils/getPresignedPost.d.ts +11 -0
- package/utils/getPresignedPost.js +46 -0
- package/utils/getPresignedPost.js.map +1 -0
- package/utils/index.d.ts +3 -0
- package/utils/index.js +51 -0
- package/utils/index.js.map +1 -0
- package/utils/lambdaEnvVariables.d.ts +20 -0
- package/utils/lambdaEnvVariables.js +78 -0
- package/utils/lambdaEnvVariables.js.map +1 -0
- package/utils/storageMigrate.d.ts +0 -0
- package/utils/storageMigrate.js +292 -0
- package/utils/storageMigrate.js.map +1 -0
- package/utils/tagResources.d.ts +5 -0
- package/utils/tagResources.js +43 -0
- package/utils/tagResources.js.map +1 -0
- package/utils/uploadFolderToS3.d.ts +26 -0
- package/utils/uploadFolderToS3.js +188 -0
- package/utils/uploadFolderToS3.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createWebsitePulumiApp","projectAppParams","app","createPulumiApp","name","path","config","program","pulumiResourceNamePrefix","getParam","onResource","resource","startsWith","pulumi","addHandler","prod","params","run","env","core","addModule","CoreOutput","vpcEnabled","vpc","VpcConfig","enabled","appBucket","createPrivateAppBucket","appCloudfront","addResource","aws","cloudfront","Distribution","waitForDeployment","origins","origin","defaultRootObject","defaultCacheBehavior","compress","targetOriginId","originId","viewerProtocolPolicy","allowedMethods","cachedMethods","forwardedValues","cookies","forward","queryString","minTtl","defaultTtl","maxTtl","priceClass","customErrorResponses","errorCode","responseCode","responsePagePath","restrictions","geoRestriction","restrictionType","viewerCertificate","cloudfrontDefaultCertificate","deliveryBucket","viewerRequest","Function","runtime","publish","code","fs","readFileSync","__dirname","deliveryCloudfront","originRequestPolicyId","functionAssociations","functionArn","output","arn","eventType","orderedCacheBehaviors","headers","pathPattern","prerendering","createPrerenderingService","dbTableName","primaryDynamodbTableName","dbTableHashKey","primaryDynamodbTableHashKey","dbTableRangeKey","primaryDynamodbTableRangeKey","appUrl","interpolate","domainName","deliveryUrl","bucket","cloudfrontId","id","domains","applyCustomDomain","previewDomains","process","WCP_PROJECT_ENVIRONMENT","WEBINY_MULTI_TENANCY","applyTenantRouter","addOutputs","appId","appStorage","apply","value","appDomain","deliveryId","deliveryStorage","deliveryDomain","tagResources","WbyProjectName","String","WbyEnvironment","delivery","withCommonLambdaEnvVariables"],"sources":["createWebsitePulumiApp.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport * as aws from \"@pulumi/aws\";\nimport fs from \"fs\";\nimport { createPulumiApp, PulumiAppParamCallback, PulumiAppParam } from \"@webiny/pulumi\";\nimport { createPrivateAppBucket } from \"../createAppBucket\";\nimport { applyCustomDomain, CustomDomainParams } from \"../customDomain\";\nimport { createPrerenderingService } from \"./WebsitePrerendering\";\nimport { CoreOutput, VpcConfig } from \"~/apps\";\nimport { tagResources, withCommonLambdaEnvVariables } from \"~/utils\";\nimport { applyTenantRouter } from \"~/apps/tenantRouter\";\n\nexport type WebsitePulumiApp = ReturnType<typeof createWebsitePulumiApp>;\n\nexport interface CreateWebsitePulumiAppParams {\n /**\n * Custom domain(s) configuration.\n */\n domains?: PulumiAppParamCallback<CustomDomainParams>;\n\n /**\n * Custom preview domain(s) configuration.\n */\n previewDomains?: PulumiAppParamCallback<CustomDomainParams>;\n\n /**\n * Enables or disables VPC for the API.\n * For VPC to work you also have to enable it in the `core` application.\n */\n vpc?: PulumiAppParam<boolean | undefined>;\n\n /**\n * Provides a way to adjust existing Pulumi code (cloud infrastructure resources)\n * or add additional ones into the mix.\n */\n pulumi?: (app: WebsitePulumiApp) => void | Promise<void>;\n\n /**\n * Prefixes names of all Pulumi cloud infrastructure resource with given prefix.\n */\n pulumiResourceNamePrefix?: PulumiAppParam<string>;\n}\n\nexport const createWebsitePulumiApp = (projectAppParams: CreateWebsitePulumiAppParams = {}) => {\n const app = createPulumiApp({\n name: \"website\",\n path: \"apps/website\",\n config: projectAppParams,\n program: async app => {\n const pulumiResourceNamePrefix = app.getParam(\n projectAppParams.pulumiResourceNamePrefix\n );\n if (pulumiResourceNamePrefix) {\n app.onResource(resource => {\n if (!resource.name.startsWith(pulumiResourceNamePrefix)) {\n resource.name = `${pulumiResourceNamePrefix}${resource.name}`;\n }\n });\n }\n\n // Overrides must be applied via a handler, registered at the very start of the program.\n // By doing this, we're ensuring user's adjustments are not applied to late.\n if (projectAppParams.pulumi) {\n app.addHandler(() => {\n return projectAppParams.pulumi!(app as WebsitePulumiApp);\n });\n }\n\n const prod = app.params.run.env === \"prod\";\n\n // Register core output as a module available for all other modules\n const core = app.addModule(CoreOutput);\n\n // Register VPC config module to be available to other modules.\n const vpcEnabled = app.getParam(projectAppParams?.vpc) ?? prod;\n app.addModule(VpcConfig, { enabled: vpcEnabled });\n\n const appBucket = createPrivateAppBucket(app, \"app\");\n\n const appCloudfront = app.addResource(aws.cloudfront.Distribution, {\n name: \"app\",\n config: {\n enabled: true,\n waitForDeployment: true,\n origins: [appBucket.origin],\n defaultRootObject: \"index.html\",\n defaultCacheBehavior: {\n compress: true,\n targetOriginId: appBucket.origin.originId,\n viewerProtocolPolicy: \"redirect-to-https\",\n allowedMethods: [\"GET\", \"HEAD\", \"OPTIONS\"],\n cachedMethods: [\"GET\", \"HEAD\", \"OPTIONS\"],\n forwardedValues: {\n cookies: { forward: \"none\" },\n queryString: false\n },\n // MinTTL <= DefaultTTL <= MaxTTL\n minTtl: 0,\n defaultTtl: 0,\n maxTtl: 0\n },\n priceClass: \"PriceClass_100\",\n customErrorResponses: [\n { errorCode: 404, responseCode: 404, responsePagePath: \"/index.html\" }\n ],\n restrictions: {\n geoRestriction: {\n restrictionType: \"none\"\n }\n },\n viewerCertificate: {\n cloudfrontDefaultCertificate: true\n }\n }\n });\n\n const deliveryBucket = createPrivateAppBucket(app, \"delivery\");\n\n /**\n * We need to have a Cloudfront Function to perform a simple request rewrite, so the request always includes\n * an \"/index.html\". This is necessary because our buckets are not \"website\" buckets, and we need to\n * have an exact object key when requesting page paths.\n */\n const viewerRequest = app.addResource(aws.cloudfront.Function, {\n name: \"cfViewerRequest\",\n config: {\n runtime: \"cloudfront-js-1.0\",\n publish: true,\n code: fs.readFileSync(__dirname + `/deliveryViewerRequest.js`, \"utf8\")\n }\n });\n\n const deliveryCloudfront = app.addResource(aws.cloudfront.Distribution, {\n name: \"delivery\",\n config: {\n enabled: true,\n waitForDeployment: true,\n origins: [deliveryBucket.origin, appBucket.origin],\n defaultRootObject: \"index.html\",\n defaultCacheBehavior: {\n compress: true,\n targetOriginId: deliveryBucket.origin.originId,\n viewerProtocolPolicy: \"redirect-to-https\",\n allowedMethods: [\"GET\", \"HEAD\", \"OPTIONS\"],\n cachedMethods: [\"GET\", \"HEAD\", \"OPTIONS\"],\n originRequestPolicyId: \"\",\n forwardedValues: {\n cookies: { forward: \"none\" },\n queryString: true\n },\n // MinTTL <= DefaultTTL <= MaxTTL\n minTtl: 0,\n defaultTtl: 30,\n maxTtl: 30,\n functionAssociations: [\n { functionArn: viewerRequest.output.arn, eventType: \"viewer-request\" }\n ]\n },\n orderedCacheBehaviors: [\n {\n compress: true,\n allowedMethods: [\"GET\", \"HEAD\", \"OPTIONS\"],\n cachedMethods: [\"GET\", \"HEAD\", \"OPTIONS\"],\n forwardedValues: {\n cookies: {\n forward: \"none\"\n },\n headers: [],\n queryString: false\n },\n pathPattern: \"/static/*\",\n viewerProtocolPolicy: \"allow-all\",\n targetOriginId: appBucket.origin.originId,\n // MinTTL <= DefaultTTL <= MaxTTL\n minTtl: 0,\n defaultTtl: 2592000, // 30 days\n maxTtl: 2592000\n }\n ],\n customErrorResponses: [\n {\n errorCode: 404,\n responseCode: 404,\n responsePagePath: \"/_NOT_FOUND_PAGE_/index.html\"\n }\n ],\n priceClass: \"PriceClass_100\",\n restrictions: {\n geoRestriction: {\n restrictionType: \"none\"\n }\n },\n viewerCertificate: {\n cloudfrontDefaultCertificate: true\n }\n }\n });\n\n const prerendering = createPrerenderingService(app, {\n dbTableName: core.primaryDynamodbTableName,\n dbTableHashKey: core.primaryDynamodbTableHashKey,\n dbTableRangeKey: core.primaryDynamodbTableRangeKey,\n appUrl: pulumi.interpolate`https://${appCloudfront.output.domainName}`,\n deliveryUrl: pulumi.interpolate`https://${deliveryCloudfront.output.domainName}`,\n bucket: deliveryBucket.bucket.output.bucket,\n cloudfrontId: deliveryCloudfront.output.id\n });\n\n const domains = app.getParam(projectAppParams.domains);\n if (domains) {\n applyCustomDomain(deliveryCloudfront, domains);\n }\n\n const previewDomains = app.getParam(projectAppParams.previewDomains);\n if (previewDomains) {\n applyCustomDomain(appCloudfront, previewDomains);\n }\n\n if (\n process.env.WCP_PROJECT_ENVIRONMENT ||\n process.env.WEBINY_MULTI_TENANCY === \"true\"\n ) {\n applyTenantRouter(app, deliveryCloudfront);\n }\n\n app.addOutputs({\n // Cloudfront and S3 bucket used to host the single-page application (SPA). The URL of the distribution is mainly\n // utilized by the Page Builder app's prerendering engine. Using this URL, it accesses the SPA and creates HTML snapshots.\n // The files that are generated in that process are stored in the `deliveryStorage` S3 bucket further below.\n appId: appCloudfront.output.id,\n appStorage: appBucket.bucket.output.id,\n appUrl: appCloudfront.output.domainName.apply(value => `https://${value}`),\n appDomain: appCloudfront.output.domainName,\n // These are the Cloudfront and S3 bucket that will deliver static pages to the actual website visitors.\n // The static HTML snapshots delivered from them still rely on the app's S3 bucket\n // defined above, for serving static assets (JS, CSS, images).\n deliveryId: deliveryCloudfront.output.id,\n deliveryStorage: deliveryBucket.bucket.output.id,\n deliveryDomain: deliveryCloudfront.output.domainName,\n deliveryUrl: deliveryCloudfront.output.domainName.apply(value => `https://${value}`)\n });\n\n tagResources({\n WbyProjectName: String(process.env[\"WEBINY_PROJECT_NAME\"]),\n WbyEnvironment: String(process.env[\"WEBINY_ENV\"])\n });\n\n return {\n prerendering,\n app: {\n ...appBucket,\n cloudfront: appCloudfront\n },\n delivery: {\n ...deliveryBucket,\n cloudfront: deliveryCloudfront\n }\n };\n }\n });\n\n return withCommonLambdaEnvVariables(app);\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function sanitizeRequestURI(uri) {
|
|
4
|
+
// Make sure that `/` is not appended to index.html, or any path with extension.
|
|
5
|
+
// We remove all slashes, filter out empty values, and reconstruct the path following
|
|
6
|
+
// the fact that every page (slug) has a dedicated folder in the S3 bucket, and an `index.html`
|
|
7
|
+
// file with the actual page HTML.
|
|
8
|
+
var parts = uri.split("/").filter(Boolean); // This means that a `/` (homepage) was requested. When the homepage is prerendered, we place its files
|
|
9
|
+
// into the root of the bucket, or in the tenant subfolder, if it's a multi-tenant system, e.g., `/root/index.html`.
|
|
10
|
+
|
|
11
|
+
if (!parts.length) {
|
|
12
|
+
return "/index.html";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
var lastPart = parts[parts.length - 1]; // If there's a `.` in the last part of the path, we assume it's a file extension.
|
|
16
|
+
// In this case, we can reconstruct the path by joining parts with slashes.
|
|
17
|
+
|
|
18
|
+
if (lastPart.includes(".")) {
|
|
19
|
+
return [""].concat(parts).join("/");
|
|
20
|
+
} // Otherwise, we assume it's a page slug, which needs to point to page's subfolder.
|
|
21
|
+
// We construct a valid S3 bucket path to an HTML file.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
return [""].concat(parts).concat("index.html").join("/");
|
|
25
|
+
} // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
function handler(event) {
|
|
29
|
+
var request = event.request;
|
|
30
|
+
request.uri = sanitizeRequestURI(request.uri);
|
|
31
|
+
return request;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["sanitizeRequestURI","uri","parts","split","filter","Boolean","length","lastPart","includes","concat","join","handler","event","request"],"sources":["deliveryViewerRequest.js"],"sourcesContent":["function sanitizeRequestURI(uri) {\n // Make sure that `/` is not appended to index.html, or any path with extension.\n // We remove all slashes, filter out empty values, and reconstruct the path following\n // the fact that every page (slug) has a dedicated folder in the S3 bucket, and an `index.html`\n // file with the actual page HTML.\n var parts = uri.split(\"/\").filter(Boolean);\n\n // This means that a `/` (homepage) was requested. When the homepage is prerendered, we place its files\n // into the root of the bucket, or in the tenant subfolder, if it's a multi-tenant system, e.g., `/root/index.html`.\n if (!parts.length) {\n return \"/index.html\";\n }\n\n var lastPart = parts[parts.length - 1];\n\n // If there's a `.` in the last part of the path, we assume it's a file extension.\n // In this case, we can reconstruct the path by joining parts with slashes.\n if (lastPart.includes(\".\")) {\n return [\"\"].concat(parts).join(\"/\");\n }\n\n // Otherwise, we assume it's a page slug, which needs to point to page's subfolder.\n // We construct a valid S3 bucket path to an HTML file.\n return [\"\"].concat(parts).concat(\"index.html\").join(\"/\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction handler(event) {\n var request = event.request;\n\n request.uri = sanitizeRequestURI(request.uri);\n\n return request;\n}\n"],"mappings":";;AAAA,SAASA,kBAAT,CAA4BC,GAA5B,EAAiC;EAC7B;EACA;EACA;EACA;EACA,IAAIC,KAAK,GAAGD,GAAG,CAACE,KAAJ,CAAU,GAAV,EAAeC,MAAf,CAAsBC,OAAtB,CAAZ,CAL6B,CAO7B;EACA;;EACA,IAAI,CAACH,KAAK,CAACI,MAAX,EAAmB;IACf,OAAO,aAAP;EACH;;EAED,IAAIC,QAAQ,GAAGL,KAAK,CAACA,KAAK,CAACI,MAAN,GAAe,CAAhB,CAApB,CAb6B,CAe7B;EACA;;EACA,IAAIC,QAAQ,CAACC,QAAT,CAAkB,GAAlB,CAAJ,EAA4B;IACxB,OAAO,CAAC,EAAD,EAAKC,MAAL,CAAYP,KAAZ,EAAmBQ,IAAnB,CAAwB,GAAxB,CAAP;EACH,CAnB4B,CAqB7B;EACA;;;EACA,OAAO,CAAC,EAAD,EAAKD,MAAL,CAAYP,KAAZ,EAAmBO,MAAnB,CAA0B,YAA1B,EAAwCC,IAAxC,CAA6C,GAA7C,CAAP;AACH,C,CAED;;;AACA,SAASC,OAAT,CAAiBC,KAAjB,EAAwB;EACpB,IAAIC,OAAO,GAAGD,KAAK,CAACC,OAApB;EAEAA,OAAO,CAACZ,GAAR,GAAcD,kBAAkB,CAACa,OAAO,CAACZ,GAAT,CAAhC;EAEA,OAAOY,OAAP;AACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./createWebsitePulumiApp";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _createWebsitePulumiApp = require("./createWebsitePulumiApp");
|
|
8
|
+
|
|
9
|
+
Object.keys(_createWebsitePulumiApp).forEach(function (key) {
|
|
10
|
+
if (key === "default" || key === "__esModule") return;
|
|
11
|
+
if (key in exports && exports[key] === _createWebsitePulumiApp[key]) return;
|
|
12
|
+
Object.defineProperty(exports, key, {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _createWebsitePulumiApp[key];
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./createWebsitePulumiApp\";\n"],"mappings":";;;;;;AAAA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import * as aws from "@pulumi/aws";
|
|
3
|
+
interface Config {
|
|
4
|
+
apiFolder?: string;
|
|
5
|
+
apiEnv?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class WebsiteTenantRouter extends pulumi.ComponentResource {
|
|
8
|
+
readonly originRequest: aws.lambda.Function;
|
|
9
|
+
constructor(name: string, config?: Config, opts?: {});
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
4
|
+
|
|
5
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
exports.WebsiteTenantRouter = void 0;
|
|
11
|
+
|
|
12
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
13
|
+
|
|
14
|
+
var _fs = require("fs");
|
|
15
|
+
|
|
16
|
+
var pulumi = _interopRequireWildcard(require("@pulumi/pulumi"));
|
|
17
|
+
|
|
18
|
+
var aws = _interopRequireWildcard(require("@pulumi/aws"));
|
|
19
|
+
|
|
20
|
+
var _utils = require("@webiny/cli-plugin-deploy-pulumi/utils");
|
|
21
|
+
|
|
22
|
+
function createFunctionArchive({
|
|
23
|
+
dynamoDbTable,
|
|
24
|
+
region
|
|
25
|
+
}) {
|
|
26
|
+
const handler = (0, _fs.readFileSync)(__dirname + "/functions/origin/request.js", "utf-8");
|
|
27
|
+
const source = handler.replace("{DB_TABLE_NAME}", dynamoDbTable).replace("{DB_TABLE_REGION}", region);
|
|
28
|
+
return new pulumi.asset.AssetArchive({
|
|
29
|
+
"index.js": new pulumi.asset.StringAsset(source)
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class WebsiteTenantRouter extends pulumi.ComponentResource {
|
|
34
|
+
constructor(name, config = {}, opts = {}) {
|
|
35
|
+
super("webiny:aws:WebsiteTenantRouter", name, {}, opts);
|
|
36
|
+
(0, _defineProperty2.default)(this, "originRequest", void 0);
|
|
37
|
+
const {
|
|
38
|
+
region,
|
|
39
|
+
dynamoDbTable
|
|
40
|
+
} = (0, _utils.getStackOutput)({
|
|
41
|
+
folder: config.apiFolder || "api",
|
|
42
|
+
env: config.apiEnv || String(process.env.WEBINY_ENV)
|
|
43
|
+
});
|
|
44
|
+
const inlinePolicies = Promise.all([aws.getCallerIdentity({})]).then(([callerIdentity]) => [{
|
|
45
|
+
name: "dynamodb-policy",
|
|
46
|
+
policy: JSON.stringify({
|
|
47
|
+
Version: "2012-10-17",
|
|
48
|
+
Statement: [{
|
|
49
|
+
Sid: "PermissionForDynamodb",
|
|
50
|
+
Effect: "Allow",
|
|
51
|
+
Action: ["dynamodb:GetItem", "dynamodb:Query"],
|
|
52
|
+
Resource: [`arn:aws:dynamodb:${region}:${callerIdentity.accountId}:table/${dynamoDbTable}`, `arn:aws:dynamodb:${region}:${callerIdentity.accountId}:table/${dynamoDbTable}/*`]
|
|
53
|
+
}]
|
|
54
|
+
})
|
|
55
|
+
}]);
|
|
56
|
+
const role = new aws.iam.Role(`${name}-role`, {
|
|
57
|
+
inlinePolicies,
|
|
58
|
+
managedPolicyArns: [aws.iam.ManagedPolicies.AWSLambdaBasicExecutionRole],
|
|
59
|
+
assumeRolePolicy: {
|
|
60
|
+
Version: "2012-10-17",
|
|
61
|
+
Statement: [{
|
|
62
|
+
Action: "sts:AssumeRole",
|
|
63
|
+
Principal: aws.iam.Principals.LambdaPrincipal,
|
|
64
|
+
Effect: "Allow"
|
|
65
|
+
}, {
|
|
66
|
+
Action: "sts:AssumeRole",
|
|
67
|
+
Principal: aws.iam.Principals.EdgeLambdaPrincipal,
|
|
68
|
+
Effect: "Allow"
|
|
69
|
+
}]
|
|
70
|
+
}
|
|
71
|
+
}, {
|
|
72
|
+
parent: this
|
|
73
|
+
}); // Some resources _must_ be put in us-east-1, such as Lambda at Edge.
|
|
74
|
+
|
|
75
|
+
const awsUsEast1 = new aws.Provider("us-east-1", {
|
|
76
|
+
region: "us-east-1"
|
|
77
|
+
});
|
|
78
|
+
this.originRequest = new aws.lambda.Function(`${name}-origin-request`, {
|
|
79
|
+
publish: true,
|
|
80
|
+
runtime: "nodejs14.x",
|
|
81
|
+
handler: "index.handler",
|
|
82
|
+
role: role.arn,
|
|
83
|
+
timeout: 5,
|
|
84
|
+
memorySize: 128,
|
|
85
|
+
code: createFunctionArchive({
|
|
86
|
+
region,
|
|
87
|
+
dynamoDbTable
|
|
88
|
+
})
|
|
89
|
+
}, {
|
|
90
|
+
provider: awsUsEast1,
|
|
91
|
+
parent: this
|
|
92
|
+
});
|
|
93
|
+
this.registerOutputs();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
exports.WebsiteTenantRouter = WebsiteTenantRouter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createFunctionArchive","dynamoDbTable","region","handler","readFileSync","__dirname","source","replace","pulumi","asset","AssetArchive","StringAsset","WebsiteTenantRouter","ComponentResource","constructor","name","config","opts","getStackOutput","folder","apiFolder","env","apiEnv","String","process","WEBINY_ENV","inlinePolicies","Promise","all","aws","getCallerIdentity","then","callerIdentity","policy","JSON","stringify","Version","Statement","Sid","Effect","Action","Resource","accountId","role","iam","Role","managedPolicyArns","ManagedPolicies","AWSLambdaBasicExecutionRole","assumeRolePolicy","Principal","Principals","LambdaPrincipal","EdgeLambdaPrincipal","parent","awsUsEast1","Provider","originRequest","lambda","Function","publish","runtime","arn","timeout","memorySize","code","provider","registerOutputs"],"sources":["WebsiteTenantRouter.ts"],"sourcesContent":["import { readFileSync } from \"fs\";\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as aws from \"@pulumi/aws\";\nimport { getStackOutput } from \"@webiny/cli-plugin-deploy-pulumi/utils\";\n\ninterface Config {\n apiFolder?: string;\n apiEnv?: string;\n}\n\ninterface Params {\n region: string;\n dynamoDbTable: string;\n}\n\nfunction createFunctionArchive({ dynamoDbTable, region }: Params) {\n const handler = readFileSync(__dirname + \"/functions/origin/request.js\", \"utf-8\");\n\n const source = handler\n .replace(\"{DB_TABLE_NAME}\", dynamoDbTable)\n .replace(\"{DB_TABLE_REGION}\", region);\n\n return new pulumi.asset.AssetArchive({\n \"index.js\": new pulumi.asset.StringAsset(source)\n });\n}\n\nexport class WebsiteTenantRouter extends pulumi.ComponentResource {\n public readonly originRequest: aws.lambda.Function;\n\n constructor(name: string, config: Config = {}, opts = {}) {\n super(\"webiny:aws:WebsiteTenantRouter\", name, {}, opts);\n\n const { region, dynamoDbTable } = getStackOutput<{ region: string; dynamoDbTable: string }>(\n {\n folder: config.apiFolder || \"api\",\n env: config.apiEnv || String(process.env.WEBINY_ENV)\n }\n );\n\n const inlinePolicies = Promise.all([aws.getCallerIdentity({})]).then(([callerIdentity]) => [\n {\n name: \"dynamodb-policy\",\n policy: JSON.stringify({\n Version: \"2012-10-17\",\n Statement: [\n {\n Sid: \"PermissionForDynamodb\",\n Effect: \"Allow\",\n Action: [\"dynamodb:GetItem\", \"dynamodb:Query\"],\n Resource: [\n `arn:aws:dynamodb:${region}:${callerIdentity.accountId}:table/${dynamoDbTable}`,\n `arn:aws:dynamodb:${region}:${callerIdentity.accountId}:table/${dynamoDbTable}/*`\n ]\n }\n ]\n })\n }\n ]);\n\n const role = new aws.iam.Role(\n `${name}-role`,\n {\n inlinePolicies,\n managedPolicyArns: [aws.iam.ManagedPolicies.AWSLambdaBasicExecutionRole],\n assumeRolePolicy: {\n Version: \"2012-10-17\",\n Statement: [\n {\n Action: \"sts:AssumeRole\",\n Principal: aws.iam.Principals.LambdaPrincipal,\n Effect: \"Allow\"\n },\n {\n Action: \"sts:AssumeRole\",\n Principal: aws.iam.Principals.EdgeLambdaPrincipal,\n Effect: \"Allow\"\n }\n ]\n }\n },\n { parent: this }\n );\n\n // Some resources _must_ be put in us-east-1, such as Lambda at Edge.\n const awsUsEast1 = new aws.Provider(\"us-east-1\", { region: \"us-east-1\" });\n\n this.originRequest = new aws.lambda.Function(\n `${name}-origin-request`,\n {\n publish: true,\n runtime: \"nodejs14.x\",\n handler: \"index.handler\",\n role: role.arn,\n timeout: 5,\n memorySize: 128,\n code: createFunctionArchive({ region, dynamoDbTable })\n },\n { provider: awsUsEast1, parent: this }\n );\n\n this.registerOutputs();\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function handler(event: any): Promise<any>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
DocumentClient
|
|
5
|
+
} = require("aws-sdk/clients/dynamodb"); // Since Lambda@Edge doesn't support ENV variables, the easiest way to pass
|
|
6
|
+
// config values to it is to inject them into the source code before deploy.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const DB_TABLE_NAME = "{DB_TABLE_NAME}";
|
|
10
|
+
const DB_TABLE_REGION = "{DB_TABLE_REGION}";
|
|
11
|
+
const documentClient = new DocumentClient({
|
|
12
|
+
convertEmptyValues: true,
|
|
13
|
+
region: DB_TABLE_REGION
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function sanitizeRequestURI(uri) {
|
|
17
|
+
// Make sure that `/` is not appended to index.html, or any path with extension.
|
|
18
|
+
// We remove all slashes, filter out empty values, and reconstruct the path following
|
|
19
|
+
// the fact that every page (slug) has a dedicated folder in the S3 bucket, and an `index.html`
|
|
20
|
+
// file with the actual page HTML.
|
|
21
|
+
const parts = uri.split("/").filter(Boolean); // This means that a `/` (homepage) was requested. When the homepage is prerendered, we place its files
|
|
22
|
+
// into the root of the tenant subfolder, e.g., `/root/index.html`.
|
|
23
|
+
|
|
24
|
+
if (!parts.length) {
|
|
25
|
+
return "/index.html";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const lastPart = parts[parts.length - 1]; // If there's a `.` in the last part of the path, we assume it's a file extension.
|
|
29
|
+
// In this case, we can reconstruct the path by joining parts with slashes.
|
|
30
|
+
|
|
31
|
+
if (lastPart.includes(".")) {
|
|
32
|
+
return ["", ...parts].join("/");
|
|
33
|
+
} // Otherwise, we assume it's a page slug, which needs to point to page's subfolder.
|
|
34
|
+
// We construct a valid S3 bucket path to an HTML file.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
return ["", ...parts, "index.html"].join("/");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function getTenantIdByDomain(domain) {
|
|
41
|
+
const params = {
|
|
42
|
+
TableName: DB_TABLE_NAME,
|
|
43
|
+
Key: {
|
|
44
|
+
PK: `DOMAIN#${domain}`,
|
|
45
|
+
SK: "A"
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const {
|
|
49
|
+
Item
|
|
50
|
+
} = await documentClient.get(params).promise();
|
|
51
|
+
return Item ? Item.tenant : undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if "root" tenant has at least one child tenant.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
async function hasMultipleTenants() {
|
|
59
|
+
const {
|
|
60
|
+
Count
|
|
61
|
+
} = await documentClient.query({
|
|
62
|
+
TableName: DB_TABLE_NAME,
|
|
63
|
+
IndexName: "GSI1",
|
|
64
|
+
Limit: 1,
|
|
65
|
+
Select: "COUNT",
|
|
66
|
+
KeyConditionExpression: "GSI1_PK = :GSI1_PK and begins_with(GSI1_SK, :GSI1_SK)",
|
|
67
|
+
ExpressionAttributeValues: {
|
|
68
|
+
":GSI1_PK": "TENANTS",
|
|
69
|
+
":GSI1_SK": "T#root#"
|
|
70
|
+
}
|
|
71
|
+
}).promise();
|
|
72
|
+
return Count > 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function handleOriginRequest(request) {
|
|
76
|
+
const origin = request.origin;
|
|
77
|
+
const isCustomOrigin = Boolean(origin.custom);
|
|
78
|
+
const requestedDomain = request.headers.host[0].value;
|
|
79
|
+
const originDomain = isCustomOrigin ? origin.custom.domainName : origin.s3.domainName;
|
|
80
|
+
let tenant;
|
|
81
|
+
|
|
82
|
+
if (await hasMultipleTenants()) {
|
|
83
|
+
// Find tenant by domain. This record is stored to the DB using the Tenant Manager app.
|
|
84
|
+
console.log(`Multiple tenants are present; loading by domain...`);
|
|
85
|
+
tenant = await getTenantIdByDomain(requestedDomain);
|
|
86
|
+
} else {
|
|
87
|
+
console.log(`Only one tenant is present; falling back to "root".`); // If the system only has one tenant, we don't need to map by domain at all.
|
|
88
|
+
|
|
89
|
+
tenant = "root";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (tenant) {
|
|
93
|
+
const uri = sanitizeRequestURI(request.uri); // To be on the safe side, make sure the requested uri doesn't already include the tenant ID.
|
|
94
|
+
|
|
95
|
+
if (uri.startsWith(`/${tenant}/`)) {
|
|
96
|
+
request.uri = uri;
|
|
97
|
+
} else {
|
|
98
|
+
// Prepend the tenant ID, to point to the correct S3 bucket folder.
|
|
99
|
+
request.uri = `/${tenant}${uri}`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(`Rewriting request from "${uri}" to "${request.uri}"`);
|
|
103
|
+
} else {
|
|
104
|
+
console.log(`Failed to find a tenant for domain "${requestedDomain}"`);
|
|
105
|
+
return {
|
|
106
|
+
status: 400,
|
|
107
|
+
statusDescription: "Unable to map tenant. Check your tenant to domain mapping."
|
|
108
|
+
};
|
|
109
|
+
} // At this point, the value of the `Host` header is set to the custom domain.
|
|
110
|
+
// Before forwarding the request to the S3 bucket, we need to set the `Host` header
|
|
111
|
+
// to the value of the origin (S3 bucket URL).
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
request.headers.host[0].value = originDomain;
|
|
115
|
+
return request;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
exports.handler = async event => {
|
|
119
|
+
const {
|
|
120
|
+
request,
|
|
121
|
+
config
|
|
122
|
+
} = event.Records[0].cf;
|
|
123
|
+
|
|
124
|
+
if (config.eventType === "origin-request") {
|
|
125
|
+
return handleOriginRequest(request);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return request;
|
|
129
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DocumentClient","require","DB_TABLE_NAME","DB_TABLE_REGION","documentClient","convertEmptyValues","region","sanitizeRequestURI","uri","parts","split","filter","Boolean","length","lastPart","includes","join","getTenantIdByDomain","domain","params","TableName","Key","PK","SK","Item","get","promise","tenant","undefined","hasMultipleTenants","Count","query","IndexName","Limit","Select","KeyConditionExpression","ExpressionAttributeValues","handleOriginRequest","request","origin","isCustomOrigin","custom","requestedDomain","headers","host","value","originDomain","domainName","s3","console","log","startsWith","status","statusDescription","exports","handler","event","config","Records","cf","eventType"],"sources":["request.js"],"sourcesContent":["const { DocumentClient } = require(\"aws-sdk/clients/dynamodb\");\n\n// Since Lambda@Edge doesn't support ENV variables, the easiest way to pass\n// config values to it is to inject them into the source code before deploy.\nconst DB_TABLE_NAME = \"{DB_TABLE_NAME}\";\nconst DB_TABLE_REGION = \"{DB_TABLE_REGION}\";\n\nconst documentClient = new DocumentClient({\n convertEmptyValues: true,\n region: DB_TABLE_REGION\n});\n\nfunction sanitizeRequestURI(uri) {\n // Make sure that `/` is not appended to index.html, or any path with extension.\n // We remove all slashes, filter out empty values, and reconstruct the path following\n // the fact that every page (slug) has a dedicated folder in the S3 bucket, and an `index.html`\n // file with the actual page HTML.\n const parts = uri.split(\"/\").filter(Boolean);\n\n // This means that a `/` (homepage) was requested. When the homepage is prerendered, we place its files\n // into the root of the tenant subfolder, e.g., `/root/index.html`.\n if (!parts.length) {\n return \"/index.html\";\n }\n\n const lastPart = parts[parts.length - 1];\n\n // If there's a `.` in the last part of the path, we assume it's a file extension.\n // In this case, we can reconstruct the path by joining parts with slashes.\n if (lastPart.includes(\".\")) {\n return [\"\", ...parts].join(\"/\");\n }\n\n // Otherwise, we assume it's a page slug, which needs to point to page's subfolder.\n // We construct a valid S3 bucket path to an HTML file.\n return [\"\", ...parts, \"index.html\"].join(\"/\");\n}\n\nasync function getTenantIdByDomain(domain) {\n const params = {\n TableName: DB_TABLE_NAME,\n Key: {\n PK: `DOMAIN#${domain}`,\n SK: \"A\"\n }\n };\n const { Item } = await documentClient.get(params).promise();\n\n return Item ? Item.tenant : undefined;\n}\n\n/**\n * Check if \"root\" tenant has at least one child tenant.\n */\nasync function hasMultipleTenants() {\n const { Count } = await documentClient\n .query({\n TableName: DB_TABLE_NAME,\n IndexName: \"GSI1\",\n Limit: 1,\n Select: \"COUNT\",\n KeyConditionExpression: \"GSI1_PK = :GSI1_PK and begins_with(GSI1_SK, :GSI1_SK)\",\n ExpressionAttributeValues: {\n \":GSI1_PK\": \"TENANTS\",\n \":GSI1_SK\": \"T#root#\"\n }\n })\n .promise();\n\n return Count > 0;\n}\n\nasync function handleOriginRequest(request) {\n const origin = request.origin;\n const isCustomOrigin = Boolean(origin.custom);\n const requestedDomain = request.headers.host[0].value;\n const originDomain = isCustomOrigin ? origin.custom.domainName : origin.s3.domainName;\n\n let tenant;\n if (await hasMultipleTenants()) {\n // Find tenant by domain. This record is stored to the DB using the Tenant Manager app.\n console.log(`Multiple tenants are present; loading by domain...`);\n tenant = await getTenantIdByDomain(requestedDomain);\n } else {\n console.log(`Only one tenant is present; falling back to \"root\".`);\n // If the system only has one tenant, we don't need to map by domain at all.\n tenant = \"root\";\n }\n\n if (tenant) {\n const uri = sanitizeRequestURI(request.uri);\n\n // To be on the safe side, make sure the requested uri doesn't already include the tenant ID.\n if (uri.startsWith(`/${tenant}/`)) {\n request.uri = uri;\n } else {\n // Prepend the tenant ID, to point to the correct S3 bucket folder.\n request.uri = `/${tenant}${uri}`;\n }\n\n console.log(`Rewriting request from \"${uri}\" to \"${request.uri}\"`);\n } else {\n console.log(`Failed to find a tenant for domain \"${requestedDomain}\"`);\n return {\n status: 400,\n statusDescription: \"Unable to map tenant. Check your tenant to domain mapping.\"\n };\n }\n\n // At this point, the value of the `Host` header is set to the custom domain.\n // Before forwarding the request to the S3 bucket, we need to set the `Host` header\n // to the value of the origin (S3 bucket URL).\n request.headers.host[0].value = originDomain;\n\n return request;\n}\n\nexports.handler = async event => {\n const { request, config } = event.Records[0].cf;\n\n if (config.eventType === \"origin-request\") {\n return handleOriginRequest(request);\n }\n\n return request;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createAdminPulumiApp, CreateAdminPulumiAppParams, AdminPulumiApp } from "../apps/admin/createAdminPulumiApp";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "AdminPulumiApp", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _createAdminPulumiApp.AdminPulumiApp;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "CreateAdminPulumiAppParams", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _createAdminPulumiApp.CreateAdminPulumiAppParams;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "createAdminPulumiApp", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _createAdminPulumiApp.createAdminPulumiApp;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
var _createAdminPulumiApp = require("../apps/admin/createAdminPulumiApp");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["createAdminPulumiApp.ts"],"sourcesContent":["// For now, no special enterprise features are available for the Admin app.\n// We're simply reexporting everything from the base Admin Pulumi app.\nexport {\n createAdminPulumiApp,\n CreateAdminPulumiAppParams,\n AdminPulumiApp\n} from \"~/apps/admin/createAdminPulumiApp\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAEA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as aws from "@pulumi/aws";
|
|
2
|
+
import { CreateApiPulumiAppParams as BaseCreateApiPulumiAppParams } from "../apps/api/createApiPulumiApp";
|
|
3
|
+
export declare type ApiPulumiApp = ReturnType<typeof createApiPulumiApp>;
|
|
4
|
+
export declare type ApiPulumiAppAdvancedVpcParams = Partial<{
|
|
5
|
+
useExistingVpc: {
|
|
6
|
+
lambdaFunctionsVpcConfig: aws.types.input.lambda.FunctionVpcConfig;
|
|
7
|
+
};
|
|
8
|
+
}>;
|
|
9
|
+
export interface CreateApiPulumiAppParams extends Omit<BaseCreateApiPulumiAppParams, "vpc"> {
|
|
10
|
+
vpc?: boolean | ApiPulumiAppAdvancedVpcParams;
|
|
11
|
+
}
|
|
12
|
+
export declare function createApiPulumiApp(projectAppParams?: CreateApiPulumiAppParams): import("@webiny/pulumi").PulumiApp<{
|
|
13
|
+
fileManager: {
|
|
14
|
+
functions: {
|
|
15
|
+
transform: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
16
|
+
manage: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
17
|
+
download: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
18
|
+
};
|
|
19
|
+
bucketNotification: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/s3/bucketNotification").BucketNotification>;
|
|
20
|
+
};
|
|
21
|
+
graphql: {
|
|
22
|
+
role: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/role").Role>;
|
|
23
|
+
policy: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/policy").Policy>;
|
|
24
|
+
functions: {
|
|
25
|
+
graphql: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
26
|
+
};
|
|
27
|
+
addRoute: (routeParams: import("..").AddRouteParams) => any;
|
|
28
|
+
};
|
|
29
|
+
headlessCms: {
|
|
30
|
+
role: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/role").Role>;
|
|
31
|
+
policy: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/policy").Policy>;
|
|
32
|
+
functions: {
|
|
33
|
+
graphql: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
apiGateway: {
|
|
37
|
+
api: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/apigatewayv2/api").Api>;
|
|
38
|
+
stage: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/apigatewayv2/stage").Stage>;
|
|
39
|
+
routes: Record<string, {
|
|
40
|
+
integration: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/apigatewayv2/integration").Integration>;
|
|
41
|
+
route: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/apigatewayv2/route").Route>;
|
|
42
|
+
permission: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/permission").Permission>;
|
|
43
|
+
}>;
|
|
44
|
+
addRoute: (name: string, params: import("..").ApiRouteParams) => void;
|
|
45
|
+
};
|
|
46
|
+
cloudfront: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/cloudfront/distribution").Distribution>;
|
|
47
|
+
apwScheduler: {
|
|
48
|
+
executeAction: {
|
|
49
|
+
role: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/role").Role>;
|
|
50
|
+
policy: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/policy").Policy>;
|
|
51
|
+
lambda: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
52
|
+
};
|
|
53
|
+
scheduleAction: {
|
|
54
|
+
role: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/role").Role>;
|
|
55
|
+
policy: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/policy").Policy>;
|
|
56
|
+
lambda: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
57
|
+
};
|
|
58
|
+
eventRule: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/cloudwatch/eventRule").EventRule>;
|
|
59
|
+
eventTarget: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/cloudwatch/eventTarget").EventTarget>;
|
|
60
|
+
};
|
|
61
|
+
}> & import("../utils/lambdaEnvVariables").WithCommonLambdaEnvVariables;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
4
|
+
|
|
5
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
exports.createApiPulumiApp = createApiPulumiApp;
|
|
11
|
+
|
|
12
|
+
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
13
|
+
|
|
14
|
+
var aws = _interopRequireWildcard(require("@pulumi/aws"));
|
|
15
|
+
|
|
16
|
+
var _createApiPulumiApp = require("../apps/api/createApiPulumiApp");
|
|
17
|
+
|
|
18
|
+
var _pulumi = require("@webiny/pulumi");
|
|
19
|
+
|
|
20
|
+
function createApiPulumiApp(projectAppParams = {}) {
|
|
21
|
+
const {
|
|
22
|
+
vpc,
|
|
23
|
+
pulumi
|
|
24
|
+
} = projectAppParams;
|
|
25
|
+
const usingAdvancedVpcParams = vpc && typeof vpc !== "boolean";
|
|
26
|
+
return (0, _createApiPulumiApp.createApiPulumiApp)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, projectAppParams), {}, {
|
|
27
|
+
// If using existing VPC, we ensure `vpc` param is set to `false`.
|
|
28
|
+
vpc: usingAdvancedVpcParams && vpc.useExistingVpc ? false : Boolean(vpc),
|
|
29
|
+
|
|
30
|
+
pulumi(...args) {
|
|
31
|
+
// Not using advanced VPC params? Then immediately exit.
|
|
32
|
+
if (!usingAdvancedVpcParams) {
|
|
33
|
+
return pulumi === null || pulumi === void 0 ? void 0 : pulumi(...args);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const [{
|
|
37
|
+
onResource
|
|
38
|
+
}] = args;
|
|
39
|
+
const {
|
|
40
|
+
useExistingVpc
|
|
41
|
+
} = vpc; // 1. We first deal with "existing VPC" setup.
|
|
42
|
+
|
|
43
|
+
if (useExistingVpc) {
|
|
44
|
+
if (!useExistingVpc.lambdaFunctionsVpcConfig) {
|
|
45
|
+
throw new Error("Cannot specify `useExistingVpc` parameter because the `lambdaFunctionsVpcConfig` parameter wasn't provided.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onResource(resource => {
|
|
49
|
+
if ((0, _pulumi.isResourceOfType)(resource, aws.lambda.Function)) {
|
|
50
|
+
resource.config.vpcConfig(useExistingVpc.lambdaFunctionsVpcConfig);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ((0, _pulumi.isResourceOfType)(resource, aws.iam.Role)) {
|
|
54
|
+
if (resource.meta.isLambdaFunctionRole) {
|
|
55
|
+
new aws.iam.RolePolicyAttachment(`${resource.name}-vpc-access-execution-role`, {
|
|
56
|
+
role: resource.output.name,
|
|
57
|
+
policyArn: aws.iam.ManagedPolicy.AWSLambdaVPCAccessExecutionRole
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return pulumi === null || pulumi === void 0 ? void 0 : pulumi(...args);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createApiPulumiApp","projectAppParams","vpc","pulumi","usingAdvancedVpcParams","baseCreateApiPulumiApp","useExistingVpc","Boolean","args","onResource","lambdaFunctionsVpcConfig","Error","resource","isResourceOfType","aws","lambda","Function","config","vpcConfig","iam","Role","meta","isLambdaFunctionRole","RolePolicyAttachment","name","role","output","policyArn","ManagedPolicy","AWSLambdaVPCAccessExecutionRole"],"sources":["createApiPulumiApp.ts"],"sourcesContent":["import * as aws from \"@pulumi/aws\";\nimport {\n createApiPulumiApp as baseCreateApiPulumiApp,\n CreateApiPulumiAppParams as BaseCreateApiPulumiAppParams\n} from \"~/apps/api/createApiPulumiApp\";\nimport { isResourceOfType } from \"@webiny/pulumi\";\n\nexport type ApiPulumiApp = ReturnType<typeof createApiPulumiApp>;\n\nexport type ApiPulumiAppAdvancedVpcParams = Partial<{\n useExistingVpc: {\n lambdaFunctionsVpcConfig: aws.types.input.lambda.FunctionVpcConfig;\n };\n}>;\n\nexport interface CreateApiPulumiAppParams extends Omit<BaseCreateApiPulumiAppParams, \"vpc\"> {\n vpc?: boolean | ApiPulumiAppAdvancedVpcParams;\n}\n\nexport function createApiPulumiApp(projectAppParams: CreateApiPulumiAppParams = {}) {\n const { vpc, pulumi } = projectAppParams;\n const usingAdvancedVpcParams = vpc && typeof vpc !== \"boolean\";\n\n return baseCreateApiPulumiApp({\n ...projectAppParams,\n // If using existing VPC, we ensure `vpc` param is set to `false`.\n vpc: usingAdvancedVpcParams && vpc.useExistingVpc ? false : Boolean(vpc),\n pulumi(...args) {\n // Not using advanced VPC params? Then immediately exit.\n if (!usingAdvancedVpcParams) {\n return pulumi?.(...args);\n }\n\n const [{ onResource }] = args;\n const { useExistingVpc } = vpc;\n\n // 1. We first deal with \"existing VPC\" setup.\n if (useExistingVpc) {\n if (!useExistingVpc.lambdaFunctionsVpcConfig) {\n throw new Error(\n \"Cannot specify `useExistingVpc` parameter because the `lambdaFunctionsVpcConfig` parameter wasn't provided.\"\n );\n }\n\n onResource(resource => {\n if (isResourceOfType(resource, aws.lambda.Function)) {\n resource.config.vpcConfig(useExistingVpc!.lambdaFunctionsVpcConfig);\n }\n\n if (isResourceOfType(resource, aws.iam.Role)) {\n if (resource.meta.isLambdaFunctionRole) {\n new aws.iam.RolePolicyAttachment(\n `${resource.name}-vpc-access-execution-role`,\n {\n role: resource.output.name,\n policyArn: aws.iam.ManagedPolicy.AWSLambdaVPCAccessExecutionRole\n }\n );\n }\n }\n });\n }\n\n return pulumi?.(...args);\n }\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;;AACA;;AAIA;;AAcO,SAASA,kBAAT,CAA4BC,gBAA0C,GAAG,EAAzE,EAA6E;EAChF,MAAM;IAAEC,GAAF;IAAOC;EAAP,IAAkBF,gBAAxB;EACA,MAAMG,sBAAsB,GAAGF,GAAG,IAAI,OAAOA,GAAP,KAAe,SAArD;EAEA,OAAO,IAAAG,sCAAA,8DACAJ,gBADA;IAEH;IACAC,GAAG,EAAEE,sBAAsB,IAAIF,GAAG,CAACI,cAA9B,GAA+C,KAA/C,GAAuDC,OAAO,CAACL,GAAD,CAHhE;;IAIHC,MAAM,CAAC,GAAGK,IAAJ,EAAU;MACZ;MACA,IAAI,CAACJ,sBAAL,EAA6B;QACzB,OAAOD,MAAP,aAAOA,MAAP,uBAAOA,MAAM,CAAG,GAAGK,IAAN,CAAb;MACH;;MAED,MAAM,CAAC;QAAEC;MAAF,CAAD,IAAmBD,IAAzB;MACA,MAAM;QAAEF;MAAF,IAAqBJ,GAA3B,CAPY,CASZ;;MACA,IAAII,cAAJ,EAAoB;QAChB,IAAI,CAACA,cAAc,CAACI,wBAApB,EAA8C;UAC1C,MAAM,IAAIC,KAAJ,CACF,6GADE,CAAN;QAGH;;QAEDF,UAAU,CAACG,QAAQ,IAAI;UACnB,IAAI,IAAAC,wBAAA,EAAiBD,QAAjB,EAA2BE,GAAG,CAACC,MAAJ,CAAWC,QAAtC,CAAJ,EAAqD;YACjDJ,QAAQ,CAACK,MAAT,CAAgBC,SAAhB,CAA0BZ,cAAc,CAAEI,wBAA1C;UACH;;UAED,IAAI,IAAAG,wBAAA,EAAiBD,QAAjB,EAA2BE,GAAG,CAACK,GAAJ,CAAQC,IAAnC,CAAJ,EAA8C;YAC1C,IAAIR,QAAQ,CAACS,IAAT,CAAcC,oBAAlB,EAAwC;cACpC,IAAIR,GAAG,CAACK,GAAJ,CAAQI,oBAAZ,CACK,GAAEX,QAAQ,CAACY,IAAK,4BADrB,EAEI;gBACIC,IAAI,EAAEb,QAAQ,CAACc,MAAT,CAAgBF,IAD1B;gBAEIG,SAAS,EAAEb,GAAG,CAACK,GAAJ,CAAQS,aAAR,CAAsBC;cAFrC,CAFJ;YAOH;UACJ;QACJ,CAhBS,CAAV;MAiBH;;MAED,OAAO1B,MAAP,aAAOA,MAAP,uBAAOA,MAAM,CAAG,GAAGK,IAAN,CAAb;IACH;;EAzCE,GAAP;AA2CH"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as aws from "@pulumi/aws";
|
|
2
|
+
import { CreateCorePulumiAppParams as BaseCreateCorePulumiAppParams } from "../apps/core/createCorePulumiApp";
|
|
3
|
+
export declare type CorePulumiApp = ReturnType<typeof createCorePulumiApp>;
|
|
4
|
+
export declare type CorePulumiAppAdvancedVpcParams = Partial<{
|
|
5
|
+
useVpcEndpoints: boolean;
|
|
6
|
+
useExistingVpc: {
|
|
7
|
+
elasticSearchDomainVpcConfig?: aws.types.input.elasticsearch.DomainVpcOptions;
|
|
8
|
+
lambdaFunctionsVpcConfig: aws.types.input.lambda.FunctionVpcConfig;
|
|
9
|
+
};
|
|
10
|
+
}>;
|
|
11
|
+
export interface CreateCorePulumiAppParams extends Omit<BaseCreateCorePulumiAppParams, "vpc"> {
|
|
12
|
+
vpc?: boolean | CorePulumiAppAdvancedVpcParams;
|
|
13
|
+
}
|
|
14
|
+
export declare function createCorePulumiApp(projectAppParams?: CreateCorePulumiAppParams): import("@webiny/pulumi").PulumiApp<{
|
|
15
|
+
fileManagerBucket: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/s3/bucket").Bucket>;
|
|
16
|
+
eventBus: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/cloudwatch/eventBus").EventBus>;
|
|
17
|
+
elasticSearch: {
|
|
18
|
+
domain: import("@webiny/pulumi").PulumiAppResource<import("@webiny/pulumi").PulumiAppResourceConstructor<import("@pulumi/aws/elasticsearch/domain").Domain, any>> | import("@webiny/pulumi").PulumiAppRemoteResource<aws.elasticsearch.GetDomainResult>;
|
|
19
|
+
domainPolicy: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/elasticsearch/domainPolicy").DomainPolicy> | undefined;
|
|
20
|
+
table: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/dynamodb/table").Table>;
|
|
21
|
+
dynamoToElastic: {
|
|
22
|
+
role: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/role").Role>;
|
|
23
|
+
policy: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/iam/policy").Policy>;
|
|
24
|
+
lambda: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/function").Function>;
|
|
25
|
+
eventSourceMapping: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/lambda/eventSourceMapping").EventSourceMapping>;
|
|
26
|
+
};
|
|
27
|
+
} | null;
|
|
28
|
+
userPool: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/cognito/userPool").UserPool>;
|
|
29
|
+
userPoolClient: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/cognito/userPoolClient").UserPoolClient>;
|
|
30
|
+
dynamoDbTable: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/dynamodb/table").Table>;
|
|
31
|
+
vpc: {
|
|
32
|
+
vpc: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/ec2/vpc").Vpc>;
|
|
33
|
+
subnets: {
|
|
34
|
+
public: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/ec2/subnet").Subnet>[];
|
|
35
|
+
private: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/ec2/subnet").Subnet>[];
|
|
36
|
+
};
|
|
37
|
+
routeTables: {
|
|
38
|
+
privateSubnets: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/ec2/routeTable").RouteTable>;
|
|
39
|
+
publicSubnets: import("@webiny/pulumi").PulumiAppResource<typeof import("@pulumi/aws/ec2/routeTable").RouteTable>;
|
|
40
|
+
};
|
|
41
|
+
} | null;
|
|
42
|
+
}>;
|