canopycms-cdk 0.0.67 → 0.0.68-int.94
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/README.md +3 -1
- package/dist/constructs/cms-distribution.d.ts +5 -4
- package/dist/constructs/cms-distribution.js +14 -61
- package/dist/constructs/cms-service.d.ts +23 -3
- package/dist/constructs/cms-service.js +24 -2
- package/dist/constructs/editor-routing.d.ts +131 -0
- package/dist/constructs/editor-routing.js +313 -0
- package/dist/index.d.ts +1 -0
- package/lambda/asset-transform/dist/handler.js +59 -29
- package/package.json +4 -4
- package/worker/dist/index.js +793 -442
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ AWS CDK constructs and EC2 worker for deploying CanopyCMS.
|
|
|
14
14
|
- Lambda Function URL (for CloudFront origin)
|
|
15
15
|
- EC2 Worker (t4g.nano spot in ASG, public subnet, EFS mount)
|
|
16
16
|
- Security groups and IAM roles (least-privilege)
|
|
17
|
+
- `attachTo(distribution)`: adds the editor's `/edit`, `/edit/*` and `/api/canopycms/*` behaviors (and, optionally, the CMS build's `assetPrefix` and the preview route) to a CloudFront distribution you already own
|
|
17
18
|
|
|
18
19
|
**`CanopyCmsDistribution`** — CloudFront + DNS (optional):
|
|
19
20
|
|
|
@@ -21,8 +22,9 @@ AWS CDK constructs and EC2 worker for deploying CanopyCMS.
|
|
|
21
22
|
- CloudFront distribution with Lambda Function URL origin
|
|
22
23
|
- Route53 A/AAAA alias records
|
|
23
24
|
- Cache policies: no-cache for API/editor, long-cache for static assets
|
|
25
|
+
- Response headers: framing protection (`frame-ancestors 'self'`), `nosniff`, HSTS, `X-Robots-Tag: noindex`
|
|
24
26
|
|
|
25
|
-
Use `CanopyCmsDistribution`
|
|
27
|
+
Use `CanopyCmsDistribution` when the CMS gets its own domain. To serve the editor from an existing distribution, call `cmsService.attachTo(distribution)` instead of wiring the `functionUrl` by hand; see [Serving the editor from a distribution you already own](../../docs/deploying-to-aws.md#serving-the-editor-from-a-distribution-you-already-own).
|
|
26
28
|
|
|
27
29
|
### EC2 Worker
|
|
28
30
|
|
|
@@ -98,17 +98,18 @@ export interface CanopyCmsDistributionProps {
|
|
|
98
98
|
/**
|
|
99
99
|
* Optional CDK construct for CanopyCMS CloudFront distribution.
|
|
100
100
|
*
|
|
101
|
-
* Use this
|
|
102
|
-
*
|
|
103
|
-
* and wire it into your own CloudFront setup.
|
|
101
|
+
* Use this when the CMS gets a domain of its own. To serve the editor from a
|
|
102
|
+
* distribution you already own, use `CanopyCmsService.attachTo` instead.
|
|
104
103
|
*
|
|
105
104
|
* Creates:
|
|
106
105
|
* - ACM certificate (DNS validated) — unless provided
|
|
107
106
|
* - CloudFront distribution with Function URL origin
|
|
108
107
|
* - Route53 A/AAAA alias records
|
|
109
|
-
* - Cache policies: no-cache
|
|
108
|
+
* - Cache policies: no-cache default behavior, cache /_next/static/*
|
|
110
109
|
* - Viewer-request CloudFront Function setting x-forwarded-host (redirect-URL
|
|
111
110
|
* derivation behind the Host-stripping OAC origin)
|
|
111
|
+
* - The editor's response headers policy (framing protection, `noindex`) on
|
|
112
|
+
* both of its own behaviors
|
|
112
113
|
* - `AssetSupport`'s `/assets/*` and `/assets/t/*` behaviors, in the required
|
|
113
114
|
* order, when the `assetSupport` prop is passed
|
|
114
115
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Construct } from 'constructs';
|
|
2
|
-
import {
|
|
3
|
-
import { DEFAULT_CMS_LAMBDA_TIMEOUT
|
|
2
|
+
import { Stack, Token, aws_cloudfront as cloudfront, aws_cloudfront_origins as origins, aws_certificatemanager as acm, aws_route53 as route53, aws_route53_targets as targets, } from 'aws-cdk-lib';
|
|
3
|
+
import { DEFAULT_CMS_LAMBDA_TIMEOUT } from './cms-service.js';
|
|
4
|
+
import { assertOriginReadTimeout, createEditorResponseHeadersPolicy, createForwardedHostFunction, createStaticCachePolicy, lambdaBehaviorOptions, } from './editor-routing.js';
|
|
4
5
|
import { ASSETS_PATH_PATTERN, ASSETS_TRANSFORM_PATH_PATTERN, ASSET_BEHAVIOR_SPREAD_MISTAKE_KEYS, } from './asset-support.js';
|
|
5
6
|
/**
|
|
6
7
|
* Merge caller behaviors over this construct's own, preserving THE CALLER'S
|
|
@@ -128,17 +129,18 @@ function assertNoAssetBehaviorOrderingHazards(merged, attachingAssetSupport) {
|
|
|
128
129
|
/**
|
|
129
130
|
* Optional CDK construct for CanopyCMS CloudFront distribution.
|
|
130
131
|
*
|
|
131
|
-
* Use this
|
|
132
|
-
*
|
|
133
|
-
* and wire it into your own CloudFront setup.
|
|
132
|
+
* Use this when the CMS gets a domain of its own. To serve the editor from a
|
|
133
|
+
* distribution you already own, use `CanopyCmsService.attachTo` instead.
|
|
134
134
|
*
|
|
135
135
|
* Creates:
|
|
136
136
|
* - ACM certificate (DNS validated) — unless provided
|
|
137
137
|
* - CloudFront distribution with Function URL origin
|
|
138
138
|
* - Route53 A/AAAA alias records
|
|
139
|
-
* - Cache policies: no-cache
|
|
139
|
+
* - Cache policies: no-cache default behavior, cache /_next/static/*
|
|
140
140
|
* - Viewer-request CloudFront Function setting x-forwarded-host (redirect-URL
|
|
141
141
|
* derivation behind the Host-stripping OAC origin)
|
|
142
|
+
* - The editor's response headers policy (framing protection, `noindex`) on
|
|
143
|
+
* both of its own behaviors
|
|
142
144
|
* - `AssetSupport`'s `/assets/*` and `/assets/t/*` behaviors, in the required
|
|
143
145
|
* order, when the `assetSupport` prop is passed
|
|
144
146
|
*/
|
|
@@ -193,75 +195,26 @@ export class CanopyCmsDistribution extends Construct {
|
|
|
193
195
|
// entirely when unset, so CloudFront's 30s service default applies and
|
|
194
196
|
// silently halves the CMS Lambda's 60s budget. See the prop's doc comment.
|
|
195
197
|
const readTimeout = props.originReadTimeout ?? DEFAULT_CMS_LAMBDA_TIMEOUT;
|
|
196
|
-
|
|
197
|
-
throw new Error(`CanopyCmsDistribution: originReadTimeout is ${readTimeout.toSeconds()}s, but CloudFront ` +
|
|
198
|
-
`allows at most ${MAX_CLOUDFRONT_ORIGIN_READ_TIMEOUT.toSeconds()}s without a service-quota ` +
|
|
199
|
-
`increase. Either lower the CMS Lambda's timeout to match, or request a quota increase for ` +
|
|
200
|
-
`"Origin response timeout" and pass the higher value explicitly. Deploying with a shorter ` +
|
|
201
|
-
`origin timeout than the Lambda's would 504 at the edge on requests that actually succeed.`);
|
|
202
|
-
}
|
|
198
|
+
assertOriginReadTimeout(readTimeout, 'CanopyCmsDistribution');
|
|
203
199
|
const origin = origins.FunctionUrlOrigin.withOriginAccessControl(props.functionUrl, {
|
|
204
200
|
readTimeout,
|
|
205
201
|
});
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
// cookieBehavior/queryStringBehavior `all()` ("The parameter CookieBehavior
|
|
210
|
-
// is invalid for policy with caching disabled"). With TTL 0 the cache key is
|
|
211
|
-
// meaningless anyway, and the origin still receives the full viewer request
|
|
212
|
-
// (headers/cookies/query string, minus Host - forwarding Host would break
|
|
213
|
-
// the OAC-signed Function URL) via the ALL_VIEWER_EXCEPT_HOST_HEADER origin
|
|
214
|
-
// request policy on the behavior.
|
|
215
|
-
const noCachePolicy = cloudfront.CachePolicy.CACHING_DISABLED;
|
|
216
|
-
const staticCachePolicy = new cloudfront.CachePolicy(this, 'StaticCachePolicy', {
|
|
217
|
-
defaultTtl: Duration.days(365),
|
|
218
|
-
maxTtl: Duration.days(365),
|
|
219
|
-
minTtl: Duration.days(365),
|
|
220
|
-
headerBehavior: cloudfront.CacheHeaderBehavior.none(),
|
|
221
|
-
queryStringBehavior: cloudfront.CacheQueryStringBehavior.none(),
|
|
222
|
-
cookieBehavior: cloudfront.CacheCookieBehavior.none(),
|
|
223
|
-
});
|
|
224
|
-
// CloudFront gives the origin the Function URL's own Host (forwarding the
|
|
225
|
-
// viewer Host would break the OAC SigV4 signature), and Lambda Web Adapter
|
|
226
|
-
// forwards no `x-forwarded-*` headers of its own - so without this function,
|
|
227
|
-
// Clerk/Next derive sign-in redirect URLs from the IAM-authed Function URL
|
|
228
|
-
// host instead of the public domain, and the redirect 403s (direct Function
|
|
229
|
-
// URL hits are rejected).
|
|
230
|
-
//
|
|
231
|
-
// ONLY x-forwarded-host: x-forwarded-proto is on CloudFront Functions'
|
|
232
|
-
// DISALLOWED header list and setting it fails every request with 502
|
|
233
|
-
// FunctionValidationError. Proto is unambiguous anyway - viewer-facing
|
|
234
|
-
// CloudFront is HTTPS-only via REDIRECT_TO_HTTPS.
|
|
235
|
-
const forwardedHostFunction = new cloudfront.Function(this, 'ForwardedHostFunction', {
|
|
236
|
-
code: cloudfront.FunctionCode.fromInline([
|
|
237
|
-
'function handler(event) {',
|
|
238
|
-
' var request = event.request;',
|
|
239
|
-
" request.headers['x-forwarded-host'] = { value: request.headers.host.value };",
|
|
240
|
-
' return request;',
|
|
241
|
-
'}',
|
|
242
|
-
].join('\n')),
|
|
243
|
-
});
|
|
202
|
+
const staticCachePolicy = createStaticCachePolicy(this, 'StaticCachePolicy');
|
|
203
|
+
const forwardedHostFunction = createForwardedHostFunction(this, 'ForwardedHostFunction');
|
|
204
|
+
const responseHeadersPolicy = createEditorResponseHeadersPolicy(this, 'EditorResponseHeadersPolicy');
|
|
244
205
|
this.distribution = new cloudfront.Distribution(this, 'Distribution', {
|
|
245
206
|
domainNames: [props.domainName],
|
|
246
207
|
certificate,
|
|
247
208
|
defaultBehavior: {
|
|
248
209
|
origin,
|
|
249
|
-
|
|
250
|
-
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
251
|
-
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
|
|
252
|
-
originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
|
|
253
|
-
functionAssociations: [
|
|
254
|
-
{
|
|
255
|
-
function: forwardedHostFunction,
|
|
256
|
-
eventType: cloudfront.FunctionEventType.VIEWER_REQUEST,
|
|
257
|
-
},
|
|
258
|
-
],
|
|
210
|
+
...lambdaBehaviorOptions(forwardedHostFunction, responseHeadersPolicy),
|
|
259
211
|
},
|
|
260
212
|
additionalBehaviors: mergeBehaviors({
|
|
261
213
|
'/_next/static/*': {
|
|
262
214
|
origin,
|
|
263
215
|
cachePolicy: staticCachePolicy,
|
|
264
216
|
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
217
|
+
responseHeadersPolicy,
|
|
265
218
|
},
|
|
266
219
|
}, props.additionalBehaviors, props.assetSupport !== undefined),
|
|
267
220
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Construct } from 'constructs';
|
|
2
|
-
import { Duration, RemovalPolicy, aws_ec2 as ec2, aws_efs as efs, aws_iam as iam, aws_lambda as lambda, aws_autoscaling as autoscaling, aws_logs as logs } from 'aws-cdk-lib';
|
|
2
|
+
import { Duration, RemovalPolicy, aws_ec2 as ec2, aws_efs as efs, aws_cloudfront as cloudfront, aws_iam as iam, aws_lambda as lambda, aws_autoscaling as autoscaling, aws_logs as logs } from 'aws-cdk-lib';
|
|
3
3
|
import type { IBucket } from 'aws-cdk-lib/aws-s3';
|
|
4
|
+
import type { CanopyCmsAttachOptions } from './editor-routing.js';
|
|
4
5
|
/**
|
|
5
6
|
* Default CMS Lambda timeout.
|
|
6
7
|
*
|
|
@@ -20,8 +21,6 @@ import type { IBucket } from 'aws-cdk-lib/aws-s3';
|
|
|
20
21
|
* than deploying a configuration that would 504.
|
|
21
22
|
*/
|
|
22
23
|
export declare const DEFAULT_CMS_LAMBDA_TIMEOUT: Duration;
|
|
23
|
-
/** CloudFront's maximum origin read timeout without a service-quota increase. */
|
|
24
|
-
export declare const MAX_CLOUDFRONT_ORIGIN_READ_TIMEOUT: Duration;
|
|
25
24
|
export interface CanopyCmsServiceProps {
|
|
26
25
|
/** Docker image for the CMS Lambda function */
|
|
27
26
|
cmsDockerImage: lambda.DockerImageCode;
|
|
@@ -360,4 +359,25 @@ export declare class CanopyCmsService extends Construct {
|
|
|
360
359
|
/** The EC2 worker's CloudWatch log group (worker stdout/stderr) */
|
|
361
360
|
readonly workerLogGroup: logs.LogGroup;
|
|
362
361
|
constructor(scope: Construct, id: string, props: CanopyCmsServiceProps);
|
|
362
|
+
/**
|
|
363
|
+
* Serve the editor from a CloudFront distribution you already own, such as
|
|
364
|
+
* the site's: adds `/edit`, `/edit/*` and `/api/canopycms/*` behaviors
|
|
365
|
+
* (plus any `previewPrefix` and `editorAssetPrefix` routes) to this
|
|
366
|
+
* service's Function URL, behind OAC, with
|
|
367
|
+
* an origin read timeout equal to {@link timeout}, no caching, the whole
|
|
368
|
+
* viewer request forwarded, an `x-forwarded-host` viewer-request function and
|
|
369
|
+
* the editor's response headers policy (framing protection, `noindex`).
|
|
370
|
+
*
|
|
371
|
+
* The behaviors are appended. Synth fails if a behavior listed before them
|
|
372
|
+
* matches an editor route, since CloudFront would never reach the editor's.
|
|
373
|
+
* It warns when the distribution has custom error responses, which also
|
|
374
|
+
* rewrite the API's errors.
|
|
375
|
+
*
|
|
376
|
+
* Pass `editorAssetPrefix` with the CMS build's Next `assetPrefix`, so the
|
|
377
|
+
* editor's chunks stay out of the site's `/_next/static/*`, and
|
|
378
|
+
* `previewPrefix` with a static-export site's preview route.
|
|
379
|
+
* `AssetSupport.attachTo` adds `/assets/*`. Use `CanopyCmsDistribution`
|
|
380
|
+
* instead when the CMS gets a domain of its own.
|
|
381
|
+
*/
|
|
382
|
+
attachTo(distribution: cloudfront.Distribution, options?: CanopyCmsAttachOptions): void;
|
|
363
383
|
}
|
|
@@ -3,6 +3,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
3
3
|
import { Construct } from 'constructs';
|
|
4
4
|
import { Duration, RemovalPolicy, Stack, Token, aws_ec2 as ec2, aws_efs as efs, aws_iam as iam, aws_lambda as lambda, aws_autoscaling as autoscaling, aws_s3_assets as s3assets, aws_logs as logs, } from 'aws-cdk-lib';
|
|
5
5
|
import { attachLambdaExecutionPolicies } from './lambda-execution-role.js';
|
|
6
|
+
import { attachEditorBehaviors } from './editor-routing.js';
|
|
6
7
|
// This package (`canopycms-cdk`) is `"type": "module"`, so its compiled output
|
|
7
8
|
// is real ESM and `__dirname` is not a global there - the worker asset path
|
|
8
9
|
// below throws `__dirname is not defined` under a real ESM runtime (e.g. `tsx`)
|
|
@@ -455,8 +456,6 @@ function assertGitHubAuthProps(props) {
|
|
|
455
456
|
* than deploying a configuration that would 504.
|
|
456
457
|
*/
|
|
457
458
|
export const DEFAULT_CMS_LAMBDA_TIMEOUT = Duration.seconds(60);
|
|
458
|
-
/** CloudFront's maximum origin read timeout without a service-quota increase. */
|
|
459
|
-
export const MAX_CLOUDFRONT_ORIGIN_READ_TIMEOUT = Duration.seconds(60);
|
|
460
459
|
/**
|
|
461
460
|
* Core CDK construct for CanopyCMS deployment.
|
|
462
461
|
*
|
|
@@ -986,4 +985,27 @@ export class CanopyCmsService extends Construct {
|
|
|
986
985
|
// EC2-health-checked ASG never notices.
|
|
987
986
|
this.workerAsg.node.addDependency(this.fileSystem.mountTargetsAvailable);
|
|
988
987
|
}
|
|
988
|
+
/**
|
|
989
|
+
* Serve the editor from a CloudFront distribution you already own, such as
|
|
990
|
+
* the site's: adds `/edit`, `/edit/*` and `/api/canopycms/*` behaviors
|
|
991
|
+
* (plus any `previewPrefix` and `editorAssetPrefix` routes) to this
|
|
992
|
+
* service's Function URL, behind OAC, with
|
|
993
|
+
* an origin read timeout equal to {@link timeout}, no caching, the whole
|
|
994
|
+
* viewer request forwarded, an `x-forwarded-host` viewer-request function and
|
|
995
|
+
* the editor's response headers policy (framing protection, `noindex`).
|
|
996
|
+
*
|
|
997
|
+
* The behaviors are appended. Synth fails if a behavior listed before them
|
|
998
|
+
* matches an editor route, since CloudFront would never reach the editor's.
|
|
999
|
+
* It warns when the distribution has custom error responses, which also
|
|
1000
|
+
* rewrite the API's errors.
|
|
1001
|
+
*
|
|
1002
|
+
* Pass `editorAssetPrefix` with the CMS build's Next `assetPrefix`, so the
|
|
1003
|
+
* editor's chunks stay out of the site's `/_next/static/*`, and
|
|
1004
|
+
* `previewPrefix` with a static-export site's preview route.
|
|
1005
|
+
* `AssetSupport.attachTo` adds `/assets/*`. Use `CanopyCmsDistribution`
|
|
1006
|
+
* instead when the CMS gets a domain of its own.
|
|
1007
|
+
*/
|
|
1008
|
+
attachTo(distribution, options) {
|
|
1009
|
+
attachEditorBehaviors(distribution, this.functionUrl, this.timeout, options);
|
|
1010
|
+
}
|
|
989
1011
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Construct } from 'constructs';
|
|
2
|
+
import { Duration, aws_cloudfront as cloudfront, aws_lambda as lambda } from 'aws-cdk-lib';
|
|
3
|
+
/** CloudFront's maximum origin read timeout without a service-quota increase. */
|
|
4
|
+
export declare const MAX_CLOUDFRONT_ORIGIN_READ_TIMEOUT: Duration;
|
|
5
|
+
/**
|
|
6
|
+
* The routes the editor needs from the CMS Lambda on a distribution it shares
|
|
7
|
+
* with a site: the editor page and the catch-all API route `canopycms init`
|
|
8
|
+
* scaffolds. `/edit` and `/edit/*` rather than `/edit*`, which also matches
|
|
9
|
+
* `/editorial` and `/edit-assets/…` and so takes site pages away from the site.
|
|
10
|
+
*
|
|
11
|
+
* Not included, because on a shared distribution they belong to the site:
|
|
12
|
+
* `/_next/static/*` (the CMS build moves its chunks out of it with Next's
|
|
13
|
+
* `assetPrefix`; see `editorAssetPrefix`) and `/assets/*`
|
|
14
|
+
* (`AssetSupport.attachTo` owns it).
|
|
15
|
+
*/
|
|
16
|
+
export declare const EDITOR_PATH_PATTERNS: readonly ["/edit", "/edit/*", "/api/canopycms/*"];
|
|
17
|
+
/**
|
|
18
|
+
* Whether a CloudFront path pattern matches a request path: `*` is any run of
|
|
19
|
+
* characters, `?` exactly one, matching is case-sensitive, and the pattern's
|
|
20
|
+
* leading `/` is optional.
|
|
21
|
+
*/
|
|
22
|
+
export declare function cloudFrontPathPatternMatches(pattern: string, path: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Throws when the origin read timeout exceeds the 60s CloudFront accepts
|
|
25
|
+
* without a quota increase, which it would reject at deploy. Neither construct
|
|
26
|
+
* takes a higher, quota-raised value.
|
|
27
|
+
*/
|
|
28
|
+
export declare function assertOriginReadTimeout(readTimeout: Duration, owner: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* The viewer-request function every Lambda behavior needs. CloudFront gives
|
|
31
|
+
* the origin the Function URL's own Host (forwarding the viewer Host would
|
|
32
|
+
* break the OAC SigV4 signature), and Lambda Web Adapter adds no
|
|
33
|
+
* `x-forwarded-*` headers, so without this Clerk/Next derive sign-in redirect
|
|
34
|
+
* URLs from the IAM-authed Function URL host and the redirect 403s.
|
|
35
|
+
*
|
|
36
|
+
* Only `x-forwarded-host`: `x-forwarded-proto` is on CloudFront Functions'
|
|
37
|
+
* disallowed list and setting it fails every request with a 502. The viewer
|
|
38
|
+
* side is HTTPS-only, so proto is unambiguous anyway.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createForwardedHostFunction(scope: Construct, id: string): cloudfront.Function;
|
|
41
|
+
/**
|
|
42
|
+
* Response headers for everything the CMS Lambda serves.
|
|
43
|
+
*
|
|
44
|
+
* - `frame-ancestors 'self'` (plus `X-Frame-Options: SAMEORIGIN` for browsers
|
|
45
|
+
* that ignore it) stops other sites framing the editor. `'self'` keeps the
|
|
46
|
+
* editor's own preview iframe working, which frames same-origin site pages.
|
|
47
|
+
* - Both framing headers have `override: false`, so an origin that sends its
|
|
48
|
+
* own CSP keeps it whole; when that CSP has no `frame-ancestors` and the
|
|
49
|
+
* origin sends no `X-Frame-Options`, this one applies.
|
|
50
|
+
* - `X-Robots-Tag: noindex` overrides: nothing the Lambda serves is meant to
|
|
51
|
+
* be indexed.
|
|
52
|
+
* - No `Cross-Origin-Opener-Policy`: it can cut the `window.opener` link a
|
|
53
|
+
* popup-based OAuth sign-in reports back through.
|
|
54
|
+
*/
|
|
55
|
+
export declare function createEditorResponseHeadersPolicy(scope: Construct, id: string): cloudfront.ResponseHeadersPolicy;
|
|
56
|
+
/**
|
|
57
|
+
* A year-long cache for content-hashed build output. The cache key carries no
|
|
58
|
+
* header, cookie or query string, so every viewer shares one copy.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createStaticCachePolicy(scope: Construct, id: string): cloudfront.CachePolicy;
|
|
61
|
+
/**
|
|
62
|
+
* Behavior options for a route the CMS Lambda serves. The managed
|
|
63
|
+
* CACHING_DISABLED policy as it is: CloudFront rejects any non-none cache-key
|
|
64
|
+
* setting on a caching-disabled policy, and the origin still gets the whole
|
|
65
|
+
* viewer request (headers, cookies, query string, minus Host, which would
|
|
66
|
+
* break the OAC signature) through ALL_VIEWER_EXCEPT_HOST_HEADER.
|
|
67
|
+
*/
|
|
68
|
+
export declare function lambdaBehaviorOptions(viewerRequestFunction: cloudfront.FunctionAssociation['function'] | undefined, responseHeadersPolicy: NonNullable<cloudfront.AddBehaviorOptions['responseHeadersPolicy']>): cloudfront.AddBehaviorOptions;
|
|
69
|
+
/** Options for `CanopyCmsService.attachTo`. */
|
|
70
|
+
export interface CanopyCmsAttachOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Viewer-request function for the editor behaviors, in place of the
|
|
73
|
+
* `x-forwarded-host` function `attachTo` otherwise creates. CloudFront allows
|
|
74
|
+
* one per behavior, so pass this when the distribution's own function must
|
|
75
|
+
* run on every route.
|
|
76
|
+
*
|
|
77
|
+
* It must set `x-forwarded-host` from the viewer's Host, or sign-in
|
|
78
|
+
* redirects point at the Function URL and 403. It must not gate on HTTP
|
|
79
|
+
* Basic auth: the API answers 401 without `WWW-Authenticate`, and a browser
|
|
80
|
+
* that sees that drops its cached Basic credential and prompts again.
|
|
81
|
+
*
|
|
82
|
+
* @default - a function that sets `x-forwarded-host` and nothing else
|
|
83
|
+
*/
|
|
84
|
+
viewerRequestFunction?: cloudfront.IFunction;
|
|
85
|
+
/**
|
|
86
|
+
* Options merged into the editor and preview behaviors, after this construct's
|
|
87
|
+
* own; keys whose value is `undefined` are ignored. A `responseHeadersPolicy`
|
|
88
|
+
* here replaces the editor's framing protection, so it must carry its own.
|
|
89
|
+
* `functionAssociations` here replaces the viewer-request function as well,
|
|
90
|
+
* which is why it cannot be combined with `viewerRequestFunction`.
|
|
91
|
+
*
|
|
92
|
+
* @default - no overrides
|
|
93
|
+
*/
|
|
94
|
+
behaviorOverrides?: Partial<cloudfront.AddBehaviorOptions>;
|
|
95
|
+
/**
|
|
96
|
+
* The CMS build's Next `assetPrefix`, such as `'/edit-assets'`: adds a
|
|
97
|
+
* `/<prefix>/*` behavior to the Lambda with a year-long cache, since the
|
|
98
|
+
* chunks under it are content-hashed.
|
|
99
|
+
*
|
|
100
|
+
* A CMS build that shares a distribution with a static site needs one.
|
|
101
|
+
* Without it the editor page loads its chunks from `/_next/static/*`, which
|
|
102
|
+
* the site serves, and they 404. Set `assetPrefix` in the CMS build's
|
|
103
|
+
* `next.config` only (not the static export's) and pass the same value here.
|
|
104
|
+
*
|
|
105
|
+
* A path starting with `/`, without a trailing `/` or wildcards, and
|
|
106
|
+
* overlapping neither the editor's routes, `/_next/*` nor AssetSupport's
|
|
107
|
+
* `/assets/*`. Of `behaviorOverrides`, only `responseHeadersPolicy` applies
|
|
108
|
+
* to this behavior.
|
|
109
|
+
*
|
|
110
|
+
* @default - no asset-prefix behavior
|
|
111
|
+
*/
|
|
112
|
+
editorAssetPrefix?: string;
|
|
113
|
+
/**
|
|
114
|
+
* The path of the CMS-only preview route, the same value as
|
|
115
|
+
* `editor.previewPrefix` in the CanopyCMS config (e.g. `'/preview'`): adds
|
|
116
|
+
* `<prefix>` and `<prefix>/*` behaviors with the editor routes' options, so
|
|
117
|
+
* the editor's preview pane reaches the CMS rather than the site.
|
|
118
|
+
*
|
|
119
|
+
* Validated like `editorAssetPrefix`, and must not overlap it either. An
|
|
120
|
+
* absolute `https://` `previewPrefix` is another origin and needs nothing
|
|
121
|
+
* here.
|
|
122
|
+
*
|
|
123
|
+
* @default - no preview behaviors
|
|
124
|
+
*/
|
|
125
|
+
previewPrefix?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Attach the editor's behaviors to a distribution. See
|
|
129
|
+
* `CanopyCmsService.attachTo`, which is the public entry point.
|
|
130
|
+
*/
|
|
131
|
+
export declare function attachEditorBehaviors(distribution: cloudfront.Distribution, functionUrl: lambda.IFunctionUrl, readTimeout: Duration, options?: CanopyCmsAttachOptions): void;
|