@composurecdk/wafv2 0.0.0-stage → 0.13.0

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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -2
  3. package/dist/commonjs/alarm-config.d.ts +60 -0
  4. package/dist/commonjs/alarm-config.d.ts.map +1 -0
  5. package/dist/commonjs/alarm-config.js +3 -0
  6. package/dist/commonjs/alarm-config.js.map +1 -0
  7. package/dist/commonjs/alarm-defaults.d.ts +34 -0
  8. package/dist/commonjs/alarm-defaults.d.ts.map +1 -0
  9. package/dist/commonjs/alarm-defaults.js +37 -0
  10. package/dist/commonjs/alarm-defaults.js.map +1 -0
  11. package/dist/commonjs/alarms.d.ts +18 -0
  12. package/dist/commonjs/alarms.d.ts.map +1 -0
  13. package/dist/commonjs/alarms.js +94 -0
  14. package/dist/commonjs/alarms.js.map +1 -0
  15. package/dist/commonjs/association.d.ts +21 -0
  16. package/dist/commonjs/association.d.ts.map +1 -0
  17. package/dist/commonjs/association.js +61 -0
  18. package/dist/commonjs/association.js.map +1 -0
  19. package/dist/commonjs/custom-response.d.ts +52 -0
  20. package/dist/commonjs/custom-response.d.ts.map +1 -0
  21. package/dist/commonjs/custom-response.js +137 -0
  22. package/dist/commonjs/custom-response.js.map +1 -0
  23. package/dist/commonjs/defaults.d.ts +89 -0
  24. package/dist/commonjs/defaults.d.ts.map +1 -0
  25. package/dist/commonjs/defaults.js +90 -0
  26. package/dist/commonjs/defaults.js.map +1 -0
  27. package/dist/commonjs/index.d.ts +30 -0
  28. package/dist/commonjs/index.d.ts.map +1 -0
  29. package/dist/commonjs/index.js +35 -0
  30. package/dist/commonjs/index.js.map +1 -0
  31. package/dist/commonjs/logging-filter.d.ts +27 -0
  32. package/dist/commonjs/logging-filter.d.ts.map +1 -0
  33. package/dist/commonjs/logging-filter.js +17 -0
  34. package/dist/commonjs/logging-filter.js.map +1 -0
  35. package/dist/commonjs/logging.d.ts +59 -0
  36. package/dist/commonjs/logging.d.ts.map +1 -0
  37. package/dist/commonjs/logging.js +91 -0
  38. package/dist/commonjs/logging.js.map +1 -0
  39. package/dist/commonjs/metrics.d.ts +58 -0
  40. package/dist/commonjs/metrics.d.ts.map +1 -0
  41. package/dist/commonjs/metrics.js +67 -0
  42. package/dist/commonjs/metrics.js.map +1 -0
  43. package/dist/commonjs/names.d.ts +46 -0
  44. package/dist/commonjs/names.d.ts.map +1 -0
  45. package/dist/commonjs/names.js +140 -0
  46. package/dist/commonjs/names.js.map +1 -0
  47. package/dist/commonjs/package.json +3 -0
  48. package/dist/commonjs/rule-builder.d.ts +123 -0
  49. package/dist/commonjs/rule-builder.d.ts.map +1 -0
  50. package/dist/commonjs/rule-builder.js +163 -0
  51. package/dist/commonjs/rule-builder.js.map +1 -0
  52. package/dist/commonjs/scope.d.ts +15 -0
  53. package/dist/commonjs/scope.d.ts.map +1 -0
  54. package/dist/commonjs/scope.js +35 -0
  55. package/dist/commonjs/scope.js.map +1 -0
  56. package/dist/commonjs/web-acl-builder.d.ts +152 -0
  57. package/dist/commonjs/web-acl-builder.d.ts.map +1 -0
  58. package/dist/commonjs/web-acl-builder.js +205 -0
  59. package/dist/commonjs/web-acl-builder.js.map +1 -0
  60. package/dist/esm/alarm-config.d.ts +60 -0
  61. package/dist/esm/alarm-config.d.ts.map +1 -0
  62. package/dist/esm/alarm-config.js +2 -0
  63. package/dist/esm/alarm-config.js.map +1 -0
  64. package/dist/esm/alarm-defaults.d.ts +34 -0
  65. package/dist/esm/alarm-defaults.d.ts.map +1 -0
  66. package/dist/esm/alarm-defaults.js +34 -0
  67. package/dist/esm/alarm-defaults.js.map +1 -0
  68. package/dist/esm/alarms.d.ts +18 -0
  69. package/dist/esm/alarms.d.ts.map +1 -0
  70. package/dist/esm/alarms.js +90 -0
  71. package/dist/esm/alarms.js.map +1 -0
  72. package/dist/esm/association.d.ts +21 -0
  73. package/dist/esm/association.d.ts.map +1 -0
  74. package/dist/esm/association.js +58 -0
  75. package/dist/esm/association.js.map +1 -0
  76. package/dist/esm/custom-response.d.ts +52 -0
  77. package/dist/esm/custom-response.d.ts.map +1 -0
  78. package/dist/esm/custom-response.js +133 -0
  79. package/dist/esm/custom-response.js.map +1 -0
  80. package/dist/esm/defaults.d.ts +89 -0
  81. package/dist/esm/defaults.d.ts.map +1 -0
  82. package/dist/esm/defaults.js +87 -0
  83. package/dist/esm/defaults.js.map +1 -0
  84. package/dist/esm/index.d.ts +30 -0
  85. package/dist/esm/index.d.ts.map +1 -0
  86. package/dist/esm/index.js +23 -0
  87. package/dist/esm/index.js.map +1 -0
  88. package/dist/esm/logging-filter.d.ts +27 -0
  89. package/dist/esm/logging-filter.d.ts.map +1 -0
  90. package/dist/esm/logging-filter.js +14 -0
  91. package/dist/esm/logging-filter.js.map +1 -0
  92. package/dist/esm/logging.d.ts +59 -0
  93. package/dist/esm/logging.d.ts.map +1 -0
  94. package/dist/esm/logging.js +88 -0
  95. package/dist/esm/logging.js.map +1 -0
  96. package/dist/esm/metrics.d.ts +58 -0
  97. package/dist/esm/metrics.d.ts.map +1 -0
  98. package/dist/esm/metrics.js +63 -0
  99. package/dist/esm/metrics.js.map +1 -0
  100. package/dist/esm/names.d.ts +46 -0
  101. package/dist/esm/names.d.ts.map +1 -0
  102. package/dist/esm/names.js +132 -0
  103. package/dist/esm/names.js.map +1 -0
  104. package/dist/esm/package.json +3 -0
  105. package/dist/esm/rule-builder.d.ts +123 -0
  106. package/dist/esm/rule-builder.d.ts.map +1 -0
  107. package/dist/esm/rule-builder.js +160 -0
  108. package/dist/esm/rule-builder.js.map +1 -0
  109. package/dist/esm/scope.d.ts +15 -0
  110. package/dist/esm/scope.d.ts.map +1 -0
  111. package/dist/esm/scope.js +32 -0
  112. package/dist/esm/scope.js.map +1 -0
  113. package/dist/esm/web-acl-builder.d.ts +152 -0
  114. package/dist/esm/web-acl-builder.d.ts.map +1 -0
  115. package/dist/esm/web-acl-builder.js +202 -0
  116. package/dist/esm/web-acl-builder.js.map +1 -0
  117. package/package.json +78 -4
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Defaults for {@link createWebAclBuilder}. Each can be overridden through the
3
+ * builder's fluent API.
4
+ */
5
+ export declare const WEB_ACL_DEFAULTS: {
6
+ /**
7
+ * Regional, for API Gateway, Application Load Balancers, AppSync, Cognito,
8
+ * App Runner and Verified Access. A web ACL for CloudFront must say
9
+ * `.scope("CLOUDFRONT")` and be deployed in `us-east-1`.
10
+ *
11
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works-resources.html
12
+ */
13
+ readonly scope: "REGIONAL";
14
+ /**
15
+ * Off, because a sampled request keeps every header, including the
16
+ * credentials that logging redacts. Turn it on only with a
17
+ * `dataProtectionConfig`, which does apply to samples.
18
+ *
19
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/waf-data-protection-and-logging.html
20
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_data_classification_define_protection.html
21
+ */
22
+ readonly sampledRequests: false;
23
+ /**
24
+ * On, to a created `aws-waf-logs-` log group, keeping the requests WAF does
25
+ * not allow ({@link DEFAULT_LOGGING_FILTER}) and redacting
26
+ * {@link DEFAULT_LOGGING_REDACTED_HEADERS}.
27
+ *
28
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
29
+ */
30
+ readonly logging: {};
31
+ };
32
+ /**
33
+ * Visibility settings that are not configurable. CloudWatch metrics are always
34
+ * on for the web ACL and every rule: they are free, and the recommended alarms
35
+ * and `metrics` helper read them.
36
+ *
37
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
38
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/waf-metrics.html
39
+ */
40
+ export declare const WEB_ACL_VISIBILITY_DEFAULTS: {
41
+ readonly cloudWatchMetricsEnabled: true;
42
+ };
43
+ /**
44
+ * Gap between the priorities of consecutive rules, so a rule can be inserted
45
+ * with an explicit `.priority(n)` without renumbering the others.
46
+ */
47
+ export declare const DEFAULT_RULE_PRIORITY_STEP = 10;
48
+ /**
49
+ * The prefix AWS WAF requires of a CloudWatch log group, S3 bucket or Firehose
50
+ * stream it logs to.
51
+ *
52
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/logging-cw-logs.html
53
+ */
54
+ export declare const WAF_LOG_GROUP_NAME_PREFIX = "aws-waf-logs-";
55
+ /**
56
+ * Headers always redacted from WAF logs. Both carry credentials a log reader
57
+ * could replay, and neither helps tune a rule.
58
+ *
59
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_data_classification_define_protection.html
60
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/logging-management.html
61
+ */
62
+ export declare const DEFAULT_LOGGING_REDACTED_HEADERS: readonly string[];
63
+ /**
64
+ * Logs every request WAF does not simply allow, and drops the rest. Filtering
65
+ * is AWS's main lever on log volume and cost, and the allowed requests are
66
+ * rarely what a rule is tuned against.
67
+ *
68
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/logging-management.html
69
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
70
+ */
71
+ export declare const DEFAULT_LOGGING_FILTER: {
72
+ readonly defaultBehavior: "DROP";
73
+ readonly filters: readonly [{
74
+ readonly behavior: "KEEP";
75
+ readonly requirement: "MEETS_ANY";
76
+ readonly conditions: readonly [{
77
+ readonly action: "BLOCK";
78
+ }, {
79
+ readonly action: "COUNT";
80
+ }, {
81
+ readonly action: "CAPTCHA";
82
+ }, {
83
+ readonly action: "CHALLENGE";
84
+ }, {
85
+ readonly action: "EXCLUDED_AS_COUNT";
86
+ }];
87
+ }];
88
+ };
89
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;;;;;OAMG;;IAGH;;;;;;;OAOG;;IAGH;;;;;;OAMG;;CAEK,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B;;CAE9B,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,kBAAkB,CAAC;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,EAAE,SAAS,MAAM,EAAgC,CAAC;AAE/F;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;CAeK,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Defaults for {@link createWebAclBuilder}. Each can be overridden through the
3
+ * builder's fluent API.
4
+ */
5
+ export const WEB_ACL_DEFAULTS = {
6
+ /**
7
+ * Regional, for API Gateway, Application Load Balancers, AppSync, Cognito,
8
+ * App Runner and Verified Access. A web ACL for CloudFront must say
9
+ * `.scope("CLOUDFRONT")` and be deployed in `us-east-1`.
10
+ *
11
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works-resources.html
12
+ */
13
+ scope: "REGIONAL",
14
+ /**
15
+ * Off, because a sampled request keeps every header, including the
16
+ * credentials that logging redacts. Turn it on only with a
17
+ * `dataProtectionConfig`, which does apply to samples.
18
+ *
19
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/waf-data-protection-and-logging.html
20
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_data_classification_define_protection.html
21
+ */
22
+ sampledRequests: false,
23
+ /**
24
+ * On, to a created `aws-waf-logs-` log group, keeping the requests WAF does
25
+ * not allow ({@link DEFAULT_LOGGING_FILTER}) and redacting
26
+ * {@link DEFAULT_LOGGING_REDACTED_HEADERS}.
27
+ *
28
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
29
+ */
30
+ logging: {},
31
+ };
32
+ /**
33
+ * Visibility settings that are not configurable. CloudWatch metrics are always
34
+ * on for the web ACL and every rule: they are free, and the recommended alarms
35
+ * and `metrics` helper read them.
36
+ *
37
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
38
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/waf-metrics.html
39
+ */
40
+ export const WEB_ACL_VISIBILITY_DEFAULTS = {
41
+ cloudWatchMetricsEnabled: true,
42
+ };
43
+ /**
44
+ * Gap between the priorities of consecutive rules, so a rule can be inserted
45
+ * with an explicit `.priority(n)` without renumbering the others.
46
+ */
47
+ export const DEFAULT_RULE_PRIORITY_STEP = 10;
48
+ /**
49
+ * The prefix AWS WAF requires of a CloudWatch log group, S3 bucket or Firehose
50
+ * stream it logs to.
51
+ *
52
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/logging-cw-logs.html
53
+ */
54
+ export const WAF_LOG_GROUP_NAME_PREFIX = "aws-waf-logs-";
55
+ /**
56
+ * Headers always redacted from WAF logs. Both carry credentials a log reader
57
+ * could replay, and neither helps tune a rule.
58
+ *
59
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_data_classification_define_protection.html
60
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/logging-management.html
61
+ */
62
+ export const DEFAULT_LOGGING_REDACTED_HEADERS = ["authorization", "cookie"];
63
+ /**
64
+ * Logs every request WAF does not simply allow, and drops the rest. Filtering
65
+ * is AWS's main lever on log volume and cost, and the allowed requests are
66
+ * rarely what a rule is tuned against.
67
+ *
68
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/logging-management.html
69
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_detect_investigate_events_app_service_logging.html
70
+ */
71
+ export const DEFAULT_LOGGING_FILTER = {
72
+ defaultBehavior: "DROP",
73
+ filters: [
74
+ {
75
+ behavior: "KEEP",
76
+ requirement: "MEETS_ANY",
77
+ conditions: [
78
+ { action: "BLOCK" },
79
+ { action: "COUNT" },
80
+ { action: "CAPTCHA" },
81
+ { action: "CHALLENGE" },
82
+ { action: "EXCLUDED_AS_COUNT" },
83
+ ],
84
+ },
85
+ ],
86
+ };
87
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B;;;;;;OAMG;IACH,KAAK,EAAE,UAAU;IAEjB;;;;;;;OAOG;IACH,eAAe,EAAE,KAAK;IAEtB;;;;;;OAMG;IACH,OAAO,EAAE,EAAE;CACH,CAAC;AAEX;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,wBAAwB,EAAE,IAAI;CACtB,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,eAAe,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAsB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAE/F;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,eAAe,EAAE,MAAM;IACvB,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE,WAAW;YACxB,UAAU,EAAE;gBACV,EAAE,MAAM,EAAE,OAAO,EAAE;gBACnB,EAAE,MAAM,EAAE,OAAO,EAAE;gBACnB,EAAE,MAAM,EAAE,SAAS,EAAE;gBACrB,EAAE,MAAM,EAAE,WAAW,EAAE;gBACvB,EAAE,MAAM,EAAE,mBAAmB,EAAE;aAChC;SACF;KACF;CACqC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { validateMetricName, validateRuleLabel, validateRuleName, validateWebAclName } from "./names.js";
2
+ export { createWebAclBuilder, type IWebAclBuilder, type WebAclBuilderProps, type WebAclBuilderResult, } from "./web-acl-builder.js";
3
+ export { type IWebAclRuleBuilder, type WebAclRuleAction, type WebAclRuleBuilderProps, } from "./rule-builder.js";
4
+ export { type WebAclAssociationTarget } from "./association.js";
5
+ export { type CustomResponse, type CustomResponseBody, SUPPORTED_CUSTOM_RESPONSE_STATUS_CODES, } from "./custom-response.js";
6
+ export { type WebAclScope } from "./scope.js";
7
+ export { type ManagedRuleGroupVersion, type WebAclMetrics, type WebAclRequestMetrics, } from "./metrics.js";
8
+ export { type WebAclAlarmConfig, type WebAclRuleAlarmConfig } from "./alarm-config.js";
9
+ export { WEB_ACL_RULE_ALARM_DEFAULTS } from "./alarm-defaults.js";
10
+ export { type WebAclLoggingConfig, type WebAclLogRedaction } from "./logging.js";
11
+ export { type WebAclLogAction, type WebAclLogCondition, type WebAclLoggingFilter, } from "./logging-filter.js";
12
+ export { DEFAULT_LOGGING_FILTER, DEFAULT_LOGGING_REDACTED_HEADERS, DEFAULT_RULE_PRIORITY_STEP, WEB_ACL_DEFAULTS, WEB_ACL_VISIBILITY_DEFAULTS, WAF_LOG_GROUP_NAME_PREFIX, } from "./defaults.js";
13
+ /**
14
+ * This package's AWS-property constraints, grouped by application strategy.
15
+ * The `constraints.validate.*` / `constraints.sanitize.*` shape is identical
16
+ * in every builder package, so it is discoverable without importing anything
17
+ * beyond the package you already use. The underlying constraint definitions
18
+ * stay module-private — this namespace is the only public surface for them.
19
+ * See ADR-0010.
20
+ */
21
+ export declare const constraints: {
22
+ validate: {
23
+ webAclName: typeof validateWebAclName;
24
+ ruleName: typeof validateRuleName;
25
+ metricName: typeof validateMetricName;
26
+ ruleLabel: typeof validateRuleLabel;
27
+ };
28
+ sanitize: {};
29
+ };
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,sCAAsC,GACvC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EAChC,0BAA0B,EAC1B,gBAAgB,EAChB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;;;;;;;;CAQO,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { validateMetricName, validateRuleLabel, validateRuleName, validateWebAclName, } from "./names.js";
2
+ export { createWebAclBuilder, } from "./web-acl-builder.js";
3
+ export { SUPPORTED_CUSTOM_RESPONSE_STATUS_CODES, } from "./custom-response.js";
4
+ export { WEB_ACL_RULE_ALARM_DEFAULTS } from "./alarm-defaults.js";
5
+ export { DEFAULT_LOGGING_FILTER, DEFAULT_LOGGING_REDACTED_HEADERS, DEFAULT_RULE_PRIORITY_STEP, WEB_ACL_DEFAULTS, WEB_ACL_VISIBILITY_DEFAULTS, WAF_LOG_GROUP_NAME_PREFIX, } from "./defaults.js";
6
+ /**
7
+ * This package's AWS-property constraints, grouped by application strategy.
8
+ * The `constraints.validate.*` / `constraints.sanitize.*` shape is identical
9
+ * in every builder package, so it is discoverable without importing anything
10
+ * beyond the package you already use. The underlying constraint definitions
11
+ * stay module-private — this namespace is the only public surface for them.
12
+ * See ADR-0010.
13
+ */
14
+ export const constraints = {
15
+ validate: {
16
+ webAclName: validateWebAclName,
17
+ ruleName: validateRuleName,
18
+ metricName: validateMetricName,
19
+ ruleLabel: validateRuleLabel,
20
+ },
21
+ sanitize: {},
22
+ };
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,GAIpB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAGL,sCAAsC,GACvC,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAOlE,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EAChC,0BAA0B,EAC1B,gBAAgB,EAChB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE;QACR,UAAU,EAAE,kBAAkB;QAC9B,QAAQ,EAAE,gBAAgB;QAC1B,UAAU,EAAE,kBAAkB;QAC9B,SAAS,EAAE,iBAAiB;KAC7B;IACD,QAAQ,EAAE,EAAE;CACiB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /** An action a logging filter condition can match on. */
2
+ export type WebAclLogAction = "ALLOW" | "BLOCK" | "COUNT" | "CAPTCHA" | "CHALLENGE" | "EXCLUDED_AS_COUNT";
3
+ /** One condition of a {@link WebAclLoggingFilter} filter: an action or a label. */
4
+ export type WebAclLogCondition = {
5
+ action: WebAclLogAction;
6
+ } | {
7
+ label: string;
8
+ };
9
+ /**
10
+ * Which requests WAF writes to the log, typed. The builder turns it into the
11
+ * PascalCase JSON CloudFormation's `LoggingFilter` expects, which CDK types
12
+ * as `any`.
13
+ *
14
+ * @see https://docs.aws.amazon.com/waf/latest/APIReference/API_LoggingFilter.html
15
+ */
16
+ export interface WebAclLoggingFilter {
17
+ /** What to do with a request no filter matches. */
18
+ readonly defaultBehavior: "KEEP" | "DROP";
19
+ readonly filters: readonly {
20
+ readonly behavior: "KEEP" | "DROP";
21
+ readonly requirement: "MEETS_ALL" | "MEETS_ANY";
22
+ readonly conditions: readonly WebAclLogCondition[];
23
+ }[];
24
+ }
25
+ /** @internal — `LoggingFilter` is `any` in CDK, so this emits CloudFormation's PascalCase. */
26
+ export declare function toFilterProperty(filter: WebAclLoggingFilter): unknown;
27
+ //# sourceMappingURL=logging-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging-filter.d.ts","sourceRoot":"","sources":["../../src/logging-filter.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,MAAM,MAAM,eAAe,GACzB,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,mBAAmB,CAAC;AAE9E,mFAAmF;AACnF,MAAM,MAAM,kBAAkB,GAAG;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;QACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,CAAC;QAChD,QAAQ,CAAC,UAAU,EAAE,SAAS,kBAAkB,EAAE,CAAC;KACpD,EAAE,CAAC;CACL;AAED,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAarE"}
@@ -0,0 +1,14 @@
1
+ /** @internal — `LoggingFilter` is `any` in CDK, so this emits CloudFormation's PascalCase. */
2
+ export function toFilterProperty(filter) {
3
+ return {
4
+ DefaultBehavior: filter.defaultBehavior,
5
+ Filters: filter.filters.map((f) => ({
6
+ Behavior: f.behavior,
7
+ Requirement: f.requirement,
8
+ Conditions: f.conditions.map((c) => "action" in c
9
+ ? { ActionCondition: { Action: c.action } }
10
+ : { LabelNameCondition: { LabelName: c.label } }),
11
+ })),
12
+ };
13
+ }
14
+ //# sourceMappingURL=logging-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging-filter.js","sourceRoot":"","sources":["../../src/logging-filter.ts"],"names":[],"mappings":"AAwBA,8FAA8F;AAC9F,MAAM,UAAU,gBAAgB,CAAC,MAA2B;IAC1D,OAAO;QACL,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClC,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjC,QAAQ,IAAI,CAAC;gBACX,CAAC,CAAC,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC3C,CAAC,CAAC,EAAE,kBAAkB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CACnD;SACF,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { type CfnLoggingConfigurationProps, type CfnWebACL } from "aws-cdk-lib/aws-wafv2";
2
+ import type { IConstruct } from "constructs";
3
+ import { type Resolvable } from "@composurecdk/core";
4
+ import { type ILogGroupBuilder } from "@composurecdk/logs";
5
+ import { type WebAclLoggingFilter } from "./logging-filter.js";
6
+ import type { WebAclBuilderResult } from "./web-acl-builder.js";
7
+ /** Request fields to redact from the log. */
8
+ export interface WebAclLogRedaction {
9
+ /**
10
+ * Header names to redact, **in addition to** `authorization` and `cookie`,
11
+ * which are always redacted.
12
+ */
13
+ readonly headers?: readonly string[];
14
+ /** Redact the query string. */
15
+ readonly queryString?: boolean;
16
+ /** Redact the URI path. */
17
+ readonly uriPath?: boolean;
18
+ /** Redact the HTTP method. */
19
+ readonly method?: boolean;
20
+ }
21
+ /**
22
+ * Configures the web ACL's logging. On by default: WAF writes the requests it
23
+ * does not allow to a created `aws-waf-logs-` CloudWatch log group, with the
24
+ * `authorization` and `cookie` headers redacted. `false` turns it off.
25
+ */
26
+ export interface WebAclLoggingConfig {
27
+ /**
28
+ * Customize the created log group. It starts with an `aws-waf-logs-` name,
29
+ * which WAF requires, and the `@composurecdk/logs` retention and removal
30
+ * defaults. The callback's builder resolves `ref`s against the build
31
+ * context. Cannot be combined with {@link destination}.
32
+ */
33
+ readonly configure?: (b: ILogGroupBuilder) => ILogGroupBuilder;
34
+ /**
35
+ * Log to an existing destination instead of a created log group: a
36
+ * CloudWatch log group, S3 bucket or Firehose stream ARN, or a reference
37
+ * CDK's `CfnLoggingConfiguration` accepts. Its name must start with
38
+ * `aws-waf-logs-`, a log group ARN must not end in `:*`, an S3 bucket must
39
+ * use SSE-S3 or a customer managed key, and a Firehose stream must be
40
+ * DirectPut. Cannot be combined with {@link configure}.
41
+ */
42
+ readonly destination?: Resolvable<NonNullable<CfnLoggingConfigurationProps["logDestinationConfigs"]>[number]>;
43
+ /**
44
+ * Which requests to log. `"non-allow"`, the default, keeps every request
45
+ * WAF blocks, counts, or answers with a CAPTCHA or challenge, and drops the
46
+ * rest. `"all"` keeps everything.
47
+ */
48
+ readonly filter?: "non-allow" | "all" | WebAclLoggingFilter;
49
+ /** Fields to redact, merged with the defaults. */
50
+ readonly redact?: WebAclLogRedaction;
51
+ }
52
+ /**
53
+ * Creates the web ACL's logging configuration and, unless a destination was
54
+ * given, its log group.
55
+ *
56
+ * @internal
57
+ */
58
+ export declare function configureLogging(scope: IConstruct, id: string, owner: string, webAcl: CfnWebACL, config: WebAclLoggingConfig | false, context: Record<string, object>): Pick<WebAclBuilderResult, "logGroup" | "logging">;
59
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/logging.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMlF,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,6CAA6C;AAC7C,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,+BAA+B;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;IAE/D;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,UAAU,CAC/B,WAAW,CAAC,4BAA4B,CAAC,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,CAC3E,CAAC;IAEF;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,GAAG,mBAAmB,CAAC;IAE5D,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAwED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,mBAAmB,GAAG,KAAK,EACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,SAAS,CAAC,CAwBnD"}
@@ -0,0 +1,88 @@
1
+ import { ArnFormat, Token } from "aws-cdk-lib";
2
+ import { CfnLoggingConfiguration, } from "aws-cdk-lib/aws-wafv2";
3
+ import { resolve } from "@composurecdk/core";
4
+ import { createLogGroupBuilder } from "@composurecdk/logs";
5
+ import { DEFAULT_LOGGING_FILTER, DEFAULT_LOGGING_REDACTED_HEADERS, WAF_LOG_GROUP_NAME_PREFIX, } from "./defaults.js";
6
+ import { toFilterProperty } from "./logging-filter.js";
7
+ import { webAclBaseName } from "./names.js";
8
+ const MAX_REDACTED_FIELDS = 100;
9
+ const LOGGING_SOURCE = "https://docs.aws.amazon.com/waf/latest/developerguide/logging.html";
10
+ function loggingFilter(filter) {
11
+ if (filter === "all")
12
+ return undefined;
13
+ return toFilterProperty(typeof filter === "object" ? filter : DEFAULT_LOGGING_FILTER);
14
+ }
15
+ function redactedFields(owner, redact) {
16
+ const headers = new Map();
17
+ for (const name of [...DEFAULT_LOGGING_REDACTED_HEADERS, ...(redact?.headers ?? [])]) {
18
+ headers.set(name.toLowerCase(), name);
19
+ }
20
+ // `FieldToMatch`'s members are `any` in CDK, so `SingleHeader` needs CloudFormation's `Name`.
21
+ const fields = [...headers.values()].map((Name) => ({ singleHeader: { Name } }));
22
+ if (redact?.queryString)
23
+ fields.push({ queryString: {} });
24
+ if (redact?.uriPath)
25
+ fields.push({ uriPath: {} });
26
+ if (redact?.method)
27
+ fields.push({ method: {} });
28
+ if (fields.length > MAX_REDACTED_FIELDS) {
29
+ throw new Error(`${owner}: logging redacts ${String(fields.length)} fields; AWS WAF allows at most ${String(MAX_REDACTED_FIELDS)}. See ${LOGGING_SOURCE}.`);
30
+ }
31
+ return fields;
32
+ }
33
+ function checkLogGroupName(owner, name) {
34
+ // The builder always seeds a name, but `configure` can replace it with a token.
35
+ if (name === undefined || Token.isUnresolved(name))
36
+ return;
37
+ if (!name.startsWith(WAF_LOG_GROUP_NAME_PREFIX)) {
38
+ throw new Error(`${owner}: the WAF log group is named "${name}", but AWS WAF only logs to log groups ` +
39
+ `whose names start with "${WAF_LOG_GROUP_NAME_PREFIX}". Rename it, or leave the ` +
40
+ `name to the builder. See ${LOGGING_SOURCE}.`);
41
+ }
42
+ }
43
+ /**
44
+ * Creates the WAF log group and returns it with the ARN WAF accepts for it.
45
+ */
46
+ function createLogGroup(scope, id, owner, webAcl, configure, context) {
47
+ let builder = createLogGroupBuilder().logGroupName(`${WAF_LOG_GROUP_NAME_PREFIX}${webAclBaseName(webAcl)}`);
48
+ if (configure)
49
+ builder = configure(builder);
50
+ checkLogGroupName(owner, builder.logGroupName());
51
+ const logGroup = builder.build(scope, `${id}Logs`, context).logGroup;
52
+ // WAF rejects the `:*` that `logGroupArn` ends in.
53
+ const arn = logGroup.stack.formatArn({
54
+ service: "logs",
55
+ resource: "log-group",
56
+ resourceName: logGroup.logGroupName,
57
+ arnFormat: ArnFormat.COLON_RESOURCE_NAME,
58
+ });
59
+ return { logGroup, arn };
60
+ }
61
+ /**
62
+ * Creates the web ACL's logging configuration and, unless a destination was
63
+ * given, its log group.
64
+ *
65
+ * @internal
66
+ */
67
+ export function configureLogging(scope, id, owner, webAcl, config, context) {
68
+ if (config === false)
69
+ return {};
70
+ const { configure, destination, filter, redact } = config;
71
+ if (configure !== undefined && destination !== undefined) {
72
+ throw new Error(`${owner}: logging 'configure' cannot be combined with 'destination' — the ` +
73
+ `destination is user-managed and not built by this builder.`);
74
+ }
75
+ const { logGroup, arn } = destination === undefined
76
+ ? createLogGroup(scope, id, owner, webAcl, configure, context)
77
+ : { logGroup: undefined, arn: resolve(destination, context) };
78
+ const logging = new CfnLoggingConfiguration(scope, `${id}Logging`, {
79
+ resourceArn: webAcl.attrArn,
80
+ logDestinationConfigs: [arn],
81
+ loggingFilter: loggingFilter(filter),
82
+ redactedFields: redactedFields(owner, redact),
83
+ });
84
+ if (logGroup)
85
+ logging.node.addDependency(logGroup);
86
+ return { logGroup, logging };
87
+ }
88
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/logging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import { Metric, type MetricOptions } from "aws-cdk-lib/aws-cloudwatch";
3
+ import type { CfnWebACL } from "aws-cdk-lib/aws-wafv2";
4
+ /**
5
+ * The request-count metrics WAF publishes for a web ACL, a rule, or the
6
+ * default action. Each is a Sum over 5 minutes unless `options` say
7
+ * otherwise. WAF publishes a datapoint only when the count is non-zero.
8
+ *
9
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/waf-metrics.html
10
+ */
11
+ export interface WebAclRequestMetrics {
12
+ allowedRequests(options?: MetricOptions): Metric;
13
+ blockedRequests(options?: MetricOptions): Metric;
14
+ countedRequests(options?: MetricOptions): Metric;
15
+ captchaRequests(options?: MetricOptions): Metric;
16
+ challengeRequests(options?: MetricOptions): Metric;
17
+ }
18
+ /**
19
+ * The metrics of a web ACL, with dimensions built from the names the builder
20
+ * gave it and its rules, so they match what WAF publishes. The top-level
21
+ * metrics cover every rule (`Rule=ALL`).
22
+ */
23
+ export interface WebAclMetrics extends WebAclRequestMetrics {
24
+ /** Requests no rule terminated, which the default action decided. */
25
+ readonly defaultAction: WebAclRequestMetrics;
26
+ /**
27
+ * The metrics of one rule, by the name given to `addRule`.
28
+ *
29
+ * @throws when the web ACL has no rule of that name.
30
+ */
31
+ rule(name: string): WebAclRequestMetrics;
32
+ /**
33
+ * Days until a pinned managed rule group version expires. Published only
34
+ * for a group the web ACL uses at that version.
35
+ *
36
+ * @see https://docs.aws.amazon.com/waf/latest/developerguide/waf-using-managed-rule-groups-expiration.html
37
+ */
38
+ daysToExpiry(group: ManagedRuleGroupVersion, options?: MetricOptions): Metric;
39
+ }
40
+ /** A managed rule group at a pinned version. */
41
+ export interface ManagedRuleGroupVersion {
42
+ readonly vendorName: string;
43
+ readonly name: string;
44
+ readonly version: string;
45
+ }
46
+ /** @internal — the period of every request metric unless overridden. */
47
+ export declare const REQUEST_METRIC_PERIOD: Duration;
48
+ /**
49
+ * Builds a web ACL's {@link WebAclMetrics}.
50
+ *
51
+ * @param metricName - The web ACL's own metric name, which WAF publishes the
52
+ * default action's metrics under as the `Rule` dimension.
53
+ * @param ruleMetricNames - Each rule's metric name, by rule name.
54
+ *
55
+ * @internal
56
+ */
57
+ export declare function webAclMetrics(webAcl: CfnWebACL, metricName: string, ruleMetricNames: ReadonlyMap<string, string>): WebAclMetrics;
58
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAoB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAS,MAAM,4BAA4B,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IACjD,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IACjD,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IACjD,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IACjD,iBAAiB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;CACpD;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,oBAAoB;IACzD,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,oBAAoB,CAAC;IAE7C;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAAC;IAEzC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,uBAAuB,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;CAC/E;AAED,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAGD,wEAAwE;AACxE,eAAO,MAAM,qBAAqB,UAAsB,CAAC;AAezD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3C,aAAa,CA8Cf"}
@@ -0,0 +1,63 @@
1
+ import { Duration, Fn, Stack, Token } from "aws-cdk-lib";
2
+ import { Metric, Stats } from "aws-cdk-lib/aws-cloudwatch";
3
+ const NAMESPACE = "AWS/WAFV2";
4
+ /** @internal — the period of every request metric unless overridden. */
5
+ export const REQUEST_METRIC_PERIOD = Duration.minutes(5);
6
+ const ALL_RULES = "ALL";
7
+ /**
8
+ * The value of a web ACL's `WebACL` dimension: its name. WAF publishes the
9
+ * name here, not the `VisibilityConfig` metric name the documentation
10
+ * describes. A web ACL without a literal name reads it from `Ref`, which is
11
+ * `name|id|scope`.
12
+ */
13
+ function webAclDimension(webAcl) {
14
+ const { name } = webAcl;
15
+ if (name !== undefined && !Token.isUnresolved(name))
16
+ return name;
17
+ return Fn.select(0, Fn.split("|", webAcl.ref));
18
+ }
19
+ /**
20
+ * Builds a web ACL's {@link WebAclMetrics}.
21
+ *
22
+ * @param metricName - The web ACL's own metric name, which WAF publishes the
23
+ * default action's metrics under as the `Rule` dimension.
24
+ * @param ruleMetricNames - Each rule's metric name, by rule name.
25
+ *
26
+ * @internal
27
+ */
28
+ export function webAclMetrics(webAcl, metricName, ruleMetricNames) {
29
+ // CloudFront metrics have no `Region` dimension.
30
+ const regionDimension = webAcl.scope === "CLOUDFRONT" ? {} : { Region: Stack.of(webAcl).region };
31
+ const webAclName = webAclDimension(webAcl);
32
+ const metric = (name, dimensionsMap, options) => new Metric({
33
+ namespace: NAMESPACE,
34
+ metricName: name,
35
+ statistic: Stats.SUM,
36
+ period: REQUEST_METRIC_PERIOD,
37
+ ...options,
38
+ dimensionsMap: { ...dimensionsMap, ...regionDimension, ...options?.dimensionsMap },
39
+ });
40
+ const requests = (rule) => {
41
+ const dimensions = { WebACL: webAclName, Rule: rule };
42
+ return {
43
+ allowedRequests: (o) => metric("AllowedRequests", dimensions, o),
44
+ blockedRequests: (o) => metric("BlockedRequests", dimensions, o),
45
+ countedRequests: (o) => metric("CountedRequests", dimensions, o),
46
+ captchaRequests: (o) => metric("CaptchaRequests", dimensions, o),
47
+ challengeRequests: (o) => metric("ChallengeRequests", dimensions, o),
48
+ };
49
+ };
50
+ return {
51
+ ...requests(ALL_RULES),
52
+ defaultAction: requests(metricName),
53
+ rule: (name) => {
54
+ const ruleMetricName = ruleMetricNames.get(name);
55
+ if (ruleMetricName === undefined) {
56
+ throw new Error(`The web ACL has no rule named "${name}". Rules: ${[...ruleMetricNames.keys()].join(", ") || "none"}.`);
57
+ }
58
+ return requests(ruleMetricName);
59
+ },
60
+ daysToExpiry: (group, options) => metric("DaysToExpiry", { Vendor: group.vendorName, ManagedRuleGroup: group.name, Version: group.version }, { statistic: Stats.MINIMUM, period: Duration.hours(1), ...options }),
61
+ };
62
+ }
63
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { CfnWebACL } from "aws-cdk-lib/aws-wafv2";
2
+ /**
3
+ * Validates a web ACL name.
4
+ *
5
+ * @throws on invalid input.
6
+ */
7
+ export declare function validateWebAclName(raw: string): void;
8
+ /**
9
+ * Validates the name of a rule in a web ACL.
10
+ *
11
+ * @throws on invalid input.
12
+ */
13
+ export declare function validateRuleName(raw: string): void;
14
+ /**
15
+ * Validates a CloudWatch metric name for a web ACL or rule. `All` and
16
+ * `Default_Action` are rejected: WAF uses them for its own metrics.
17
+ *
18
+ * @throws on invalid input.
19
+ */
20
+ export declare function validateMetricName(raw: string): void;
21
+ /**
22
+ * The web ACL's name when it is a literal, and otherwise a name derived from
23
+ * its construct path, unique in the app. The base of its default metric and
24
+ * log group names.
25
+ *
26
+ * @internal
27
+ */
28
+ export declare function webAclBaseName(webAcl: CfnWebACL): string;
29
+ /**
30
+ * Turns a construct path or other derived string into a legal metric name, for
31
+ * when the user has not chosen one.
32
+ *
33
+ * @internal
34
+ */
35
+ export declare function sanitizeMetricName(raw: string): string;
36
+ /**
37
+ * Validates a label a rule adds to matching requests: up to five
38
+ * colon-separated namespaces and a name, each 1–128 characters of
39
+ * `[A-Za-z0-9_-]`, none of them one of WAF's reserved words. WAF adds the
40
+ * `awswaf:<account>:webacl:<name>:` prefix itself, so it is not part of the
41
+ * label.
42
+ *
43
+ * @throws on invalid input.
44
+ */
45
+ export declare function validateRuleLabel(raw: string): void;
46
+ //# sourceMappingURL=names.d.ts.map