@jaypie/constructs 1.2.29 → 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.
@@ -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,62 @@ 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: "Cross-Origin-Opener-Policy",
2466
+ override: true,
2467
+ value: "same-origin",
2468
+ },
2469
+ {
2470
+ header: "Cross-Origin-Resource-Policy",
2471
+ override: true,
2472
+ value: "same-origin",
2473
+ },
2474
+ {
2475
+ header: "Permissions-Policy",
2476
+ override: true,
2477
+ value: overrides.permissionsPolicy ??
2478
+ CDK$2.SECURITY_HEADERS.PERMISSIONS_POLICY,
2479
+ },
2480
+ ],
2481
+ },
2482
+ removeHeaders: ["Server"],
2483
+ securityHeadersBehavior: {
2484
+ contentSecurityPolicy: {
2485
+ contentSecurityPolicy: overrides.contentSecurityPolicy ??
2486
+ CDK$2.SECURITY_HEADERS.CONTENT_SECURITY_POLICY,
2487
+ override: true,
2488
+ },
2489
+ contentTypeOptions: { override: true },
2490
+ frameOptions: {
2491
+ frameOption: overrides.frameOption ?? cloudfront__namespace.HeadersFrameOption.DENY,
2492
+ override: true,
2493
+ },
2494
+ referrerPolicy: {
2495
+ referrerPolicy: overrides.referrerPolicy ??
2496
+ cloudfront__namespace.HeadersReferrerPolicy
2497
+ .STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
2498
+ override: true,
2499
+ },
2500
+ strictTransportSecurity: {
2501
+ accessControlMaxAge: cdk.Duration.seconds(overrides.hstsMaxAge ?? CDK$2.SECURITY_HEADERS.HSTS_MAX_AGE),
2502
+ includeSubdomains: overrides.hstsIncludeSubdomains ?? true,
2503
+ override: true,
2504
+ preload: true,
2505
+ },
2506
+ },
2507
+ });
2508
+ }
2509
+ this.responseHeadersPolicy = resolvedResponseHeadersPolicy;
2449
2510
  // Build default behavior
2450
2511
  let defaultBehavior;
2451
2512
  if (propsDefaultBehavior) {
@@ -2457,6 +2518,9 @@ class JaypieDistribution extends constructs.Construct {
2457
2518
  cachePolicy: cloudfront__namespace.CachePolicy.CACHING_DISABLED,
2458
2519
  origin,
2459
2520
  originRequestPolicy: cloudfront__namespace.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
2521
+ ...(resolvedResponseHeadersPolicy
2522
+ ? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
2523
+ : {}),
2460
2524
  viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2461
2525
  };
2462
2526
  }
@@ -2764,12 +2828,6 @@ function indexesToGsi(indexes) {
2764
2828
  * const table = new JaypieDynamoDb(this, "myApp");
2765
2829
  *
2766
2830
  * @example
2767
- * // With default Jaypie indexes
2768
- * const table = new JaypieDynamoDb(this, "myApp", {
2769
- * indexes: JaypieDynamoDb.DEFAULT_INDEXES,
2770
- * });
2771
- *
2772
- * @example
2773
2831
  * // With explicit table name (overrides CDK-generated name)
2774
2832
  * const table = new JaypieDynamoDb(this, "MyTable", {
2775
2833
  * tableName: "custom-table-name",
@@ -2908,11 +2966,6 @@ class JaypieDynamoDb extends constructs.Construct {
2908
2966
  return this._table.metricUserErrors(props);
2909
2967
  }
2910
2968
  }
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
2969
 
2917
2970
  class JaypieEventsRule extends constructs.Construct {
2918
2971
  /**