@jaypie/constructs 1.2.28 → 1.2.30
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/dist/cjs/JaypieDistribution.d.ts +22 -0
- package/dist/cjs/JaypieDynamoDb.d.ts +0 -19
- package/dist/cjs/constants.d.ts +5 -0
- package/dist/cjs/index.cjs +78 -13
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/esm/JaypieDistribution.d.ts +22 -0
- package/dist/esm/JaypieDynamoDb.d.ts +0 -19
- package/dist/esm/constants.d.ts +5 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +79 -14
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { JaypieCertificate, JaypieCertificateProps } from "./JaypieCertificate";
|
|
|
7
7
|
export { JaypieDatadogBucket, JaypieDatadogBucketProps, } from "./JaypieDatadogBucket";
|
|
8
8
|
export { JaypieDatadogForwarder, JaypieDatadogForwarderProps, } from "./JaypieDatadogForwarder";
|
|
9
9
|
export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
|
|
10
|
-
export { JaypieDistribution, JaypieDistributionProps, } from "./JaypieDistribution";
|
|
10
|
+
export { JaypieDistribution, JaypieDistributionProps, SecurityHeadersOverrides, } from "./JaypieDistribution";
|
|
11
11
|
export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
|
|
12
12
|
export { JaypieDynamoDb, JaypieDynamoDbProps } from "./JaypieDynamoDb";
|
|
13
13
|
export type { IndexDefinition } from "@jaypie/fabric";
|
|
@@ -7,6 +7,14 @@ import * as s3 from "aws-cdk-lib/aws-s3";
|
|
|
7
7
|
import { LambdaDestination } from "aws-cdk-lib/aws-s3-notifications";
|
|
8
8
|
import { Construct } from "constructs";
|
|
9
9
|
import { HostConfig } from "./helpers";
|
|
10
|
+
export interface SecurityHeadersOverrides {
|
|
11
|
+
contentSecurityPolicy?: string;
|
|
12
|
+
frameOption?: cloudfront.HeadersFrameOption;
|
|
13
|
+
hstsIncludeSubdomains?: boolean;
|
|
14
|
+
hstsMaxAge?: number;
|
|
15
|
+
permissionsPolicy?: string;
|
|
16
|
+
referrerPolicy?: cloudfront.HeadersReferrerPolicy;
|
|
17
|
+
}
|
|
10
18
|
export interface JaypieDistributionProps extends Omit<cloudfront.DistributionProps, "certificate" | "defaultBehavior" | "logBucket"> {
|
|
11
19
|
/**
|
|
12
20
|
* SSL certificate for the CloudFront distribution
|
|
@@ -73,6 +81,19 @@ export interface JaypieDistributionProps extends Omit<cloudfront.DistributionPro
|
|
|
73
81
|
* @max Duration.seconds(120)
|
|
74
82
|
*/
|
|
75
83
|
originReadTimeout?: Duration;
|
|
84
|
+
/**
|
|
85
|
+
* Full override for the response headers policy.
|
|
86
|
+
* When provided, bypasses all default security header logic.
|
|
87
|
+
*/
|
|
88
|
+
responseHeadersPolicy?: cloudfront.IResponseHeadersPolicy;
|
|
89
|
+
/**
|
|
90
|
+
* Security headers configuration.
|
|
91
|
+
* - true/undefined: apply sensible defaults (HSTS, X-Frame-Options, CSP, etc.)
|
|
92
|
+
* - false: disable security headers entirely
|
|
93
|
+
* - SecurityHeadersOverrides object: merge overrides with defaults
|
|
94
|
+
* @default true
|
|
95
|
+
*/
|
|
96
|
+
securityHeaders?: boolean | SecurityHeadersOverrides;
|
|
76
97
|
/**
|
|
77
98
|
* Role tag for tagging resources
|
|
78
99
|
* @default CDK.ROLE.HOSTING
|
|
@@ -94,6 +115,7 @@ export declare class JaypieDistribution extends Construct implements cloudfront.
|
|
|
94
115
|
readonly functionUrl?: lambda.FunctionUrl;
|
|
95
116
|
readonly host?: string;
|
|
96
117
|
readonly logBucket?: s3.IBucket;
|
|
118
|
+
readonly responseHeadersPolicy?: cloudfront.IResponseHeadersPolicy;
|
|
97
119
|
constructor(scope: Construct, id: string, props: JaypieDistributionProps);
|
|
98
120
|
private isIOrigin;
|
|
99
121
|
private isIFunctionUrl;
|
|
@@ -8,19 +8,11 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
|
|
|
8
8
|
* - `undefined`: No GSIs (default)
|
|
9
9
|
* - Array of IndexDefinition: Use the specified indexes
|
|
10
10
|
*
|
|
11
|
-
* Use `JaypieDynamoDb.DEFAULT_INDEXES` for the standard Jaypie GSIs.
|
|
12
|
-
*
|
|
13
11
|
* @example
|
|
14
12
|
* // No GSIs (default)
|
|
15
13
|
* new JaypieDynamoDb(this, "myTable");
|
|
16
14
|
*
|
|
17
15
|
* @example
|
|
18
|
-
* // With default Jaypie indexes
|
|
19
|
-
* new JaypieDynamoDb(this, "myTable", {
|
|
20
|
-
* indexes: JaypieDynamoDb.DEFAULT_INDEXES,
|
|
21
|
-
* });
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
16
|
* // With custom indexes
|
|
25
17
|
* new JaypieDynamoDb(this, "myTable", {
|
|
26
18
|
* indexes: [
|
|
@@ -73,12 +65,6 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
|
|
|
73
65
|
* const table = new JaypieDynamoDb(this, "myApp");
|
|
74
66
|
*
|
|
75
67
|
* @example
|
|
76
|
-
* // With default Jaypie indexes
|
|
77
|
-
* const table = new JaypieDynamoDb(this, "myApp", {
|
|
78
|
-
* indexes: JaypieDynamoDb.DEFAULT_INDEXES,
|
|
79
|
-
* });
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
68
|
* // With explicit table name (overrides CDK-generated name)
|
|
83
69
|
* const table = new JaypieDynamoDb(this, "MyTable", {
|
|
84
70
|
* tableName: "custom-table-name",
|
|
@@ -89,11 +75,6 @@ export interface JaypieDynamoDbProps extends Omit<dynamodb.TablePropsV2, "global
|
|
|
89
75
|
* });
|
|
90
76
|
*/
|
|
91
77
|
export declare class JaypieDynamoDb extends Construct implements dynamodb.ITableV2 {
|
|
92
|
-
/**
|
|
93
|
-
* Default Jaypie GSI definitions from @jaypie/fabric.
|
|
94
|
-
* Pass to `indexes` prop to create all standard GSIs.
|
|
95
|
-
*/
|
|
96
|
-
static readonly DEFAULT_INDEXES: IndexDefinition[];
|
|
97
78
|
private readonly _table;
|
|
98
79
|
constructor(scope: Construct, id: string, props?: JaypieDynamoDbProps);
|
|
99
80
|
/**
|
package/dist/esm/constants.d.ts
CHANGED
|
@@ -98,6 +98,11 @@ export declare const CDK: {
|
|
|
98
98
|
PROJECT: {
|
|
99
99
|
INFRASTRUCTURE: string;
|
|
100
100
|
};
|
|
101
|
+
SECURITY_HEADERS: {
|
|
102
|
+
CONTENT_SECURITY_POLICY: string;
|
|
103
|
+
HSTS_MAX_AGE: number;
|
|
104
|
+
PERMISSIONS_POLICY: string;
|
|
105
|
+
};
|
|
101
106
|
ROLE: {
|
|
102
107
|
API: string;
|
|
103
108
|
DEPLOY: string;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { JaypieCertificate, JaypieCertificateProps } from "./JaypieCertificate";
|
|
|
7
7
|
export { JaypieDatadogBucket, JaypieDatadogBucketProps, } from "./JaypieDatadogBucket";
|
|
8
8
|
export { JaypieDatadogForwarder, JaypieDatadogForwarderProps, } from "./JaypieDatadogForwarder";
|
|
9
9
|
export { JaypieDatadogSecret } from "./JaypieDatadogSecret";
|
|
10
|
-
export { JaypieDistribution, JaypieDistributionProps, } from "./JaypieDistribution";
|
|
10
|
+
export { JaypieDistribution, JaypieDistributionProps, SecurityHeadersOverrides, } from "./JaypieDistribution";
|
|
11
11
|
export { JaypieDnsRecord, JaypieDnsRecordProps } from "./JaypieDnsRecord";
|
|
12
12
|
export { JaypieDynamoDb, JaypieDynamoDbProps } from "./JaypieDynamoDb";
|
|
13
13
|
export type { IndexDefinition } from "@jaypie/fabric";
|
package/dist/esm/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets';
|
|
|
25
25
|
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
|
|
26
26
|
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
|
|
27
27
|
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
28
|
-
import {
|
|
28
|
+
import { generateIndexName, DEFAULT_SORT_KEY } from '@jaypie/fabric';
|
|
29
29
|
import { Nextjs } from 'cdk-nextjs-standalone';
|
|
30
30
|
import * as path from 'path';
|
|
31
31
|
import { Trail, ReadWriteType } from 'aws-cdk-lib/aws-cloudtrail';
|
|
@@ -135,6 +135,11 @@ const CDK$2 = {
|
|
|
135
135
|
PROJECT: {
|
|
136
136
|
INFRASTRUCTURE: "infrastructure",
|
|
137
137
|
},
|
|
138
|
+
SECURITY_HEADERS: {
|
|
139
|
+
CONTENT_SECURITY_POLICY: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; frame-ancestors 'none'; base-uri 'self'; form-action 'self';",
|
|
140
|
+
HSTS_MAX_AGE: 63072000, // 2 years
|
|
141
|
+
PERMISSIONS_POLICY: "camera=(), microphone=(), geolocation=(), payment=()",
|
|
142
|
+
},
|
|
138
143
|
ROLE: {
|
|
139
144
|
API: "api",
|
|
140
145
|
DEPLOY: "deploy",
|
|
@@ -2330,7 +2335,7 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
|
|
|
2330
2335
|
class JaypieDistribution extends Construct {
|
|
2331
2336
|
constructor(scope, id, props) {
|
|
2332
2337
|
super(scope, id);
|
|
2333
|
-
const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, logBucket: logBucketProp, originReadTimeout = Duration.seconds(CDK$2.DURATION.CLOUDFRONT_API), roleTag = CDK$2.ROLE.API, streaming = false, zone: propsZone, ...distributionProps } = props;
|
|
2338
|
+
const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, logBucket: logBucketProp, originReadTimeout = Duration.seconds(CDK$2.DURATION.CLOUDFRONT_API), responseHeadersPolicy: responseHeadersPolicyProp, roleTag = CDK$2.ROLE.API, securityHeaders: securityHeadersProp, streaming = false, zone: propsZone, ...distributionProps } = props;
|
|
2334
2339
|
// Validate environment variables
|
|
2335
2340
|
if (process.env.CDK_ENV_API_SUBDOMAIN &&
|
|
2336
2341
|
!isValidSubdomain(process.env.CDK_ENV_API_SUBDOMAIN)) {
|
|
@@ -2412,6 +2417,62 @@ class JaypieDistribution extends Construct {
|
|
|
2412
2417
|
handler.addEnvironment("PROJECT_BASE_URL", `https://${host}`);
|
|
2413
2418
|
}
|
|
2414
2419
|
}
|
|
2420
|
+
// Resolve response headers policy for security headers
|
|
2421
|
+
let resolvedResponseHeadersPolicy;
|
|
2422
|
+
if (responseHeadersPolicyProp) {
|
|
2423
|
+
resolvedResponseHeadersPolicy = responseHeadersPolicyProp;
|
|
2424
|
+
}
|
|
2425
|
+
else if (securityHeadersProp !== false) {
|
|
2426
|
+
const overrides = typeof securityHeadersProp === "object" ? securityHeadersProp : {};
|
|
2427
|
+
resolvedResponseHeadersPolicy = new cloudfront.ResponseHeadersPolicy(this, "SecurityHeaders", {
|
|
2428
|
+
customHeadersBehavior: {
|
|
2429
|
+
customHeaders: [
|
|
2430
|
+
{
|
|
2431
|
+
header: "Cross-Origin-Opener-Policy",
|
|
2432
|
+
override: true,
|
|
2433
|
+
value: "same-origin",
|
|
2434
|
+
},
|
|
2435
|
+
{
|
|
2436
|
+
header: "Cross-Origin-Resource-Policy",
|
|
2437
|
+
override: true,
|
|
2438
|
+
value: "same-origin",
|
|
2439
|
+
},
|
|
2440
|
+
{
|
|
2441
|
+
header: "Permissions-Policy",
|
|
2442
|
+
override: true,
|
|
2443
|
+
value: overrides.permissionsPolicy ??
|
|
2444
|
+
CDK$2.SECURITY_HEADERS.PERMISSIONS_POLICY,
|
|
2445
|
+
},
|
|
2446
|
+
],
|
|
2447
|
+
},
|
|
2448
|
+
removeHeaders: ["Server"],
|
|
2449
|
+
securityHeadersBehavior: {
|
|
2450
|
+
contentSecurityPolicy: {
|
|
2451
|
+
contentSecurityPolicy: overrides.contentSecurityPolicy ??
|
|
2452
|
+
CDK$2.SECURITY_HEADERS.CONTENT_SECURITY_POLICY,
|
|
2453
|
+
override: true,
|
|
2454
|
+
},
|
|
2455
|
+
contentTypeOptions: { override: true },
|
|
2456
|
+
frameOptions: {
|
|
2457
|
+
frameOption: overrides.frameOption ?? cloudfront.HeadersFrameOption.DENY,
|
|
2458
|
+
override: true,
|
|
2459
|
+
},
|
|
2460
|
+
referrerPolicy: {
|
|
2461
|
+
referrerPolicy: overrides.referrerPolicy ??
|
|
2462
|
+
cloudfront.HeadersReferrerPolicy
|
|
2463
|
+
.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
|
|
2464
|
+
override: true,
|
|
2465
|
+
},
|
|
2466
|
+
strictTransportSecurity: {
|
|
2467
|
+
accessControlMaxAge: Duration.seconds(overrides.hstsMaxAge ?? CDK$2.SECURITY_HEADERS.HSTS_MAX_AGE),
|
|
2468
|
+
includeSubdomains: overrides.hstsIncludeSubdomains ?? true,
|
|
2469
|
+
override: true,
|
|
2470
|
+
preload: true,
|
|
2471
|
+
},
|
|
2472
|
+
},
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
this.responseHeadersPolicy = resolvedResponseHeadersPolicy;
|
|
2415
2476
|
// Build default behavior
|
|
2416
2477
|
let defaultBehavior;
|
|
2417
2478
|
if (propsDefaultBehavior) {
|
|
@@ -2423,6 +2484,9 @@ class JaypieDistribution extends Construct {
|
|
|
2423
2484
|
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
|
|
2424
2485
|
origin,
|
|
2425
2486
|
originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
|
|
2487
|
+
...(resolvedResponseHeadersPolicy
|
|
2488
|
+
? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
|
|
2489
|
+
: {}),
|
|
2426
2490
|
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
2427
2491
|
};
|
|
2428
2492
|
}
|
|
@@ -2730,12 +2794,6 @@ function indexesToGsi(indexes) {
|
|
|
2730
2794
|
* const table = new JaypieDynamoDb(this, "myApp");
|
|
2731
2795
|
*
|
|
2732
2796
|
* @example
|
|
2733
|
-
* // With default Jaypie indexes
|
|
2734
|
-
* const table = new JaypieDynamoDb(this, "myApp", {
|
|
2735
|
-
* indexes: JaypieDynamoDb.DEFAULT_INDEXES,
|
|
2736
|
-
* });
|
|
2737
|
-
*
|
|
2738
|
-
* @example
|
|
2739
2797
|
* // With explicit table name (overrides CDK-generated name)
|
|
2740
2798
|
* const table = new JaypieDynamoDb(this, "MyTable", {
|
|
2741
2799
|
* tableName: "custom-table-name",
|
|
@@ -2874,11 +2932,6 @@ class JaypieDynamoDb extends Construct {
|
|
|
2874
2932
|
return this._table.metricUserErrors(props);
|
|
2875
2933
|
}
|
|
2876
2934
|
}
|
|
2877
|
-
/**
|
|
2878
|
-
* Default Jaypie GSI definitions from @jaypie/fabric.
|
|
2879
|
-
* Pass to `indexes` prop to create all standard GSIs.
|
|
2880
|
-
*/
|
|
2881
|
-
JaypieDynamoDb.DEFAULT_INDEXES = DEFAULT_INDEXES;
|
|
2882
2935
|
|
|
2883
2936
|
class JaypieEventsRule extends Construct {
|
|
2884
2937
|
/**
|
|
@@ -3661,6 +3714,7 @@ class JaypieSsoPermissions extends Construct {
|
|
|
3661
3714
|
"servicecatalog:*",
|
|
3662
3715
|
"sns:*",
|
|
3663
3716
|
"sqs:*",
|
|
3717
|
+
"ssm:*",
|
|
3664
3718
|
"states:*",
|
|
3665
3719
|
"tag:*",
|
|
3666
3720
|
"uxc:*",
|
|
@@ -3888,8 +3942,9 @@ class JaypieWebDeploymentBucket extends Construct {
|
|
|
3888
3942
|
if (process.env.CDK_ENV_REPO) {
|
|
3889
3943
|
repo = `repo:${process.env.CDK_ENV_REPO}:*`;
|
|
3890
3944
|
}
|
|
3945
|
+
let bucketDeployRole;
|
|
3891
3946
|
if (repo) {
|
|
3892
|
-
|
|
3947
|
+
bucketDeployRole = new Role(this, "DestinationBucketDeployRole", {
|
|
3893
3948
|
assumedBy: new FederatedPrincipal(Fn.importValue(CDK$2.IMPORT.OIDC_PROVIDER), {
|
|
3894
3949
|
StringLike: {
|
|
3895
3950
|
"token.actions.githubusercontent.com:sub": repo,
|
|
@@ -3989,6 +4044,16 @@ class JaypieWebDeploymentBucket extends Construct {
|
|
|
3989
4044
|
new CfnOutput(this, "DistributionId", {
|
|
3990
4045
|
value: this.distribution.distributionId,
|
|
3991
4046
|
});
|
|
4047
|
+
// Add CloudFront invalidation permission to deploy role if it exists
|
|
4048
|
+
if (bucketDeployRole) {
|
|
4049
|
+
bucketDeployRole.addToPolicy(new PolicyStatement({
|
|
4050
|
+
effect: Effect.ALLOW,
|
|
4051
|
+
actions: ["cloudfront:CreateInvalidation"],
|
|
4052
|
+
resources: [
|
|
4053
|
+
`arn:aws:cloudfront::${Stack.of(this).account}:distribution/${this.distribution.distributionId}`,
|
|
4054
|
+
],
|
|
4055
|
+
}));
|
|
4056
|
+
}
|
|
3992
4057
|
}
|
|
3993
4058
|
}
|
|
3994
4059
|
// Implement remaining IBucket methods by delegating to the bucket
|