@kensio/yulin 1.21.7 → 1.21.9
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/README.md +22 -2
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +2 -0
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.js +1 -1
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.d.ts +2 -0
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-input.js +4 -0
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping-refusals.js +0 -5
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.d.ts +2 -0
- package/dist/service/lambda/command/event-source-mapping/create-event-source-mapping.handler.js +2 -0
- package/dist/service/lambda/command/event-source-mapping/sim-lambda-event-source-mapping-commands.d.ts +2 -0
- package/dist/service/lambda/destination/sim-lambda-destination-targets.d.ts +2 -1
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.d.ts +0 -4
- package/dist/service/lambda/event-source/poll/kinesis/sim-lambda-kinesis-shard-poller.js +10 -15
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.d.ts +1 -6
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-event-source-poller.js +9 -27
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.d.ts +19 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-dynamodb-stream-polling.js +27 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.d.ts +1 -1
- package/dist/service/lambda/event-source/poll/sim-lambda-event-source-function.js +3 -1
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.d.ts +13 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-age.js +27 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.d.ts +15 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-info.js +26 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.d.ts +1 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-outcome.js +7 -1
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.d.ts +17 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-batch-processing.js +12 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.d.ts +15 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-cursor.js +28 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.d.ts +19 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-expiry.js +23 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.d.ts +3 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-context.js +19 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.d.ts +15 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-destination.js +38 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.d.ts +41 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-failure-record.js +17 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.d.ts +21 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress-state.js +39 -0
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.d.ts +7 -37
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-progress.js +22 -62
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.d.ts +4 -39
- package/dist/service/lambda/event-source/poll/sim-lambda-stream-retry.js +12 -64
- package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.d.ts +10 -3
- package/dist/service/lambda/event-source/sim-lambda-event-source-mapping.js +12 -3
- package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.d.ts +7 -0
- package/dist/service/lambda/event-source/sim-lambda-stream-destination-config.js +38 -0
- package/dist/service/lambda/event-source/stream/kinesis/sim-kinesis-event-source-streams.js +1 -0
- package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-reader.js +1 -0
- package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.d.ts +1 -0
- package/dist/service/lambda/event-source/stream/sim-dynamodb-event-source-stream-shard.js +7 -0
- package/dist/service/lambda/event-source/stream/sim-lambda-event-source-streams.d.ts +1 -0
- package/dist/service/lambda/index.d.ts +1 -0
- package/dist/service/lambda/sim-lambda-commands.js +1 -0
- package/dist/service/ses/command/authorize/sim-ses-authorizer.d.ts +9 -0
- package/dist/service/ses/command/authorize/sim-ses-authorizer.js +18 -2
- package/dist/service/ses/command/send/sim-ses-send-email.js +2 -1
- package/docs/README.md +7 -0
- package/docs/ai-skill/README.md +6 -1
- package/docs/sdk/README.md +15 -0
- package/docs/services/acm/README.md +24 -40
- package/docs/services/apigateway/README.md +52 -71
- package/docs/services/apigatewayv2/README.md +55 -74
- package/docs/services/athena/README.md +17 -26
- package/docs/services/backup/README.md +29 -39
- package/docs/services/bedrock/README.md +38 -52
- package/docs/services/cloudformation/README.md +43 -55
- package/docs/services/cloudfront/README.md +69 -95
- package/docs/services/cloudwatch/README.md +40 -54
- package/docs/services/cognito/README.md +30 -45
- package/docs/services/dynamodb/README.md +34 -51
- package/docs/services/ecr/README.md +36 -77
- package/docs/services/ecs/README.md +26 -46
- package/docs/services/elbv2/README.md +19 -29
- package/docs/services/eventbridge/README.md +14 -18
- package/docs/services/firehose/README.md +24 -32
- package/docs/services/glue/README.md +41 -78
- package/docs/services/iam/README.md +13 -15
- package/docs/services/kinesis/README.md +53 -93
- package/docs/services/kms/README.md +22 -32
- package/docs/services/lambda/README.md +112 -85
- package/docs/services/logs/README.md +41 -50
- package/docs/services/organizations/README.md +50 -85
- package/docs/services/personalize/README.md +28 -44
- package/docs/services/rekognition/README.md +26 -38
- package/docs/services/route53/README.md +17 -17
- package/docs/services/s3/README.md +47 -51
- package/docs/services/scheduler/README.md +41 -52
- package/docs/services/secretsmanager/README.md +27 -42
- package/docs/services/ses/README.md +24 -34
- package/docs/services/sns/README.md +18 -26
- package/docs/services/sqs/README.md +14 -14
- package/docs/services/ssm/README.md +13 -17
- package/docs/services/stepfunctions/README.md +18 -20
- package/docs/services/sts/README.md +32 -45
- package/docs/services/wafv2/README.md +12 -17
- package/docs/testing/README.md +228 -0
- package/docs/time/README.md +10 -0
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# Simulated SSM Parameter Store
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
5
|
-
simulated IAM.
|
|
3
|
+
Yulin simulates AWS Systems Manager Parameter Store for tests and local development. You can create,
|
|
4
|
+
read, update and delete parameters through the AWS SDK or a CloudFormation template. Parameters are
|
|
5
|
+
stored in memory, each write creates a version, and simulated IAM authorizes every operation.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
SSM-specific types are imported from the `@kensio/yulin/ssm` subpath.
|
|
7
|
+
Other Systems Manager features, such as Run Command and Session Manager, are not simulated. Import
|
|
8
|
+
SSM-specific types from `@kensio/yulin/ssm`.
|
|
10
9
|
|
|
11
10
|
## Writing and reading a parameter
|
|
12
11
|
|
|
@@ -292,8 +291,7 @@ console.log(origins.length); // 2
|
|
|
292
291
|
|
|
293
292
|
## Parameter names
|
|
294
293
|
|
|
295
|
-
|
|
296
|
-
deployment failure a passing test would have hidden. A name:
|
|
294
|
+
Parameter names use the same validation rules as AWS. A name:
|
|
297
295
|
|
|
298
296
|
- may contain letters, digits, `_`, `.`, `-` and `/`
|
|
299
297
|
- must start with `/` if it contains a hierarchy at all
|
|
@@ -302,8 +300,8 @@ deployment failure a passing test would have hidden. A name:
|
|
|
302
300
|
- may not contain spaces between characters, though surrounding spaces are stripped
|
|
303
301
|
- may not make an ARN longer than 1011 characters, counting the ARN prefix for the account and region
|
|
304
302
|
|
|
305
|
-
A `String` or `StringList` value holds at most
|
|
306
|
-
|
|
303
|
+
A `String` or `StringList` value holds at most 4 KB, the standard tier limit. Larger configuration
|
|
304
|
+
documents must be split across parameters or stored elsewhere.
|
|
307
305
|
|
|
308
306
|
## Deploying a parameter from CloudFormation
|
|
309
307
|
|
|
@@ -455,9 +453,9 @@ covers that one.
|
|
|
455
453
|
|
|
456
454
|
### A reference the simulation cannot answer
|
|
457
455
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
456
|
+
When a reference names a parameter that does not exist, simulated CloudFormation substitutes
|
|
457
|
+
`dummy-value-for-<name>` and continues the deployment. This lets a test deploy the rest of a
|
|
458
|
+
template without setting up unrelated configuration.
|
|
461
459
|
|
|
462
460
|
The substitution is recorded on
|
|
463
461
|
[`stack.ignoredProperties`](https://yulinsim.dev/services/cloudformation/#properties-a-resource-was-created-without),
|
|
@@ -998,9 +996,9 @@ console.log(read.Parameter?.Value); // "hunter2"
|
|
|
998
996
|
|
|
999
997
|
`DescribeParameters` reports the key each `SecureString` is encrypted under as `KeyId`.
|
|
1000
998
|
|
|
1001
|
-
##
|
|
999
|
+
## Supported operations
|
|
1002
1000
|
|
|
1003
|
-
|
|
1001
|
+
Simulated Parameter Store supports:
|
|
1004
1002
|
|
|
1005
1003
|
- `PutParameterCommand`, creating a parameter or overwriting one
|
|
1006
1004
|
- `GetParameterCommand`, by name, by `name:version` or by `name:label`
|
|
@@ -1026,8 +1024,6 @@ Sim SSM currently supports:
|
|
|
1026
1024
|
|
|
1027
1025
|
## Limitations
|
|
1028
1026
|
|
|
1029
|
-
Current documented limitations:
|
|
1030
|
-
|
|
1031
1027
|
- Only standard tier `SecureString` encryption is simulated, which encrypts under the KMS key
|
|
1032
1028
|
directly. The advanced tier's envelope encryption through the AWS Encryption SDK is left out, and
|
|
1033
1029
|
`kms:GenerateDataKey` is never needed.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# Simulated Step Functions
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Yulin interprets Amazon States Language and runs Step Functions state machines in the same process
|
|
4
|
+
as the code under test. Tests can start executions, invoke simulated services, advance waits and
|
|
5
|
+
inspect execution history without deploying a workflow.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Import Step Functions-specific types from `@kensio/yulin/stepfunctions`.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Supported state machine features
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
All eight state types are supported: `Pass`, `Task`, `Succeed`, `Fail`, `Choice`, `Wait`, `Parallel`
|
|
12
|
+
and `Map`.
|
|
13
13
|
|
|
14
|
-
The data-flow fields
|
|
15
|
-
|
|
14
|
+
The data-flow fields `InputPath`, `Parameters`, `ResultSelector`, `ResultPath` and `OutputPath` run in
|
|
15
|
+
that order. They support Reference Paths and intrinsic functions.
|
|
16
16
|
|
|
17
17
|
A `Task` state invokes a simulated Lambda function, calls an operation on any other simulated
|
|
18
18
|
service, or starts another state machine. A `Resource` this simulator has no answer for is refused
|
|
@@ -114,23 +114,21 @@ console.log(described.status); // FAILED
|
|
|
114
114
|
console.log(described.error); // NotEligible
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
A
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
elsewhere in the same test.
|
|
117
|
+
A failed execution records its status and error instead of throwing from `StartExecution`. Read it
|
|
118
|
+
with `DescribeExecution` or the inspection API. This keeps workflow failure available for
|
|
119
|
+
assertions.
|
|
121
120
|
|
|
122
121
|
## Invoking a Lambda function
|
|
123
122
|
|
|
124
123
|
A `Task` state invokes a simulated Lambda function, through either of the two `Resource` forms CDK's
|
|
125
124
|
`LambdaInvoke` emits.
|
|
126
125
|
|
|
127
|
-
`arn:aws:states:::lambda:invoke`
|
|
128
|
-
the
|
|
129
|
-
`Payload`
|
|
130
|
-
under `Payload`.
|
|
126
|
+
With `arn:aws:states:::lambda:invoke`, `Parameters` has the shape of a Lambda `Invoke` request.
|
|
127
|
+
`FunctionName` selects the function, `Payload` contains its input, and the handler result appears
|
|
128
|
+
under `Payload` in the task output.
|
|
131
129
|
|
|
132
|
-
A function ARN sends the state
|
|
133
|
-
|
|
130
|
+
A function ARN sends the state input directly to the handler and uses the handler result as the task
|
|
131
|
+
output. CDK emits this form when `payloadResponseOnly` is enabled.
|
|
134
132
|
|
|
135
133
|
```typescript sim-step-functions-task
|
|
136
134
|
/**
|
|
@@ -1334,7 +1332,7 @@ reference contradicts itself here, listing a differing role ARN under `StateMach
|
|
|
1334
1332
|
while the operation's own note says the difference is ignored. The note is the more specific of the
|
|
1335
1333
|
two and is what this follows.
|
|
1336
1334
|
|
|
1337
|
-
##
|
|
1335
|
+
## Limitations
|
|
1338
1336
|
|
|
1339
1337
|
- Distributed Map, with `ItemReader`, `ResultWriter` and the `ToleratedFailure` fields.
|
|
1340
1338
|
- The `.sync` pattern, task tokens and activities.
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
# Simulated STS
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
5
|
-
Sim STS is used through `SimAws` as `simAws.sts()`, scoped to the Account making the assume request.
|
|
6
|
-
It simulates assuming IAM Roles. An assume request is evaluated against
|
|
7
|
-
[simulated IAM](https://yulinsim.dev/services/iam/) policies, and a request that passes issues temporary session credentials
|
|
8
|
-
that the rest of the simulated environment authenticates like real AWS credentials.
|
|
3
|
+
Yulin simulates `AssumeRole` and `GetCallerIdentity`. Access the service through `simAws.sts()` or an
|
|
4
|
+
intercepted `STSClient`.
|
|
9
5
|
|
|
10
6
|
## Basic usage
|
|
11
7
|
|
|
12
|
-
Create a
|
|
13
|
-
|
|
8
|
+
Create a role with a trust policy, then call `assumeRole`. A request with no caller runs as the
|
|
9
|
+
account root.
|
|
14
10
|
|
|
15
11
|
```typescript sim-sts-assume-role
|
|
16
12
|
/**
|
|
@@ -50,23 +46,28 @@ console.log(assumeRoleOutput.Credentials?.AccessKeyId);
|
|
|
50
46
|
console.log(assumeRoleOutput.Credentials?.Expiration);
|
|
51
47
|
```
|
|
52
48
|
|
|
53
|
-
|
|
49
|
+
`AssumedRoleUser.Arn` is the session ARN, such as
|
|
54
50
|
`arn:aws:sts::123456789012:assumed-role/TargetRole/test-session`, and `Credentials` carries the
|
|
55
51
|
temporary `AccessKeyId`, `SecretAccessKey`, `SessionToken`, and `Expiration`.
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
Yulin registers the credentials with simulated IAM in the target account. Later requests use the
|
|
54
|
+
role's identity policies. See [STS sessions in simulated IAM](https://yulinsim.dev/services/iam/#sts-assumerole-sessions).
|
|
55
|
+
Credentials fail after `Expiration` or when the session token is missing.
|
|
56
|
+
|
|
57
|
+
`DurationSeconds` defaults to 3,600 seconds and must be a positive integer.
|
|
58
|
+
|
|
59
|
+
## Reading the current identity
|
|
62
60
|
|
|
63
|
-
`
|
|
64
|
-
|
|
61
|
+
`getCallerIdentity` reports the caller's ARN, account ID and user ID. It handles account roots, IAM
|
|
62
|
+
users and assumed-role sessions. The intercepted and served STS APIs also support
|
|
63
|
+
`GetCallerIdentityCommand`.
|
|
64
|
+
|
|
65
|
+
An unattributed request reports the configured default caller, or the account root when no default
|
|
66
|
+
caller is configured. An anonymous caller receives `AccessDenied`.
|
|
65
67
|
|
|
66
68
|
## Role-to-Role assumption
|
|
67
69
|
|
|
68
|
-
Pass
|
|
69
|
-
are then evaluated:
|
|
70
|
+
Pass `caller` to assume a role as a specific principal. STS checks both sides of the request:
|
|
70
71
|
|
|
71
72
|
- The target Role's trust policy must allow the caller to perform `sts:AssumeRole`
|
|
72
73
|
- A non-root caller also needs an identity policy allowing `sts:AssumeRole` on the target Role's
|
|
@@ -144,33 +145,25 @@ const assumeRoleOutput = await account.sts().assumeRole(
|
|
|
144
145
|
console.log(assumeRoleOutput.AssumedRoleUser?.Arn);
|
|
145
146
|
```
|
|
146
147
|
|
|
147
|
-
STS
|
|
148
|
-
|
|
149
|
-
or an explicit `Deny` matches. The error has a `403` status code and names the `sts:AssumeRole`
|
|
150
|
-
action and the target Role ARN. No session is created.
|
|
148
|
+
If either check fails, STS raises a 403 access-denied error naming `sts:AssumeRole` and the target
|
|
149
|
+
role ARN. No session is created.
|
|
151
150
|
|
|
152
|
-
Cross-
|
|
153
|
-
|
|
154
|
-
`sts()`. The issued session belongs to the target Role's Account.
|
|
151
|
+
Cross-account assumption uses the same checks. Call `assumeRole` through the source account. The
|
|
152
|
+
session belongs to the target role's account.
|
|
155
153
|
|
|
156
154
|
## Role chaining
|
|
157
155
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
sides of the decision are written against. The trust policy of the target names that Role, and the
|
|
161
|
-
identity policy allowing `sts:AssumeRole` belongs to it.
|
|
156
|
+
For role chaining, use the first session as the caller of the second `assumeRole` request. The target
|
|
157
|
+
trust policy names the first role, and that role needs identity permission to assume the target.
|
|
162
158
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
decided at run time rather than written into a policy.
|
|
159
|
+
A trust policy may name the role ARN or one assumed-role session ARN. Prefer the role ARN when the
|
|
160
|
+
session name is chosen at run time.
|
|
166
161
|
|
|
167
|
-
|
|
168
|
-
second, and the caller they resolve to carries the Role along with the session.
|
|
162
|
+
The served endpoint resolves session credentials in the same way.
|
|
169
163
|
|
|
170
164
|
## ExternalId
|
|
171
165
|
|
|
172
|
-
A trust policy can require
|
|
173
|
-
`ExternalId` supplied to `AssumeRoleCommand` is matched against it.
|
|
166
|
+
A trust policy can require `sts:ExternalId`. Pass the matching `ExternalId` to `AssumeRoleCommand`.
|
|
174
167
|
|
|
175
168
|
```typescript sim-sts-external-id
|
|
176
169
|
/**
|
|
@@ -214,14 +207,14 @@ const assumeRoleOutput = await account.sts().assumeRole(
|
|
|
214
207
|
console.log(assumeRoleOutput.AssumedRoleUser?.Arn);
|
|
215
208
|
```
|
|
216
209
|
|
|
217
|
-
An omitted or mismatched
|
|
218
|
-
request is denied.
|
|
210
|
+
An omitted or mismatched value denies the request.
|
|
219
211
|
|
|
220
212
|
## Available functionality
|
|
221
213
|
|
|
222
214
|
Sim STS currently supports:
|
|
223
215
|
|
|
224
216
|
- `AssumeRoleCommand`
|
|
217
|
+
- `GetCallerIdentityCommand`
|
|
225
218
|
- Trust-policy evaluation against the target Role's assume-role policy document
|
|
226
219
|
- Identity-policy evaluation of the source caller, requiring `sts:AssumeRole` permission on the
|
|
227
220
|
target Role
|
|
@@ -231,15 +224,9 @@ Sim STS currently supports:
|
|
|
231
224
|
- Temporary credentials registered with the target Account's sim IAM, including session-token and
|
|
232
225
|
expiry validation
|
|
233
226
|
|
|
234
|
-
Unsupported STS options may be ignored or may throw errors depending on whether the simulator needs
|
|
235
|
-
them to model the requested behaviour.
|
|
236
|
-
|
|
237
227
|
## Limitations
|
|
238
228
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
- `AssumeRoleCommand` is the only supported command. There is no `GetCallerIdentity`, federation, or
|
|
242
|
-
web-identity support
|
|
229
|
+
- Federation, web identity and session-token commands are unsupported.
|
|
243
230
|
- Session policies (`Policy` / `PolicyArns`), tags, and `SourceIdentity` requests are not evaluated
|
|
244
231
|
- Condition support in trust policies is limited to the operators supported by
|
|
245
232
|
[sim IAM](https://yulinsim.dev/services/iam/#policy-conditions)
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
# Simulated WAFv2
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Yulin simulates AWS WAFv2 web ACLs, IP sets and regex pattern sets for tests and local development.
|
|
4
|
+
You can evaluate a `Request` directly or associate a web ACL with a simulated API Gateway REST API,
|
|
5
|
+
Cognito user pool or CloudFront distribution. Each request is checked against the web ACL before
|
|
6
|
+
the protected service handles it.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
and a simulated Cognito user pool each take one through `AssociateWebACL`, and a simulated
|
|
10
|
-
CloudFront distribution takes one through its own `WebACLId`. The requests that stage, pool or
|
|
11
|
-
distribution serves are then put through the web ACL's rules.
|
|
12
|
-
|
|
13
|
-
WAFv2 specific types are imported from the `@kensio/yulin/wafv2` subpath.
|
|
8
|
+
Import WAFv2-specific types from `@kensio/yulin/wafv2`.
|
|
14
9
|
|
|
15
10
|
## Deciding what happens to a request
|
|
16
11
|
|
|
@@ -91,11 +86,11 @@ carrying the status, the body and any headers the rule named.
|
|
|
91
86
|
|
|
92
87
|
## Rules run in priority order
|
|
93
88
|
|
|
94
|
-
Rules are evaluated
|
|
95
|
-
rule
|
|
89
|
+
Rules are evaluated by ascending `Priority`, regardless of their order in the input list. The first
|
|
90
|
+
matching rule with an `Allow` or `Block` action decides the request.
|
|
96
91
|
|
|
97
|
-
A `Count` action records the match and
|
|
98
|
-
before
|
|
92
|
+
A `Count` action records the match and continues to the next rule. Tests can inspect
|
|
93
|
+
`countedRuleNames` before changing a rule to `Allow` or `Block`.
|
|
99
94
|
|
|
100
95
|
```typescript sim-wafv2-count
|
|
101
96
|
/**
|
|
@@ -154,8 +149,8 @@ whatever serves the request has usually read it by the time WAF gets a look.
|
|
|
154
149
|
|
|
155
150
|
## What a statement can inspect
|
|
156
151
|
|
|
157
|
-
A statement
|
|
158
|
-
|
|
152
|
+
A statement selects part of the request, applies its text transformations, and then tests the
|
|
153
|
+
result.
|
|
159
154
|
|
|
160
155
|
The parts a statement can be pointed at are `UriPath`, `QueryString`, `SingleQueryArgument`,
|
|
161
156
|
`AllQueryArguments`, `SingleHeader`, `Headers`, `Cookies`, `Method` and `Body`. `Headers` and
|
|
@@ -1371,7 +1366,7 @@ Tags, logging, sampled requests and CloudWatch metrics for a web ACL are not sim
|
|
|
1371
1366
|
`AssociationConfig`, `DataProtectionConfig`, `OnSourceDDoSProtectionConfig` and `ApplicationConfig`
|
|
1372
1367
|
are refused for the same reason, each naming what it would have configured.
|
|
1373
1368
|
|
|
1374
|
-
##
|
|
1369
|
+
## Supported operations
|
|
1375
1370
|
|
|
1376
1371
|
`CreateWebACL`, `GetWebACL`, `UpdateWebACL`, `ListWebACLs`, `DeleteWebACL`, `CreateIPSet`,
|
|
1377
1372
|
`GetIPSet`, `UpdateIPSet`, `ListIPSets`, `DeleteIPSet`, `CreateRegexPatternSet`,
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Test suite setup
|
|
2
|
+
|
|
3
|
+
Run one Yulin environment for an application's test suite. Create the simulation, deploy the
|
|
4
|
+
application's infrastructure, and install AWS SDK interception once. Every test then interacts with
|
|
5
|
+
the same simulated account and resources.
|
|
6
|
+
|
|
7
|
+
This is the recommended setup. It matches the way a suite uses a shared AWS account or a
|
|
8
|
+
container-based simulator such as LocalStack. Creating a new Yulin environment for every test or
|
|
9
|
+
test file is supported, but it should be reserved for cases that need a blank simulated account.
|
|
10
|
+
|
|
11
|
+
The simulated clock is the main exception. A suite-wide `SimAws` has one clock, so a test that moves
|
|
12
|
+
it changes time for every resource in that environment. Keep the majority of tests in the shared
|
|
13
|
+
environment without changing its clock. Put clock-controlling tests in a smaller isolated group.
|
|
14
|
+
|
|
15
|
+
## Split the Vitest suite
|
|
16
|
+
|
|
17
|
+
Yulin holds state in the process that created it. Vitest must run the Yulin tests in one worker for
|
|
18
|
+
all shared files to reach the same environment. Give that project disabled file parallelism and file
|
|
19
|
+
isolation, then load a setup module before each test file.
|
|
20
|
+
|
|
21
|
+
The second project below matches files ending in `.clock.test.ts`. Those tests do not load the shared
|
|
22
|
+
setup and can create isolated Yulin environments:
|
|
23
|
+
|
|
24
|
+
```typescript testing-vitest-config
|
|
25
|
+
import { defineConfig } from "vitest/config";
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
test: {
|
|
29
|
+
environment: "node",
|
|
30
|
+
projects: [
|
|
31
|
+
{
|
|
32
|
+
extends: true,
|
|
33
|
+
test: {
|
|
34
|
+
name: "shared Yulin",
|
|
35
|
+
include: ["test/**/*.test.ts"],
|
|
36
|
+
exclude: ["test/**/*.clock.test.ts"],
|
|
37
|
+
fileParallelism: false,
|
|
38
|
+
isolate: false,
|
|
39
|
+
setupFiles: ["./test/setup-yulin.ts"],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
extends: true,
|
|
44
|
+
test: {
|
|
45
|
+
name: "isolated Yulin clock",
|
|
46
|
+
include: ["test/**/*.clock.test.ts"],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Vitest executes a `setupFiles` entry before every test file. With isolation disabled, modules
|
|
55
|
+
imported by that entry stay cached in the worker. Put the Yulin initialization in an imported module
|
|
56
|
+
to make it run once.
|
|
57
|
+
|
|
58
|
+
See Vitest's documentation for [`setupFiles`](https://vitest.dev/config/setupfiles),
|
|
59
|
+
[`fileParallelism`](https://vitest.dev/config/fileparallelism), and
|
|
60
|
+
[`isolate`](https://vitest.dev/config/isolate).
|
|
61
|
+
|
|
62
|
+
## Create and deploy the shared environment
|
|
63
|
+
|
|
64
|
+
Put the suite environment in a module such as `test/yulin-environment.ts`. Intercept client classes
|
|
65
|
+
used by the application and deploy its synthesized CDK cloud assembly:
|
|
66
|
+
|
|
67
|
+
```typescript testing-shared-yulin-environment
|
|
68
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
69
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
70
|
+
import type { SimAws } from "@kensio/yulin";
|
|
71
|
+
import { SimSdk } from "@kensio/yulin/sdk";
|
|
72
|
+
|
|
73
|
+
interface YulinTestEnvironment {
|
|
74
|
+
readonly simAws: SimAws;
|
|
75
|
+
readonly simSdk: SimSdk;
|
|
76
|
+
readonly uploadsBucketName: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type YulinTestGlobal = typeof globalThis & {
|
|
80
|
+
yulinEnvironment?: Promise<YulinTestEnvironment>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const testGlobal = globalThis as YulinTestGlobal;
|
|
84
|
+
|
|
85
|
+
// oxlint-disable-next-line unicorn-js/prefer-top-level-await -- The shared promise prevents setup from running again before another test file.
|
|
86
|
+
export const yulin = await (testGlobal.yulinEnvironment ??= startYulin());
|
|
87
|
+
|
|
88
|
+
async function startYulin(): Promise<YulinTestEnvironment> {
|
|
89
|
+
const simSdk = new SimSdk();
|
|
90
|
+
simSdk.intercept(DynamoDBClient);
|
|
91
|
+
simSdk.intercept(S3Client);
|
|
92
|
+
|
|
93
|
+
const stacks = await simSdk.simAws.cloudFormation().deployCdkOut({
|
|
94
|
+
directoryPath: "cdk.out",
|
|
95
|
+
stackNames: ["ApplicationStack"],
|
|
96
|
+
});
|
|
97
|
+
const appStack = stacks.get("ApplicationStack");
|
|
98
|
+
|
|
99
|
+
if (appStack === undefined) {
|
|
100
|
+
throw new Error("ApplicationStack was not deployed");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
process.once("exit", () => {
|
|
104
|
+
simSdk.restoreAll();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
simAws: simSdk.simAws,
|
|
109
|
+
simSdk,
|
|
110
|
+
uploadsBucketName: appStack.output("UploadsBucketName"),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Use the same templates that the application deploys. `deployCdkOut(...)` can deploy the whole cloud
|
|
116
|
+
assembly or the named application Stacks. Read generated resource names from stack outputs or
|
|
117
|
+
resource accessors after deployment.
|
|
118
|
+
|
|
119
|
+
The configured setup entry only needs to import that module:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// test/setup-yulin.ts
|
|
123
|
+
import "./yulin-environment.js";
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Do not put the initialization directly in `setup-yulin.ts`. Vitest executes that file for every test
|
|
127
|
+
file, even when isolation is disabled.
|
|
128
|
+
|
|
129
|
+
## Use the environment from every test
|
|
130
|
+
|
|
131
|
+
Application code continues to construct and send through ordinary AWS SDK clients. Class-level
|
|
132
|
+
interception routes all of them to the suite's Yulin environment.
|
|
133
|
+
|
|
134
|
+
A test that needs direct access can import the shared environment:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { randomUUID } from "node:crypto";
|
|
138
|
+
|
|
139
|
+
import {
|
|
140
|
+
GetObjectCommand,
|
|
141
|
+
PutObjectCommand,
|
|
142
|
+
S3Client,
|
|
143
|
+
} from "@aws-sdk/client-s3";
|
|
144
|
+
import { expect, it } from "vitest";
|
|
145
|
+
|
|
146
|
+
import { yulin } from "../yulin-environment.js";
|
|
147
|
+
|
|
148
|
+
it("stores an upload", async () => {
|
|
149
|
+
const key = `test-uploads/${randomUUID()}.txt`;
|
|
150
|
+
const s3 = new S3Client({ region: "eu-west-2" });
|
|
151
|
+
|
|
152
|
+
await s3.send(
|
|
153
|
+
new PutObjectCommand({
|
|
154
|
+
Bucket: yulin.uploadsBucketName,
|
|
155
|
+
Key: key,
|
|
156
|
+
Body: "an upload",
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const stored = await yulin.simAws
|
|
161
|
+
.region("eu-west-2")
|
|
162
|
+
.s3()
|
|
163
|
+
.getObject(
|
|
164
|
+
new GetObjectCommand({
|
|
165
|
+
Bucket: yulin.uploadsBucketName,
|
|
166
|
+
Key: key,
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
expect(await stored?.Body?.transformToString()).toBe("an upload");
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The `SimAws` object is mainly useful for preparing input state and reading state back in assertions.
|
|
175
|
+
Exercise the application through its normal interfaces whenever possible.
|
|
176
|
+
|
|
177
|
+
## Keep tests independent in shared state
|
|
178
|
+
|
|
179
|
+
Shared infrastructure does not require tests to depend on one another. Give each test's records,
|
|
180
|
+
object keys, user names, and other mutable data unique values. Read CloudFormation-generated names
|
|
181
|
+
from the deployed stack. Avoid assertions that assume the simulated account contains no other data.
|
|
182
|
+
|
|
183
|
+
Keep `beforeEach` for the records a test needs. A per-file `beforeAll` can prepare data used by every
|
|
184
|
+
test in that file. Leave the suite's stacks and SDK interception in place until the worker exits.
|
|
185
|
+
|
|
186
|
+
Tests run sequentially with `fileParallelism: false`. If a test uses `it.concurrent`, its data still
|
|
187
|
+
needs unique identifiers because those cases share the same environment at the same time.
|
|
188
|
+
|
|
189
|
+
## Give clock-controlling tests their own environment
|
|
190
|
+
|
|
191
|
+
Every service in a `SimAws` reads the same simulated clock. Calling `advanceBy(...)` can expire
|
|
192
|
+
credentials, delete resources whose retention period has passed, and run scheduled work anywhere in
|
|
193
|
+
the environment. Resetting the clock afterwards cannot reverse those changes.
|
|
194
|
+
|
|
195
|
+
Tests in the shared project should treat the clock as read-only. Put a test that calls `freeze()`,
|
|
196
|
+
`setTo(...)`, `advanceBy(...)`, or `resume()` in a `.clock.test.ts` file and create a fresh environment
|
|
197
|
+
inside the test:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { SimAws, SimFixedClock } from "@kensio/yulin";
|
|
201
|
+
import { it } from "vitest";
|
|
202
|
+
|
|
203
|
+
it("expires a session", async () => {
|
|
204
|
+
const simAws = new SimAws({
|
|
205
|
+
clock: new SimFixedClock(new Date("2026-09-04T09:00:00.000Z")),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Deploy only the infrastructure this clock-controlling test needs.
|
|
209
|
+
|
|
210
|
+
await simAws.clock().advanceBy({ minutes: 20 });
|
|
211
|
+
|
|
212
|
+
// Assert the behaviour after the time change.
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Create a `SimSdk` around that `SimAws` when application code uses SDK clients. Restore its
|
|
217
|
+
interceptions at the end of the test. The [simulated time guide](https://yulinsim.dev/time/) describes
|
|
218
|
+
what moving the clock runs and changes.
|
|
219
|
+
|
|
220
|
+
## When to create another environment
|
|
221
|
+
|
|
222
|
+
A fresh `SimAws` or `SimSdk` is useful when the empty environment is part of the behaviour under
|
|
223
|
+
test, or when the test needs to control simulated time. Yulin's own service unit tests are another
|
|
224
|
+
example because they test resource creation and account isolation directly.
|
|
225
|
+
|
|
226
|
+
Vitest workers cannot share an in-memory `SimAws`. A suite that keeps file parallelism creates one
|
|
227
|
+
environment per worker. Put Yulin-based application tests in a Vitest project with
|
|
228
|
+
`fileParallelism: false` when the rest of the unit suite should remain parallel.
|
package/docs/time/README.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
Each `SimAws` has its own clock. Yulin uses that clock for resource timestamps, expiry checks, and
|
|
4
4
|
scheduled work.
|
|
5
5
|
|
|
6
|
+
## Isolate tests that control time
|
|
7
|
+
|
|
8
|
+
A shared [test suite environment](https://yulinsim.dev/testing/) also has one shared clock. Most
|
|
9
|
+
tests should use that environment without calling `freeze()`, `setTo(...)`, `advanceBy(...)`, or
|
|
10
|
+
`resume()`.
|
|
11
|
+
|
|
12
|
+
Put tests that control simulated time in a separate test group. Give each of those tests its own
|
|
13
|
+
`SimAws` or `SimSdk`, along with the infrastructure it needs. A clock change then affects only that
|
|
14
|
+
test's environment. The rest of the suite can keep sharing one deployment and SDK interception.
|
|
15
|
+
|
|
6
16
|
## Start at a known time
|
|
7
17
|
|
|
8
18
|
A new simulation follows the system clock by default. Pass a `SimFixedClock` when a test needs an
|
package/llms.txt
CHANGED
|
@@ -57,4 +57,5 @@ The same pages are on the web at https://yulinsim.dev/ for whichever release is
|
|
|
57
57
|
- [Non-AWS dependencies](docs/non-aws-dependencies/README.md): Dependencies Yulin does not simulate usage docs
|
|
58
58
|
- [Serving on localhost](docs/serve/README.md): Serving simulated AWS on localhost usage docs
|
|
59
59
|
- [Simulated time](docs/time/README.md): Simulated time usage docs
|
|
60
|
+
- [Test suite setup](docs/testing/README.md): Sharing one Yulin environment across a test suite
|
|
60
61
|
- [Terraform](docs/terraform/README.md): Deploying Terraform into simulated AWS usage docs
|
package/package.json
CHANGED