@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.
- package/dist/service/athena/engine/sim-athena-ast-nodes.d.ts +11 -0
- package/dist/service/athena/engine/sim-athena-ast-nodes.js +22 -0
- package/dist/service/athena/engine/sim-athena-string-shims.js +29 -1
- package/dist/service/athena/engine/sim-athena-unnest-item.js +6 -15
- package/dist/service/athena/engine/sim-athena-unnest-rewrite.d.ts +4 -4
- package/dist/service/athena/engine/sim-athena-unnest-rewrite.js +4 -4
- package/dist/service/athena/engine/sim-athena-unnest-source.d.ts +10 -9
- package/dist/service/athena/engine/sim-athena-unnest-source.js +25 -11
- package/dist/service/athena/sim-athena-flattened-events.fixture.d.ts +3 -0
- package/dist/service/athena/sim-athena-flattened-events.fixture.js +46 -0
- 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/athena/README.md +21 -2
- 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
|
@@ -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
|
+
}
|
|
@@ -59,8 +59,8 @@ function nestedCapacity(statement) {
|
|
|
59
59
|
*
|
|
60
60
|
* A group is fixed at the capacity its owner gave it, and a scope-down
|
|
61
61
|
* statement is charged on top. A group this simulation does not carry
|
|
62
|
-
* contributes nothing,
|
|
63
|
-
*
|
|
62
|
+
* contributes nothing, so a web ACL holding one reports less than AWS would
|
|
63
|
+
* charge.
|
|
64
64
|
*/
|
|
65
65
|
function managedGroupCapacity(statement) {
|
|
66
66
|
const named = statement.ManagedRuleGroupStatement;
|
|
@@ -13,6 +13,11 @@ export interface SimWafWebAclConfiguration {
|
|
|
13
13
|
readonly visibilityConfig?: unknown;
|
|
14
14
|
readonly description?: string | undefined;
|
|
15
15
|
readonly associationConfig?: SimWafAssociationConfigInput | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* The members held as written and not acted on, such as `CaptchaConfig`,
|
|
18
|
+
* keyed by the name the API gives them.
|
|
19
|
+
*/
|
|
20
|
+
readonly heldMembers?: Readonly<Record<string, unknown>> | undefined;
|
|
16
21
|
}
|
|
17
22
|
/**
|
|
18
23
|
* Read the action a request no rule claims is given.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SimWafDecision } from "../evaluate/sim-waf-decision.js";
|
|
2
2
|
import type { SimWafInspectedRequest } from "../evaluate/sim-waf-inspected-request.js";
|
|
3
3
|
import { SimWafResource, type SimWafResourceProperties } from "../resource/sim-waf-resource.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { SimWafUnsimulatedPart } from "../resource/sim-waf-unsimulated-part.js";
|
|
5
5
|
import type { SimWafWebAclRuleScope } from "./sim-waf-rule.type.js";
|
|
6
6
|
import { type SimWafWebAclConfiguration } from "./sim-waf-web-acl-configuration.js";
|
|
7
7
|
interface SimWafWebAclProperties extends SimWafResourceProperties, SimWafWebAclRuleScope {
|
|
@@ -33,6 +33,14 @@ export declare class SimWafWebAcl extends SimWafResource {
|
|
|
33
33
|
* What this web ACL's rules add up to in capacity units.
|
|
34
34
|
*/
|
|
35
35
|
get capacity(): number;
|
|
36
|
+
/**
|
|
37
|
+
* What this web ACL was written with and the simulation does not act on.
|
|
38
|
+
*
|
|
39
|
+
* A rule listed here claims no request, a member is held and does nothing,
|
|
40
|
+
* and a body inspection limit applies to no request. `GetWebACL` returns
|
|
41
|
+
* every one of them as written.
|
|
42
|
+
*/
|
|
43
|
+
get unsimulated(): readonly SimWafUnsimulatedPart[];
|
|
36
44
|
/**
|
|
37
45
|
* What this web ACL was last written with, as the API reports it.
|
|
38
46
|
*/
|
|
@@ -42,6 +50,7 @@ export declare class SimWafWebAcl extends SimWafResource {
|
|
|
42
50
|
*
|
|
43
51
|
* The rules are compiled before anything is replaced, so a web ACL that
|
|
44
52
|
* refuses an update keeps the rules it had rather than being left with none.
|
|
53
|
+
* The tags stay as they were created, since UpdateWebACL takes none.
|
|
45
54
|
*/
|
|
46
55
|
reconfigure(configuration: SimWafWebAclConfiguration, lockToken: string | undefined): void;
|
|
47
56
|
/**
|
|
@@ -51,7 +60,7 @@ export declare class SimWafWebAcl extends SimWafResource {
|
|
|
51
60
|
* `AssociationConfig` raises it per resource type, and a web ACL written
|
|
52
61
|
* without one reads the 16 KB default everything it protects has.
|
|
53
62
|
*/
|
|
54
|
-
bodyInspectionLimitBytes(resourceType:
|
|
63
|
+
bodyInspectionLimitBytes(resourceType: string | undefined): number;
|
|
55
64
|
/**
|
|
56
65
|
* Decide what happens to one request.
|
|
57
66
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { simWafDecision, } from "../evaluate/sim-waf-decision.js";
|
|
2
2
|
import { simWafEvaluateRules } from "../evaluate/sim-waf-evaluate-rules.js";
|
|
3
|
+
import { unsimulatedSimWafWebAclMembers } from "../command/web-acl/sim-wafv2-unsimulated-web-acl-input.js";
|
|
3
4
|
import { SimWafResource, } from "../resource/sim-waf-resource.js";
|
|
4
|
-
import { SimWafBodyInspectionLimits
|
|
5
|
+
import { SimWafBodyInspectionLimits } from "./sim-waf-association-config.js";
|
|
5
6
|
import { compileSimWafWebAclRules } from "./sim-waf-rules.js";
|
|
6
7
|
import { simWafWebAclCapacity } from "./sim-waf-web-acl-capacity.js";
|
|
7
8
|
import { readSimWafDefaultAction, } from "./sim-waf-web-acl-configuration.js";
|
|
@@ -49,6 +50,23 @@ export class SimWafWebAcl extends SimWafResource {
|
|
|
49
50
|
get capacity() {
|
|
50
51
|
return this.#capacity;
|
|
51
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* What this web ACL was written with and the simulation does not act on.
|
|
55
|
+
*
|
|
56
|
+
* A rule listed here claims no request, a member is held and does nothing,
|
|
57
|
+
* and a body inspection limit applies to no request. `GetWebACL` returns
|
|
58
|
+
* every one of them as written.
|
|
59
|
+
*/
|
|
60
|
+
get unsimulated() {
|
|
61
|
+
return [
|
|
62
|
+
...this.#rules.flatMap(({ name, unsimulatedReason }) => unsimulatedReason === undefined
|
|
63
|
+
? []
|
|
64
|
+
: [{ part: `Rules.${name}`, reason: unsimulatedReason }]),
|
|
65
|
+
...unsimulatedSimWafWebAclMembers(this.#configuration.heldMembers ?? {}),
|
|
66
|
+
...this.#bodyInspectionLimits.unsimulated,
|
|
67
|
+
...super.unsimulated,
|
|
68
|
+
];
|
|
69
|
+
}
|
|
52
70
|
/**
|
|
53
71
|
* What this web ACL was last written with, as the API reports it.
|
|
54
72
|
*/
|
|
@@ -60,6 +78,7 @@ export class SimWafWebAcl extends SimWafResource {
|
|
|
60
78
|
*
|
|
61
79
|
* The rules are compiled before anything is replaced, so a web ACL that
|
|
62
80
|
* refuses an update keeps the rules it had rather than being left with none.
|
|
81
|
+
* The tags stay as they were created, since UpdateWebACL takes none.
|
|
63
82
|
*/
|
|
64
83
|
reconfigure(configuration, lockToken) {
|
|
65
84
|
const defaultAction = readSimWafDefaultAction(configuration);
|
|
@@ -486,7 +486,7 @@ Every ascending sort is emitted carrying `NULLS LAST`, because Trino orders null
|
|
|
486
486
|
direction it sorts and SQLite orders them first ascending. Both were cases where a query answered
|
|
487
487
|
differently while still succeeding, which is the failure that costs the most to find.
|
|
488
488
|
|
|
489
|
-
### Flattening an array or a
|
|
489
|
+
### Flattening an array, a map or a split value
|
|
490
490
|
|
|
491
491
|
`UNNEST` runs. An array or a map column is held as its JSON text, and SQLite reads that with
|
|
492
492
|
`json_each`, so a statement flattening one returns a row per element the way Athena does.
|
|
@@ -505,6 +505,22 @@ falls back rather than reading a scalar as a collection.
|
|
|
505
505
|
One flattening per statement is what this covers, joined with `CROSS JOIN`. A second `UNNEST`, a
|
|
506
506
|
`LEFT JOIN UNNEST`, a `SELECT *` beside one, and a position taken from a map all fall back.
|
|
507
507
|
|
|
508
|
+
A table with no array column in it can still be flattened. `split` answers an array, and an `UNNEST`
|
|
509
|
+
over the call cuts one stored string into a row per part. This is how a packed access log row is
|
|
510
|
+
read, since Glue builds a log table's columns from what the delivery was configured with.
|
|
511
|
+
|
|
512
|
+
```sql
|
|
513
|
+
SELECT t.part
|
|
514
|
+
FROM rainlytics.logs
|
|
515
|
+
CROSS JOIN UNNEST(split(url_extract_parameter(cs_uri_stem || '?' || cs_uri_query, 'b'), ';'))
|
|
516
|
+
AS t(part)
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Splitting an empty value answers one empty part, as it does on Trino. A row whose value is null
|
|
520
|
+
answers no parts at all and drops out, the way an empty array column does. The call is what says the
|
|
521
|
+
value is a collection (an expression has no schema entry to read). `split` and `slice` are the two
|
|
522
|
+
calls the flattening reaches, and any other expression under an `UNNEST` falls back.
|
|
523
|
+
|
|
508
524
|
### The functions a statement can call
|
|
509
525
|
|
|
510
526
|
SQLite carries a much smaller function library than Trino, and the engine fills the gap for the ones
|
|
@@ -516,7 +532,7 @@ its declared result.
|
|
|
516
532
|
| Date and time | `current_date`, `current_timestamp`, `date_add`, `date_diff`, `date_trunc`, `date_format`, `at_timezone`, `from_unixtime`, `to_unixtime`, `from_iso8601_timestamp`, `from_iso8601_date`, `to_iso8601` |
|
|
517
533
|
| JSON | `json_extract`, `json_extract_scalar`, `json_parse`, `json_size` |
|
|
518
534
|
| Array and map | `array_agg`, `cardinality`, `contains`, `element_at`, `array_join`, `slice` |
|
|
519
|
-
| String | `regexp_like`, `regexp_extract`, `regexp_replace`, `split_part`, `strpos`
|
|
535
|
+
| String | `regexp_like`, `regexp_extract`, `regexp_replace`, `split`, `split_part`, `strpos` |
|
|
520
536
|
| Binary | `md5`, `sha1`, `sha256`, `sha512`, `xxhash64`, `murmur3`, `crc32`, `to_hex`, `from_hex`, `to_base64`, `from_base64`, `to_utf8`, `from_utf8` |
|
|
521
537
|
| URL | `url_extract_host`, `url_extract_path`, `url_extract_protocol`, `url_extract_port`, `url_extract_query`, `url_extract_fragment`, `url_extract_parameter`, `url_decode`, `url_encode` |
|
|
522
538
|
| Approximate | `approx_distinct`, `approx_percentile` |
|
|
@@ -992,6 +1008,7 @@ own and authorizes work on one against the workgroup it belongs to. This asks th
|
|
|
992
1008
|
- `StartQueryExecution`, `GetQueryExecution`, `GetQueryResults` and `StopQueryExecution`
|
|
993
1009
|
- A `SELECT` run for real over JSON lines and CSV objects in simulated S3, answered by SQLite
|
|
994
1010
|
- `UNNEST` over an array or a map column, with `WITH ORDINALITY` where a query wants the position
|
|
1011
|
+
- `UNNEST` over a `split` or a `slice` call, flattening one stored string into a row per part
|
|
995
1012
|
- Trino's date, JSON, array, string and URL functions, with `current_timestamp` reading the
|
|
996
1013
|
simulated clock
|
|
997
1014
|
- Declared results, matched on the query text, ahead of the engine for one statement and behind it
|
|
@@ -1027,6 +1044,8 @@ Current documented limitations:
|
|
|
1027
1044
|
gives a map's keys rather than its positions.
|
|
1028
1045
|
- `UNNEST` over a `ROW` or a struct array falls back. The element needs field access and the
|
|
1029
1046
|
flattened column is JSON text here.
|
|
1047
|
+
- `UNNEST` over an expression reaches `split` and `slice`. The engine reads the call to decide that
|
|
1048
|
+
a value is a collection, and a call to anything else falls back.
|
|
1030
1049
|
- The Trino function library reaches as far as the table under
|
|
1031
1050
|
[the functions a statement can call](#the-functions-a-statement-can-call). A query reaching for
|
|
1032
1051
|
anything else Trino has and SQLite lacks falls back.
|