@kensio/yulin 1.21.4 → 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/cdk/assets/sim-cdk-assets-publisher.d.ts +18 -13
- package/dist/service/cloudformation/cdk/assets/sim-cdk-assets-publisher.js +16 -24
- package/dist/service/cloudformation/cdk/sim-cdk-cloud-assembly.factory.d.ts +12 -0
- package/dist/service/cloudformation/cdk/sim-cdk-cloud-assembly.factory.js +16 -7
- package/dist/service/cloudformation/command/create-stack/create-stack.handler.d.ts +3 -0
- package/dist/service/cloudformation/command/create-stack/create-stack.handler.js +4 -1
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.d.ts +6 -0
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.js +7 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-deployer.js +2 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-options-deployed.d.ts +10 -0
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-options-deployed.js +14 -0
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.d.ts +11 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.js +3 -2
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.d.ts +5 -8
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.js +0 -14
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts +9 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js +2 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts +10 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js +2 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.js +1 -0
- 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/cloudformation/stack/sim-cfn-stack-deploy-context.d.ts +47 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.js +46 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +9 -19
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +12 -26
- package/dist/service/cloudformation/stack/sim-cfn-stack.js +2 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.type.d.ts +14 -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/dist/service/s3/bucket/sim-s3-bucket-maker.d.ts +31 -0
- package/dist/service/s3/bucket/sim-s3-bucket-maker.js +41 -0
- package/dist/service/s3/command/create-bucket/create-bucket.handler.d.ts +2 -2
- package/dist/service/s3/command/create-bucket/create-bucket.handler.js +4 -12
- package/dist/service/s3/sim-s3-commands.d.ts +6 -0
- package/dist/service/s3/sim-s3-commands.js +7 -0
- package/dist/service/s3/sim-s3.d.ts +16 -0
- package/dist/service/s3/sim-s3.js +25 -0
- package/docs/services/cloudformation/README.md +144 -25
- 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 +2 -2
- package/dist/service/iam/cfn/sim-cfn-iam-optional-string.js +0 -17
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kensio/yulin",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.6",
|
|
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/",
|
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
"eslint-plugin-jsdoc": "^63.3.2",
|
|
294
294
|
"eslint-plugin-no-secrets": "^2.3.3",
|
|
295
295
|
"eslint-plugin-security": "^4.0.1",
|
|
296
|
-
"eslint-plugin-unicorn": "^
|
|
296
|
+
"eslint-plugin-unicorn": "^73.0.0",
|
|
297
297
|
"execa": "^10.0.0",
|
|
298
298
|
"fta-cli": "^3.0.0",
|
|
299
299
|
"hyparquet": "^1.29.2",
|
|
@@ -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
|
-
}
|