@kensio/yulin 1.21.10 → 1.21.12

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 (75) hide show
  1. package/dist/serve/payload-2/sim-payload-2-endpoint.d.ts +9 -0
  2. package/dist/serve/payload-2/sim-payload-2-request-context.js +1 -1
  3. package/dist/service/apigatewayv2/api/sim-http-api-lambda-proxy.factory.d.ts +6 -0
  4. package/dist/service/apigatewayv2/api/sim-http-api-lambda-proxy.factory.js +2 -0
  5. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-format.d.ts +8 -0
  6. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-format.js +36 -0
  7. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-request.d.ts +53 -0
  8. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-request.js +1 -0
  9. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-settings.d.ts +26 -0
  10. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-settings.js +44 -0
  11. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-settings.type.d.ts +21 -0
  12. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-settings.type.js +1 -0
  13. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-stream-name.d.ts +13 -0
  14. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-stream-name.js +23 -0
  15. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-variables.d.ts +17 -0
  16. package/dist/service/apigatewayv2/api/stage/access-log/sim-http-api-access-log-variables.js +86 -0
  17. package/dist/service/apigatewayv2/api/stage/sim-http-api-stage.d.ts +9 -0
  18. package/dist/service/apigatewayv2/api/stage/sim-http-api-stage.js +9 -0
  19. package/dist/service/apigatewayv2/cfn/stage/sim-cfn-http-api-access-log-settings-properties.d.ts +24 -0
  20. package/dist/service/apigatewayv2/cfn/stage/sim-cfn-http-api-access-log-settings-properties.js +30 -0
  21. package/dist/service/apigatewayv2/cfn/stage/sim-cfn-http-api-stage-properties.d.ts +1 -0
  22. package/dist/service/apigatewayv2/cfn/stage/sim-cfn-http-api-stage-properties.js +10 -4
  23. package/dist/service/apigatewayv2/command/stage/sim-http-api-access-log-settings-input.d.ts +15 -0
  24. package/dist/service/apigatewayv2/command/stage/sim-http-api-access-log-settings-input.js +33 -0
  25. package/dist/service/apigatewayv2/command/stage/sim-http-api-stage-commands.js +4 -0
  26. package/dist/service/apigatewayv2/command/stage/stage.command.d.ts +2 -0
  27. package/dist/service/apigatewayv2/serve/auth/sim-http-api-route-authorize-input.d.ts +6 -0
  28. package/dist/service/apigatewayv2/serve/sim-api-gateway-v2-controller.d.ts +13 -15
  29. package/dist/service/apigatewayv2/serve/sim-api-gateway-v2-controller.js +26 -60
  30. package/dist/service/apigatewayv2/serve/sim-http-api-access-log-record.d.ts +31 -0
  31. package/dist/service/apigatewayv2/serve/sim-http-api-access-log-record.js +88 -0
  32. package/dist/service/apigatewayv2/serve/sim-http-api-access-log.d.ts +43 -0
  33. package/dist/service/apigatewayv2/serve/sim-http-api-access-log.js +72 -0
  34. package/dist/service/apigatewayv2/serve/sim-http-api-endpoint.js +1 -0
  35. package/dist/service/apigatewayv2/serve/sim-http-api-integration-input.d.ts +22 -0
  36. package/dist/service/apigatewayv2/serve/sim-http-api-integration-input.js +1 -0
  37. package/dist/service/apigatewayv2/serve/sim-http-api-integration-invocation.d.ts +5 -22
  38. package/dist/service/apigatewayv2/serve/sim-http-api-integration-invocation.js +17 -20
  39. package/dist/service/apigatewayv2/serve/sim-http-api-integration-outcome.d.ts +27 -0
  40. package/dist/service/apigatewayv2/serve/sim-http-api-integration-outcome.js +13 -0
  41. package/dist/service/apigatewayv2/serve/sim-http-api-may-invoke.d.ts +19 -0
  42. package/dist/service/apigatewayv2/serve/sim-http-api-may-invoke.js +19 -0
  43. package/dist/service/apigatewayv2/serve/sim-http-api-serve-pipeline.d.ts +27 -0
  44. package/dist/service/apigatewayv2/serve/sim-http-api-serve-pipeline.js +75 -0
  45. package/dist/service/apigatewayv2/serve/sim-http-api-served.d.ts +22 -0
  46. package/dist/service/apigatewayv2/serve/sim-http-api-served.js +1 -0
  47. package/dist/service/apigatewayv2/serve/sim-http-api-serving.d.ts +12 -0
  48. package/dist/service/apigatewayv2/serve/sim-http-api-serving.js +1 -0
  49. package/dist/service/cloudfront/controller/web-acl/sim-cf-web-acl-guard.js +1 -0
  50. package/dist/service/logs/group/sim-logs-arn.d.ts +15 -0
  51. package/dist/service/logs/group/sim-logs-arn.js +33 -0
  52. package/dist/service/wafv2/association/sim-waf-associations.js +1 -1
  53. package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.js +1 -0
  54. package/dist/service/wafv2/command/web-acl/sim-waf-web-acl-output.js +1 -0
  55. package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.js +0 -6
  56. package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.js +1 -0
  57. package/dist/service/wafv2/command/web-acl/web-acl.command.d.ts +3 -1
  58. package/dist/service/wafv2/evaluate/sim-waf-evaluation-request.d.ts +8 -0
  59. package/dist/service/wafv2/evaluate/sim-waf-inspected-request.d.ts +14 -1
  60. package/dist/service/wafv2/evaluate/sim-waf-inspected-request.js +7 -1
  61. package/dist/service/wafv2/index.d.ts +2 -1
  62. package/dist/service/wafv2/index.js +2 -1
  63. package/dist/service/wafv2/managed/sim-waf-managed-request.js +1 -2
  64. package/dist/service/wafv2/sim-wafv2.js +2 -1
  65. package/dist/service/wafv2/statement/sim-waf-field-content.d.ts +9 -6
  66. package/dist/service/wafv2/statement/sim-waf-field-content.js +16 -10
  67. package/dist/service/wafv2/statement/sim-waf-set-field.js +3 -3
  68. package/dist/service/wafv2/web-acl/sim-waf-association-config.d.ts +54 -0
  69. package/dist/service/wafv2/web-acl/sim-waf-association-config.js +92 -0
  70. package/dist/service/wafv2/web-acl/sim-waf-web-acl-configuration.d.ts +2 -0
  71. package/dist/service/wafv2/web-acl/sim-waf-web-acl.d.ts +9 -0
  72. package/dist/service/wafv2/web-acl/sim-waf-web-acl.js +15 -0
  73. package/docs/services/apigatewayv2/README.md +162 -6
  74. package/docs/services/wafv2/README.md +19 -5
  75. package/package.json +1 -1
@@ -0,0 +1,92 @@
1
+ import { SimWafInvalidParameterException, SimWafUnsimulatedInputException, } from "../error/sim-wafv2.error.js";
2
+ /**
3
+ * How much of a request body WAF reads for a resource type given no
4
+ * `AssociationConfig`.
5
+ *
6
+ * CloudFront, API Gateway and Cognito all default to 16 KB. A load balancer
7
+ * and an AppSync API are fixed at 8 KB, and a web ACL cannot be put in front
8
+ * of either one here.
9
+ */
10
+ export const simWafBodyInspectionLimitBytes = 16_384;
11
+ /**
12
+ * The four sizes `DefaultSizeInspectionLimit` names, in bytes.
13
+ */
14
+ const inspectionLimits = new Map([
15
+ ["KB_16", 16_384],
16
+ ["KB_32", 32_768],
17
+ ["KB_48", 49_152],
18
+ ["KB_64", 65_536],
19
+ ]);
20
+ const simulatedResourceTypes = [
21
+ "CLOUDFRONT",
22
+ "API_GATEWAY",
23
+ "COGNITO_USER_POOL",
24
+ ];
25
+ /**
26
+ * How much of a request body a web ACL's rules read, by resource type.
27
+ *
28
+ * A web ACL holds one of these whether or not it was written with an
29
+ * `AssociationConfig`, and a resource type the config left out reads the
30
+ * default 16 KB.
31
+ */
32
+ export class SimWafBodyInspectionLimits {
33
+ limits;
34
+ constructor(limits) {
35
+ this.limits = limits;
36
+ }
37
+ /**
38
+ * Read the limits an `AssociationConfig` sets, refusing anything WAF would
39
+ * refuse and anything this simulation cannot apply.
40
+ */
41
+ static read(input) {
42
+ const configured = Object.entries(input?.RequestBody ?? {});
43
+ const limits = new Map();
44
+ for (const [resourceType, config] of configured) {
45
+ limits.set(simulatedResourceType(resourceType), inspectionLimit(resourceType, config));
46
+ }
47
+ return new SimWafBodyInspectionLimits(limits);
48
+ }
49
+ /**
50
+ * How many bytes of a body a request reaching one resource type is inspected
51
+ * for.
52
+ *
53
+ * A request evaluated against a web ACL that no resource holds names no
54
+ * resource type, and reads the default.
55
+ */
56
+ bytesFor(resourceType) {
57
+ if (resourceType === undefined) {
58
+ return simWafBodyInspectionLimitBytes;
59
+ }
60
+ return this.limits.get(resourceType) ?? simWafBodyInspectionLimitBytes;
61
+ }
62
+ }
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
+ /**
76
+ * Read one resource type's `DefaultSizeInspectionLimit`.
77
+ *
78
+ * An entry carrying no size is refused the same way one carrying a size WAF
79
+ * has no setting for is. A template writes this part of a web ACL by hand, and
80
+ * an entry that says nothing about the limit it is there to set is a mistake
81
+ * worth reporting as one.
82
+ */
83
+ function inspectionLimit(resourceType, config) {
84
+ const limit = config?.DefaultSizeInspectionLimit;
85
+ const bytes = limit === undefined ? undefined : inspectionLimits.get(limit);
86
+ if (bytes === undefined) {
87
+ throw new SimWafInvalidParameterException(`Error reason: The DefaultSizeInspectionLimit ${String(limit)} is one ` +
88
+ `of ${inspectionLimits.keys().toArray().join(", ")}, field: ` +
89
+ `ASSOCIATION_CONFIG, parameter: ${resourceType}`);
90
+ }
91
+ return bytes;
92
+ }
@@ -1,4 +1,5 @@
1
1
  import { SimWafAction } from "./sim-waf-action.js";
2
+ import type { SimWafAssociationConfigInput } from "./sim-waf-association-config.js";
2
3
  import type { SimWafActionInput } from "./sim-waf-action.type.js";
3
4
  import type { SimWafCustomResponseBodies } from "./sim-waf-custom-response.type.js";
4
5
  import type { SimWafRuleInput } from "./sim-waf-rule.type.js";
@@ -11,6 +12,7 @@ export interface SimWafWebAclConfiguration {
11
12
  readonly customResponseBodies?: SimWafCustomResponseBodies | undefined;
12
13
  readonly visibilityConfig?: unknown;
13
14
  readonly description?: string | undefined;
15
+ readonly associationConfig?: SimWafAssociationConfigInput | undefined;
14
16
  }
15
17
  /**
16
18
  * Read the action a request no rule claims is given.
@@ -1,6 +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 { type SimWafBodyInspectionResourceType } from "./sim-waf-association-config.js";
4
5
  import type { SimWafWebAclRuleScope } from "./sim-waf-rule.type.js";
5
6
  import { type SimWafWebAclConfiguration } from "./sim-waf-web-acl-configuration.js";
6
7
  interface SimWafWebAclProperties extends SimWafResourceProperties, SimWafWebAclRuleScope {
@@ -43,6 +44,14 @@ export declare class SimWafWebAcl extends SimWafResource {
43
44
  * refuses an update keeps the rules it had rather than being left with none.
44
45
  */
45
46
  reconfigure(configuration: SimWafWebAclConfiguration, lockToken: string | undefined): void;
47
+ /**
48
+ * How many bytes of a request body this web ACL reads in front of one
49
+ * resource type.
50
+ *
51
+ * `AssociationConfig` raises it per resource type, and a web ACL written
52
+ * without one reads the 16 KB default everything it protects has.
53
+ */
54
+ bodyInspectionLimitBytes(resourceType: SimWafBodyInspectionResourceType | undefined): number;
46
55
  /**
47
56
  * Decide what happens to one request.
48
57
  */
@@ -1,6 +1,7 @@
1
1
  import { simWafDecision, } from "../evaluate/sim-waf-decision.js";
2
2
  import { simWafEvaluateRules } from "../evaluate/sim-waf-evaluate-rules.js";
3
3
  import { SimWafResource, } from "../resource/sim-waf-resource.js";
4
+ import { SimWafBodyInspectionLimits, } from "./sim-waf-association-config.js";
4
5
  import { compileSimWafWebAclRules } from "./sim-waf-rules.js";
5
6
  import { simWafWebAclCapacity } from "./sim-waf-web-acl-capacity.js";
6
7
  import { readSimWafDefaultAction, } from "./sim-waf-web-acl-configuration.js";
@@ -29,6 +30,7 @@ export class SimWafWebAcl extends SimWafResource {
29
30
  #defaultAction;
30
31
  #rules;
31
32
  #capacity;
33
+ #bodyInspectionLimits;
32
34
  constructor(properties) {
33
35
  super("webacl", properties);
34
36
  this.#scope = properties;
@@ -36,6 +38,7 @@ export class SimWafWebAcl extends SimWafResource {
36
38
  this.#defaultAction = readSimWafDefaultAction(properties.configuration);
37
39
  this.#rules = compileSimWafWebAclRules(properties.configuration, this.#scope);
38
40
  this.#capacity = simWafWebAclCapacity(properties.configuration.rules);
41
+ this.#bodyInspectionLimits = SimWafBodyInspectionLimits.read(properties.configuration.associationConfig);
39
42
  this.labelNamespace =
40
43
  `awswaf:${properties.accountRegionScope.accountId}:webacl:` +
41
44
  `${properties.name}:`;
@@ -61,12 +64,24 @@ export class SimWafWebAcl extends SimWafResource {
61
64
  reconfigure(configuration, lockToken) {
62
65
  const defaultAction = readSimWafDefaultAction(configuration);
63
66
  const rules = compileSimWafWebAclRules(configuration, this.#scope);
67
+ const bodyInspectionLimits = SimWafBodyInspectionLimits.read(configuration.associationConfig);
64
68
  this.takeLock(lockToken);
65
69
  this.replaceDescription(configuration.description);
66
70
  this.#configuration = configuration;
67
71
  this.#defaultAction = defaultAction;
68
72
  this.#rules = rules;
69
73
  this.#capacity = simWafWebAclCapacity(configuration.rules);
74
+ this.#bodyInspectionLimits = bodyInspectionLimits;
75
+ }
76
+ /**
77
+ * How many bytes of a request body this web ACL reads in front of one
78
+ * resource type.
79
+ *
80
+ * `AssociationConfig` raises it per resource type, and a web ACL written
81
+ * without one reads the 16 KB default everything it protects has.
82
+ */
83
+ bodyInspectionLimitBytes(resourceType) {
84
+ return this.#bodyInspectionLimits.bytesFor(resourceType);
70
85
  }
71
86
  /**
72
87
  * Decide what happens to one request.
@@ -666,8 +666,146 @@ route configured that way is served unthrottled.
666
666
  `GetStages` answers with the settings a stage was created with. `AWS::ApiGatewayV2::Stage` deploys
667
667
  both properties as well (see [CloudFormation](#cloudformation)). The three members of `RouteSettings`
668
668
  that say nothing about throttling, `DetailedMetricsEnabled`, `LoggingLevel` and `DataTraceEnabled`,
669
- are refused by `CreateStage`. A template carrying one deploys, and the member it named is recorded on
670
- `stack.ignoredProperties`.
669
+ are refused by `CreateStage`. They are execution logging, which is a different log from the one
670
+ [`AccessLogSettings` writes](#writing-a-stages-access-log). A template carrying one deploys, and the
671
+ member it named is recorded on `stack.ignoredProperties`.
672
+
673
+ ## Writing a stage's access log
674
+
675
+ `AccessLogSettings` sends one line per request to a CloudWatch Logs log group. `DestinationArn` names
676
+ the group and `Format` is the line, with `$context` variables substituted from the request that
677
+ produced it.
678
+
679
+ The line is written whether or not an integration ran. A request the stage throttle refused, one a
680
+ Lambda authorizer denied, and one with no identity source header all reach the log group, and for
681
+ those the access log is the only record of the request.
682
+
683
+ ```typescript sim-apigatewayv2-access-log
684
+ /**
685
+ * Recording a simulated HTTP API stage's access log, including a request the
686
+ * stage's throttle refused.
687
+ */
688
+
689
+ import {
690
+ CreateApiCommand,
691
+ CreateIntegrationCommand,
692
+ CreateRouteCommand,
693
+ CreateStageCommand,
694
+ } from "@aws-sdk/client-apigatewayv2";
695
+ import {
696
+ CreateLogGroupCommand,
697
+ FilterLogEventsCommand,
698
+ } from "@aws-sdk/client-cloudwatch-logs";
699
+ import {
700
+ AddPermissionCommand,
701
+ CreateFunctionCommand,
702
+ } from "@aws-sdk/client-lambda";
703
+
704
+ import { SimAws } from "@kensio/yulin";
705
+ import { makeLambdaZipFileInput } from "@kensio/yulin/lambda";
706
+ import { serveSimAws } from "@kensio/yulin/serve";
707
+
708
+ const simAws = new SimAws();
709
+ const logGroupName = "/aws/vendedlogs/user-api";
710
+
711
+ await simAws.logs().createLogGroup(new CreateLogGroupCommand({ logGroupName }));
712
+
713
+ const { FunctionArn } = await simAws.lambda().createFunction(
714
+ new CreateFunctionCommand({
715
+ FunctionName: "users",
716
+ Role: "arn:aws:iam::111111111111:role/UsersRole",
717
+ Code: {
718
+ ZipFile: makeLambdaZipFileInput(() => ({
719
+ statusCode: 200,
720
+ headers: { "content-type": "text/plain" },
721
+ body: "ok",
722
+ })),
723
+ },
724
+ }),
725
+ );
726
+
727
+ const apiGateway = simAws.apiGatewayV2();
728
+ const { ApiId, ApiEndpoint } = await apiGateway.createApi(
729
+ new CreateApiCommand({ Name: "users", ProtocolType: "HTTP" }),
730
+ );
731
+
732
+ const { IntegrationId } = await apiGateway.createIntegration(
733
+ new CreateIntegrationCommand({
734
+ ApiId,
735
+ IntegrationType: "AWS_PROXY",
736
+ IntegrationUri: FunctionArn,
737
+ PayloadFormatVersion: "2.0",
738
+ }),
739
+ );
740
+
741
+ await apiGateway.createRoute(
742
+ new CreateRouteCommand({
743
+ ApiId,
744
+ RouteKey: "GET /user/profile",
745
+ Target: `integrations/${IntegrationId}`,
746
+ }),
747
+ );
748
+
749
+ await apiGateway.createStage(
750
+ new CreateStageCommand({
751
+ ApiId,
752
+ StageName: "$default",
753
+ AutoDeploy: true,
754
+ DefaultRouteSettings: { ThrottlingRateLimit: 1, ThrottlingBurstLimit: 1 },
755
+ AccessLogSettings: {
756
+ DestinationArn: `arn:aws:logs:us-east-1:888888888888:log-group:${logGroupName}:*`,
757
+ Format:
758
+ "$context.httpMethod $context.path $context.status " +
759
+ "$context.error.message",
760
+ },
761
+ }),
762
+ );
763
+
764
+ await simAws.lambda().addPermission(
765
+ new AddPermissionCommand({
766
+ FunctionName: "users",
767
+ StatementId: "api-gateway-invoke",
768
+ Action: "lambda:InvokeFunction",
769
+ Principal: "apigateway.amazonaws.com",
770
+ SourceArn: `arn:aws:execute-api:us-east-1:888888888888:${ApiId}/*/*`,
771
+ }),
772
+ );
773
+
774
+ const srv = await serveSimAws({ simAws });
775
+ simAws.clock().freeze();
776
+
777
+ const profile = srv.localUrl(`${ApiEndpoint}/user/profile`);
778
+ await fetch(profile);
779
+ await fetch(profile);
780
+
781
+ const { events } = await simAws
782
+ .logs()
783
+ .filterLogEvents(new FilterLogEventsCommand({ logGroupName }));
784
+
785
+ const lines = events ?? [];
786
+
787
+ for (const event of lines) {
788
+ console.log(event.message);
789
+ }
790
+
791
+ await srv.close();
792
+ ```
793
+
794
+ The served request and the throttled one are both there. A variable with no value renders as a dash,
795
+ which is what `$context.error.message` does for the request the integration answered:
796
+
797
+ ```text
798
+ GET /user/profile 200 -
799
+ GET /user/profile 429 Too Many Requests
800
+ ```
801
+
802
+ The lines go to the log group and nowhere else. An API answering a few hundred requests in one test
803
+ file would otherwise bury the suite's own output, so nothing here is forwarded to the console the way
804
+ a [Lambda handler's output](https://yulinsim.dev/services/lambda/#capturing-handler-output) is.
805
+
806
+ A `DestinationArn` naming a log group nothing has created yet is written to anyway, and the group is
807
+ made by the first line. `Format` is copied through apart from its `$context` references, so a JSON
808
+ format string arrives as JSON.
671
809
 
672
810
  ## Protecting a route with a Cognito user pool
673
811
 
@@ -2287,7 +2425,7 @@ parts behaves differently to the template. The simulated properties are:
2287
2425
  - `Integration`: `ApiId`, `IntegrationType`, `IntegrationUri`, `PayloadFormatVersion`, `Description`
2288
2426
  - `Route`: `ApiId`, `RouteKey`, `Target`, `AuthorizationType`, `AuthorizerId`, `AuthorizationScopes`
2289
2427
  - `Stage`: `ApiId`, `StageName`, `AutoDeploy`, `StageVariables`, `Description`,
2290
- `DefaultRouteSettings`, `RouteSettings`
2428
+ `DefaultRouteSettings`, `RouteSettings`, `AccessLogSettings`
2291
2429
 
2292
2430
  CDK's `HttpIamAuthorizer` deploys too. It emits no `AWS::ApiGatewayV2::Authorizer` and no
2293
2431
  `AuthorizerId`, only `AuthorizationType: "AWS_IAM"` on the `Route`, and the deployed route then
@@ -2436,6 +2574,9 @@ the simulation without being given one. See the
2436
2574
  under their own path segment, including stage variables
2437
2575
  - `DefaultRouteSettings` and `RouteSettings` throttling, with a token bucket per route refilling
2438
2576
  against the simulated clock and a 429 for the requests past it
2577
+ - `AccessLogSettings`, writing one line per request to the log group `DestinationArn` names, with the
2578
+ `Format` string's `$context` variables substituted, including for a request the throttle or an
2579
+ authorizer refused before any integration ran
2439
2580
  - Serving the generated endpoint through `serveSimAws`, invoking the integrated function with a
2440
2581
  payload format 2.0 event and turning its result back into an HTTP response
2441
2582
  - The invoke permission of an integration's function and of an authorizer's, each evaluated against
@@ -2474,9 +2615,24 @@ Current documented limitations:
2474
2615
  - Deployments are outside the simulation, so `CreateStage` requires `AutoDeploy: true`. A stage
2475
2616
  without it serves whichever Deployment it was given, which on real AWS is nothing until one is
2476
2617
  created.
2477
- - `AccessLogSettings` on a stage is refused, as is any other option `CreateStage` takes and this one
2478
- lacks. `RouteSettings` and `DefaultRouteSettings` are taken, and only their throttling members are
2479
- read. `DetailedMetricsEnabled`, `LoggingLevel` and `DataTraceEnabled` are refused by name.
2618
+ - Any option `CreateStage` takes and this one lacks is refused. `RouteSettings` and
2619
+ `DefaultRouteSettings` are taken, and only their throttling members are read.
2620
+ `DetailedMetricsEnabled`, `LoggingLevel` and `DataTraceEnabled` are refused by name. Those three
2621
+ are execution logging, which is a different log from the access log and is not simulated.
2622
+ - An access log `DestinationArn` has to name a CloudWatch Logs log group. A Kinesis Data Firehose
2623
+ delivery stream, which a REST API stage may name, is refused.
2624
+ - The access log variables carrying a value are `accountId`, `apiId`, `domainName`, `domainPrefix`,
2625
+ `stage`, `routeKey`, `httpMethod`, `path`, `protocol`, `requestId`, `extendedRequestId`,
2626
+ `requestTime`, `requestTimeEpoch`, `status`, `responseLength`, `responseLatency`,
2627
+ `identity.sourceIp`, `identity.userAgent`, `integrationStatus`, `integrationLatency`,
2628
+ `integrationErrorMessage`, `authorizer.error`, `error.message`, `error.messageString`,
2629
+ `customDomain.basePathMatched`, the `integration.*` aliases, and `authorizer.claims.<property>` and
2630
+ `authorizer.<property>` from the route's authorizer. Anything else AWS documents renders as a dash.
2631
+ - `responseLatency` and `integrationLatency` are simulated milliseconds, so a test holding the clock
2632
+ still logs zero rather than however long the process took.
2633
+ - The access log stream is named for the hour it was written in, dated from the simulation's clock.
2634
+ Real API Gateway appends an identifier this simulation has no counterpart for, so a test should
2635
+ filter the log group rather than name the stream.
2480
2636
  - `AWS_PROXY` is the only integration type, and its URI must name a Lambda function ARN, written
2481
2637
  either as that ARN or as the
2482
2638
  `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/<function-arn>/invocations` form.
@@ -173,9 +173,22 @@ resource, and `CreateWebACL` here refuses it too.
173
173
  Matching is case sensitive, as it is on AWS. A rule that means to ignore case says so with a
174
174
  `LOWERCASE` transformation and a lower case search string.
175
175
 
176
- WAF stops reading a body, a header set or a cookie set at 8 KB. The rule's `OversizeHandling` says
177
- what content past that point counts as. `MATCH` and `NO_MATCH` settle the statement without looking,
178
- and `CONTINUE` inspects as much as WAF would have read.
176
+ WAF stops reading a header set or a cookie set at 8 KB. A body runs to 16 KB, the figure
177
+ CloudFront, API Gateway and Cognito all send for inspection, and a web ACL raises it to 32, 48 or 64
178
+ KB with `AssociationConfig`:
179
+
180
+ ```typescript
181
+ AssociationConfig: {
182
+ RequestBody: {
183
+ CLOUDFRONT: { DefaultSizeInspectionLimit: "KB_64" },
184
+ },
185
+ },
186
+ ```
187
+
188
+ The key is the resource type the raised limit applies to, and `CLOUDFRONT`, `API_GATEWAY` and
189
+ `COGNITO_USER_POOL` are the three a web ACL goes in front of here. The rule's `OversizeHandling`
190
+ says what content past the limit counts as. `MATCH` and `NO_MATCH` settle the statement without
191
+ looking, and `CONTINUE` inspects as much as WAF would have read.
179
192
 
180
193
  ## Rate limiting
181
194
 
@@ -1363,8 +1376,9 @@ fields to match. The `Captcha` and `Challenge` actions are refused, along with t
1363
1376
  `ChallengeConfig` and `TokenDomains` that configure them, because a browser has to answer them.
1364
1377
 
1365
1378
  Tags, logging, sampled requests and CloudWatch metrics for a web ACL are not simulated.
1366
- `AssociationConfig`, `DataProtectionConfig`, `OnSourceDDoSProtectionConfig` and `ApplicationConfig`
1367
- are refused for the same reason, each naming what it would have configured.
1379
+ `DataProtectionConfig`, `OnSourceDDoSProtectionConfig` and `ApplicationConfig` are refused for the
1380
+ same reason, each naming what it would have configured. An `AssociationConfig` naming a resource
1381
+ type this simulation has no association for is refused too.
1368
1382
 
1369
1383
  ## Supported operations
1370
1384
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kensio/yulin",
3
- "version": "1.21.10",
3
+ "version": "1.21.12",
4
4
  "description": "AWS system behaviour simulation for isolated unit testing",
5
5
  "repository": "https://github.com/KensioSoftware/yulin",
6
6
  "homepage": "https://yulinsim.dev/",