@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;
package/dist/esm/index.js CHANGED
@@ -2395,8 +2395,8 @@ class JaypieDatadogSecret extends JaypieEnvSecret {
2395
2395
  }
2396
2396
  }
2397
2397
 
2398
- const DEFAULT_RATE_LIMIT = 2000;
2399
- const DEFAULT_MANAGED_RULES = [
2398
+ const DEFAULT_RATE_LIMIT$1 = 2000;
2399
+ const DEFAULT_MANAGED_RULES$1 = [
2400
2400
  "AWSManagedRulesCommonRuleSet",
2401
2401
  "AWSManagedRulesKnownBadInputsRuleSet",
2402
2402
  ];
@@ -2657,7 +2657,7 @@ class JaypieDistribution extends Construct {
2657
2657
  }
2658
2658
  else {
2659
2659
  // Create new WebACL
2660
- const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES, rateLimitPerIp = DEFAULT_RATE_LIMIT, } = wafConfig;
2660
+ const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES$1, rateLimitPerIp = DEFAULT_RATE_LIMIT$1, } = wafConfig;
2661
2661
  let priority = 0;
2662
2662
  const rules = [];
2663
2663
  // Add managed rule groups
@@ -4200,10 +4200,16 @@ class JaypieSsoSyncApplication extends Construct {
4200
4200
  }
4201
4201
  }
4202
4202
 
4203
+ const DEFAULT_RATE_LIMIT = 2000;
4204
+ const DEFAULT_MANAGED_RULES = [
4205
+ "AWSManagedRulesCommonRuleSet",
4206
+ "AWSManagedRulesKnownBadInputsRuleSet",
4207
+ ];
4203
4208
  class JaypieWebDeploymentBucket extends Construct {
4204
4209
  constructor(scope, id, props = {}) {
4205
4210
  super(scope, id);
4206
- const roleTag = props.roleTag || CDK$2.ROLE.HOSTING;
4211
+ 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;
4212
+ const roleTag = roleTagProp || CDK$2.ROLE.HOSTING;
4207
4213
  // Environment variable validation
4208
4214
  if (process.env.CDK_ENV_WEB_SUBDOMAIN &&
4209
4215
  !isValidSubdomain(process.env.CDK_ENV_WEB_SUBDOMAIN)) {
@@ -4218,8 +4224,19 @@ class JaypieWebDeploymentBucket extends Construct {
4218
4224
  throw new ConfigurationError("CDK_ENV_HOSTED_ZONE is not a valid hostname");
4219
4225
  }
4220
4226
  // Determine host from props or environment
4221
- let host = props.host;
4222
- if (!host) {
4227
+ let host;
4228
+ if (typeof propsHost === "string") {
4229
+ host = propsHost;
4230
+ }
4231
+ else if (typeof propsHost === "object") {
4232
+ try {
4233
+ host = envHostname(propsHost);
4234
+ }
4235
+ catch {
4236
+ host = undefined;
4237
+ }
4238
+ }
4239
+ else {
4223
4240
  try {
4224
4241
  host =
4225
4242
  process.env.CDK_ENV_WEB_HOST ||
@@ -4235,7 +4252,7 @@ class JaypieWebDeploymentBucket extends Construct {
4235
4252
  throw new ConfigurationError("Host is not a valid hostname");
4236
4253
  }
4237
4254
  // Determine zone from props or environment
4238
- const zone = props.zone ||
4255
+ const zone = propsZone ||
4239
4256
  process.env.CDK_ENV_WEB_HOSTED_ZONE ||
4240
4257
  process.env.CDK_ENV_HOSTED_ZONE;
4241
4258
  // Create the S3 bucket
@@ -4243,13 +4260,13 @@ class JaypieWebDeploymentBucket extends Construct {
4243
4260
  accessControl: s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
4244
4261
  autoDeleteObjects: true,
4245
4262
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS_ONLY,
4246
- bucketName: props.name || constructEnvName("web"),
4263
+ bucketName: nameProp || constructEnvName("web"),
4247
4264
  publicReadAccess: true,
4248
4265
  removalPolicy: RemovalPolicy.DESTROY,
4249
4266
  versioned: false,
4250
4267
  websiteErrorDocument: "index.html",
4251
4268
  websiteIndexDocument: "index.html",
4252
- ...props,
4269
+ ...bucketProps,
4253
4270
  });
4254
4271
  // Delegate IBucket properties to the bucket
4255
4272
  this.bucketArn = this.bucket.bucketArn;
@@ -4331,7 +4348,7 @@ class JaypieWebDeploymentBucket extends Construct {
4331
4348
  }
4332
4349
  // Use resolveCertificate to create certificate at stack level (enables reuse when swapping constructs)
4333
4350
  this.certificate = resolveCertificate(this, {
4334
- certificate: props.certificate,
4351
+ certificate: certificateProp,
4335
4352
  domainName: host,
4336
4353
  roleTag,
4337
4354
  zone: hostedZone,
@@ -4341,15 +4358,126 @@ class JaypieWebDeploymentBucket extends Construct {
4341
4358
  value: this.certificate.certificateArn,
4342
4359
  });
4343
4360
  }
4361
+ // Resolve response headers policy for security headers
4362
+ let resolvedResponseHeadersPolicy;
4363
+ if (responseHeadersPolicyProp) {
4364
+ resolvedResponseHeadersPolicy = responseHeadersPolicyProp;
4365
+ }
4366
+ else if (securityHeadersProp !== false) {
4367
+ const overrides = typeof securityHeadersProp === "object" ? securityHeadersProp : {};
4368
+ resolvedResponseHeadersPolicy = new cloudfront.ResponseHeadersPolicy(this, "SecurityHeaders", {
4369
+ customHeadersBehavior: {
4370
+ customHeaders: [
4371
+ {
4372
+ header: "Cache-Control",
4373
+ override: true,
4374
+ value: "no-store, no-cache, must-revalidate, proxy-revalidate",
4375
+ },
4376
+ {
4377
+ header: "Cross-Origin-Embedder-Policy",
4378
+ override: true,
4379
+ value: "unsafe-none",
4380
+ },
4381
+ {
4382
+ header: "Cross-Origin-Opener-Policy",
4383
+ override: true,
4384
+ value: "same-origin",
4385
+ },
4386
+ {
4387
+ header: "Cross-Origin-Resource-Policy",
4388
+ override: true,
4389
+ value: "same-origin",
4390
+ },
4391
+ {
4392
+ header: "Permissions-Policy",
4393
+ override: true,
4394
+ value: overrides.permissionsPolicy ??
4395
+ CDK$2.SECURITY_HEADERS.PERMISSIONS_POLICY,
4396
+ },
4397
+ ],
4398
+ },
4399
+ removeHeaders: ["Server"],
4400
+ securityHeadersBehavior: {
4401
+ contentSecurityPolicy: {
4402
+ contentSecurityPolicy: overrides.contentSecurityPolicy ??
4403
+ CDK$2.SECURITY_HEADERS.CONTENT_SECURITY_POLICY,
4404
+ override: true,
4405
+ },
4406
+ contentTypeOptions: { override: true },
4407
+ frameOptions: {
4408
+ frameOption: overrides.frameOption ?? cloudfront.HeadersFrameOption.DENY,
4409
+ override: true,
4410
+ },
4411
+ referrerPolicy: {
4412
+ referrerPolicy: overrides.referrerPolicy ??
4413
+ cloudfront.HeadersReferrerPolicy
4414
+ .STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
4415
+ override: true,
4416
+ },
4417
+ strictTransportSecurity: {
4418
+ accessControlMaxAge: Duration.seconds(overrides.hstsMaxAge ?? CDK$2.SECURITY_HEADERS.HSTS_MAX_AGE),
4419
+ includeSubdomains: overrides.hstsIncludeSubdomains ?? true,
4420
+ override: true,
4421
+ preload: true,
4422
+ },
4423
+ },
4424
+ });
4425
+ }
4426
+ this.responseHeadersPolicy = resolvedResponseHeadersPolicy;
4427
+ // Resolve or create access log bucket
4428
+ let accessLogBucket;
4429
+ const isExternalLogBucket = logBucketProp !== undefined;
4430
+ if (logBucketProp !== undefined) {
4431
+ accessLogBucket = this.resolveLogBucket(logBucketProp);
4432
+ }
4433
+ else if (destinationProp !== false) {
4434
+ const createdBucket = new s3.Bucket(this, constructEnvName("LogBucket"), {
4435
+ autoDeleteObjects: true,
4436
+ lifecycleRules: [
4437
+ {
4438
+ expiration: Duration.days(90),
4439
+ transitions: [
4440
+ {
4441
+ storageClass: s3.StorageClass.INFREQUENT_ACCESS,
4442
+ transitionAfter: Duration.days(30),
4443
+ },
4444
+ ],
4445
+ },
4446
+ ],
4447
+ objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,
4448
+ removalPolicy: RemovalPolicy.DESTROY,
4449
+ });
4450
+ Tags.of(createdBucket).add(CDK$2.TAG.ROLE, CDK$2.ROLE.STORAGE);
4451
+ accessLogBucket = createdBucket;
4452
+ }
4453
+ if (accessLogBucket &&
4454
+ destinationProp !== false &&
4455
+ !isExternalLogBucket) {
4456
+ const lambdaDestination = destinationProp === true
4457
+ ? new LambdaDestination(resolveDatadogForwarderFunction(this))
4458
+ : destinationProp;
4459
+ accessLogBucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaDestination);
4460
+ }
4461
+ this.logBucket = accessLogBucket;
4344
4462
  // Create CloudFront distribution
4345
4463
  this.distribution = new cloudfront.Distribution(this, "Distribution", {
4346
4464
  defaultBehavior: {
4347
4465
  cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
4348
4466
  origin: new origins.S3StaticWebsiteOrigin(this.bucket),
4467
+ ...(resolvedResponseHeadersPolicy
4468
+ ? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
4469
+ : {}),
4349
4470
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
4350
4471
  },
4351
4472
  certificate: this.certificate,
4352
4473
  domainNames: [host],
4474
+ ...(accessLogBucket
4475
+ ? {
4476
+ enableLogging: true,
4477
+ logBucket: accessLogBucket,
4478
+ logFilePrefix: "cloudfront-logs/",
4479
+ }
4480
+ : {}),
4353
4481
  });
4354
4482
  Tags.of(this.distribution).add(CDK$2.TAG.ROLE, roleTag);
4355
4483
  // If this is production, enable caching on everything but index.html
@@ -4357,6 +4485,9 @@ class JaypieWebDeploymentBucket extends Construct {
4357
4485
  this.distribution.addBehavior("/*", new origins.S3StaticWebsiteOrigin(this.bucket), {
4358
4486
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
4359
4487
  cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
4488
+ ...(resolvedResponseHeadersPolicy
4489
+ ? { responseHeadersPolicy: resolvedResponseHeadersPolicy }
4490
+ : {}),
4360
4491
  });
4361
4492
  }
4362
4493
  // Create DNS record
@@ -4381,8 +4512,148 @@ class JaypieWebDeploymentBucket extends Construct {
4381
4512
  ],
4382
4513
  }));
4383
4514
  }
4515
+ // Create and attach WAF WebACL
4516
+ let resolvedWebAclArn;
4517
+ const wafConfig = this.resolveWafConfig(wafProp, id);
4518
+ if (wafConfig) {
4519
+ if (wafConfig.webAclArn) {
4520
+ resolvedWebAclArn = wafConfig.webAclArn;
4521
+ this.distribution.attachWebAclId(wafConfig.webAclArn);
4522
+ }
4523
+ else {
4524
+ const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES, rateLimitPerIp = DEFAULT_RATE_LIMIT, } = wafConfig;
4525
+ let priority = 0;
4526
+ const rules = [];
4527
+ for (const ruleName of managedRules) {
4528
+ const ruleActionOverrides = managedRuleOverrides?.[ruleName];
4529
+ const scopeDownStatement = managedRuleScopeDowns?.[ruleName];
4530
+ rules.push({
4531
+ name: ruleName,
4532
+ priority: priority++,
4533
+ overrideAction: { none: {} },
4534
+ statement: {
4535
+ managedRuleGroupStatement: {
4536
+ name: ruleName,
4537
+ vendorName: "AWS",
4538
+ ...(ruleActionOverrides && { ruleActionOverrides }),
4539
+ ...(scopeDownStatement && { scopeDownStatement }),
4540
+ },
4541
+ },
4542
+ visibilityConfig: {
4543
+ cloudWatchMetricsEnabled: true,
4544
+ metricName: ruleName,
4545
+ sampledRequestsEnabled: true,
4546
+ },
4547
+ });
4548
+ }
4549
+ rules.push({
4550
+ name: "RateLimitPerIp",
4551
+ priority,
4552
+ action: { block: {} },
4553
+ statement: {
4554
+ rateBasedStatement: {
4555
+ aggregateKeyType: "IP",
4556
+ limit: rateLimitPerIp,
4557
+ },
4558
+ },
4559
+ visibilityConfig: {
4560
+ cloudWatchMetricsEnabled: true,
4561
+ metricName: "RateLimitPerIp",
4562
+ sampledRequestsEnabled: true,
4563
+ },
4564
+ });
4565
+ const webAclName = constructEnvName(`${wafConfig.name}-WebAcl`);
4566
+ const webAcl = new wafv2.CfnWebACL(this, "WebAcl", {
4567
+ defaultAction: { allow: {} },
4568
+ name: webAclName,
4569
+ rules,
4570
+ scope: "CLOUDFRONT",
4571
+ visibilityConfig: {
4572
+ cloudWatchMetricsEnabled: true,
4573
+ metricName: webAclName,
4574
+ sampledRequestsEnabled: true,
4575
+ },
4576
+ });
4577
+ this.webAcl = webAcl;
4578
+ resolvedWebAclArn = webAcl.attrArn;
4579
+ this.distribution.attachWebAclId(webAcl.attrArn);
4580
+ Tags.of(webAcl).add(CDK$2.TAG.ROLE, roleTag);
4581
+ }
4582
+ }
4583
+ // Create WAF logging
4584
+ if (resolvedWebAclArn && wafConfig) {
4585
+ const { logBucket: wafLogBucketProp = true } = wafConfig;
4586
+ let wafLogBucket;
4587
+ if (wafLogBucketProp === true) {
4588
+ const wafLogBucketId = constructEnvName(`${wafConfig.name}-WafLogBucket`);
4589
+ const wafLogBucketName = `aws-waf-logs-${constructEnvName(`${wafConfig.name}-waf`).toLowerCase()}`;
4590
+ const createdBucket = new s3.Bucket(this, wafLogBucketId, {
4591
+ bucketName: wafLogBucketName,
4592
+ lifecycleRules: [
4593
+ {
4594
+ expiration: Duration.days(90),
4595
+ transitions: [
4596
+ {
4597
+ storageClass: s3.StorageClass.INFREQUENT_ACCESS,
4598
+ transitionAfter: Duration.days(30),
4599
+ },
4600
+ ],
4601
+ },
4602
+ ],
4603
+ objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,
4604
+ removalPolicy: RemovalPolicy.RETAIN,
4605
+ });
4606
+ Tags.of(createdBucket).add(CDK$2.TAG.ROLE, CDK$2.ROLE.MONITORING);
4607
+ if (destinationProp !== false) {
4608
+ const lambdaDestination = destinationProp === true
4609
+ ? new LambdaDestination(resolveDatadogForwarderFunction(this))
4610
+ : destinationProp;
4611
+ createdBucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaDestination);
4612
+ }
4613
+ wafLogBucket = createdBucket;
4614
+ }
4615
+ else if (typeof wafLogBucketProp === "object") {
4616
+ wafLogBucket = wafLogBucketProp;
4617
+ }
4618
+ if (wafLogBucket) {
4619
+ this.wafLogBucket = wafLogBucket;
4620
+ new wafv2.CfnLoggingConfiguration(this, "WafLoggingConfig", {
4621
+ logDestinationConfigs: [wafLogBucket.bucketArn],
4622
+ resourceArn: resolvedWebAclArn,
4623
+ });
4624
+ }
4625
+ }
4384
4626
  }
4385
4627
  }
4628
+ resolveWafConfig(wafProp, defaultName) {
4629
+ if (wafProp === false)
4630
+ return undefined;
4631
+ if (wafProp === true)
4632
+ return { name: defaultName };
4633
+ if (wafProp.enabled === false)
4634
+ return undefined;
4635
+ return { ...wafProp, name: wafProp.name || defaultName };
4636
+ }
4637
+ isExportNameObject(value) {
4638
+ return (typeof value === "object" &&
4639
+ value !== null &&
4640
+ "exportName" in value &&
4641
+ typeof value.exportName === "string");
4642
+ }
4643
+ resolveLogBucket(logBucketProp) {
4644
+ if (logBucketProp === true) {
4645
+ const bucketName = Fn.importValue(CDK$2.IMPORT.LOG_BUCKET);
4646
+ return s3.Bucket.fromBucketName(this, "ImportedLogBucket", bucketName);
4647
+ }
4648
+ if (this.isExportNameObject(logBucketProp)) {
4649
+ const bucketName = Fn.importValue(logBucketProp.exportName);
4650
+ return s3.Bucket.fromBucketName(this, "ImportedLogBucket", bucketName);
4651
+ }
4652
+ if (typeof logBucketProp === "string") {
4653
+ return s3.Bucket.fromBucketName(this, "ImportedLogBucket", logBucketProp);
4654
+ }
4655
+ return logBucketProp;
4656
+ }
4386
4657
  // Implement remaining IBucket methods by delegating to the bucket
4387
4658
  addEventNotification(event, dest, ...filters) {
4388
4659
  this.bucket.addEventNotification(event, dest, ...filters);