@jaypie/constructs 1.2.51 → 1.2.52

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.
@@ -1,11 +1,13 @@
1
1
  import { Construct } from "constructs";
2
+ import { HostConfig } from "./helpers";
2
3
  import { JaypieWebDeploymentBucket, JaypieWebDeploymentBucketProps } from "./JaypieWebDeploymentBucket";
3
4
  export interface JaypieStaticWebBucketProps extends Omit<JaypieWebDeploymentBucketProps, "host" | "name" | "roleTag"> {
4
5
  /**
5
- * The domain name for the website
6
+ * The domain name for the website. Accepts a string or a HostConfig
7
+ * object resolved via envHostname().
6
8
  * @default envHostname({ subdomain: "static" })
7
9
  */
8
- host?: string;
10
+ host?: string | HostConfig;
9
11
  /**
10
12
  * Optional bucket name
11
13
  * @default constructEnvName("static")
@@ -4,9 +4,21 @@ import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
4
4
  import { AddToResourcePolicyResult, PolicyStatement } from "aws-cdk-lib/aws-iam";
5
5
  import * as route53 from "aws-cdk-lib/aws-route53";
6
6
  import * as s3 from "aws-cdk-lib/aws-s3";
7
+ import { LambdaDestination } from "aws-cdk-lib/aws-s3-notifications";
7
8
  import * as kms from "aws-cdk-lib/aws-kms";
9
+ import * as wafv2 from "aws-cdk-lib/aws-wafv2";
8
10
  import { Construct } from "constructs";
11
+ import { HostConfig } from "./helpers";
12
+ import { JaypieWafConfig, SecurityHeadersOverrides } from "./JaypieDistribution";
9
13
  import { JaypieHostedZone } from "./JaypieHostedZone";
14
+ /**
15
+ * WAF configuration for JaypieWebDeploymentBucket. Same shape as
16
+ * JaypieDistribution's JaypieWafConfig, but `name` is optional — when omitted,
17
+ * the construct id is used to namespace the WebACL and WAF log bucket.
18
+ */
19
+ export type JaypieWebDeploymentBucketWafConfig = Omit<JaypieWafConfig, "name"> & {
20
+ name?: string;
21
+ };
10
22
  export interface JaypieWebDeploymentBucketProps extends s3.BucketProps {
11
23
  /**
12
24
  * SSL certificate for the CloudFront distribution
@@ -14,19 +26,75 @@ export interface JaypieWebDeploymentBucketProps extends s3.BucketProps {
14
26
  */
15
27
  certificate?: boolean | acm.ICertificate;
16
28
  /**
17
- * The domain name for the website
29
+ * Log destination configuration for CloudFront access logs.
30
+ * - LambdaDestination: Use a specific Lambda destination for S3 notifications
31
+ * - true: Use Datadog forwarder for S3 notifications (default)
32
+ * - false: Disable S3 notifications (logging still occurs if logBucket is set)
33
+ * @default true
34
+ */
35
+ destination?: LambdaDestination | boolean;
36
+ /**
37
+ * The domain name for the website.
38
+ *
39
+ * Supports both string and config object:
40
+ * - String: used directly as the domain name (e.g., "app.example.com")
41
+ * - Object: passed to envHostname() to construct the domain name
42
+ * - { subdomain, domain, env, component }
43
+ *
18
44
  * @default mergeDomain(CDK_ENV_WEB_SUBDOMAIN, CDK_ENV_WEB_HOSTED_ZONE || CDK_ENV_HOSTED_ZONE)
45
+ *
46
+ * @example
47
+ * // Direct string
48
+ * host: "app.example.com"
49
+ *
50
+ * @example
51
+ * // Config object - resolves using envHostname()
52
+ * host: { subdomain: "app" }
19
53
  */
20
- host?: string;
54
+ host?: string | HostConfig;
55
+ /**
56
+ * External log bucket for CloudFront access logs.
57
+ * - IBucket: Use existing bucket directly
58
+ * - string: Bucket name to import
59
+ * - { exportName: string }: CloudFormation export name to import
60
+ * - true: Use account logging bucket (CDK.IMPORT.LOG_BUCKET)
61
+ * @default undefined (creates new bucket if destination !== false)
62
+ */
63
+ logBucket?: s3.IBucket | string | {
64
+ exportName: string;
65
+ } | true;
21
66
  /**
22
67
  * Optional bucket name
23
68
  */
24
69
  name?: string;
70
+ /**
71
+ * Full override for the response headers policy.
72
+ * When provided, bypasses all default security header logic.
73
+ */
74
+ responseHeadersPolicy?: cloudfront.IResponseHeadersPolicy;
25
75
  /**
26
76
  * Role tag for tagging resources
27
77
  * @default CDK.ROLE.HOSTING
28
78
  */
29
79
  roleTag?: string;
80
+ /**
81
+ * Security headers configuration.
82
+ * - true/undefined: apply sensible defaults (HSTS, X-Frame-Options, CSP, etc.)
83
+ * - false: disable security headers entirely
84
+ * - SecurityHeadersOverrides object: merge overrides with defaults
85
+ * @default true
86
+ */
87
+ securityHeaders?: boolean | SecurityHeadersOverrides;
88
+ /**
89
+ * WAF WebACL configuration for the CloudFront distribution.
90
+ * - true/undefined: create and attach a WebACL with sensible defaults; the
91
+ * construct id is used to namespace the WebACL and WAF log bucket
92
+ * - false: disable WAF
93
+ * - JaypieWebDeploymentBucketWafConfig: customize WAF behavior; if `name`
94
+ * is omitted the construct id is used
95
+ * @default true
96
+ */
97
+ waf?: boolean | JaypieWebDeploymentBucketWafConfig;
30
98
  /**
31
99
  * The hosted zone for DNS records
32
100
  * @default CDK_ENV_WEB_HOSTED_ZONE || CDK_ENV_HOSTED_ZONE
@@ -50,7 +118,14 @@ export declare class JaypieWebDeploymentBucket extends Construct implements s3.I
50
118
  readonly distributionDomainName?: string;
51
119
  readonly certificate?: acm.ICertificate;
52
120
  readonly distribution?: cloudfront.Distribution;
121
+ readonly logBucket?: s3.IBucket;
122
+ readonly responseHeadersPolicy?: cloudfront.IResponseHeadersPolicy;
123
+ readonly wafLogBucket?: s3.IBucket;
124
+ readonly webAcl?: wafv2.CfnWebACL;
53
125
  constructor(scope: Construct, id: string, props?: JaypieWebDeploymentBucketProps);
126
+ private resolveWafConfig;
127
+ private isExportNameObject;
128
+ private resolveLogBucket;
54
129
  addEventNotification(event: s3.EventType, dest: s3.IBucketNotificationDestination, ...filters: s3.NotificationKeyFilter[]): void;
55
130
  addObjectCreatedNotification(dest: s3.IBucketNotificationDestination, ...filters: s3.NotificationKeyFilter[]): void;
56
131
  addObjectRemovedNotification(dest: s3.IBucketNotificationDestination, ...filters: s3.NotificationKeyFilter[]): void;
@@ -2431,8 +2431,8 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
2431
2431
  }
2432
2432
  }
2433
2433
 
2434
- const DEFAULT_RATE_LIMIT = 2000;
2435
- const DEFAULT_MANAGED_RULES = [
2434
+ const DEFAULT_RATE_LIMIT$1 = 2000;
2435
+ const DEFAULT_MANAGED_RULES$1 = [
2436
2436
  "AWSManagedRulesCommonRuleSet",
2437
2437
  "AWSManagedRulesKnownBadInputsRuleSet",
2438
2438
  ];
@@ -2693,7 +2693,7 @@ class JaypieDistribution extends constructs.Construct {
2693
2693
  }
2694
2694
  else {
2695
2695
  // Create new WebACL
2696
- const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES, rateLimitPerIp = DEFAULT_RATE_LIMIT, } = wafConfig;
2696
+ const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES$1, rateLimitPerIp = DEFAULT_RATE_LIMIT$1, } = wafConfig;
2697
2697
  let priority = 0;
2698
2698
  const rules = [];
2699
2699
  // Add managed rule groups
@@ -4236,10 +4236,16 @@ class JaypieSsoSyncApplication extends constructs.Construct {
4236
4236
  }
4237
4237
  }
4238
4238
 
4239
+ const DEFAULT_RATE_LIMIT = 2000;
4240
+ const DEFAULT_MANAGED_RULES = [
4241
+ "AWSManagedRulesCommonRuleSet",
4242
+ "AWSManagedRulesKnownBadInputsRuleSet",
4243
+ ];
4239
4244
  class JaypieWebDeploymentBucket extends constructs.Construct {
4240
4245
  constructor(scope, id, props = {}) {
4241
4246
  super(scope, id);
4242
- const roleTag = props.roleTag || CDK$2.ROLE.HOSTING;
4247
+ const { certificate: certificateProp, destination: destinationProp = true, host: propsHost, logBucket: logBucketProp, name: nameProp, responseHeadersPolicy: responseHeadersPolicyProp, roleTag: roleTagProp, securityHeaders: securityHeadersProp, waf: wafProp = true, zone: propsZone, ...bucketProps } = props;
4248
+ const roleTag = roleTagProp || CDK$2.ROLE.HOSTING;
4243
4249
  // Environment variable validation
4244
4250
  if (process.env.CDK_ENV_WEB_SUBDOMAIN &&
4245
4251
  !isValidSubdomain(process.env.CDK_ENV_WEB_SUBDOMAIN)) {
@@ -4254,8 +4260,19 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4254
4260
  throw new errors.ConfigurationError("CDK_ENV_HOSTED_ZONE is not a valid hostname");
4255
4261
  }
4256
4262
  // Determine host from props or environment
4257
- let host = props.host;
4258
- if (!host) {
4263
+ let host;
4264
+ if (typeof propsHost === "string") {
4265
+ host = propsHost;
4266
+ }
4267
+ else if (typeof propsHost === "object") {
4268
+ try {
4269
+ host = envHostname(propsHost);
4270
+ }
4271
+ catch {
4272
+ host = undefined;
4273
+ }
4274
+ }
4275
+ else {
4259
4276
  try {
4260
4277
  host =
4261
4278
  process.env.CDK_ENV_WEB_HOST ||
@@ -4271,7 +4288,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4271
4288
  throw new errors.ConfigurationError("Host is not a valid hostname");
4272
4289
  }
4273
4290
  // Determine zone from props or environment
4274
- const zone = props.zone ||
4291
+ const zone = propsZone ||
4275
4292
  process.env.CDK_ENV_WEB_HOSTED_ZONE ||
4276
4293
  process.env.CDK_ENV_HOSTED_ZONE;
4277
4294
  // Create the S3 bucket
@@ -4279,13 +4296,13 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4279
4296
  accessControl: s3__namespace.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
4280
4297
  autoDeleteObjects: true,
4281
4298
  blockPublicAccess: s3__namespace.BlockPublicAccess.BLOCK_ACLS_ONLY,
4282
- bucketName: props.name || constructEnvName("web"),
4299
+ bucketName: nameProp || constructEnvName("web"),
4283
4300
  publicReadAccess: true,
4284
4301
  removalPolicy: cdk.RemovalPolicy.DESTROY,
4285
4302
  versioned: false,
4286
4303
  websiteErrorDocument: "index.html",
4287
4304
  websiteIndexDocument: "index.html",
4288
- ...props,
4305
+ ...bucketProps,
4289
4306
  });
4290
4307
  // Delegate IBucket properties to the bucket
4291
4308
  this.bucketArn = this.bucket.bucketArn;
@@ -4367,7 +4384,7 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4367
4384
  }
4368
4385
  // Use resolveCertificate to create certificate at stack level (enables reuse when swapping constructs)
4369
4386
  this.certificate = resolveCertificate(this, {
4370
- certificate: props.certificate,
4387
+ certificate: certificateProp,
4371
4388
  domainName: host,
4372
4389
  roleTag,
4373
4390
  zone: hostedZone,
@@ -4377,15 +4394,126 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4377
4394
  value: this.certificate.certificateArn,
4378
4395
  });
4379
4396
  }
4397
+ // Resolve response headers policy for security headers
4398
+ let resolvedResponseHeadersPolicy;
4399
+ if (responseHeadersPolicyProp) {
4400
+ resolvedResponseHeadersPolicy = responseHeadersPolicyProp;
4401
+ }
4402
+ else if (securityHeadersProp !== false) {
4403
+ const overrides = typeof securityHeadersProp === "object" ? securityHeadersProp : {};
4404
+ resolvedResponseHeadersPolicy = new cloudfront__namespace.ResponseHeadersPolicy(this, "SecurityHeaders", {
4405
+ customHeadersBehavior: {
4406
+ customHeaders: [
4407
+ {
4408
+ header: "Cache-Control",
4409
+ override: true,
4410
+ value: "no-store, no-cache, must-revalidate, proxy-revalidate",
4411
+ },
4412
+ {
4413
+ header: "Cross-Origin-Embedder-Policy",
4414
+ override: true,
4415
+ value: "unsafe-none",
4416
+ },
4417
+ {
4418
+ header: "Cross-Origin-Opener-Policy",
4419
+ override: true,
4420
+ value: "same-origin",
4421
+ },
4422
+ {
4423
+ header: "Cross-Origin-Resource-Policy",
4424
+ override: true,
4425
+ value: "same-origin",
4426
+ },
4427
+ {
4428
+ header: "Permissions-Policy",
4429
+ override: true,
4430
+ value: overrides.permissionsPolicy ??
4431
+ CDK$2.SECURITY_HEADERS.PERMISSIONS_POLICY,
4432
+ },
4433
+ ],
4434
+ },
4435
+ removeHeaders: ["Server"],
4436
+ securityHeadersBehavior: {
4437
+ contentSecurityPolicy: {
4438
+ contentSecurityPolicy: overrides.contentSecurityPolicy ??
4439
+ CDK$2.SECURITY_HEADERS.CONTENT_SECURITY_POLICY,
4440
+ override: true,
4441
+ },
4442
+ contentTypeOptions: { override: true },
4443
+ frameOptions: {
4444
+ frameOption: overrides.frameOption ?? cloudfront__namespace.HeadersFrameOption.DENY,
4445
+ override: true,
4446
+ },
4447
+ referrerPolicy: {
4448
+ referrerPolicy: overrides.referrerPolicy ??
4449
+ cloudfront__namespace.HeadersReferrerPolicy
4450
+ .STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
4451
+ override: true,
4452
+ },
4453
+ strictTransportSecurity: {
4454
+ accessControlMaxAge: cdk.Duration.seconds(overrides.hstsMaxAge ?? CDK$2.SECURITY_HEADERS.HSTS_MAX_AGE),
4455
+ includeSubdomains: overrides.hstsIncludeSubdomains ?? true,
4456
+ override: true,
4457
+ preload: true,
4458
+ },
4459
+ },
4460
+ });
4461
+ }
4462
+ this.responseHeadersPolicy = resolvedResponseHeadersPolicy;
4463
+ // Resolve or create access log bucket
4464
+ let accessLogBucket;
4465
+ const isExternalLogBucket = logBucketProp !== undefined;
4466
+ if (logBucketProp !== undefined) {
4467
+ accessLogBucket = this.resolveLogBucket(logBucketProp);
4468
+ }
4469
+ else if (destinationProp !== false) {
4470
+ const createdBucket = new s3__namespace.Bucket(this, constructEnvName("LogBucket"), {
4471
+ autoDeleteObjects: true,
4472
+ lifecycleRules: [
4473
+ {
4474
+ expiration: cdk.Duration.days(90),
4475
+ transitions: [
4476
+ {
4477
+ storageClass: s3__namespace.StorageClass.INFREQUENT_ACCESS,
4478
+ transitionAfter: cdk.Duration.days(30),
4479
+ },
4480
+ ],
4481
+ },
4482
+ ],
4483
+ objectOwnership: s3__namespace.ObjectOwnership.OBJECT_WRITER,
4484
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
4485
+ });
4486
+ cdk.Tags.of(createdBucket).add(CDK$2.TAG.ROLE, CDK$2.ROLE.STORAGE);
4487
+ accessLogBucket = createdBucket;
4488
+ }
4489
+ if (accessLogBucket &&
4490
+ destinationProp !== false &&
4491
+ !isExternalLogBucket) {
4492
+ const lambdaDestination = destinationProp === true
4493
+ ? new s3n.LambdaDestination(resolveDatadogForwarderFunction(this))
4494
+ : destinationProp;
4495
+ accessLogBucket.addEventNotification(s3__namespace.EventType.OBJECT_CREATED, lambdaDestination);
4496
+ }
4497
+ this.logBucket = accessLogBucket;
4380
4498
  // Create CloudFront distribution
4381
4499
  this.distribution = new cloudfront__namespace.Distribution(this, "Distribution", {
4382
4500
  defaultBehavior: {
4383
4501
  cachePolicy: cloudfront__namespace.CachePolicy.CACHING_DISABLED,
4384
4502
  origin: new origins__namespace.S3StaticWebsiteOrigin(this.bucket),
4503
+ ...(resolvedResponseHeadersPolicy
4504
+ ? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
4505
+ : {}),
4385
4506
  viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
4386
4507
  },
4387
4508
  certificate: this.certificate,
4388
4509
  domainNames: [host],
4510
+ ...(accessLogBucket
4511
+ ? {
4512
+ enableLogging: true,
4513
+ logBucket: accessLogBucket,
4514
+ logFilePrefix: "cloudfront-logs/",
4515
+ }
4516
+ : {}),
4389
4517
  });
4390
4518
  cdk.Tags.of(this.distribution).add(CDK$2.TAG.ROLE, roleTag);
4391
4519
  // If this is production, enable caching on everything but index.html
@@ -4393,6 +4521,9 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4393
4521
  this.distribution.addBehavior("/*", new origins__namespace.S3StaticWebsiteOrigin(this.bucket), {
4394
4522
  viewerProtocolPolicy: cloudfront__namespace.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
4395
4523
  cachePolicy: cloudfront__namespace.CachePolicy.CACHING_OPTIMIZED,
4524
+ ...(resolvedResponseHeadersPolicy
4525
+ ? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
4526
+ : {}),
4396
4527
  });
4397
4528
  }
4398
4529
  // Create DNS record
@@ -4417,8 +4548,148 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
4417
4548
  ],
4418
4549
  }));
4419
4550
  }
4551
+ // Create and attach WAF WebACL
4552
+ let resolvedWebAclArn;
4553
+ const wafConfig = this.resolveWafConfig(wafProp, id);
4554
+ if (wafConfig) {
4555
+ if (wafConfig.webAclArn) {
4556
+ resolvedWebAclArn = wafConfig.webAclArn;
4557
+ this.distribution.attachWebAclId(wafConfig.webAclArn);
4558
+ }
4559
+ else {
4560
+ const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES, rateLimitPerIp = DEFAULT_RATE_LIMIT, } = wafConfig;
4561
+ let priority = 0;
4562
+ const rules = [];
4563
+ for (const ruleName of managedRules) {
4564
+ const ruleActionOverrides = managedRuleOverrides?.[ruleName];
4565
+ const scopeDownStatement = managedRuleScopeDowns?.[ruleName];
4566
+ rules.push({
4567
+ name: ruleName,
4568
+ priority: priority++,
4569
+ overrideAction: { none: {} },
4570
+ statement: {
4571
+ managedRuleGroupStatement: {
4572
+ name: ruleName,
4573
+ vendorName: "AWS",
4574
+ ...(ruleActionOverrides && { ruleActionOverrides }),
4575
+ ...(scopeDownStatement && { scopeDownStatement }),
4576
+ },
4577
+ },
4578
+ visibilityConfig: {
4579
+ cloudWatchMetricsEnabled: true,
4580
+ metricName: ruleName,
4581
+ sampledRequestsEnabled: true,
4582
+ },
4583
+ });
4584
+ }
4585
+ rules.push({
4586
+ name: "RateLimitPerIp",
4587
+ priority,
4588
+ action: { block: {} },
4589
+ statement: {
4590
+ rateBasedStatement: {
4591
+ aggregateKeyType: "IP",
4592
+ limit: rateLimitPerIp,
4593
+ },
4594
+ },
4595
+ visibilityConfig: {
4596
+ cloudWatchMetricsEnabled: true,
4597
+ metricName: "RateLimitPerIp",
4598
+ sampledRequestsEnabled: true,
4599
+ },
4600
+ });
4601
+ const webAclName = constructEnvName(`${wafConfig.name}-WebAcl`);
4602
+ const webAcl = new wafv2__namespace.CfnWebACL(this, "WebAcl", {
4603
+ defaultAction: { allow: {} },
4604
+ name: webAclName,
4605
+ rules,
4606
+ scope: "CLOUDFRONT",
4607
+ visibilityConfig: {
4608
+ cloudWatchMetricsEnabled: true,
4609
+ metricName: webAclName,
4610
+ sampledRequestsEnabled: true,
4611
+ },
4612
+ });
4613
+ this.webAcl = webAcl;
4614
+ resolvedWebAclArn = webAcl.attrArn;
4615
+ this.distribution.attachWebAclId(webAcl.attrArn);
4616
+ cdk.Tags.of(webAcl).add(CDK$2.TAG.ROLE, roleTag);
4617
+ }
4618
+ }
4619
+ // Create WAF logging
4620
+ if (resolvedWebAclArn && wafConfig) {
4621
+ const { logBucket: wafLogBucketProp = true } = wafConfig;
4622
+ let wafLogBucket;
4623
+ if (wafLogBucketProp === true) {
4624
+ const wafLogBucketId = constructEnvName(`${wafConfig.name}-WafLogBucket`);
4625
+ const wafLogBucketName = `aws-waf-logs-${constructEnvName(`${wafConfig.name}-waf`).toLowerCase()}`;
4626
+ const createdBucket = new s3__namespace.Bucket(this, wafLogBucketId, {
4627
+ bucketName: wafLogBucketName,
4628
+ lifecycleRules: [
4629
+ {
4630
+ expiration: cdk.Duration.days(90),
4631
+ transitions: [
4632
+ {
4633
+ storageClass: s3__namespace.StorageClass.INFREQUENT_ACCESS,
4634
+ transitionAfter: cdk.Duration.days(30),
4635
+ },
4636
+ ],
4637
+ },
4638
+ ],
4639
+ objectOwnership: s3__namespace.ObjectOwnership.OBJECT_WRITER,
4640
+ removalPolicy: cdk.RemovalPolicy.RETAIN,
4641
+ });
4642
+ cdk.Tags.of(createdBucket).add(CDK$2.TAG.ROLE, CDK$2.ROLE.MONITORING);
4643
+ if (destinationProp !== false) {
4644
+ const lambdaDestination = destinationProp === true
4645
+ ? new s3n.LambdaDestination(resolveDatadogForwarderFunction(this))
4646
+ : destinationProp;
4647
+ createdBucket.addEventNotification(s3__namespace.EventType.OBJECT_CREATED, lambdaDestination);
4648
+ }
4649
+ wafLogBucket = createdBucket;
4650
+ }
4651
+ else if (typeof wafLogBucketProp === "object") {
4652
+ wafLogBucket = wafLogBucketProp;
4653
+ }
4654
+ if (wafLogBucket) {
4655
+ this.wafLogBucket = wafLogBucket;
4656
+ new wafv2__namespace.CfnLoggingConfiguration(this, "WafLoggingConfig", {
4657
+ logDestinationConfigs: [wafLogBucket.bucketArn],
4658
+ resourceArn: resolvedWebAclArn,
4659
+ });
4660
+ }
4661
+ }
4420
4662
  }
4421
4663
  }
4664
+ resolveWafConfig(wafProp, defaultName) {
4665
+ if (wafProp === false)
4666
+ return undefined;
4667
+ if (wafProp === true)
4668
+ return { name: defaultName };
4669
+ if (wafProp.enabled === false)
4670
+ return undefined;
4671
+ return { ...wafProp, name: wafProp.name || defaultName };
4672
+ }
4673
+ isExportNameObject(value) {
4674
+ return (typeof value === "object" &&
4675
+ value !== null &&
4676
+ "exportName" in value &&
4677
+ typeof value.exportName === "string");
4678
+ }
4679
+ resolveLogBucket(logBucketProp) {
4680
+ if (logBucketProp === true) {
4681
+ const bucketName = cdk.Fn.importValue(CDK$2.IMPORT.LOG_BUCKET);
4682
+ return s3__namespace.Bucket.fromBucketName(this, "ImportedLogBucket", bucketName);
4683
+ }
4684
+ if (this.isExportNameObject(logBucketProp)) {
4685
+ const bucketName = cdk.Fn.importValue(logBucketProp.exportName);
4686
+ return s3__namespace.Bucket.fromBucketName(this, "ImportedLogBucket", bucketName);
4687
+ }
4688
+ if (typeof logBucketProp === "string") {
4689
+ return s3__namespace.Bucket.fromBucketName(this, "ImportedLogBucket", logBucketProp);
4690
+ }
4691
+ return logBucketProp;
4692
+ }
4422
4693
  // Implement remaining IBucket methods by delegating to the bucket
4423
4694
  addEventNotification(event, dest, ...filters) {
4424
4695
  this.bucket.addEventNotification(event, dest, ...filters);