@kensio/yulin 1.21.22 → 1.21.24

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 (104) hide show
  1. package/dist/service/athena/engine/sim-athena-ast-nodes.d.ts +11 -0
  2. package/dist/service/athena/engine/sim-athena-ast-nodes.js +22 -0
  3. package/dist/service/athena/engine/sim-athena-string-shims.js +29 -1
  4. package/dist/service/athena/engine/sim-athena-unnest-item.js +6 -15
  5. package/dist/service/athena/engine/sim-athena-unnest-rewrite.d.ts +4 -4
  6. package/dist/service/athena/engine/sim-athena-unnest-rewrite.js +4 -4
  7. package/dist/service/athena/engine/sim-athena-unnest-source.d.ts +10 -9
  8. package/dist/service/athena/engine/sim-athena-unnest-source.js +25 -11
  9. package/dist/service/athena/sim-athena-flattened-events.fixture.d.ts +3 -0
  10. package/dist/service/athena/sim-athena-flattened-events.fixture.js +46 -0
  11. package/dist/service/wafv2/association/sim-aws-waf-protected-resources.js +4 -0
  12. package/dist/service/wafv2/association/sim-waf-associations.d.ts +6 -0
  13. package/dist/service/wafv2/association/sim-waf-associations.js +17 -0
  14. package/dist/service/wafv2/association/sim-waf-protected-resource.d.ts +13 -8
  15. package/dist/service/wafv2/association/sim-waf-protected-resource.js +23 -23
  16. package/dist/service/wafv2/association/sim-waf-protected-resources.d.ts +11 -6
  17. package/dist/service/wafv2/association/sim-waf-protected-resources.js +10 -7
  18. package/dist/service/wafv2/association/sim-waf-unsimulated-resource.d.ts +33 -0
  19. package/dist/service/wafv2/association/sim-waf-unsimulated-resource.js +66 -0
  20. package/dist/service/wafv2/cfn/association/sim-cfn-waf-association-creator.js +5 -0
  21. package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-config.js +1 -0
  22. package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-creator.js +2 -0
  23. package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-config.js +1 -0
  24. package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-creator.js +2 -0
  25. package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.d.ts +4 -0
  26. package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.js +10 -0
  27. package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.d.ts +10 -0
  28. package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.js +12 -0
  29. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.d.ts +1 -13
  30. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.js +8 -21
  31. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.d.ts +4 -9
  32. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.js +7 -15
  33. package/dist/service/wafv2/command/association/sim-wafv2-association-commands.js +2 -1
  34. package/dist/service/wafv2/command/association/sim-wafv2-association-input.d.ts +10 -2
  35. package/dist/service/wafv2/command/association/sim-wafv2-association-input.js +25 -13
  36. package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.d.ts +3 -3
  37. package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.js +5 -5
  38. package/dist/service/wafv2/command/managed-rule-group/sim-wafv2-managed-rule-group-commands.js +4 -4
  39. package/dist/service/wafv2/command/regex-pattern-set/sim-wafv2-regex-pattern-set-commands.js +2 -2
  40. package/dist/service/wafv2/command/sim-wafv2-input.d.ts +0 -7
  41. package/dist/service/wafv2/command/sim-wafv2-input.js +1 -13
  42. package/dist/service/wafv2/command/web-acl/sim-waf-web-acl-output.js +1 -0
  43. package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.d.ts +9 -12
  44. package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.js +27 -28
  45. package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.d.ts +3 -3
  46. package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.js +6 -6
  47. package/dist/service/wafv2/command/web-acl/web-acl.command.d.ts +6 -0
  48. package/dist/service/wafv2/index.d.ts +3 -0
  49. package/dist/service/wafv2/index.js +1 -0
  50. package/dist/service/wafv2/managed/group/sim-waf-bot-control.d.ts +27 -0
  51. package/dist/service/wafv2/managed/group/sim-waf-bot-control.js +68 -0
  52. package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.d.ts +18 -0
  53. package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.js +51 -0
  54. package/dist/service/wafv2/managed/sim-waf-bot-declaration.d.ts +35 -0
  55. package/dist/service/wafv2/managed/sim-waf-bot-declaration.js +42 -0
  56. package/dist/service/wafv2/managed/sim-waf-managed-declaration.d.ts +35 -0
  57. package/dist/service/wafv2/managed/sim-waf-managed-declaration.js +30 -0
  58. package/dist/service/wafv2/managed/sim-waf-managed-group-configs.d.ts +11 -0
  59. package/dist/service/wafv2/managed/sim-waf-managed-group-configs.js +42 -0
  60. package/dist/service/wafv2/managed/sim-waf-managed-group-input.d.ts +5 -4
  61. package/dist/service/wafv2/managed/sim-waf-managed-group-input.js +7 -9
  62. package/dist/service/wafv2/managed/sim-waf-managed-group-statement.js +16 -14
  63. package/dist/service/wafv2/managed/sim-waf-managed-group.type.d.ts +2 -2
  64. package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.d.ts +30 -0
  65. package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.js +26 -0
  66. package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.d.ts +5 -3
  67. package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.js +10 -3
  68. package/dist/service/wafv2/managed/sim-waf-managed-rule.type.d.ts +11 -2
  69. package/dist/service/wafv2/managed/sim-waf-managed-rules.d.ts +14 -9
  70. package/dist/service/wafv2/managed/sim-waf-managed-rules.js +15 -5
  71. package/dist/service/wafv2/resource/sim-waf-resource.d.ts +10 -0
  72. package/dist/service/wafv2/resource/sim-waf-resource.js +12 -0
  73. package/dist/service/wafv2/resource/sim-waf-unsimulated-part.d.ts +24 -0
  74. package/dist/service/wafv2/resource/sim-waf-unsimulated-part.js +8 -0
  75. package/dist/service/wafv2/sim-wafv2.d.ts +12 -12
  76. package/dist/service/wafv2/sim-wafv2.fixture.d.ts +19 -1
  77. package/dist/service/wafv2/sim-wafv2.fixture.js +29 -0
  78. package/dist/service/wafv2/sim-wafv2.js +25 -23
  79. package/dist/service/wafv2/statement/sim-waf-field-to-match.type.d.ts +2 -2
  80. package/dist/service/wafv2/statement/sim-waf-rule-refusals.d.ts +6 -4
  81. package/dist/service/wafv2/statement/sim-waf-rule-refusals.js +7 -6
  82. package/dist/service/wafv2/statement/sim-waf-statement.d.ts +3 -3
  83. package/dist/service/wafv2/statement/sim-waf-statement.js +3 -3
  84. package/dist/service/wafv2/statement/sim-waf-statement.type.d.ts +3 -3
  85. package/dist/service/wafv2/statement/sim-waf-unsimulated-statement.js +1 -1
  86. package/dist/service/wafv2/web-acl/sim-waf-association-config.d.ts +14 -7
  87. package/dist/service/wafv2/web-acl/sim-waf-association-config.js +17 -27
  88. package/dist/service/wafv2/web-acl/sim-waf-rule.d.ts +15 -3
  89. package/dist/service/wafv2/web-acl/sim-waf-rule.js +46 -10
  90. package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.d.ts +4 -4
  91. package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.js +4 -4
  92. package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.d.ts +6 -0
  93. package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.js +23 -0
  94. package/dist/service/wafv2/web-acl/sim-waf-web-acl-capacity.js +2 -2
  95. package/dist/service/wafv2/web-acl/sim-waf-web-acl-configuration.d.ts +5 -0
  96. package/dist/service/wafv2/web-acl/sim-waf-web-acl.d.ts +11 -2
  97. package/dist/service/wafv2/web-acl/sim-waf-web-acl.js +20 -1
  98. package/docs/services/athena/README.md +21 -2
  99. package/docs/services/wafv2/README.md +243 -51
  100. package/package.json +2 -2
  101. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.d.ts +0 -15
  102. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.js +0 -21
  103. package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.d.ts +0 -25
  104. package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.js +0 -33
@@ -1,6 +1,7 @@
1
1
  import { compileSimWafStatement } from "../statement/sim-waf-statement.js";
2
- import { SimWafAction } from "../web-acl/sim-waf-action.js";
3
2
  import { requiredSimWafManagedRuleGroup, simWafGroupCountsEverything, } from "./sim-waf-managed-group-input.js";
3
+ import { simWafDeclaredGroupLabels } from "./sim-waf-managed-declaration.js";
4
+ import { simWafAddGroupLabels, simWafManagedRuleActions, } from "./sim-waf-managed-rule-actions.js";
4
5
  import { simWafManagedRuleOverrides } from "./sim-waf-managed-rule-overrides.js";
5
6
  import { simWafManagedRequestParts } from "./sim-waf-managed-request.js";
6
7
  /**
@@ -20,8 +21,11 @@ import { simWafManagedRequestParts } from "./sim-waf-managed-request.js";
20
21
  export function compileSimWafManagedRuleGroup(properties) {
21
22
  const { statement, ruleName, scope } = properties;
22
23
  const group = requiredSimWafManagedRuleGroup(statement, ruleName);
23
- const overrides = simWafManagedRuleOverrides(statement, group, ruleName, scope.customResponseBodies);
24
- const counting = simWafGroupCountsEverything(properties.overrideAction, ruleName);
24
+ const actions = simWafManagedRuleActions({
25
+ ruleName,
26
+ overrides: simWafManagedRuleOverrides(statement, group, ruleName, scope.customResponseBodies),
27
+ counting: simWafGroupCountsEverything(properties.overrideAction, ruleName),
28
+ });
25
29
  const scopeDown = statement.ScopeDownStatement === undefined
26
30
  ? undefined
27
31
  : compileSimWafStatement(statement.ScopeDownStatement, {
@@ -29,10 +33,6 @@ export function compileSimWafManagedRuleGroup(properties) {
29
33
  clock: scope.clock,
30
34
  ruleName,
31
35
  });
32
- // Every rule in the three simulated groups blocks by default, and a group
33
- // that is counting counts whatever the rule that matched was set to.
34
- const blocking = SimWafAction.read({ Block: {} }, ruleName, {});
35
- const counted = SimWafAction.read({ Count: {} }, ruleName, {});
36
36
  const { managedRules } = scope;
37
37
  return (request) => {
38
38
  // A scope-down statement decides whether the group sees the request at
@@ -41,21 +41,23 @@ export function compileSimWafManagedRuleGroup(properties) {
41
41
  return undefined;
42
42
  }
43
43
  const parts = simWafManagedRequestParts(request);
44
- const declared = managedRules.declaredMatches(request);
44
+ const declared = managedRules.declared(request);
45
45
  let matched = false;
46
+ simWafAddGroupLabels(request, group, simWafDeclaredGroupLabels(declared, group.name));
46
47
  for (const rule of group.rules) {
47
- if (!declared.has(rule.name) && rule.detects?.(parts) !== true) {
48
+ if (!declared.matches.has(rule.name) && rule.detects?.(parts) !== true) {
48
49
  continue;
49
50
  }
50
- request.labels.add(`${group.labelNamespace}:${rule.label}`);
51
- const action = counting
52
- ? counted
53
- : (overrides.get(rule.name) ?? blocking);
51
+ simWafAddGroupLabels(request, group, [
52
+ rule.label,
53
+ ...(rule.labels ?? []),
54
+ ]);
55
+ const action = actions.of(rule);
54
56
  if (action.isTerminating) {
55
57
  return action;
56
58
  }
57
59
  matched = true;
58
60
  }
59
- return matched ? counted : undefined;
61
+ return matched ? actions.counted : undefined;
60
62
  };
61
63
  }
@@ -3,8 +3,8 @@ import type { SimWafActionInput } from "../web-acl/sim-waf-action.type.js";
3
3
  /**
4
4
  * Minimal structural WAFv2 ManagedRuleGroupStatement.
5
5
  *
6
- * The members Yulin refuses are declared here rather than left out, so a
7
- * statement that names one is refused by name.
6
+ * The members Yulin does not simulate are declared here rather than left out,
7
+ * so a rule whose statement names one is held and reported by name.
8
8
  *
9
9
  * https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/wafv2/Interface/ManagedRuleGroupStatement/
10
10
  */
@@ -0,0 +1,30 @@
1
+ import type { SimWafInspectedRequest } from "../evaluate/sim-waf-inspected-request.js";
2
+ import { SimWafAction } from "../web-acl/sim-waf-action.js";
3
+ import type { SimWafManagedRuleDefinition, SimWafManagedRuleGroupDefinition } from "./sim-waf-managed-rule.type.js";
4
+ interface SimWafManagedRuleActionsProperties {
5
+ readonly ruleName: string;
6
+ readonly overrides: ReadonlyMap<string, SimWafAction>;
7
+ readonly counting: boolean;
8
+ }
9
+ /**
10
+ * What each rule of one managed rule group does to a request it claims.
11
+ */
12
+ export interface SimWafManagedRuleActions {
13
+ /** The action one rule of the group takes. */
14
+ of(rule: SimWafManagedRuleDefinition): SimWafAction;
15
+ /** The action a group answers with when its rules only counted. */
16
+ readonly counted: SimWafAction;
17
+ }
18
+ /**
19
+ * Settle what the rules of a group do, where the rule naming it is compiled.
20
+ *
21
+ * A rule takes its own default (`Block`, or `Count` for the few AWS ships
22
+ * counting), an action override replaces that, and a group counting as a
23
+ * whole counts whatever its rules were set to.
24
+ */
25
+ export declare function simWafManagedRuleActions(properties: SimWafManagedRuleActionsProperties): SimWafManagedRuleActions;
26
+ /**
27
+ * Add labels to a request within a group's namespace.
28
+ */
29
+ export declare function simWafAddGroupLabels(request: SimWafInspectedRequest, group: SimWafManagedRuleGroupDefinition, labels: readonly string[]): void;
30
+ export {};
@@ -0,0 +1,26 @@
1
+ import { SimWafAction } from "../web-acl/sim-waf-action.js";
2
+ /**
3
+ * Settle what the rules of a group do, where the rule naming it is compiled.
4
+ *
5
+ * A rule takes its own default (`Block`, or `Count` for the few AWS ships
6
+ * counting), an action override replaces that, and a group counting as a
7
+ * whole counts whatever its rules were set to.
8
+ */
9
+ export function simWafManagedRuleActions(properties) {
10
+ const { ruleName, overrides, counting } = properties;
11
+ const blocking = SimWafAction.read({ Block: {} }, ruleName, {});
12
+ const counted = SimWafAction.read({ Count: {} }, ruleName, {});
13
+ const ownAction = (rule) => rule.counts === true ? counted : blocking;
14
+ return {
15
+ of: (rule) => counting ? counted : (overrides.get(rule.name) ?? ownAction(rule)),
16
+ counted,
17
+ };
18
+ }
19
+ /**
20
+ * Add labels to a request within a group's namespace.
21
+ */
22
+ export function simWafAddGroupLabels(request, group, labels) {
23
+ for (const label of labels) {
24
+ request.labels.add(`${group.labelNamespace}:${label}`);
25
+ }
26
+ }
@@ -2,8 +2,9 @@ import type { SimWafManagedRuleDefinition, SimWafManagedRuleGroupDefinition } fr
2
2
  /**
3
3
  * The vendor the simulated managed rule groups belong to.
4
4
  *
5
- * A group from any other vendor is refused, marketplace groups included: a
6
- * subscription buys rules nobody outside the vendor has ever seen.
5
+ * A rule naming a group from any other vendor is held unevaluated,
6
+ * marketplace groups included: a subscription buys rules nobody outside the
7
+ * vendor has ever seen.
7
8
  */
8
9
  export declare const simWafManagedVendorName = "AWS";
9
10
  /**
@@ -18,7 +19,8 @@ export interface SimWafManagedRuleEntry {
18
19
  */
19
20
  export declare function findSimWafManagedRuleGroup(vendorName: string | undefined, name: string | undefined): SimWafManagedRuleGroupDefinition | undefined;
20
21
  /**
21
- * The groups that are simulated, named as a refusal names them.
22
+ * The groups that are simulated, named as an unsimulated group's reason names
23
+ * them.
22
24
  */
23
25
  export declare function simWafManagedRuleGroupNames(): readonly string[];
24
26
  /**
@@ -1,17 +1,23 @@
1
1
  import { simWafAdminProtectionRuleSet } from "./group/sim-waf-admin-protection.js";
2
+ import { simWafBotControlRuleSet } from "./group/sim-waf-bot-control.js";
2
3
  import { simWafCommonRuleSet } from "./group/sim-waf-common-rule-set.js";
4
+ import { simWafAnonymousIpList, simWafIpReputationList, } from "./group/sim-waf-ip-reputation.js";
3
5
  import { simWafKnownBadInputsRuleSet } from "./group/sim-waf-known-bad-inputs.js";
4
6
  /**
5
7
  * The vendor the simulated managed rule groups belong to.
6
8
  *
7
- * A group from any other vendor is refused, marketplace groups included: a
8
- * subscription buys rules nobody outside the vendor has ever seen.
9
+ * A rule naming a group from any other vendor is held unevaluated,
10
+ * marketplace groups included: a subscription buys rules nobody outside the
11
+ * vendor has ever seen.
9
12
  */
10
13
  export const simWafManagedVendorName = "AWS";
11
14
  const groups = [
12
15
  simWafCommonRuleSet,
13
16
  simWafKnownBadInputsRuleSet,
14
17
  simWafAdminProtectionRuleSet,
18
+ simWafIpReputationList,
19
+ simWafAnonymousIpList,
20
+ simWafBotControlRuleSet,
15
21
  ];
16
22
  const byName = new Map(groups.map((group) => [group.name, group]));
17
23
  const rulesByName = new Map(groups.flatMap((group) => group.rules.map((rule) => [rule.name, { group, rule }])));
@@ -24,7 +30,8 @@ export function findSimWafManagedRuleGroup(vendorName, name) {
24
30
  : undefined;
25
31
  }
26
32
  /**
27
- * The groups that are simulated, named as a refusal names them.
33
+ * The groups that are simulated, named as an unsimulated group's reason names
34
+ * them.
28
35
  */
29
36
  export function simWafManagedRuleGroupNames() {
30
37
  return groups.map((group) => group.name);
@@ -23,14 +23,23 @@ export type SimWafManagedDetector = (parts: SimWafManagedRequestParts) => boolea
23
23
  /**
24
24
  * One rule of an AWS managed rule group.
25
25
  *
26
- * Every rule in the three simulated groups blocks by default, so the action is
27
- * not carried here. A rule with no detector is a declared-only rule.
26
+ * A rule blocks by default unless it says it counts. A rule with no detector
27
+ * is a declared-only rule.
28
28
  */
29
29
  export interface SimWafManagedRuleDefinition {
30
30
  /** The rule name, as AWS names it and as an override names it. */
31
31
  readonly name: string;
32
32
  /** The label this rule adds, within its group's namespace. */
33
33
  readonly label: string;
34
+ /**
35
+ * The labels the rule adds beside its own, within its group's namespace.
36
+ *
37
+ * A Bot Control rule labels the bot category or the signal it found as well
38
+ * as itself.
39
+ */
40
+ readonly labels?: readonly string[] | undefined;
41
+ /** Whether the rule counts by default where most rules block. */
42
+ readonly counts?: boolean | undefined;
34
43
  readonly tier: SimWafManagedRuleTier;
35
44
  readonly detects?: SimWafManagedDetector | undefined;
36
45
  }
@@ -1,13 +1,8 @@
1
1
  import type { SimWafInspectedRequest } from "../evaluate/sim-waf-inspected-request.js";
2
2
  import { type SimWafManagedRuleReport } from "./sim-waf-managed-rule-report.js";
3
3
  import type { SimWafManagedRuleTier } from "./sim-waf-managed-rule.type.js";
4
- /**
5
- * The managed rules a test says claim a request.
6
- */
7
- export interface SimWafManagedMatchDeclaration {
8
- /** The rules that claim the request, by the name AWS gives them. */
9
- readonly matches: readonly string[];
10
- }
4
+ import { type SimWafDeclared, type SimWafManagedMatchDeclaration } from "./sim-waf-managed-declaration.js";
5
+ export type { SimWafDeclared, SimWafManagedMatchDeclaration, } from "./sim-waf-managed-declaration.js";
11
6
  /**
12
7
  * The managed rule matches this simulated WAFv2 answers with, and what it
13
8
  * covers of each rule.
@@ -24,6 +19,15 @@ export interface SimWafManagedMatchDeclaration {
24
19
  * });
25
20
  * ```
26
21
  *
22
+ * Bot Control is declared by the bot rather than the rule, since a verified
23
+ * bot is labelled and matches no rule:
24
+ *
25
+ * ```typescript
26
+ * simAws.wafV2().managedRules().onRequest("/search", {
27
+ * bot: { category: "search_engine", name: "googlebot", verified: true },
28
+ * });
29
+ * ```
30
+ *
27
31
  * A declared match is a match, and everything after it is what the group would
28
32
  * have done anyway: the rule adds its label, an action override applies to it,
29
33
  * and the group blocks by that rule.
@@ -39,9 +43,10 @@ export declare class SimWafManagedRules {
39
43
  */
40
44
  onRequest(uriPath: string, declaration: SimWafManagedMatchDeclaration): void;
41
45
  /**
42
- * The rules declared to claim one request.
46
+ * What a test declared about one request: the rules that claim it, and the
47
+ * labels a group adds to it whatever its rules decide.
43
48
  */
44
- declaredMatches(request: SimWafInspectedRequest): ReadonlySet<string>;
49
+ declared(request: SimWafInspectedRequest): SimWafDeclared;
45
50
  /**
46
51
  * What this simulation covers of one managed rule.
47
52
  */
@@ -1,7 +1,7 @@
1
1
  import { SimWafDeclarationError } from "../error/sim-wafv2.error.js";
2
2
  import { findSimWafManagedRule, } from "./sim-waf-managed-rule-groups.js";
3
3
  import { simWafManagedRuleReports, } from "./sim-waf-managed-rule-report.js";
4
- const noMatches = new Set();
4
+ import { simWafNothingDeclared, simWafReadDeclaration, } from "./sim-waf-managed-declaration.js";
5
5
  /**
6
6
  * The managed rule matches this simulated WAFv2 answers with, and what it
7
7
  * covers of each rule.
@@ -18,6 +18,15 @@ const noMatches = new Set();
18
18
  * });
19
19
  * ```
20
20
  *
21
+ * Bot Control is declared by the bot rather than the rule, since a verified
22
+ * bot is labelled and matches no rule:
23
+ *
24
+ * ```typescript
25
+ * simAws.wafV2().managedRules().onRequest("/search", {
26
+ * bot: { category: "search_engine", name: "googlebot", verified: true },
27
+ * });
28
+ * ```
29
+ *
21
30
  * A declared match is a match, and everything after it is what the group would
22
31
  * have done anyway: the rule adds its label, an action override applies to it,
23
32
  * and the group blocks by that rule.
@@ -36,13 +45,14 @@ export class SimWafManagedRules {
36
45
  throw new SimWafDeclarationError("A declared managed rule match needs the URI path of the request it " +
37
46
  "is declared for");
38
47
  }
39
- this.#byUriPath.set(uriPath, new Set(declaration.matches.map((name) => this.requiredRule(name).rule.name)));
48
+ this.#byUriPath.set(uriPath, simWafReadDeclaration(declaration, (name) => this.requiredRule(name).rule.name));
40
49
  }
41
50
  /**
42
- * The rules declared to claim one request.
51
+ * What a test declared about one request: the rules that claim it, and the
52
+ * labels a group adds to it whatever its rules decide.
43
53
  */
44
- declaredMatches(request) {
45
- return this.#byUriPath.get(request.uriPath) ?? noMatches;
54
+ declared(request) {
55
+ return this.#byUriPath.get(request.uriPath) ?? simWafNothingDeclared;
46
56
  }
47
57
  /**
48
58
  * What this simulation covers of one managed rule.
@@ -1,6 +1,7 @@
1
1
  import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-scope.js";
2
2
  import { type SimWafResourceKind } from "../sim-wafv2-arn.js";
3
3
  import type { SimWafScope } from "../scope/sim-waf-scope.js";
4
+ import { type SimWafUnsimulatedPart } from "./sim-waf-unsimulated-part.js";
4
5
  /**
5
6
  * What every WAFv2 resource reports about itself in a listing.
6
7
  */
@@ -16,6 +17,7 @@ export interface SimWafResourceProperties {
16
17
  readonly scope: SimWafScope;
17
18
  readonly accountRegionScope: SimAwsAccountRegionScope;
18
19
  readonly description?: string | undefined;
20
+ readonly tags?: readonly unknown[] | undefined;
19
21
  }
20
22
  /**
21
23
  * What a web ACL, an IP set and a regex pattern set have in common.
@@ -32,11 +34,19 @@ export declare abstract class SimWafResource {
32
34
  readonly scope: SimWafScope;
33
35
  readonly id: string;
34
36
  readonly arn: string;
37
+ /** The tags the resource was created with, held as they were written. */
38
+ readonly tags: readonly unknown[];
35
39
  protected constructor(kind: SimWafResourceKind, properties: SimWafResourceProperties);
36
40
  /**
37
41
  * What the resource was created or last updated with as its description.
38
42
  */
39
43
  get description(): string | undefined;
44
+ /**
45
+ * What this resource was written with and the simulation does not act on.
46
+ *
47
+ * A web ACL adds the rules and members it holds without evaluating.
48
+ */
49
+ get unsimulated(): readonly SimWafUnsimulatedPart[];
40
50
  /**
41
51
  * The token the next write to this resource has to present.
42
52
  */
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { SimWafOptimisticLockException } from "../error/sim-wafv2.error.js";
3
3
  import { simWafArn } from "../sim-wafv2-arn.js";
4
+ import { simWafTagsParts, } from "./sim-waf-unsimulated-part.js";
4
5
  /**
5
6
  * What a web ACL, an IP set and a regex pattern set have in common.
6
7
  *
@@ -15,12 +16,15 @@ export class SimWafResource {
15
16
  scope;
16
17
  id = randomUUID();
17
18
  arn;
19
+ /** The tags the resource was created with, held as they were written. */
20
+ tags;
18
21
  #description;
19
22
  #lockToken = randomUUID();
20
23
  constructor(kind, properties) {
21
24
  this.name = properties.name;
22
25
  this.scope = properties.scope;
23
26
  this.#description = properties.description;
27
+ this.tags = properties.tags ?? [];
24
28
  this.arn = simWafArn({
25
29
  accountRegionScope: properties.accountRegionScope,
26
30
  scope: properties.scope,
@@ -35,6 +39,14 @@ export class SimWafResource {
35
39
  get description() {
36
40
  return this.#description;
37
41
  }
42
+ /**
43
+ * What this resource was written with and the simulation does not act on.
44
+ *
45
+ * A web ACL adds the rules and members it holds without evaluating.
46
+ */
47
+ get unsimulated() {
48
+ return simWafTagsParts(this.tags);
49
+ }
38
50
  /**
39
51
  * The token the next write to this resource has to present.
40
52
  */
@@ -0,0 +1,24 @@
1
+ /**
2
+ * One part of a WAFv2 write this simulation holds and does not act on.
3
+ *
4
+ * A write carrying something Yulin does not simulate is accepted, and the read
5
+ * that follows returns it as written. What the simulation leaves out is
6
+ * reported here instead, so a test can find out how far the resource it wrote
7
+ * is from the one AWS would run.
8
+ */
9
+ export interface SimWafUnsimulatedPart {
10
+ /**
11
+ * Where the part sits in what was written.
12
+ *
13
+ * A rule is `Rules.<rule name>`, a web ACL member is its own name, and a body
14
+ * inspection limit is `AssociationConfig.RequestBody.<resource type>`. These
15
+ * are the names a CloudFormation Resource records them under.
16
+ */
17
+ readonly part: string;
18
+ /** Why the simulation does not act on it. */
19
+ readonly reason: string;
20
+ }
21
+ /**
22
+ * What a resource's tags leave out, which is nothing when it has none.
23
+ */
24
+ export declare function simWafTagsParts(tags: readonly unknown[]): readonly SimWafUnsimulatedPart[];
@@ -0,0 +1,8 @@
1
+ const tagsReason = "the tags are held and nothing reads them, since ListTagsForResource is " +
2
+ "not simulated";
3
+ /**
4
+ * What a resource's tags leave out, which is nothing when it has none.
5
+ */
6
+ export function simWafTagsParts(tags) {
7
+ return tags.length === 0 ? [] : [{ part: "Tags", reason: tagsReason }];
8
+ }
@@ -8,12 +8,11 @@ import type { SimWafIpSet } from "./ip-set/sim-waf-ip-set.js";
8
8
  import type { SimWafManagedRules } from "./managed/sim-waf-managed-rules.js";
9
9
  import type { SimWafRegexPatternSet } from "./regex-pattern-set/sim-waf-regex-pattern-set.js";
10
10
  import type { SimWafScope } from "./scope/sim-waf-scope.js";
11
+ import type { SimWafUnsimulatedPart } from "./resource/sim-waf-unsimulated-part.js";
11
12
  import { type SimWafV2Properties } from "./sim-wafv2-commands.js";
12
13
  import { SimWafCfnResourceFactory } from "./cfn/sim-waf-cfn-resource-factory.js";
13
14
  import { SimWafSets } from "./sim-wafv2-sets.js";
14
15
  import type { SimWafWebAcl } from "./web-acl/sim-waf-web-acl.js";
15
- import { type SimWafUnevaluatableRule } from "./web-acl/sim-waf-unevaluatable-rules.js";
16
- import type { SimWafWebAclWriteInput } from "./command/web-acl/web-acl.command.js";
17
16
  export type { SimWafEvaluationRequest } from "./evaluate/sim-waf-evaluation-request.js";
18
17
  /**
19
18
  * Simulated AWS WAFv2. Handles SDK commands. Emulates AWS behaviour and state.
@@ -71,6 +70,13 @@ export declare class SimWafV2 extends SimWafSets {
71
70
  * compiled against, since a reference carries the ARN and nothing else.
72
71
  */
73
72
  findRegexPatternSetByArn(regexPatternSetArn: string): SimWafRegexPatternSet | undefined;
73
+ /**
74
+ * What a web ACL holds and this simulation does not act on, each part with
75
+ * its reason: a rule that claims no request (`Rules.<rule name>`), a member
76
+ * such as `CaptchaConfig`, a body inspection limit, the tags, and an
77
+ * association nothing is evaluated through (`Association.<resource ARN>`).
78
+ */
79
+ unsimulatedParts(webAclArn: string): readonly SimWafUnsimulatedPart[];
74
80
  /**
75
81
  * Evaluate one HTTP request against a web ACL's rules.
76
82
  *
@@ -89,16 +95,6 @@ export declare class SimWafV2 extends SimWafSets {
89
95
  * nothing here, and `rules()` reports what is covered of each.
90
96
  */
91
97
  managedRules(): SimWafManagedRules;
92
- /**
93
- * The rules of a web ACL input this simulation cannot evaluate.
94
- *
95
- * The simulator's own accessor rather than a WAFv2 operation. `CreateWebACL`
96
- * refuses a web ACL carrying such a rule, because a web ACL that accepted
97
- * one would allow a request AWS blocks. A template is deployed rule by rule
98
- * instead, so the CloudFormation layer asks this first and leaves the rules
99
- * it names out of the web ACL it writes.
100
- */
101
- unevaluatableWebAclRules(input: SimWafWebAclWriteInput): readonly SimWafUnevaluatableRule[];
102
98
  /**
103
99
  * Handle a CreateWebACL Command from the SDK.
104
100
  */
@@ -147,4 +143,8 @@ export declare class SimWafV2 extends SimWafSets {
147
143
  * Get this service's SDK Command router for SDK client interception.
148
144
  */
149
145
  sdkCommandRouter(): SimSdkCommandRouter;
146
+ /**
147
+ * Find a web ACL by its ARN, refusing one that is not here.
148
+ */
149
+ private requireWebAcl;
150
150
  }
@@ -1,5 +1,6 @@
1
- import type { SimCreateWebAclCommandInput, SimWafSummaryOutput } from "./command/web-acl/web-acl.command.js";
1
+ import type { SimCreateWebAclCommandInput, SimWafSummaryOutput, SimWafWebAclOutput } from "./command/web-acl/web-acl.command.js";
2
2
  import type { SimWafDecision } from "./evaluate/sim-waf-decision.js";
3
+ import type { SimWafUnsimulatedPart } from "./resource/sim-waf-unsimulated-part.js";
3
4
  import type { SimWafStatementInput } from "./statement/sim-waf-statement.type.js";
4
5
  import type { SimWafRuleInput } from "./web-acl/sim-waf-rule.type.js";
5
6
  import type { SimWafV2 } from "./sim-wafv2.js";
@@ -47,3 +48,20 @@ export declare function simWafWebAclDecisions(simWaf: SimWafV2, rules: readonly
47
48
  * makes its requests with this.
48
49
  */
49
50
  export declare function simWafBrowserRequest(url: string, init?: RequestInit): Request;
51
+ /**
52
+ * A web ACL as GetWebACL reads it back, what the simulation says it left out
53
+ * of it, and what it decided about an ordinary request.
54
+ */
55
+ export interface SimWafHeld {
56
+ readonly webAcl: SimWafWebAclOutput;
57
+ readonly parts: readonly SimWafUnsimulatedPart[];
58
+ readonly blocked: boolean;
59
+ }
60
+ /**
61
+ * Create a web ACL, read it back, and put one request through it.
62
+ */
63
+ export declare function simWafHeldWebAcl(simWaf: SimWafV2, webAcl: Partial<SimCreateWebAclCommandInput>): Promise<SimWafHeld>;
64
+ /**
65
+ * The reason the simulation gives for leaving out one part.
66
+ */
67
+ export declare function simWafUnsimulatedReason(parts: readonly SimWafUnsimulatedPart[], part: string): string;
@@ -60,3 +60,32 @@ export function simWafBrowserRequest(url, init = {}) {
60
60
  return new Request(url, { ...init, headers });
61
61
  }
62
62
  const browserUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36";
63
+ /**
64
+ * Create a web ACL, read it back, and put one request through it.
65
+ */
66
+ export async function simWafHeldWebAcl(simWaf, webAcl) {
67
+ const created = await createSimWafWebAcl(simWaf, {
68
+ ...simWafCreateWebAclFactory.make(),
69
+ ...webAcl,
70
+ });
71
+ const read = await simWaf.getWebAcl({
72
+ input: { Name: created.Name, Scope: "REGIONAL", Id: created.Id },
73
+ });
74
+ assertDefined(read.WebACL, "Simulated WAFv2 read back no web ACL");
75
+ return {
76
+ webAcl: read.WebACL,
77
+ parts: simWaf.unsimulatedParts(created.ARN),
78
+ blocked: simWaf.evaluateRequest({
79
+ webAclArn: created.ARN,
80
+ request: new Request("https://example.com/search"),
81
+ }).action === "BLOCK",
82
+ };
83
+ }
84
+ /**
85
+ * The reason the simulation gives for leaving out one part.
86
+ */
87
+ export function simWafUnsimulatedReason(parts, part) {
88
+ const found = parts.find((candidate) => candidate.part === part);
89
+ assertDefined(found, `Simulated WAFv2 reported no unsimulated part ${part}`);
90
+ return found.reason;
91
+ }
@@ -4,7 +4,6 @@ import { SimWafSdkCommandRouter } from "./sdk/sim-wafv2-sdk-command-router.js";
4
4
  import { SimWafCommands, } from "./sim-wafv2-commands.js";
5
5
  import { SimWafCfnResourceFactory } from "./cfn/sim-waf-cfn-resource-factory.js";
6
6
  import { SimWafSets } from "./sim-wafv2-sets.js";
7
- import { unevaluatableSimWafRules, } from "./web-acl/sim-waf-unevaluatable-rules.js";
8
7
  /**
9
8
  * Simulated AWS WAFv2. Handles SDK commands. Emulates AWS behaviour and state.
10
9
  *
@@ -74,6 +73,19 @@ export class SimWafV2 extends SimWafSets {
74
73
  findRegexPatternSetByArn(regexPatternSetArn) {
75
74
  return this.commands.regexPatternSets.findByArn(regexPatternSetArn);
76
75
  }
76
+ /**
77
+ * What a web ACL holds and this simulation does not act on, each part with
78
+ * its reason: a rule that claims no request (`Rules.<rule name>`), a member
79
+ * such as `CaptchaConfig`, a body inspection limit, the tags, and an
80
+ * association nothing is evaluated through (`Association.<resource ARN>`).
81
+ */
82
+ unsimulatedParts(webAclArn) {
83
+ const webAcl = this.requireWebAcl(webAclArn);
84
+ return [
85
+ ...webAcl.unsimulated,
86
+ ...this.commands.associations.unsimulatedFor(webAcl),
87
+ ];
88
+ }
77
89
  /**
78
90
  * Evaluate one HTTP request against a web ACL's rules.
79
91
  *
@@ -84,11 +96,7 @@ export class SimWafV2 extends SimWafSets {
84
96
  * front of.
85
97
  */
86
98
  evaluateRequest(evaluation) {
87
- const webAcl = this.findWebAclByArn(evaluation.webAclArn);
88
- if (webAcl === undefined) {
89
- throw new SimWafNonexistentItemException(`AWS WAF couldn't perform the operation because your resource ` +
90
- `doesn't exist: web ACL ${evaluation.webAclArn}.`);
91
- }
99
+ const webAcl = this.requireWebAcl(evaluation.webAclArn);
92
100
  const limitBytes = webAcl.bodyInspectionLimitBytes(evaluation.resourceType);
93
101
  return webAcl.evaluate(simWafInspectedRequest(evaluation.request, evaluation.body, limitBytes));
94
102
  }
@@ -102,23 +110,6 @@ export class SimWafV2 extends SimWafSets {
102
110
  managedRules() {
103
111
  return this.commands.managedRules;
104
112
  }
105
- /**
106
- * The rules of a web ACL input this simulation cannot evaluate.
107
- *
108
- * The simulator's own accessor rather than a WAFv2 operation. `CreateWebACL`
109
- * refuses a web ACL carrying such a rule, because a web ACL that accepted
110
- * one would allow a request AWS blocks. A template is deployed rule by rule
111
- * instead, so the CloudFormation layer asks this first and leaves the rules
112
- * it names out of the web ACL it writes.
113
- */
114
- unevaluatableWebAclRules(input) {
115
- return unevaluatableSimWafRules(input.Rules, {
116
- regexPatternSets: this.commands.regexPatternSets,
117
- managedRules: this.commands.managedRules,
118
- clock: this.commands.background,
119
- customResponseBodies: input.CustomResponseBodies ?? {},
120
- });
121
- }
122
113
  /**
123
114
  * Handle a CreateWebACL Command from the SDK.
124
115
  */
@@ -201,4 +192,15 @@ export class SimWafV2 extends SimWafSets {
201
192
  sdkCommandRouter() {
202
193
  return this.#sdkRouter;
203
194
  }
195
+ /**
196
+ * Find a web ACL by its ARN, refusing one that is not here.
197
+ */
198
+ requireWebAcl(webAclArn) {
199
+ const webAcl = this.findWebAclByArn(webAclArn);
200
+ if (webAcl === undefined) {
201
+ throw new SimWafNonexistentItemException(`AWS WAF couldn't perform the operation because your resource ` +
202
+ `doesn't exist: web ACL ${webAclArn}.`);
203
+ }
204
+ return webAcl;
205
+ }
204
206
  }
@@ -4,8 +4,8 @@ import type { SimWafMatchPatternInput } from "./sim-waf-match-pattern.js";
4
4
  * shape.
5
5
  *
6
6
  * The members Yulin does not simulate are declared here rather than left out,
7
- * so a rule that names one is refused by name instead of being read as a rule
8
- * with no field at all.
7
+ * so a rule that names one is held and reported by name instead of being read
8
+ * as a rule with no field at all.
9
9
  */
10
10
  export interface SimWafFieldToMatchInput {
11
11
  readonly UriPath?: unknown;
@@ -1,10 +1,12 @@
1
1
  /**
2
- * Refuse something in a rule that real WAFv2 takes and this simulation does
2
+ * Stop compiling a rule at something real WAFv2 takes and this simulation does
3
3
  * not.
4
4
  *
5
- * Every refusal names the rule and what in it was refused, because a web ACL
6
- * is a list of rules that all look alike from the outside and the name is the
7
- * only thing that says which one to go and look at.
5
+ * `SimWafRule.compile` catches it and holds the rule unevaluated, with this
6
+ * message as the reason the web ACL reports. The message names the rule and
7
+ * what in it was left out, because a web ACL is a list of rules that all look
8
+ * alike from the outside and the name is the only thing that says which one to
9
+ * go and look at.
8
10
  */
9
11
  export declare function refuseSimWafRuleInput(ruleName: string, refused: string, reason: string): never;
10
12
  /**