@kensio/yulin 1.21.23 → 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.
- package/dist/service/wafv2/association/sim-aws-waf-protected-resources.js +4 -0
- package/dist/service/wafv2/association/sim-waf-associations.d.ts +6 -0
- package/dist/service/wafv2/association/sim-waf-associations.js +17 -0
- package/dist/service/wafv2/association/sim-waf-protected-resource.d.ts +13 -8
- package/dist/service/wafv2/association/sim-waf-protected-resource.js +23 -23
- package/dist/service/wafv2/association/sim-waf-protected-resources.d.ts +11 -6
- package/dist/service/wafv2/association/sim-waf-protected-resources.js +10 -7
- package/dist/service/wafv2/association/sim-waf-unsimulated-resource.d.ts +33 -0
- package/dist/service/wafv2/association/sim-waf-unsimulated-resource.js +66 -0
- package/dist/service/wafv2/cfn/association/sim-cfn-waf-association-creator.js +5 -0
- package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-config.js +1 -0
- package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-creator.js +2 -0
- package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-config.js +1 -0
- package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-creator.js +2 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.d.ts +4 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.js +10 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.d.ts +10 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.js +12 -0
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.d.ts +1 -13
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.js +8 -21
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.d.ts +4 -9
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.js +7 -15
- package/dist/service/wafv2/command/association/sim-wafv2-association-commands.js +2 -1
- package/dist/service/wafv2/command/association/sim-wafv2-association-input.d.ts +10 -2
- package/dist/service/wafv2/command/association/sim-wafv2-association-input.js +25 -13
- package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.d.ts +3 -3
- package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.js +5 -5
- package/dist/service/wafv2/command/managed-rule-group/sim-wafv2-managed-rule-group-commands.js +4 -4
- package/dist/service/wafv2/command/regex-pattern-set/sim-wafv2-regex-pattern-set-commands.js +2 -2
- package/dist/service/wafv2/command/sim-wafv2-input.d.ts +0 -7
- package/dist/service/wafv2/command/sim-wafv2-input.js +1 -13
- package/dist/service/wafv2/command/web-acl/sim-waf-web-acl-output.js +1 -0
- package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.d.ts +9 -12
- package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.js +27 -28
- package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.d.ts +3 -3
- package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.js +6 -6
- package/dist/service/wafv2/command/web-acl/web-acl.command.d.ts +6 -0
- package/dist/service/wafv2/index.d.ts +3 -0
- package/dist/service/wafv2/index.js +1 -0
- package/dist/service/wafv2/managed/group/sim-waf-bot-control.d.ts +27 -0
- package/dist/service/wafv2/managed/group/sim-waf-bot-control.js +68 -0
- package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.d.ts +18 -0
- package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.js +51 -0
- package/dist/service/wafv2/managed/sim-waf-bot-declaration.d.ts +35 -0
- package/dist/service/wafv2/managed/sim-waf-bot-declaration.js +42 -0
- package/dist/service/wafv2/managed/sim-waf-managed-declaration.d.ts +35 -0
- package/dist/service/wafv2/managed/sim-waf-managed-declaration.js +30 -0
- package/dist/service/wafv2/managed/sim-waf-managed-group-configs.d.ts +11 -0
- package/dist/service/wafv2/managed/sim-waf-managed-group-configs.js +42 -0
- package/dist/service/wafv2/managed/sim-waf-managed-group-input.d.ts +5 -4
- package/dist/service/wafv2/managed/sim-waf-managed-group-input.js +7 -9
- package/dist/service/wafv2/managed/sim-waf-managed-group-statement.js +16 -14
- package/dist/service/wafv2/managed/sim-waf-managed-group.type.d.ts +2 -2
- package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.d.ts +30 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.js +26 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.d.ts +5 -3
- package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.js +10 -3
- package/dist/service/wafv2/managed/sim-waf-managed-rule.type.d.ts +11 -2
- package/dist/service/wafv2/managed/sim-waf-managed-rules.d.ts +14 -9
- package/dist/service/wafv2/managed/sim-waf-managed-rules.js +15 -5
- package/dist/service/wafv2/resource/sim-waf-resource.d.ts +10 -0
- package/dist/service/wafv2/resource/sim-waf-resource.js +12 -0
- package/dist/service/wafv2/resource/sim-waf-unsimulated-part.d.ts +24 -0
- package/dist/service/wafv2/resource/sim-waf-unsimulated-part.js +8 -0
- package/dist/service/wafv2/sim-wafv2.d.ts +12 -12
- package/dist/service/wafv2/sim-wafv2.fixture.d.ts +19 -1
- package/dist/service/wafv2/sim-wafv2.fixture.js +29 -0
- package/dist/service/wafv2/sim-wafv2.js +25 -23
- package/dist/service/wafv2/statement/sim-waf-field-to-match.type.d.ts +2 -2
- package/dist/service/wafv2/statement/sim-waf-rule-refusals.d.ts +6 -4
- package/dist/service/wafv2/statement/sim-waf-rule-refusals.js +7 -6
- package/dist/service/wafv2/statement/sim-waf-statement.d.ts +3 -3
- package/dist/service/wafv2/statement/sim-waf-statement.js +3 -3
- package/dist/service/wafv2/statement/sim-waf-statement.type.d.ts +3 -3
- package/dist/service/wafv2/statement/sim-waf-unsimulated-statement.js +1 -1
- package/dist/service/wafv2/web-acl/sim-waf-association-config.d.ts +14 -7
- package/dist/service/wafv2/web-acl/sim-waf-association-config.js +17 -27
- package/dist/service/wafv2/web-acl/sim-waf-rule.d.ts +15 -3
- package/dist/service/wafv2/web-acl/sim-waf-rule.js +46 -10
- package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.d.ts +4 -4
- package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.js +4 -4
- package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.d.ts +6 -0
- package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.js +23 -0
- package/dist/service/wafv2/web-acl/sim-waf-web-acl-capacity.js +2 -2
- package/dist/service/wafv2/web-acl/sim-waf-web-acl-configuration.d.ts +5 -0
- package/dist/service/wafv2/web-acl/sim-waf-web-acl.d.ts +11 -2
- package/dist/service/wafv2/web-acl/sim-waf-web-acl.js +20 -1
- package/docs/services/wafv2/README.md +243 -51
- package/package.json +2 -2
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.d.ts +0 -15
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.js +0 -21
- package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.d.ts +0 -25
- package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.js +0 -33
|
@@ -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.
|
|
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
|
|
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
|
-
*
|
|
2
|
+
* Stop compiling a rule at something real WAFv2 takes and this simulation does
|
|
3
3
|
* not.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
/**
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { SimWafInvalidParameterException, SimWafUnsimulatedInputException, } from "../error/sim-wafv2.error.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Stop compiling a rule at something real WAFv2 takes and this simulation does
|
|
4
4
|
* not.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* `SimWafRule.compile` catches it and holds the rule unevaluated, with this
|
|
7
|
+
* message as the reason the web ACL reports. The message names the rule and
|
|
8
|
+
* what in it was left out, because a web ACL is a list of rules that all look
|
|
9
|
+
* alike from the outside and the name is the only thing that says which one to
|
|
10
|
+
* go and look at.
|
|
9
11
|
*/
|
|
10
12
|
export function refuseSimWafRuleInput(ruleName, refused, reason) {
|
|
11
13
|
throw new SimWafUnsimulatedInputException(`Rule ${ruleName} uses ${refused}, which Yulin does not simulate: ` +
|
|
12
|
-
`${reason}.
|
|
13
|
-
`allow a request AWS blocks.`);
|
|
14
|
+
`${reason}. The rule is held and claims no request.`);
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
17
|
* Refuse a rule real WAFv2 would refuse too.
|
|
@@ -19,8 +19,8 @@ export interface SimWafStatementScope {
|
|
|
19
19
|
* Turn one statement into the matcher a rule evaluates a request with.
|
|
20
20
|
*
|
|
21
21
|
* Compiling happens when the web ACL is written rather than when a request
|
|
22
|
-
* arrives, which is
|
|
23
|
-
*
|
|
24
|
-
* meets is a closure over what the rule already worked out.
|
|
22
|
+
* arrives, which is where a statement kind Yulin cannot evaluate is found and
|
|
23
|
+
* its rule held unevaluated. It also means a rule does no parsing per request:
|
|
24
|
+
* what a request meets is a closure over what the rule already worked out.
|
|
25
25
|
*/
|
|
26
26
|
export declare function compileSimWafStatement(statement: SimWafStatementInput | undefined, scope: SimWafStatementScope): SimWafMatcher;
|
|
@@ -11,9 +11,9 @@ import { refuseUnsimulatedSimWafStatement } from "./sim-waf-unsimulated-statemen
|
|
|
11
11
|
* Turn one statement into the matcher a rule evaluates a request with.
|
|
12
12
|
*
|
|
13
13
|
* Compiling happens when the web ACL is written rather than when a request
|
|
14
|
-
* arrives, which is
|
|
15
|
-
*
|
|
16
|
-
* meets is a closure over what the rule already worked out.
|
|
14
|
+
* arrives, which is where a statement kind Yulin cannot evaluate is found and
|
|
15
|
+
* its rule held unevaluated. It also means a rule does no parsing per request:
|
|
16
|
+
* what a request meets is a closure over what the rule already worked out.
|
|
17
17
|
*/
|
|
18
18
|
export function compileSimWafStatement(statement, scope) {
|
|
19
19
|
const { ruleName } = scope;
|
|
@@ -16,9 +16,9 @@ export interface SimWafFieldStatementInput {
|
|
|
16
16
|
/**
|
|
17
17
|
* Minimal structural WAFv2 Statement.
|
|
18
18
|
*
|
|
19
|
-
* The kinds Yulin
|
|
20
|
-
* rule that uses one is
|
|
21
|
-
* statement in it.
|
|
19
|
+
* The kinds Yulin does not evaluate are declared alongside the ones it does,
|
|
20
|
+
* so a rule that uses one is held and reported by name rather than read as a
|
|
21
|
+
* rule with no statement in it.
|
|
22
22
|
*
|
|
23
23
|
* https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/wafv2/Interface/Statement/
|
|
24
24
|
*/
|
|
@@ -6,7 +6,7 @@ const undocumentedDetection = "AWS does not document the detection it runs, so a
|
|
|
6
6
|
"agree with real WAF by coincidence or not at all";
|
|
7
7
|
/**
|
|
8
8
|
* The statement kinds real WAFv2 evaluates and this simulation does not, and
|
|
9
|
-
* why
|
|
9
|
+
* why a rule using one is held unevaluated.
|
|
10
10
|
*/
|
|
11
11
|
const refusedStatements = new Map([
|
|
12
12
|
["IPSetReferenceStatement", oneClientAddress],
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { SimWafUnsimulatedPart } from "../resource/sim-waf-unsimulated-part.js";
|
|
1
2
|
/**
|
|
2
3
|
* A resource type whose body inspection limit a web ACL can set.
|
|
3
4
|
*
|
|
4
5
|
* Real WAF keys `AssociationConfig.RequestBody` by resource type, and these
|
|
5
|
-
* three are the ones a
|
|
6
|
-
* `VERIFIED_ACCESS_INSTANCE` are keys AWS takes for resources
|
|
7
|
-
*
|
|
6
|
+
* three are the ones a request reaches a web ACL through here. `APP_RUNNER_SERVICE`
|
|
7
|
+
* and `VERIFIED_ACCESS_INSTANCE` are keys AWS takes for resources a web ACL
|
|
8
|
+
* can be associated with and no simulated request passes through.
|
|
8
9
|
*/
|
|
9
10
|
export type SimWafBodyInspectionResourceType = "CLOUDFRONT" | "API_GATEWAY" | "COGNITO_USER_POOL";
|
|
10
11
|
/**
|
|
@@ -12,8 +13,8 @@ export type SimWafBodyInspectionResourceType = "CLOUDFRONT" | "API_GATEWAY" | "C
|
|
|
12
13
|
* `AssociationConfig`.
|
|
13
14
|
*
|
|
14
15
|
* CloudFront, API Gateway and Cognito all default to 16 KB. A load balancer
|
|
15
|
-
* and an AppSync API are fixed at 8 KB, and
|
|
16
|
-
*
|
|
16
|
+
* and an AppSync API are fixed at 8 KB, and no simulated request reaches a web
|
|
17
|
+
* ACL through either one.
|
|
17
18
|
*/
|
|
18
19
|
export declare const simWafBodyInspectionLimitBytes = 16384;
|
|
19
20
|
/**
|
|
@@ -40,9 +41,15 @@ export declare class SimWafBodyInspectionLimits {
|
|
|
40
41
|
private constructor();
|
|
41
42
|
/**
|
|
42
43
|
* Read the limits an `AssociationConfig` sets, refusing anything WAF would
|
|
43
|
-
* refuse
|
|
44
|
+
* refuse.
|
|
44
45
|
*/
|
|
45
46
|
static read(input: SimWafAssociationConfigInput | undefined): SimWafBodyInspectionLimits;
|
|
47
|
+
/**
|
|
48
|
+
* The limits set for resource types no simulated request passes through.
|
|
49
|
+
*
|
|
50
|
+
* Each is checked as WAF checks it and held, and applies to nothing.
|
|
51
|
+
*/
|
|
52
|
+
get unsimulated(): readonly SimWafUnsimulatedPart[];
|
|
46
53
|
/**
|
|
47
54
|
* How many bytes of a body a request reaching one resource type is inspected
|
|
48
55
|
* for.
|
|
@@ -50,5 +57,5 @@ export declare class SimWafBodyInspectionLimits {
|
|
|
50
57
|
* A request evaluated against a web ACL that no resource holds names no
|
|
51
58
|
* resource type, and reads the default.
|
|
52
59
|
*/
|
|
53
|
-
bytesFor(resourceType:
|
|
60
|
+
bytesFor(resourceType: string | undefined): number;
|
|
54
61
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { SimWafInvalidParameterException
|
|
1
|
+
import { SimWafInvalidParameterException } from "../error/sim-wafv2.error.js";
|
|
2
|
+
import { unsimulatedSimWafBodyLimits } from "./sim-waf-unsimulated-body-limit.js";
|
|
2
3
|
/**
|
|
3
4
|
* How much of a request body WAF reads for a resource type given no
|
|
4
5
|
* `AssociationConfig`.
|
|
5
6
|
*
|
|
6
7
|
* CloudFront, API Gateway and Cognito all default to 16 KB. A load balancer
|
|
7
|
-
* and an AppSync API are fixed at 8 KB, and
|
|
8
|
-
*
|
|
8
|
+
* and an AppSync API are fixed at 8 KB, and no simulated request reaches a web
|
|
9
|
+
* ACL through either one.
|
|
9
10
|
*/
|
|
10
11
|
export const simWafBodyInspectionLimitBytes = 16_384;
|
|
11
12
|
/**
|
|
@@ -17,11 +18,6 @@ const inspectionLimits = new Map([
|
|
|
17
18
|
["KB_48", 49_152],
|
|
18
19
|
["KB_64", 65_536],
|
|
19
20
|
]);
|
|
20
|
-
const simulatedResourceTypes = [
|
|
21
|
-
"CLOUDFRONT",
|
|
22
|
-
"API_GATEWAY",
|
|
23
|
-
"COGNITO_USER_POOL",
|
|
24
|
-
];
|
|
25
21
|
/**
|
|
26
22
|
* How much of a request body a web ACL's rules read, by resource type.
|
|
27
23
|
*
|
|
@@ -36,15 +32,21 @@ export class SimWafBodyInspectionLimits {
|
|
|
36
32
|
}
|
|
37
33
|
/**
|
|
38
34
|
* Read the limits an `AssociationConfig` sets, refusing anything WAF would
|
|
39
|
-
* refuse
|
|
35
|
+
* refuse.
|
|
40
36
|
*/
|
|
41
37
|
static read(input) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
return new SimWafBodyInspectionLimits(new Map(Object.entries(input?.RequestBody ?? {}).map(([resourceType, config]) => [
|
|
39
|
+
resourceType,
|
|
40
|
+
inspectionLimit(resourceType, config),
|
|
41
|
+
])));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The limits set for resource types no simulated request passes through.
|
|
45
|
+
*
|
|
46
|
+
* Each is checked as WAF checks it and held, and applies to nothing.
|
|
47
|
+
*/
|
|
48
|
+
get unsimulated() {
|
|
49
|
+
return unsimulatedSimWafBodyLimits(this.limits.keys());
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
52
|
* How many bytes of a body a request reaching one resource type is inspected
|
|
@@ -60,18 +62,6 @@ export class SimWafBodyInspectionLimits {
|
|
|
60
62
|
return this.limits.get(resourceType) ?? simWafBodyInspectionLimitBytes;
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Hold a `RequestBody` key to the resource types this simulation associates.
|
|
65
|
-
*/
|
|
66
|
-
function simulatedResourceType(resourceType) {
|
|
67
|
-
const simulated = simulatedResourceTypes.find((candidate) => candidate === resourceType);
|
|
68
|
-
if (simulated === undefined) {
|
|
69
|
-
throw new SimWafUnsimulatedInputException(`AssociationConfig sets the body inspection limit for ${resourceType} ` +
|
|
70
|
-
`resources, and ${simulatedResourceTypes.join(" and ")} are the ` +
|
|
71
|
-
`types a web ACL goes in front of in Yulin`);
|
|
72
|
-
}
|
|
73
|
-
return simulated;
|
|
74
|
-
}
|
|
75
65
|
/**
|
|
76
66
|
* Read one resource type's `DefaultSizeInspectionLimit`.
|
|
77
67
|
*
|
|
@@ -4,17 +4,29 @@ import type { SimWafRuleInput, SimWafRuleScope } from "./sim-waf-rule.type.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* One rule of a web ACL, compiled so a request can be evaluated against it.
|
|
6
6
|
*
|
|
7
|
-
* The statement is turned into an evaluator when the web ACL is written
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* The statement is turned into an evaluator when the web ACL is written. A
|
|
8
|
+
* rule using something Yulin does not simulate is held all the same, as a
|
|
9
|
+
* rule that claims no request, and says why in `unsimulatedReason`. The web
|
|
10
|
+
* ACL reports it from there.
|
|
10
11
|
*/
|
|
11
12
|
export declare class SimWafRule {
|
|
12
13
|
#private;
|
|
13
14
|
readonly name: string;
|
|
14
15
|
readonly priority: number;
|
|
16
|
+
/**
|
|
17
|
+
* Why this rule claims no request, when it uses something Yulin does not
|
|
18
|
+
* simulate.
|
|
19
|
+
*
|
|
20
|
+
* AWS would evaluate it. A request it would have claimed goes on to the
|
|
21
|
+
* next rule here.
|
|
22
|
+
*/
|
|
23
|
+
readonly unsimulatedReason: string | undefined;
|
|
15
24
|
private constructor();
|
|
16
25
|
/**
|
|
17
26
|
* Compile one rule as it was written.
|
|
27
|
+
*
|
|
28
|
+
* Input WAFv2 itself would refuse is refused here too. A rule using
|
|
29
|
+
* something only Yulin leaves out compiles to one that claims nothing.
|
|
18
30
|
*/
|
|
19
31
|
static compile(input: SimWafRuleInput, scope: SimWafRuleScope): SimWafRule;
|
|
20
32
|
/**
|
|
@@ -1,16 +1,32 @@
|
|
|
1
|
+
import { SimWafUnsimulatedInputException } from "../error/sim-wafv2.error.js";
|
|
1
2
|
import { refuseUnsimulatedSimWafRuleInput, requiredSimWafRuleName, requiredSimWafRulePriority, } from "./sim-waf-rule-input.js";
|
|
2
3
|
import { simWafRuleLabels } from "./sim-waf-rule-labels.js";
|
|
3
4
|
import { compileSimWafRuleEvaluator } from "./sim-waf-rule-evaluator.js";
|
|
5
|
+
/**
|
|
6
|
+
* What a rule held without being evaluated does with every request.
|
|
7
|
+
*/
|
|
8
|
+
function claimsNothing() {
|
|
9
|
+
// A held rule claims no request, so every request goes on to the next rule.
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* One rule of a web ACL, compiled so a request can be evaluated against it.
|
|
6
13
|
*
|
|
7
|
-
* The statement is turned into an evaluator when the web ACL is written
|
|
8
|
-
*
|
|
9
|
-
*
|
|
14
|
+
* The statement is turned into an evaluator when the web ACL is written. A
|
|
15
|
+
* rule using something Yulin does not simulate is held all the same, as a
|
|
16
|
+
* rule that claims no request, and says why in `unsimulatedReason`. The web
|
|
17
|
+
* ACL reports it from there.
|
|
10
18
|
*/
|
|
11
19
|
export class SimWafRule {
|
|
12
20
|
name;
|
|
13
21
|
priority;
|
|
22
|
+
/**
|
|
23
|
+
* Why this rule claims no request, when it uses something Yulin does not
|
|
24
|
+
* simulate.
|
|
25
|
+
*
|
|
26
|
+
* AWS would evaluate it. A request it would have claimed goes on to the
|
|
27
|
+
* next rule here.
|
|
28
|
+
*/
|
|
29
|
+
unsimulatedReason;
|
|
14
30
|
#labels;
|
|
15
31
|
#evaluate;
|
|
16
32
|
constructor(properties) {
|
|
@@ -18,19 +34,39 @@ export class SimWafRule {
|
|
|
18
34
|
this.priority = properties.priority;
|
|
19
35
|
this.#labels = properties.labels;
|
|
20
36
|
this.#evaluate = properties.evaluate;
|
|
37
|
+
this.unsimulatedReason = properties.unsimulatedReason;
|
|
21
38
|
}
|
|
22
39
|
/**
|
|
23
40
|
* Compile one rule as it was written.
|
|
41
|
+
*
|
|
42
|
+
* Input WAFv2 itself would refuse is refused here too. A rule using
|
|
43
|
+
* something only Yulin leaves out compiles to one that claims nothing.
|
|
24
44
|
*/
|
|
25
45
|
static compile(input, scope) {
|
|
26
46
|
const name = requiredSimWafRuleName(input.Name);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
const priority = requiredSimWafRulePriority(input.Priority, name);
|
|
48
|
+
const labels = simWafRuleLabels(input.RuleLabels, name);
|
|
49
|
+
try {
|
|
50
|
+
refuseUnsimulatedSimWafRuleInput(input, name);
|
|
51
|
+
return new SimWafRule({
|
|
52
|
+
name,
|
|
53
|
+
priority,
|
|
54
|
+
labels,
|
|
55
|
+
evaluate: compileSimWafRuleEvaluator(input, name, scope),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (!(error instanceof SimWafUnsimulatedInputException)) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
return new SimWafRule({
|
|
63
|
+
name,
|
|
64
|
+
priority,
|
|
65
|
+
labels,
|
|
66
|
+
evaluate: claimsNothing,
|
|
67
|
+
unsimulatedReason: error.message,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
34
70
|
}
|
|
35
71
|
/**
|
|
36
72
|
* What this rule does with a request, which is nothing when it does not
|
|
@@ -2,9 +2,9 @@ import type { SimWafStatementInput } from "../statement/sim-waf-statement.type.j
|
|
|
2
2
|
/**
|
|
3
3
|
* What the statements that inspect a request cost.
|
|
4
4
|
*
|
|
5
|
-
* Only the kinds this simulation evaluates are counted.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* for the same reason.
|
|
5
|
+
* Only the kinds this simulation evaluates are counted. A rule using any
|
|
6
|
+
* other kind is held unevaluated and contributes nothing, so a web ACL holding
|
|
7
|
+
* one reports less than AWS would charge. Doubling the base cost for a JSON
|
|
8
|
+
* body never applies here for the same reason.
|
|
9
9
|
*/
|
|
10
10
|
export declare function simWafMatchCapacity(statement: SimWafStatementInput): number;
|
|
@@ -19,10 +19,10 @@ const textTransformationCost = 10;
|
|
|
19
19
|
/**
|
|
20
20
|
* What the statements that inspect a request cost.
|
|
21
21
|
*
|
|
22
|
-
* Only the kinds this simulation evaluates are counted.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* for the same reason.
|
|
22
|
+
* Only the kinds this simulation evaluates are counted. A rule using any
|
|
23
|
+
* other kind is held unevaluated and contributes nothing, so a web ACL holding
|
|
24
|
+
* one reports less than AWS would charge. Doubling the base cost for a JSON
|
|
25
|
+
* body never applies here for the same reason.
|
|
26
26
|
*/
|
|
27
27
|
export function simWafMatchCapacity(statement) {
|
|
28
28
|
return (byteMatchCapacity(statement.ByteMatchStatement) +
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SimWafUnsimulatedPart } from "../resource/sim-waf-unsimulated-part.js";
|
|
2
|
+
/**
|
|
3
|
+
* What the body inspection limits a web ACL sets leave out, one part per
|
|
4
|
+
* resource type no simulated request passes through.
|
|
5
|
+
*/
|
|
6
|
+
export declare function unsimulatedSimWafBodyLimits(resourceTypes: Iterable<string>): readonly SimWafUnsimulatedPart[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The resource types a simulated request reaches a web ACL through.
|
|
3
|
+
*/
|
|
4
|
+
const simulatedResourceTypes = new Set([
|
|
5
|
+
"CLOUDFRONT",
|
|
6
|
+
"API_GATEWAY",
|
|
7
|
+
"COGNITO_USER_POOL",
|
|
8
|
+
]);
|
|
9
|
+
/**
|
|
10
|
+
* What the body inspection limits a web ACL sets leave out, one part per
|
|
11
|
+
* resource type no simulated request passes through.
|
|
12
|
+
*/
|
|
13
|
+
export function unsimulatedSimWafBodyLimits(resourceTypes) {
|
|
14
|
+
return [...resourceTypes]
|
|
15
|
+
.filter((resourceType) => !simulatedResourceTypes.has(resourceType))
|
|
16
|
+
.map((resourceType) => ({
|
|
17
|
+
part: `AssociationConfig.RequestBody.${resourceType}`,
|
|
18
|
+
reason: `AssociationConfig sets the body inspection limit for ` +
|
|
19
|
+
`${resourceType} resources, and ` +
|
|
20
|
+
`${[...simulatedResourceTypes].join(" and ")} are the types a ` +
|
|
21
|
+
`simulated request reaches a web ACL through`,
|
|
22
|
+
}));
|
|
23
|
+
}
|