@kensio/yulin 1.21.5 → 1.21.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/service/cloudformation/resource/cfn/sim-cfn-default-resource-value-adapter.d.ts +8 -1
- package/dist/service/cloudformation/resource/cfn/sim-cfn-default-resource-value-adapter.js +9 -2
- package/dist/service/cloudformation/resource/cfn/sim-cfn-resource-value-adapter.d.ts +6 -1
- package/dist/service/cloudformation/resource/cfn/sim-cfn-resource-value-adapter.js +2 -1
- package/dist/service/cloudformation/resource/create/sim-cfn-resource-create-operation.d.ts +4 -0
- package/dist/service/cloudformation/resource/create/sim-cfn-resource-create-operation.js +6 -0
- package/dist/service/cloudformation/resource/sim-cfn-resource-record.d.ts +19 -0
- package/dist/service/cloudformation/resource/sim-cfn-resource-record.js +26 -0
- package/dist/service/cloudformation/resource/sim-cfn-resource.js +1 -0
- package/dist/service/cloudformation/resource/unsupported/sim-cfn-named-skip.d.ts +26 -0
- package/dist/service/cloudformation/resource/unsupported/sim-cfn-named-skip.js +31 -0
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.js +10 -2
- package/dist/service/cloudfront/cfn/origin-access-control/sim-cfn-cf-oac-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/origin-access-control/sim-cfn-cf-oac-creator.js +10 -2
- package/dist/service/cloudfront/cfn/origin-request-policy/sim-cfn-cf-orp-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/origin-request-policy/sim-cfn-cf-orp-creator.js +10 -2
- package/dist/service/cloudfront/cfn/policy/sim-cfn-cf-policy-creators.d.ts +33 -0
- package/dist/service/cloudfront/cfn/policy/sim-cfn-cf-policy-creators.js +39 -0
- package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-creator.js +10 -2
- package/dist/service/cloudfront/cfn/sim-cfn-cf-authorizer.d.ts +40 -0
- package/dist/service/cloudfront/cfn/sim-cfn-cf-authorizer.js +50 -0
- package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.d.ts +1 -4
- package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.js +14 -46
- package/dist/service/cloudfront/sim-cloudfront-commands.d.ts +6 -0
- package/dist/service/cloudfront/sim-cloudfront-commands.js +7 -0
- package/dist/service/cloudfront/sim-cloudfront.d.ts +6 -0
- package/dist/service/cloudfront/sim-cloudfront.js +7 -0
- package/dist/service/dynamodb/document/sim-dynamodb-document-command-paths.d.ts +8 -0
- package/dist/service/dynamodb/document/sim-dynamodb-document-command-paths.js +62 -0
- package/dist/service/dynamodb/document/sim-dynamodb-document-routes.d.ts +1 -1
- package/dist/service/dynamodb/document/sim-dynamodb-document-routes.js +3 -1
- package/dist/service/iam/authorize/sim-iam-action-authorizer.d.ts +8 -3
- package/dist/service/iam/authorize/sim-iam-action-authorizer.js +13 -4
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-creator.js +1 -0
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.d.ts +1 -0
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.js +21 -14
- package/dist/service/iam/cfn/{sim-cfn-iam-optional-string.d.ts → sim-cfn-iam-property.d.ts} +10 -2
- package/dist/service/iam/cfn/sim-cfn-iam-property.js +31 -0
- package/dist/service/iam/cfn/user/sim-cfn-iam-user-properties-parser.js +1 -1
- package/dist/service/iam/command/role/create-role/create-role-record-factory.js +3 -0
- package/dist/service/iam/command/role/create-role/create-role.command.d.ts +10 -0
- package/dist/service/iam/command/role/get-role/get-role.command.d.ts +2 -0
- package/dist/service/iam/command/role/get-role/get-role.handler.js +2 -0
- package/dist/service/iam/command/role/sim-iam-role-command-handlers.js +15 -1
- package/dist/service/iam/role/sim-iam-role-boundary.d.ts +24 -0
- package/dist/service/iam/role/sim-iam-role-boundary.js +24 -0
- package/dist/service/iam/role/sim-iam-role-with-policy.factory.d.ts +1 -0
- package/dist/service/iam/role/sim-iam-role.d.ts +10 -0
- package/dist/service/iam/serve/sim-iam-query-entity.d.ts +6 -1
- package/dist/service/iam/serve/sim-iam-query-entity.js +10 -4
- package/dist/service/iam/serve/sim-iam-query-role-operations.js +15 -3
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-runtime-skip.d.ts +6 -0
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-runtime-skip.js +9 -2
- package/dist/service/route53/command/create-hosted-zone/sim-route53-zone-id.js +23 -1
- package/docs/services/cloudformation/README.md +88 -23
- package/docs/services/cloudfront/README.md +109 -0
- package/docs/services/dynamodb/README.md +128 -8
- package/docs/services/iam/README.md +125 -2
- package/docs/services/route53/README.md +11 -0
- package/package.json +1 -1
- package/dist/service/iam/cfn/sim-cfn-iam-optional-string.js +0 -17
|
@@ -2443,6 +2443,123 @@ console.log(output.Responses[1]); // {}
|
|
|
2443
2443
|
That is the difference from `BatchGetItem`, which leaves a missing item out of its answer
|
|
2444
2444
|
altogether. Here the answers stay lined up with the Gets that asked for them.
|
|
2445
2445
|
|
|
2446
|
+
### Transactions through the document client
|
|
2447
|
+
|
|
2448
|
+
`TransactWriteCommand` and `TransactGetCommand` from `@aws-sdk/lib-dynamodb` reach the same two
|
|
2449
|
+
operations. Every action's `Item`, `Key` and `ExpressionAttributeValues` are converted on the way in,
|
|
2450
|
+
and the `Item` of each `Responses` entry on the way out.
|
|
2451
|
+
|
|
2452
|
+
```typescript sim-dynamodb-document-transactions
|
|
2453
|
+
/**
|
|
2454
|
+
* Writing an order and the claim on its code together, in plain JavaScript.
|
|
2455
|
+
*/
|
|
2456
|
+
|
|
2457
|
+
import { CreateTableCommand, DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2458
|
+
import {
|
|
2459
|
+
DynamoDBDocumentClient,
|
|
2460
|
+
TransactGetCommand,
|
|
2461
|
+
TransactWriteCommand,
|
|
2462
|
+
} from "@aws-sdk/lib-dynamodb";
|
|
2463
|
+
|
|
2464
|
+
import { SimSdk } from "@kensio/yulin/sdk";
|
|
2465
|
+
|
|
2466
|
+
using simSdk = new SimSdk();
|
|
2467
|
+
|
|
2468
|
+
const documents = DynamoDBDocumentClient.from(
|
|
2469
|
+
new DynamoDBClient({ region: "eu-west-2" }),
|
|
2470
|
+
);
|
|
2471
|
+
simSdk.intercept(documents);
|
|
2472
|
+
|
|
2473
|
+
for (const [tableName, keyName] of [
|
|
2474
|
+
["OrdersTable", "orderId"],
|
|
2475
|
+
["ClaimsTable", "code"],
|
|
2476
|
+
] as const) {
|
|
2477
|
+
await documents.send(
|
|
2478
|
+
new CreateTableCommand({
|
|
2479
|
+
TableName: tableName,
|
|
2480
|
+
KeySchema: [{ AttributeName: keyName, KeyType: "HASH" }],
|
|
2481
|
+
AttributeDefinitions: [{ AttributeName: keyName, AttributeType: "S" }],
|
|
2482
|
+
BillingMode: "PAY_PER_REQUEST",
|
|
2483
|
+
}),
|
|
2484
|
+
);
|
|
2485
|
+
}
|
|
2486
|
+
await simSdk.simAws.backgroundTasksComplete();
|
|
2487
|
+
|
|
2488
|
+
const claim = {
|
|
2489
|
+
TableName: "ClaimsTable",
|
|
2490
|
+
ConditionExpression: "attribute_not_exists(code)",
|
|
2491
|
+
};
|
|
2492
|
+
|
|
2493
|
+
// The order and the claim on its code go in together.
|
|
2494
|
+
await documents.send(
|
|
2495
|
+
new TransactWriteCommand({
|
|
2496
|
+
TransactItems: [
|
|
2497
|
+
{
|
|
2498
|
+
Put: {
|
|
2499
|
+
TableName: "OrdersTable",
|
|
2500
|
+
Item: { orderId: "order-1", total: 42, lines: [{ sku: "widget" }] },
|
|
2501
|
+
},
|
|
2502
|
+
},
|
|
2503
|
+
{ Put: { ...claim, Item: { code: "ABC123", orderId: "order-1" } } },
|
|
2504
|
+
],
|
|
2505
|
+
}),
|
|
2506
|
+
);
|
|
2507
|
+
|
|
2508
|
+
const read = await documents.send(
|
|
2509
|
+
new TransactGetCommand({
|
|
2510
|
+
TransactItems: [
|
|
2511
|
+
{ Get: { TableName: "OrdersTable", Key: { orderId: "order-1" } } },
|
|
2512
|
+
{ Get: { TableName: "ClaimsTable", Key: { code: "ABC123" } } },
|
|
2513
|
+
],
|
|
2514
|
+
}),
|
|
2515
|
+
);
|
|
2516
|
+
|
|
2517
|
+
const lines = read.Responses?.[0]?.Item?.["lines"] as { sku: string }[];
|
|
2518
|
+
console.log(lines[0]?.sku); // widget
|
|
2519
|
+
console.log(read.Responses?.[1]?.Item?.["orderId"]); // order-1
|
|
2520
|
+
|
|
2521
|
+
// A second order wanting the same code loses the claim, and loses the order
|
|
2522
|
+
// with it.
|
|
2523
|
+
try {
|
|
2524
|
+
await documents.send(
|
|
2525
|
+
new TransactWriteCommand({
|
|
2526
|
+
TransactItems: [
|
|
2527
|
+
{
|
|
2528
|
+
Put: {
|
|
2529
|
+
TableName: "OrdersTable",
|
|
2530
|
+
Item: { orderId: "order-2", total: 7 },
|
|
2531
|
+
},
|
|
2532
|
+
},
|
|
2533
|
+
{ Put: { ...claim, Item: { code: "ABC123", orderId: "order-2" } } },
|
|
2534
|
+
],
|
|
2535
|
+
}),
|
|
2536
|
+
);
|
|
2537
|
+
} catch (error) {
|
|
2538
|
+
const cancelled = error as {
|
|
2539
|
+
name: string;
|
|
2540
|
+
CancellationReasons?: { Code: string }[];
|
|
2541
|
+
};
|
|
2542
|
+
|
|
2543
|
+
console.log(cancelled.name); // "TransactionCanceledException"
|
|
2544
|
+
console.log(cancelled.CancellationReasons?.map((reason) => reason.Code));
|
|
2545
|
+
// ["None", "ConditionalCheckFailed"]
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
const second = await documents.send(
|
|
2549
|
+
new TransactGetCommand({
|
|
2550
|
+
TransactItems: [
|
|
2551
|
+
{ Get: { TableName: "OrdersTable", Key: { orderId: "order-2" } } },
|
|
2552
|
+
],
|
|
2553
|
+
}),
|
|
2554
|
+
);
|
|
2555
|
+
|
|
2556
|
+
console.log(second.Responses?.[0]); // {}
|
|
2557
|
+
```
|
|
2558
|
+
|
|
2559
|
+
`CancellationReasons` arrive as the low-level Command reports them. There is one per action, in
|
|
2560
|
+
`TransactItems` order. A reason's `Item` holds AttributeValues, because a cancelled transaction is
|
|
2561
|
+
thrown, and the real document client converts nothing on the way out of a transactional write.
|
|
2562
|
+
|
|
2446
2563
|
## Expiring items with time to live
|
|
2447
2564
|
|
|
2448
2565
|
`UpdateTimeToLive` names the attribute a table expires items by, and `DescribeTimeToLive` reports
|
|
@@ -2930,8 +3047,11 @@ console.log(tags.has("priority")); // true
|
|
|
2930
3047
|
```
|
|
2931
3048
|
|
|
2932
3049
|
`PutCommand`, `GetCommand`, `DeleteCommand`, `UpdateCommand`, `QueryCommand`, `ScanCommand`,
|
|
2933
|
-
`BatchWriteCommand` and `
|
|
2934
|
-
|
|
3050
|
+
`BatchWriteCommand`, `BatchGetCommand`, `TransactWriteCommand` and `TransactGetCommand` are
|
|
3051
|
+
converted. The two transactional ones have
|
|
3052
|
+
[a section of their own](#transactions-through-the-document-client). A document Command with no route
|
|
3053
|
+
here, such as the PartiQL `ExecuteStatementCommand`, is refused by name before anything tries to
|
|
3054
|
+
convert its values.
|
|
2935
3055
|
|
|
2936
3056
|
Intercept the document client itself. `DynamoDBDocumentClient.from(client)` builds a separate object
|
|
2937
3057
|
outside the `DynamoDBClient` class, so intercepting the base client leaves Commands sent through the
|
|
@@ -3621,15 +3741,15 @@ Arn`, `Fn::GetAtt … StreamArn` and `Fn::GetAtt … TableId` answering. A CDK `
|
|
|
3621
3741
|
- SDK interception, and an intercepted `DynamoDBClient` or `DynamoDBStreamsClient` reaches the
|
|
3622
3742
|
simulation.
|
|
3623
3743
|
- The `@aws-sdk/lib-dynamodb` document client, with `PutCommand`, `GetCommand`, `DeleteCommand`,
|
|
3624
|
-
`UpdateCommand`, `QueryCommand`, `ScanCommand`, `BatchWriteCommand
|
|
3625
|
-
converting native JavaScript values on the way in
|
|
3626
|
-
paging through a simulated table.
|
|
3744
|
+
`UpdateCommand`, `QueryCommand`, `ScanCommand`, `BatchWriteCommand`, `BatchGetCommand`,
|
|
3745
|
+
`TransactWriteCommand` and `TransactGetCommand` converting native JavaScript values on the way in
|
|
3746
|
+
and out, and `paginateQuery` and `paginateScan` paging through a simulated table.
|
|
3627
3747
|
|
|
3628
3748
|
## Limitations
|
|
3629
3749
|
|
|
3630
|
-
- The document client's
|
|
3631
|
-
|
|
3632
|
-
|
|
3750
|
+
- The document client's PartiQL Commands go unconverted, because PartiQL is an operation this
|
|
3751
|
+
simulation lacks yet. `ExecuteStatementCommand`, `BatchExecuteStatementCommand` and
|
|
3752
|
+
`ExecuteTransactionCommand` are refused by name, never half converted.
|
|
3633
3753
|
- A document client's translate config goes unread. The marshalling options it was built with do not
|
|
3634
3754
|
apply. See [the SDK docs](https://yulinsim.dev/sdk/#limitations).
|
|
3635
3755
|
- `Expected`, `ConditionalOperator`, `AttributeUpdates`, `KeyConditions`, `QueryFilter` and
|
|
@@ -260,6 +260,11 @@ from the resolved caller and `aws:RequestedRegion` from the Region the request w
|
|
|
260
260
|
service supplies under either name is overwritten by the derived one. Context-key names are matched
|
|
261
261
|
case-insensitively, while string values remain case-sensitive.
|
|
262
262
|
|
|
263
|
+
IAM's own requests carry two service keys. A Role handed to a service carries
|
|
264
|
+
[`iam:PassedToService`](#passing-a-role-to-a-service), and a `CreateRole` request carries the
|
|
265
|
+
boundary it declares as
|
|
266
|
+
[`iam:PermissionsBoundary`](#creating-a-role-under-a-permissions-boundary).
|
|
267
|
+
|
|
263
268
|
Every simulated service supplies its own Region. A policy conditioned on `aws:RequestedRegion`
|
|
264
269
|
therefore sees the Region of the service that handled the request, whichever Region the caller was
|
|
265
270
|
in, and a CloudFormation deployment carries the Region of the Stack it is deploying. IAM, CloudFront
|
|
@@ -1045,6 +1050,115 @@ await simAws.backgroundTasksComplete();
|
|
|
1045
1050
|
A request naming no caller is decided as the Account root, which may pass any Role. A test that never
|
|
1046
1051
|
mentions IAM keeps working.
|
|
1047
1052
|
|
|
1053
|
+
## Creating a Role under a permissions boundary
|
|
1054
|
+
|
|
1055
|
+
An account that requires every Role to carry a permissions boundary allows `iam:CreateRole` only
|
|
1056
|
+
under `StringEquals` on `iam:PermissionsBoundary`. Its CloudFormation execution policy is written
|
|
1057
|
+
that way, and the CDK `PermissionsBoundary.fromName(...)` aspect puts the boundary ARN on every Role
|
|
1058
|
+
the app synthesizes. A `CreateRoleCommand` carrying `PermissionsBoundary` supplies the key, and
|
|
1059
|
+
`AWS::IAM::Role` supplies it from the template property of the same name.
|
|
1060
|
+
|
|
1061
|
+
A request that leaves the property out leaves the key unset. A positive operator over an unset key
|
|
1062
|
+
matches nothing, and the guard refuses the Role. A request naming some other policy is refused the
|
|
1063
|
+
same way. A test can assert both refusals, and that is what makes the policy worth standing up as a
|
|
1064
|
+
deploy Role.
|
|
1065
|
+
|
|
1066
|
+
`CreateRole` and `GetRole` then describe the boundary the Role carries, in the attachment shape IAM
|
|
1067
|
+
answers with (`PermissionsBoundaryType` and `PermissionsBoundaryArn`). `ListRoles` leaves the field
|
|
1068
|
+
out, as IAM does, and points a caller at `GetRole`. The boundary is not yet evaluated as a policy
|
|
1069
|
+
source of its own, and does not narrow what the Role may then do
|
|
1070
|
+
(see [Limitations](#limitations)).
|
|
1071
|
+
|
|
1072
|
+
```typescript sim-iam-permissions-boundary
|
|
1073
|
+
/**
|
|
1074
|
+
* Deploying into an account that requires a permissions boundary.
|
|
1075
|
+
*/
|
|
1076
|
+
|
|
1077
|
+
import { GetRoleCommand } from "@aws-sdk/client-iam";
|
|
1078
|
+
import { SimAws } from "@kensio/yulin";
|
|
1079
|
+
|
|
1080
|
+
const simAws = new SimAws({ defaultAccountId: "123456789012" });
|
|
1081
|
+
const boundaryArn = "arn:aws:iam::123456789012:policy/DeveloperBoundary";
|
|
1082
|
+
|
|
1083
|
+
const deployer = await simAws.iam().makeDeployRole({
|
|
1084
|
+
roleName: "cfn-exec",
|
|
1085
|
+
policyDocument: {
|
|
1086
|
+
Version: "2012-10-17",
|
|
1087
|
+
Statement: [
|
|
1088
|
+
{
|
|
1089
|
+
Effect: "Allow",
|
|
1090
|
+
Action: "iam:CreateRole",
|
|
1091
|
+
Resource: "*",
|
|
1092
|
+
Condition: {
|
|
1093
|
+
StringEquals: { "iam:PermissionsBoundary": boundaryArn },
|
|
1094
|
+
},
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
Effect: "Allow",
|
|
1098
|
+
Action: ["cloudformation:*", "iam:PutRolePolicy", "iam:PassRole"],
|
|
1099
|
+
Resource: "*",
|
|
1100
|
+
},
|
|
1101
|
+
],
|
|
1102
|
+
},
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
const jobRoleTrust = {
|
|
1106
|
+
Version: "2012-10-17",
|
|
1107
|
+
Statement: {
|
|
1108
|
+
Effect: "Allow",
|
|
1109
|
+
Action: "sts:AssumeRole",
|
|
1110
|
+
Principal: { Service: "lambda.amazonaws.com" },
|
|
1111
|
+
},
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
const stack = await simAws.cloudFormation().deployTemplate({
|
|
1115
|
+
stackName: "guarded-stack",
|
|
1116
|
+
template: {
|
|
1117
|
+
Resources: {
|
|
1118
|
+
JobRole: {
|
|
1119
|
+
Type: "AWS::IAM::Role",
|
|
1120
|
+
Properties: {
|
|
1121
|
+
RoleName: "JobRole",
|
|
1122
|
+
PermissionsBoundary: boundaryArn,
|
|
1123
|
+
AssumeRolePolicyDocument: jobRoleTrust,
|
|
1124
|
+
},
|
|
1125
|
+
},
|
|
1126
|
+
},
|
|
1127
|
+
},
|
|
1128
|
+
caller: deployer,
|
|
1129
|
+
});
|
|
1130
|
+
|
|
1131
|
+
// CREATE_COMPLETE
|
|
1132
|
+
console.log(stack.getResource("JobRole")?.status);
|
|
1133
|
+
|
|
1134
|
+
const roleRead = await simAws
|
|
1135
|
+
.iam()
|
|
1136
|
+
.getRole(new GetRoleCommand({ RoleName: "JobRole" }));
|
|
1137
|
+
|
|
1138
|
+
// arn:aws:iam::123456789012:policy/DeveloperBoundary
|
|
1139
|
+
console.log(roleRead.Role.PermissionsBoundary?.PermissionsBoundaryArn);
|
|
1140
|
+
|
|
1141
|
+
try {
|
|
1142
|
+
await simAws.cloudFormation().deployTemplate({
|
|
1143
|
+
stackName: "unguarded-stack",
|
|
1144
|
+
template: {
|
|
1145
|
+
Resources: {
|
|
1146
|
+
BareRole: {
|
|
1147
|
+
Type: "AWS::IAM::Role",
|
|
1148
|
+
Properties: {
|
|
1149
|
+
RoleName: "BareRole",
|
|
1150
|
+
AssumeRolePolicyDocument: jobRoleTrust,
|
|
1151
|
+
},
|
|
1152
|
+
},
|
|
1153
|
+
},
|
|
1154
|
+
},
|
|
1155
|
+
caller: deployer,
|
|
1156
|
+
});
|
|
1157
|
+
} catch (error) {
|
|
1158
|
+
console.error("A Role declaring no boundary was refused", error);
|
|
1159
|
+
}
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1048
1162
|
## A Role for a CloudFormation deployment
|
|
1049
1163
|
|
|
1050
1164
|
`makeDeployRole(...)` creates a Role from a policy document and hands back a caller. Pass it as
|
|
@@ -1241,6 +1355,11 @@ the logical ID when it is omitted, and inline `Policies` declared on a Role are
|
|
|
1241
1355
|
Role's inline policies. The `ReadOnlyAccess` policy above is attached to `LambdaExecutionRole`.
|
|
1242
1356
|
Authorization for that Role reads the policy document the template gave it.
|
|
1243
1357
|
|
|
1358
|
+
A Role's `PermissionsBoundary` reaches the authorization decision the deployment is made under, and
|
|
1359
|
+
is recorded on the Role it names.
|
|
1360
|
+
[Creating a Role under a permissions boundary](#creating-a-role-under-a-permissions-boundary) covers
|
|
1361
|
+
the guard it exists for.
|
|
1362
|
+
|
|
1244
1363
|
### Users
|
|
1245
1364
|
|
|
1246
1365
|
An `AWS::IAM::User` creates a User in the Stack's Account. `UserName` names it and falls back to the
|
|
@@ -1534,6 +1653,8 @@ Sim IAM currently supports:
|
|
|
1534
1653
|
- IAM authorization at simulated service boundaries, such as Route53 actions
|
|
1535
1654
|
- `iam:PassRole` authorization of a Role handed to simulated Lambda, Scheduler, EventBridge, Step
|
|
1536
1655
|
Functions, ECS or Firehose, with `iam:PassedToService` supplied
|
|
1656
|
+
- `iam:CreateRole` authorization against `iam:PermissionsBoundary`, from the `PermissionsBoundary`
|
|
1657
|
+
a request or an `AWS::IAM::Role` declares
|
|
1537
1658
|
- Resolving the caller of an HTTP request, from an `x-sim-aws-caller` header or a verified SigV4
|
|
1538
1659
|
signature, defaulting to anonymous, and the resource it is made on behalf of from
|
|
1539
1660
|
`x-sim-aws-source-arn` and `x-sim-aws-source-account`
|
|
@@ -1551,8 +1672,10 @@ Sim IAM models the policy behaviour that multi-service tests most commonly need.
|
|
|
1551
1672
|
|
|
1552
1673
|
- Groups are absent. An `AWS::IAM::User` naming one fails, and an `AWS::IAM::Policy` naming one
|
|
1553
1674
|
fails too
|
|
1554
|
-
- Permissions boundaries and session policies are not evaluated.
|
|
1555
|
-
|
|
1675
|
+
- Permissions boundaries and session policies are not evaluated. A boundary a `CreateRole` request
|
|
1676
|
+
declares is authorized against `iam:PermissionsBoundary` and described by `GetRole`, and stops
|
|
1677
|
+
there. Service control policies are evaluated, and are attached through
|
|
1678
|
+
[simulated Organizations](https://yulinsim.dev/services/organizations/ "Simulated Organizations service control policies usage docs")
|
|
1556
1679
|
- Managed Policies have a single version, and the policy version commands are absent
|
|
1557
1680
|
- A policy document is measured against IAM's character limit one document at a time. The
|
|
1558
1681
|
20,480-character cap on the sum of a User's inline policies is absent, and so is the cap on how
|
|
@@ -139,6 +139,17 @@ Register the zone yourself when a test depends on its name, such as one listing
|
|
|
139
139
|
when its name is a suffix of no record the stack holds. A registered zone keeps the name it was
|
|
140
140
|
given, and its records are stored under the name you chose.
|
|
141
141
|
|
|
142
|
+
### A lookup that never resolved
|
|
143
|
+
|
|
144
|
+
`HostedZone.fromLookup` needs credentials for the account holding the zone, or a `cdk.context.json`
|
|
145
|
+
holding a previous lookup's answer. With neither, CDK synthesizes the literal `DUMMY` as the Hosted
|
|
146
|
+
Zone ID and writes it into every `AWS::Route53::RecordSet` in the template. Deploying that template
|
|
147
|
+
gives `InvalidInput`, naming `DUMMY` as the stand-in and pointing back at the synth.
|
|
148
|
+
|
|
149
|
+
Run `cdk synth` with credentials for that account, or commit the `cdk.context.json` a resolved
|
|
150
|
+
lookup writes. Either one puts the real Hosted Zone ID in the template, and the zone is then
|
|
151
|
+
registered on demand like any other looked-up zone.
|
|
152
|
+
|
|
142
153
|
## Creating records
|
|
143
154
|
|
|
144
155
|
Use `ChangeResourceRecordSetsCommand` to add records to a Hosted Zone.
|
package/package.json
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Read a string property an IAM Resource may leave out.
|
|
3
|
-
*
|
|
4
|
-
* A Role and a User read most of their own properties this way, and both
|
|
5
|
-
* refuse a non-string the same way, naming the Resource type the template
|
|
6
|
-
* declared.
|
|
7
|
-
*/
|
|
8
|
-
export function simCfnIamOptionalString(properties) {
|
|
9
|
-
const { resourceType, resource, value, label } = properties;
|
|
10
|
-
if (value === undefined) {
|
|
11
|
-
return undefined;
|
|
12
|
-
}
|
|
13
|
-
if (typeof value !== "string") {
|
|
14
|
-
throw new TypeError(`Invalid ${resourceType} ${resource.logicalId}: ${label} must be a string`);
|
|
15
|
-
}
|
|
16
|
-
return value;
|
|
17
|
-
}
|