@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.
Files changed (93) hide show
  1. package/dist/service/wafv2/association/sim-aws-waf-protected-resources.js +4 -0
  2. package/dist/service/wafv2/association/sim-waf-associations.d.ts +6 -0
  3. package/dist/service/wafv2/association/sim-waf-associations.js +17 -0
  4. package/dist/service/wafv2/association/sim-waf-protected-resource.d.ts +13 -8
  5. package/dist/service/wafv2/association/sim-waf-protected-resource.js +23 -23
  6. package/dist/service/wafv2/association/sim-waf-protected-resources.d.ts +11 -6
  7. package/dist/service/wafv2/association/sim-waf-protected-resources.js +10 -7
  8. package/dist/service/wafv2/association/sim-waf-unsimulated-resource.d.ts +33 -0
  9. package/dist/service/wafv2/association/sim-waf-unsimulated-resource.js +66 -0
  10. package/dist/service/wafv2/cfn/association/sim-cfn-waf-association-creator.js +5 -0
  11. package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-config.js +1 -0
  12. package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-creator.js +2 -0
  13. package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-config.js +1 -0
  14. package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-creator.js +2 -0
  15. package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.d.ts +4 -0
  16. package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.js +10 -0
  17. package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.d.ts +10 -0
  18. package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.js +12 -0
  19. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.d.ts +1 -13
  20. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.js +8 -21
  21. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.d.ts +4 -9
  22. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.js +7 -15
  23. package/dist/service/wafv2/command/association/sim-wafv2-association-commands.js +2 -1
  24. package/dist/service/wafv2/command/association/sim-wafv2-association-input.d.ts +10 -2
  25. package/dist/service/wafv2/command/association/sim-wafv2-association-input.js +25 -13
  26. package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.d.ts +3 -3
  27. package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.js +5 -5
  28. package/dist/service/wafv2/command/managed-rule-group/sim-wafv2-managed-rule-group-commands.js +4 -4
  29. package/dist/service/wafv2/command/regex-pattern-set/sim-wafv2-regex-pattern-set-commands.js +2 -2
  30. package/dist/service/wafv2/command/sim-wafv2-input.d.ts +0 -7
  31. package/dist/service/wafv2/command/sim-wafv2-input.js +1 -13
  32. package/dist/service/wafv2/command/web-acl/sim-waf-web-acl-output.js +1 -0
  33. package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.d.ts +9 -12
  34. package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.js +27 -28
  35. package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.d.ts +3 -3
  36. package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.js +6 -6
  37. package/dist/service/wafv2/command/web-acl/web-acl.command.d.ts +6 -0
  38. package/dist/service/wafv2/index.d.ts +3 -0
  39. package/dist/service/wafv2/index.js +1 -0
  40. package/dist/service/wafv2/managed/group/sim-waf-bot-control.d.ts +27 -0
  41. package/dist/service/wafv2/managed/group/sim-waf-bot-control.js +68 -0
  42. package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.d.ts +18 -0
  43. package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.js +51 -0
  44. package/dist/service/wafv2/managed/sim-waf-bot-declaration.d.ts +35 -0
  45. package/dist/service/wafv2/managed/sim-waf-bot-declaration.js +42 -0
  46. package/dist/service/wafv2/managed/sim-waf-managed-declaration.d.ts +35 -0
  47. package/dist/service/wafv2/managed/sim-waf-managed-declaration.js +30 -0
  48. package/dist/service/wafv2/managed/sim-waf-managed-group-configs.d.ts +11 -0
  49. package/dist/service/wafv2/managed/sim-waf-managed-group-configs.js +42 -0
  50. package/dist/service/wafv2/managed/sim-waf-managed-group-input.d.ts +5 -4
  51. package/dist/service/wafv2/managed/sim-waf-managed-group-input.js +7 -9
  52. package/dist/service/wafv2/managed/sim-waf-managed-group-statement.js +16 -14
  53. package/dist/service/wafv2/managed/sim-waf-managed-group.type.d.ts +2 -2
  54. package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.d.ts +30 -0
  55. package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.js +26 -0
  56. package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.d.ts +5 -3
  57. package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.js +10 -3
  58. package/dist/service/wafv2/managed/sim-waf-managed-rule.type.d.ts +11 -2
  59. package/dist/service/wafv2/managed/sim-waf-managed-rules.d.ts +14 -9
  60. package/dist/service/wafv2/managed/sim-waf-managed-rules.js +15 -5
  61. package/dist/service/wafv2/resource/sim-waf-resource.d.ts +10 -0
  62. package/dist/service/wafv2/resource/sim-waf-resource.js +12 -0
  63. package/dist/service/wafv2/resource/sim-waf-unsimulated-part.d.ts +24 -0
  64. package/dist/service/wafv2/resource/sim-waf-unsimulated-part.js +8 -0
  65. package/dist/service/wafv2/sim-wafv2.d.ts +12 -12
  66. package/dist/service/wafv2/sim-wafv2.fixture.d.ts +19 -1
  67. package/dist/service/wafv2/sim-wafv2.fixture.js +29 -0
  68. package/dist/service/wafv2/sim-wafv2.js +25 -23
  69. package/dist/service/wafv2/statement/sim-waf-field-to-match.type.d.ts +2 -2
  70. package/dist/service/wafv2/statement/sim-waf-rule-refusals.d.ts +6 -4
  71. package/dist/service/wafv2/statement/sim-waf-rule-refusals.js +7 -6
  72. package/dist/service/wafv2/statement/sim-waf-statement.d.ts +3 -3
  73. package/dist/service/wafv2/statement/sim-waf-statement.js +3 -3
  74. package/dist/service/wafv2/statement/sim-waf-statement.type.d.ts +3 -3
  75. package/dist/service/wafv2/statement/sim-waf-unsimulated-statement.js +1 -1
  76. package/dist/service/wafv2/web-acl/sim-waf-association-config.d.ts +14 -7
  77. package/dist/service/wafv2/web-acl/sim-waf-association-config.js +17 -27
  78. package/dist/service/wafv2/web-acl/sim-waf-rule.d.ts +15 -3
  79. package/dist/service/wafv2/web-acl/sim-waf-rule.js +46 -10
  80. package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.d.ts +4 -4
  81. package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.js +4 -4
  82. package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.d.ts +6 -0
  83. package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.js +23 -0
  84. package/dist/service/wafv2/web-acl/sim-waf-web-acl-capacity.js +2 -2
  85. package/dist/service/wafv2/web-acl/sim-waf-web-acl-configuration.d.ts +5 -0
  86. package/dist/service/wafv2/web-acl/sim-waf-web-acl.d.ts +11 -2
  87. package/dist/service/wafv2/web-acl/sim-waf-web-acl.js +20 -1
  88. package/docs/services/wafv2/README.md +243 -51
  89. package/package.json +2 -2
  90. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.d.ts +0 -15
  91. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.js +0 -21
  92. package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.d.ts +0 -25
  93. package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.js +0 -33
@@ -1,3 +1,4 @@
1
+ import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
1
2
  /**
2
3
  * The resources of one simulated AWS instance a web ACL can be put in front
3
4
  * of.
@@ -19,6 +20,9 @@ export class SimAwsWafProtectedResources {
19
20
  * Whether the resource an ARN names is one this scope holds.
20
21
  */
21
22
  has(resource) {
23
+ if (resource instanceof SimWafUnsimulatedResource) {
24
+ return true;
25
+ }
22
26
  if (resource.resourceType === "COGNITO_USER_POOL") {
23
27
  return this.hasUserPool(resource);
24
28
  }
@@ -1,4 +1,5 @@
1
1
  import type { SimWafDecision } from "../evaluate/sim-waf-decision.js";
2
+ import type { SimWafUnsimulatedPart } from "../resource/sim-waf-unsimulated-part.js";
2
3
  import type { SimWafWebAcl } from "../web-acl/sim-waf-web-acl.js";
3
4
  import type { SimWafProtectedResource, SimWafProtectedResourceType } from "./sim-waf-protected-resource.js";
4
5
  import type { SimWafProtectedRequest, SimWafProtection } from "./sim-waf-protection.js";
@@ -32,6 +33,11 @@ export declare class SimWafAssociations implements SimWafProtection {
32
33
  * is what `DeleteWebACL` asks for when it refuses a web ACL still in use.
33
34
  */
34
35
  resourceArnsFor(webAcl: SimWafWebAcl, resourceType?: SimWafProtectedResourceType): readonly string[];
36
+ /**
37
+ * The associations of one web ACL that nothing is evaluated through, one
38
+ * part per resource ARN.
39
+ */
40
+ unsimulatedFor(webAcl: SimWafWebAcl): readonly SimWafUnsimulatedPart[];
35
41
  /**
36
42
  * Whether a web ACL is in front of one resource.
37
43
  */
@@ -1,4 +1,5 @@
1
1
  import { simWafInspectedRequest } from "../evaluate/sim-waf-inspected-request.js";
2
+ import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
2
3
  /**
3
4
  * The web ACLs one Account and Region has in front of things.
4
5
  *
@@ -19,6 +20,9 @@ export class SimWafAssociations {
19
20
  this.#associations.set(resource.arn, {
20
21
  webAcl,
21
22
  resourceType: resource.resourceType,
23
+ unsimulatedReason: resource instanceof SimWafUnsimulatedResource
24
+ ? resource.reason
25
+ : undefined,
22
26
  });
23
27
  }
24
28
  /**
@@ -44,6 +48,19 @@ export class SimWafAssociations {
44
48
  .map(([resourceArn]) => resourceArn)
45
49
  .toArray();
46
50
  }
51
+ /**
52
+ * The associations of one web ACL that nothing is evaluated through, one
53
+ * part per resource ARN.
54
+ */
55
+ unsimulatedFor(webAcl) {
56
+ return this.#associations
57
+ .entries()
58
+ .filter(([, association]) => association.webAcl === webAcl)
59
+ .flatMap(([resourceArn, { unsimulatedReason }]) => unsimulatedReason === undefined
60
+ ? []
61
+ : [{ part: `Association.${resourceArn}`, reason: unsimulatedReason }])
62
+ .toArray();
63
+ }
47
64
  /**
48
65
  * Whether a web ACL is in front of one resource.
49
66
  */
@@ -1,13 +1,16 @@
1
1
  import { SimWafRestApiStage } from "./sim-waf-rest-api-stage.js";
2
+ import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
2
3
  import { SimWafUserPool } from "./sim-waf-user-pool.js";
3
4
  /**
4
5
  * A resource a `REGIONAL` web ACL can be put in front of.
5
6
  *
6
- * Two types are simulated. A third one joins this union and the reader below
7
- * gains a branch for it, and everything that holds an association goes on
7
+ * Requests reach a web ACL through two types here. The rest are held as
8
+ * `SimWafUnsimulatedResource`, associated and listed, with nothing evaluated
9
+ * in front of them. A type that starts serving requests gets a class of its
10
+ * own in this union, and everything that holds an association goes on
8
11
  * addressing a resource by its ARN.
9
12
  */
10
- export type SimWafProtectedResource = SimWafRestApiStage | SimWafUserPool;
13
+ export type SimWafProtectedResource = SimWafRestApiStage | SimWafUserPool | SimWafUnsimulatedResource;
11
14
  /**
12
15
  * The type ListResourcesForWebACL lists one simulated resource under.
13
16
  */
@@ -21,17 +24,19 @@ export declare const simWafApiGatewayResourceType = "API_GATEWAY";
21
24
  */
22
25
  export declare const simWafUserPoolResourceType = "COGNITO_USER_POOL";
23
26
  /**
24
- * The resource types this simulation holds, as a refusal names them.
27
+ * The resource types ListResourcesForWebACL lists, which are all the types
28
+ * an association can hold.
25
29
  */
26
30
  export declare const simWafProtectedResourceTypes: readonly SimWafProtectedResourceType[];
27
31
  /**
28
32
  * Read the resource an association names, refusing anything a web ACL cannot
29
- * be put in front of here.
33
+ * be put in front of.
30
34
  *
31
35
  * The three refusals mean different things. An HTTP API stage is refused
32
36
  * because AWS WAF protects no HTTP API, so an association accepted here would
33
- * let a test cover protection AWS never applies. A load balancer and the rest
34
- * are resource types AWS does protect and this simulation does not, which is
35
- * the ordinary unsimulated refusal. Anything else is not a resource ARN.
37
+ * let a test cover protection AWS never applies. An Amplify app takes a
38
+ * `CLOUDFRONT` web ACL from `us-east-1` for an app in any Region, and a WAFv2
39
+ * here reaches web ACLs in its own Region only. Anything else is not a
40
+ * resource ARN.
36
41
  */
37
42
  export declare function simWafProtectedResource(arn: string): SimWafProtectedResource;
@@ -1,5 +1,6 @@
1
1
  import { SimWafInvalidParameterException, SimWafUnsimulatedInputException, } from "../error/sim-wafv2.error.js";
2
2
  import { SimWafRestApiStage } from "./sim-waf-rest-api-stage.js";
3
+ import { SimWafUnsimulatedResource, simWafUnsimulatedResourceTypes, } from "./sim-waf-unsimulated-resource.js";
3
4
  import { SimWafUserPool } from "./sim-waf-user-pool.js";
4
5
  /**
5
6
  * The type ListResourcesForWebACL lists a simulated REST API stage under.
@@ -10,32 +11,28 @@ export const simWafApiGatewayResourceType = "API_GATEWAY";
10
11
  */
11
12
  export const simWafUserPoolResourceType = "COGNITO_USER_POOL";
12
13
  /**
13
- * The resource types this simulation holds, as a refusal names them.
14
+ * The resource types ListResourcesForWebACL lists, which are all the types
15
+ * an association can hold.
14
16
  */
15
- export const simWafProtectedResourceTypes = [simWafApiGatewayResourceType, simWafUserPoolResourceType];
17
+ export const simWafProtectedResourceTypes = [
18
+ simWafApiGatewayResourceType,
19
+ simWafUserPoolResourceType,
20
+ ...simWafUnsimulatedResourceTypes,
21
+ ];
16
22
  const restApiStagePattern = /^arn:aws:apigateway:(?<regionName>[^:]+)::\/restapis\/(?<restApiId>[^/]+)\/stages\/(?<stageName>[^/]+)$/u;
17
23
  const httpApiStagePattern = /^arn:aws:apigateway:[^:]+::\/apis\/[^/]+\/stages\/[^/]+$/u;
18
24
  const userPoolPattern = /^arn:aws:cognito-idp:(?<regionName>[^:]+):(?<accountId>[^:]+):userpool\/(?<userPoolId>[^/]+)$/u;
19
- /**
20
- * The resource types real WAF protects that this simulation does not, by the
21
- * service in their ARN.
22
- */
23
- const unsimulatedResources = new Map([
24
- ["elasticloadbalancing", "an Application Load Balancer"],
25
- ["appsync", "an AppSync GraphQL API"],
26
- ["apprunner", "an App Runner service"],
27
- ["amplify", "an Amplify app"],
28
- ["ec2", "a Verified Access instance"],
29
- ]);
25
+ const amplifyAppPattern = /^arn:aws:amplify:[^:]+:[^:]+:apps\/[^/]+$/u;
30
26
  /**
31
27
  * Read the resource an association names, refusing anything a web ACL cannot
32
- * be put in front of here.
28
+ * be put in front of.
33
29
  *
34
30
  * The three refusals mean different things. An HTTP API stage is refused
35
31
  * because AWS WAF protects no HTTP API, so an association accepted here would
36
- * let a test cover protection AWS never applies. A load balancer and the rest
37
- * are resource types AWS does protect and this simulation does not, which is
38
- * the ordinary unsimulated refusal. Anything else is not a resource ARN.
32
+ * let a test cover protection AWS never applies. An Amplify app takes a
33
+ * `CLOUDFRONT` web ACL from `us-east-1` for an app in any Region, and a WAFv2
34
+ * here reaches web ACLs in its own Region only. Anything else is not a
35
+ * resource ARN.
39
36
  */
40
37
  export function simWafProtectedResource(arn) {
41
38
  const stage = restApiStage(arn);
@@ -46,6 +43,10 @@ export function simWafProtectedResource(arn) {
46
43
  if (userPool !== undefined) {
47
44
  return userPool;
48
45
  }
46
+ const unsimulated = SimWafUnsimulatedResource.read(arn);
47
+ if (unsimulated !== undefined) {
48
+ return unsimulated;
49
+ }
49
50
  if (httpApiStagePattern.test(arn)) {
50
51
  throw new SimWafInvalidParameterException(`AWS WAF does not protect an API Gateway HTTP API. The resource types ` +
51
52
  `it protects cover a REST API stage and not an HTTP API stage, so ` +
@@ -87,13 +88,12 @@ function simWafUserPool(arn) {
87
88
  });
88
89
  }
89
90
  /**
90
- * Refuse an ARN naming a resource type AWS WAF protects and Yulin does not.
91
+ * Refuse an Amplify app, whose web ACL is out of this WAFv2's reach.
91
92
  */
92
93
  function refuseUnsimulatedResource(arn) {
93
- const described = unsimulatedResources.get(arn.split(":", 3)[2] ?? "");
94
- if (described !== undefined) {
95
- throw new SimWafUnsimulatedInputException(`AWS WAF protects ${described}, and Yulin does not simulate a web ACL ` +
96
- `in front of one, so ${arn} is refused rather than protected by ` +
97
- `nothing.`);
94
+ if (amplifyAppPattern.test(arn)) {
95
+ throw new SimWafUnsimulatedInputException(`AWS WAF protects an Amplify app with a CLOUDFRONT web ACL held in ` +
96
+ `us-east-1, and a simulated WAFv2 associates web ACLs of its own ` +
97
+ `Region only, so ${arn} is refused.`);
98
98
  }
99
99
  }
@@ -9,20 +9,25 @@ import type { SimWafProtectedResource } from "./sim-waf-protected-resource.js";
9
9
  export interface SimWafProtectedResources {
10
10
  /**
11
11
  * Whether this simulation holds the resource an ARN names.
12
+ *
13
+ * A `SimWafUnsimulatedResource` is held by no simulated service, so there is
14
+ * nothing to look for, and it is taken as named.
12
15
  */
13
16
  has(resource: SimWafProtectedResource): boolean;
14
17
  }
15
18
  /**
16
19
  * The resources available to a WAFv2 with nothing around it to ask.
17
20
  *
18
- * Every ARN resolves to nothing, so a standalone simulated WAFv2 associates a
19
- * web ACL with nothing at all. That is the safe answer: an association held
20
- * against a resource no request will ever reach protects nothing, and saying
21
- * so is better than reporting a web ACL in front of something imaginary.
21
+ * Every simulated resource ARN resolves to nothing, so a standalone simulated
22
+ * WAFv2 associates a web ACL with no stage or pool. That is the safe answer:
23
+ * an association held against a resource no request will ever reach protects
24
+ * nothing, and saying so is better than reporting a web ACL in front of
25
+ * something imaginary. A `SimWafUnsimulatedResource` is taken as named here
26
+ * as everywhere else.
22
27
  */
23
28
  export declare class SimWafNoProtectedResources implements SimWafProtectedResources {
24
29
  /**
25
- * No resource is reachable here.
30
+ * Whether the resource is one no simulated service holds.
26
31
  */
27
- has(): boolean;
32
+ has(resource: SimWafProtectedResource): boolean;
28
33
  }
@@ -1,16 +1,19 @@
1
+ import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
1
2
  /**
2
3
  * The resources available to a WAFv2 with nothing around it to ask.
3
4
  *
4
- * Every ARN resolves to nothing, so a standalone simulated WAFv2 associates a
5
- * web ACL with nothing at all. That is the safe answer: an association held
6
- * against a resource no request will ever reach protects nothing, and saying
7
- * so is better than reporting a web ACL in front of something imaginary.
5
+ * Every simulated resource ARN resolves to nothing, so a standalone simulated
6
+ * WAFv2 associates a web ACL with no stage or pool. That is the safe answer:
7
+ * an association held against a resource no request will ever reach protects
8
+ * nothing, and saying so is better than reporting a web ACL in front of
9
+ * something imaginary. A `SimWafUnsimulatedResource` is taken as named here
10
+ * as everywhere else.
8
11
  */
9
12
  export class SimWafNoProtectedResources {
10
13
  /**
11
- * No resource is reachable here.
14
+ * Whether the resource is one no simulated service holds.
12
15
  */
13
- has() {
14
- return false;
16
+ has(resource) {
17
+ return resource instanceof SimWafUnsimulatedResource;
15
18
  }
16
19
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The resource types AWS WAF protects that no simulated request passes
3
+ * through, as ListResourcesForWebACL lists them.
4
+ */
5
+ export type SimWafUnsimulatedResourceType = "APPLICATION_LOAD_BALANCER" | "APPSYNC" | "APP_RUNNER_SERVICE" | "VERIFIED_ACCESS_INSTANCE";
6
+ /**
7
+ * The types listed for a resource AWS WAF protects and Yulin does not.
8
+ */
9
+ export declare const simWafUnsimulatedResourceTypes: readonly SimWafUnsimulatedResourceType[];
10
+ /**
11
+ * A resource AWS WAF protects and no simulated request passes through.
12
+ *
13
+ * An association with one is held, and GetWebACLForResource and
14
+ * ListResourcesForWebACL report it. Nothing is evaluated in front of it,
15
+ * because nothing here serves a request through it. Whether the resource
16
+ * exists is not checked, since no simulated service holds it to ask.
17
+ */
18
+ export declare class SimWafUnsimulatedResource {
19
+ readonly resourceType: SimWafUnsimulatedResourceType;
20
+ readonly arn: string;
21
+ readonly regionName: string;
22
+ readonly accountId: string;
23
+ /** Why the web ACL in front of this resource evaluates nothing. */
24
+ readonly reason: string;
25
+ private constructor();
26
+ /**
27
+ * The unsimulated resource an ARN names, or nothing when it names none.
28
+ *
29
+ * Every pattern places the Region and the Account where any ARN does, so a
30
+ * match is read for them by position.
31
+ */
32
+ static read(arn: string): SimWafUnsimulatedResource | undefined;
33
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The ARN shapes AWS documents for each of them.
3
+ */
4
+ const kinds = [
5
+ {
6
+ resourceType: "APPLICATION_LOAD_BALANCER",
7
+ described: "an Application Load Balancer",
8
+ pattern: /^arn:aws:elasticloadbalancing:[^:]+:[^:]+:loadbalancer\/app\/[^/]+\/[^/]+$/u,
9
+ },
10
+ {
11
+ resourceType: "APPSYNC",
12
+ described: "an AppSync GraphQL API",
13
+ pattern: /^arn:aws:appsync:[^:]+:[^:]+:apis\/[^/]+$/u,
14
+ },
15
+ {
16
+ resourceType: "APP_RUNNER_SERVICE",
17
+ described: "an App Runner service",
18
+ pattern: /^arn:aws:apprunner:[^:]+:[^:]+:service\/[^/]+\/[^/]+$/u,
19
+ },
20
+ {
21
+ resourceType: "VERIFIED_ACCESS_INSTANCE",
22
+ described: "a Verified Access instance",
23
+ pattern: /^arn:aws:ec2:[^:]+:[^:]+:verified-access-instance\/[^/]+$/u,
24
+ },
25
+ ];
26
+ /**
27
+ * The types listed for a resource AWS WAF protects and Yulin does not.
28
+ */
29
+ export const simWafUnsimulatedResourceTypes = kinds.map((kind) => kind.resourceType);
30
+ /**
31
+ * A resource AWS WAF protects and no simulated request passes through.
32
+ *
33
+ * An association with one is held, and GetWebACLForResource and
34
+ * ListResourcesForWebACL report it. Nothing is evaluated in front of it,
35
+ * because nothing here serves a request through it. Whether the resource
36
+ * exists is not checked, since no simulated service holds it to ask.
37
+ */
38
+ export class SimWafUnsimulatedResource {
39
+ resourceType;
40
+ arn;
41
+ regionName;
42
+ accountId;
43
+ /** Why the web ACL in front of this resource evaluates nothing. */
44
+ reason;
45
+ constructor(arn, kind) {
46
+ const [regionName, accountId] = arn.split(":").slice(3, 5);
47
+ this.resourceType = kind.resourceType;
48
+ this.arn = arn;
49
+ this.regionName = String(regionName);
50
+ this.accountId = String(accountId);
51
+ this.reason =
52
+ `AWS WAF protects ${kind.described}, and no simulated request passes ` +
53
+ `through one, so the association with ${arn} is held and nothing in ` +
54
+ `front of it is evaluated`;
55
+ }
56
+ /**
57
+ * The unsimulated resource an ARN names, or nothing when it names none.
58
+ *
59
+ * Every pattern places the Region and the Account where any ARN does, so a
60
+ * match is read for them by position.
61
+ */
62
+ static read(arn) {
63
+ const kind = kinds.find((candidate) => candidate.pattern.test(arn));
64
+ return kind && new SimWafUnsimulatedResource(arn, kind);
65
+ }
66
+ }
@@ -1,3 +1,4 @@
1
+ import { SimWafUnsimulatedResource } from "../../association/sim-waf-unsimulated-resource.js";
1
2
  import { SimWafUnavailableEntityException } from "../../error/sim-wafv2.error.js";
2
3
  import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
3
4
  import { wafWebAclAssociationResourceType } from "../sim-cfn-waf-resource-types.js";
@@ -44,6 +45,10 @@ export class SimCfnWafAssociationCreator {
44
45
  WebACLArn: association.webAclArn,
45
46
  },
46
47
  }, options);
48
+ const unsimulated = SimWafUnsimulatedResource.read(association.resourceArn);
49
+ if (unsimulated !== undefined) {
50
+ resource.ignoreProperty("ResourceArn", unsimulated.reason);
51
+ }
47
52
  return association;
48
53
  });
49
54
  }
@@ -20,6 +20,7 @@ export class SimCfnWafIpSetConfig extends SimCfnWafResourceConfig {
20
20
  Name: this.name(),
21
21
  Scope: this.scope(),
22
22
  Description: this.description(),
23
+ Tags: this.tags(),
23
24
  IPAddressVersion: this.text("IPAddressVersion"),
24
25
  Addresses: this.requiredStrings("Addresses"),
25
26
  };
@@ -1,5 +1,6 @@
1
1
  import { assertDefined } from "../../../../util/type-guard/defined.js";
2
2
  import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
3
+ import { simCfnWafRecordUnsimulated } from "../sim-cfn-waf-unsimulated.js";
3
4
  import { wafIpSetResourceType } from "../sim-cfn-waf-resource-types.js";
4
5
  import { SimCfnWafIpSetConfig } from "./sim-cfn-waf-ip-set-config.js";
5
6
  /**
@@ -29,6 +30,7 @@ export class SimCfnWafIpSetCreator {
29
30
  assertDefined(arn, `sim WAFv2 IP set ARN for CloudFormation Resource ${resource.logicalId}`);
30
31
  const ipSet = this.#wafV2.findIpSetByArn(arn);
31
32
  assertDefined(ipSet, `sim WAFv2 IP set ${arn} after CloudFormation creation`);
33
+ simCfnWafRecordUnsimulated(resource, ipSet);
32
34
  return ipSet;
33
35
  });
34
36
  }
@@ -21,6 +21,7 @@ export class SimCfnWafRegexPatternSetConfig extends SimCfnWafResourceConfig {
21
21
  Name: this.name(),
22
22
  Scope: this.scope(),
23
23
  Description: this.description(),
24
+ Tags: this.tags(),
24
25
  RegularExpressionList: this.requiredStrings("RegularExpressionList").map((pattern) => ({ RegexString: pattern })),
25
26
  };
26
27
  }
@@ -1,5 +1,6 @@
1
1
  import { assertDefined } from "../../../../util/type-guard/defined.js";
2
2
  import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
3
+ import { simCfnWafRecordUnsimulated } from "../sim-cfn-waf-unsimulated.js";
3
4
  import { wafRegexPatternSetResourceType } from "../sim-cfn-waf-resource-types.js";
4
5
  import { SimCfnWafRegexPatternSetConfig } from "./sim-cfn-waf-regex-set-config.js";
5
6
  /**
@@ -29,6 +30,7 @@ export class SimCfnWafRegexPatternSetCreator {
29
30
  assertDefined(arn, `sim WAFv2 regex pattern set ARN for CloudFormation Resource ${resource.logicalId}`);
30
31
  const patternSet = this.#wafV2.findRegexPatternSetByArn(arn);
31
32
  assertDefined(patternSet, `sim WAFv2 regex pattern set ${arn} after CloudFormation creation`);
33
+ simCfnWafRecordUnsimulated(resource, patternSet);
32
34
  return patternSet;
33
35
  });
34
36
  }
@@ -45,6 +45,10 @@ export declare abstract class SimCfnWafResourceConfig {
45
45
  /**
46
46
  * One property of the Resource, whatever shape it is in.
47
47
  */
48
+ /**
49
+ * The tags the template gave the Resource, as written.
50
+ */
51
+ tags(): readonly unknown[] | undefined;
48
52
  protected value(key: string): SimCfnTemplateValue | undefined;
49
53
  /**
50
54
  * One string property, or nothing when the template left it out.
@@ -57,6 +57,16 @@ export class SimCfnWafResourceConfig {
57
57
  /**
58
58
  * One property of the Resource, whatever shape it is in.
59
59
  */
60
+ /**
61
+ * The tags the template gave the Resource, as written.
62
+ */
63
+ tags() {
64
+ const tags = this.value("Tags");
65
+ if (tags !== undefined && !Array.isArray(tags)) {
66
+ this.refuse("Tags must be a list");
67
+ }
68
+ return tags;
69
+ }
60
70
  value(key) {
61
71
  // oxlint-disable-next-line security/detect-object-injection
62
72
  return this.properties[key] ?? undefined;
@@ -0,0 +1,10 @@
1
+ import type { SimCfnResource } from "../../cloudformation/resource/sim-cfn-resource.js";
2
+ import type { SimWafResource } from "../resource/sim-waf-resource.js";
3
+ /**
4
+ * Record on a Resource each part of the WAFv2 resource it created that the
5
+ * simulation holds and does not act on.
6
+ *
7
+ * The path is the one `unsimulatedParts` reports, so `stack.ignoredProperties`
8
+ * and an SDK caller read the same names.
9
+ */
10
+ export declare function simCfnWafRecordUnsimulated(resource: SimCfnResource, created: SimWafResource): void;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Record on a Resource each part of the WAFv2 resource it created that the
3
+ * simulation holds and does not act on.
4
+ *
5
+ * The path is the one `unsimulatedParts` reports, so `stack.ignoredProperties`
6
+ * and an SDK caller read the same names.
7
+ */
8
+ export function simCfnWafRecordUnsimulated(resource, created) {
9
+ for (const { part, reason } of created.unsimulated) {
10
+ resource.ignoreProperty(part, reason);
11
+ }
12
+ }
@@ -8,26 +8,14 @@ import { SimCfnWafResourceConfig } from "../sim-cfn-waf-resource-config.js";
8
8
  * template wrote them. They are not read here at all: every rule is compiled
9
9
  * by CreateWebACL, which is where a statement kind Yulin cannot evaluate is
10
10
  * found, and reading them twice would mean two answers to the same question.
11
+ * The members Yulin holds without acting on are handed over the same way.
11
12
  */
12
13
  export declare class SimCfnWafWebAclConfig extends SimCfnWafResourceConfig {
13
14
  protected get resourceType(): string;
14
15
  /**
15
16
  * The input the web ACL this Resource describes is created from.
16
- *
17
- * The properties this simulation has no behaviour for are left out of it and
18
- * recorded, so the web ACL deploys with the rest of what the template wrote.
19
- * An SDK caller is refused for the same properties, because a request that
20
- * was answered and then quietly dropped is a worse answer than a refusal.
21
17
  */
22
18
  createInput(): SimCreateWebAclCommandInput;
23
- /**
24
- * Record the web ACL members this simulation has no behaviour for.
25
- *
26
- * Each of them changes what a web ACL does on real WAF, so a web ACL
27
- * deployed without one behaves differently to the one the template
28
- * describes. `stack.ignoredProperties` is where a test reads that.
29
- */
30
- private recordUnsimulatedMembers;
31
19
  /**
32
20
  * The rules the template declared.
33
21
  *
@@ -1,4 +1,3 @@
1
- import { simWafUnsimulatedWebAclMembers } from "../../command/web-acl/sim-wafv2-unsimulated-web-acl-input.js";
2
1
  import { SimCfnWafResourceConfig } from "../sim-cfn-waf-resource-config.js";
3
2
  import { wafWebAclResourceType } from "../sim-cfn-waf-resource-types.js";
4
3
  /**
@@ -9,6 +8,7 @@ import { wafWebAclResourceType } from "../sim-cfn-waf-resource-types.js";
9
8
  * template wrote them. They are not read here at all: every rule is compiled
10
9
  * by CreateWebACL, which is where a statement kind Yulin cannot evaluate is
11
10
  * found, and reading them twice would mean two answers to the same question.
11
+ * The members Yulin holds without acting on are handed over the same way.
12
12
  */
13
13
  export class SimCfnWafWebAclConfig extends SimCfnWafResourceConfig {
14
14
  get resourceType() {
@@ -16,39 +16,26 @@ export class SimCfnWafWebAclConfig extends SimCfnWafResourceConfig {
16
16
  }
17
17
  /**
18
18
  * The input the web ACL this Resource describes is created from.
19
- *
20
- * The properties this simulation has no behaviour for are left out of it and
21
- * recorded, so the web ACL deploys with the rest of what the template wrote.
22
- * An SDK caller is refused for the same properties, because a request that
23
- * was answered and then quietly dropped is a worse answer than a refusal.
24
19
  */
25
20
  createInput() {
26
- this.recordUnsimulatedMembers();
27
21
  return {
28
22
  Name: this.name(),
29
23
  Scope: this.scope(),
30
24
  Description: this.description(),
25
+ Tags: this.tags(),
31
26
  DefaultAction: this.value("DefaultAction"),
32
27
  Rules: this.rules(),
33
28
  VisibilityConfig: this.value("VisibilityConfig"),
34
29
  CustomResponseBodies: this.value("CustomResponseBodies"),
35
30
  AssociationConfig: this.value("AssociationConfig"),
31
+ CaptchaConfig: this.value("CaptchaConfig"),
32
+ ChallengeConfig: this.value("ChallengeConfig"),
33
+ TokenDomains: this.value("TokenDomains"),
34
+ DataProtectionConfig: this.value("DataProtectionConfig"),
35
+ OnSourceDDoSProtectionConfig: this.value("OnSourceDDoSProtectionConfig"),
36
+ ApplicationConfig: this.value("ApplicationConfig"),
36
37
  };
37
38
  }
38
- /**
39
- * Record the web ACL members this simulation has no behaviour for.
40
- *
41
- * Each of them changes what a web ACL does on real WAF, so a web ACL
42
- * deployed without one behaves differently to the one the template
43
- * describes. `stack.ignoredProperties` is where a test reads that.
44
- */
45
- recordUnsimulatedMembers() {
46
- for (const [member, reason] of simWafUnsimulatedWebAclMembers) {
47
- if (this.value(member) !== undefined) {
48
- this.resource.ignoreProperty(member, `${member} is not simulated: ${reason}`);
49
- }
50
- }
51
- }
52
39
  /**
53
40
  * The rules the template declared.
54
41
  *
@@ -14,15 +14,10 @@ interface SimCfnWafWebAclCreatorProperties {
14
14
  * caller would have got: the same compilation of every rule, and the same
15
15
  * refusals.
16
16
  *
17
- * A rule this simulation cannot evaluate is the exception, and the two part
18
- * company over it. An SDK caller has the whole web ACL refused. A template
19
- * deploys the web ACL without that rule and records it on
20
- * `stack.ignoredProperties`, because the alternative is one rule taking a
21
- * user pool, a table and two functions in the same template down with it.
22
- *
23
- * The web ACL is then real, and thinner than the one the template describes.
24
- * That is the cost of deploying it at all, and the record of the dropped rule
25
- * is what a test reads to know the size of it.
17
+ * A rule or member this simulation cannot act on is held by the web ACL as the
18
+ * template wrote it, and recorded on `stack.ignoredProperties` under the name
19
+ * the web ACL reports it by. That record is what a test reads to know how far
20
+ * the deployed web ACL is from the one AWS would run.
26
21
  */
27
22
  export declare class SimCfnWafWebAclCreator {
28
23
  #private;
@@ -1,7 +1,7 @@
1
1
  import { assertDefined } from "../../../../util/type-guard/defined.js";
2
2
  import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
3
+ import { simCfnWafRecordUnsimulated } from "../sim-cfn-waf-unsimulated.js";
3
4
  import { wafWebAclResourceType } from "../sim-cfn-waf-resource-types.js";
4
- import { simCfnWafEvaluatableRules } from "./sim-cfn-waf-evaluatable-rules.js";
5
5
  import { SimCfnWafWebAclConfig } from "./sim-cfn-waf-web-acl-config.js";
6
6
  /**
7
7
  * Creates simulated web ACLs from AWS::WAFv2::WebACL Resources.
@@ -11,15 +11,10 @@ import { SimCfnWafWebAclConfig } from "./sim-cfn-waf-web-acl-config.js";
11
11
  * caller would have got: the same compilation of every rule, and the same
12
12
  * refusals.
13
13
  *
14
- * A rule this simulation cannot evaluate is the exception, and the two part
15
- * company over it. An SDK caller has the whole web ACL refused. A template
16
- * deploys the web ACL without that rule and records it on
17
- * `stack.ignoredProperties`, because the alternative is one rule taking a
18
- * user pool, a table and two functions in the same template down with it.
19
- *
20
- * The web ACL is then real, and thinner than the one the template describes.
21
- * That is the cost of deploying it at all, and the record of the dropped rule
22
- * is what a test reads to know the size of it.
14
+ * A rule or member this simulation cannot act on is held by the web ACL as the
15
+ * template wrote it, and recorded on `stack.ignoredProperties` under the name
16
+ * the web ACL reports it by. That record is what a test reads to know how far
17
+ * the deployed web ACL is from the one AWS would run.
23
18
  */
24
19
  export class SimCfnWafWebAclCreator {
25
20
  #wafV2;
@@ -34,16 +29,13 @@ export class SimCfnWafWebAclCreator {
34
29
  resource,
35
30
  properties,
36
31
  }).createInput();
37
- const deployable = {
38
- ...input,
39
- Rules: simCfnWafEvaluatableRules(this.#wafV2, resource, input),
40
- };
41
32
  return await simCfnWafResourceCommand(wafWebAclResourceType, resource.logicalId, async () => {
42
- const created = await this.#wafV2.createWebAcl({ input: deployable }, options);
33
+ const created = await this.#wafV2.createWebAcl({ input }, options);
43
34
  const arn = created.Summary?.ARN;
44
35
  assertDefined(arn, `sim WAFv2 web ACL ARN for CloudFormation Resource ${resource.logicalId}`);
45
36
  const webAcl = this.#wafV2.findWebAclByArn(arn);
46
37
  assertDefined(webAcl, `sim WAFv2 web ACL ${arn} after CloudFormation creation`);
38
+ simCfnWafRecordUnsimulated(resource, webAcl);
47
39
  return webAcl;
48
40
  });
49
41
  }