@jaypie/constructs 1.2.29 → 1.2.31

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.
@@ -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
  /**
@@ -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;
@@ -169,6 +169,11 @@ const CDK$2 = {
169
169
  PROJECT: {
170
170
  INFRASTRUCTURE: "infrastructure",
171
171
  },
172
+ SECURITY_HEADERS: {
173
+ 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';",
174
+ HSTS_MAX_AGE: 63072000, // 2 years
175
+ PERMISSIONS_POLICY: "camera=(), microphone=(), geolocation=(), payment=()",
176
+ },
172
177
  ROLE: {
173
178
  API: "api",
174
179
  DEPLOY: "deploy",
@@ -2364,7 +2369,7 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
2364
2369
  class JaypieDistribution extends constructs.Construct {
2365
2370
  constructor(scope, id, props) {
2366
2371
  super(scope, id);
2367
- const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, logBucket: logBucketProp, originReadTimeout = cdk.Duration.seconds(CDK$2.DURATION.CLOUDFRONT_API), roleTag = CDK$2.ROLE.API, streaming = false, zone: propsZone, ...distributionProps } = props;
2372
+ const { certificate: certificateProp = true, defaultBehavior: propsDefaultBehavior, destination: destinationProp = true, handler, host: propsHost, logBucket: logBucketProp, originReadTimeout = cdk.Duration.seconds(CDK$2.DURATION.CLOUDFRONT_API), responseHeadersPolicy: responseHeadersPolicyProp, roleTag = CDK$2.ROLE.API, securityHeaders: securityHeadersProp, streaming = false, zone: propsZone, ...distributionProps } = props;
2368
2373
  // Validate environment variables
2369
2374
  if (process.env.CDK_ENV_API_SUBDOMAIN &&
2370
2375
  !isValidSubdomain(process.env.CDK_ENV_API_SUBDOMAIN)) {
@@ -2446,6 +2451,72 @@ class JaypieDistribution extends constructs.Construct {
2446
2451
  handler.addEnvironment("PROJECT_BASE_URL", `https://${host}`);
2447
2452
  }
2448
2453
  }
2454
+ // Resolve response headers policy for security headers
2455
+ let resolvedResponseHeadersPolicy;
2456
+ if (responseHeadersPolicyProp) {
2457
+ resolvedResponseHeadersPolicy = responseHeadersPolicyProp;
2458
+ }
2459
+ else if (securityHeadersProp !== false) {
2460
+ const overrides = typeof securityHeadersProp === "object" ? securityHeadersProp : {};
2461
+ resolvedResponseHeadersPolicy = new cloudfront__namespace.ResponseHeadersPolicy(this, "SecurityHeaders", {
2462
+ customHeadersBehavior: {
2463
+ customHeaders: [
2464
+ {
2465
+ header: "Cache-Control",
2466
+ override: true,
2467
+ value: "no-store, no-cache, must-revalidate, proxy-revalidate",
2468
+ },
2469
+ {
2470
+ header: "Cross-Origin-Embedder-Policy",
2471
+ override: true,
2472
+ value: "unsafe-none",
2473
+ },
2474
+ {
2475
+ header: "Cross-Origin-Opener-Policy",
2476
+ override: true,
2477
+ value: "same-origin",
2478
+ },
2479
+ {
2480
+ header: "Cross-Origin-Resource-Policy",
2481
+ override: true,
2482
+ value: "same-origin",
2483
+ },
2484
+ {
2485
+ header: "Permissions-Policy",
2486
+ override: true,
2487
+ value: overrides.permissionsPolicy ??
2488
+ CDK$2.SECURITY_HEADERS.PERMISSIONS_POLICY,
2489
+ },
2490
+ ],
2491
+ },
2492
+ removeHeaders: ["Server"],
2493
+ securityHeadersBehavior: {
2494
+ contentSecurityPolicy: {
2495
+ contentSecurityPolicy: overrides.contentSecurityPolicy ??
2496
+ CDK$2.SECURITY_HEADERS.CONTENT_SECURITY_POLICY,
2497
+ override: true,
2498
+ },
2499
+ contentTypeOptions: { override: true },
2500
+ frameOptions: {
2501
+ frameOption: overrides.frameOption ?? cloudfront__namespace.HeadersFrameOption.DENY,
2502
+ override: true,
2503
+ },
2504
+ referrerPolicy: {
2505
+ referrerPolicy: overrides.referrerPolicy ??
2506
+ cloudfront__namespace.HeadersReferrerPolicy
2507
+ .STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
2508
+ override: true,
2509
+ },
2510
+ strictTransportSecurity: {
2511
+ accessControlMaxAge: cdk.Duration.seconds(overrides.hstsMaxAge ?? CDK$2.SECURITY_HEADERS.HSTS_MAX_AGE),
2512
+ includeSubdomains: overrides.hstsIncludeSubdomains ?? true,
2513
+ override: true,
2514
+ preload: true,
2515
+ },
2516
+ },
2517
+ });
2518
+ }
2519
+ this.responseHeadersPolicy = resolvedResponseHeadersPolicy;
2449
2520
  // Build default behavior
2450
2521
  let defaultBehavior;
2451
2522
  if (propsDefaultBehavior) {
@@ -2457,6 +2528,9 @@ class JaypieDistribution extends constructs.Construct {
2457
2528
  cachePolicy: cloudfront__namespace.CachePolicy.CACHING_DISABLED,
2458
2529
  origin,
2459
2530
  originRequestPolicy: cloudfront__namespace.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
2531
+ ...(resolvedResponseHeadersPolicy
2532
+ ? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
2533
+ : {}),
2460
2534
  viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2461
2535
  };
2462
2536
  }
@@ -2764,12 +2838,6 @@ function indexesToGsi(indexes) {
2764
2838
  * const table = new JaypieDynamoDb(this, "myApp");
2765
2839
  *
2766
2840
  * @example
2767
- * // With default Jaypie indexes
2768
- * const table = new JaypieDynamoDb(this, "myApp", {
2769
- * indexes: JaypieDynamoDb.DEFAULT_INDEXES,
2770
- * });
2771
- *
2772
- * @example
2773
2841
  * // With explicit table name (overrides CDK-generated name)
2774
2842
  * const table = new JaypieDynamoDb(this, "MyTable", {
2775
2843
  * tableName: "custom-table-name",
@@ -2908,11 +2976,6 @@ class JaypieDynamoDb extends constructs.Construct {
2908
2976
  return this._table.metricUserErrors(props);
2909
2977
  }
2910
2978
  }
2911
- /**
2912
- * Default Jaypie GSI definitions from @jaypie/fabric.
2913
- * Pass to `indexes` prop to create all standard GSIs.
2914
- */
2915
- JaypieDynamoDb.DEFAULT_INDEXES = fabric.DEFAULT_INDEXES;
2916
2979
 
2917
2980
  class JaypieEventsRule extends constructs.Construct {
2918
2981
  /**