@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.
Files changed (97) hide show
  1. package/dist/service/cloudformation/cdk/assets/sim-cdk-assets-publisher.d.ts +18 -13
  2. package/dist/service/cloudformation/cdk/assets/sim-cdk-assets-publisher.js +16 -24
  3. package/dist/service/cloudformation/cdk/sim-cdk-cloud-assembly.factory.d.ts +12 -0
  4. package/dist/service/cloudformation/cdk/sim-cdk-cloud-assembly.factory.js +16 -7
  5. package/dist/service/cloudformation/command/create-stack/create-stack.handler.d.ts +3 -0
  6. package/dist/service/cloudformation/command/create-stack/create-stack.handler.js +4 -1
  7. package/dist/service/cloudformation/command/update-stack/update-stack.handler.d.ts +6 -0
  8. package/dist/service/cloudformation/command/update-stack/update-stack.handler.js +7 -1
  9. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-deployer.js +2 -1
  10. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-options-deployed.d.ts +10 -0
  11. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-options-deployed.js +14 -0
  12. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.d.ts +11 -1
  13. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.js +3 -2
  14. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.d.ts +5 -8
  15. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.js +0 -14
  16. package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts +9 -0
  17. package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js +2 -0
  18. package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts +10 -0
  19. package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js +2 -1
  20. package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.js +1 -0
  21. package/dist/service/cloudformation/resource/cfn/sim-cfn-default-resource-value-adapter.d.ts +8 -1
  22. package/dist/service/cloudformation/resource/cfn/sim-cfn-default-resource-value-adapter.js +9 -2
  23. package/dist/service/cloudformation/resource/cfn/sim-cfn-resource-value-adapter.d.ts +6 -1
  24. package/dist/service/cloudformation/resource/cfn/sim-cfn-resource-value-adapter.js +2 -1
  25. package/dist/service/cloudformation/resource/create/sim-cfn-resource-create-operation.d.ts +4 -0
  26. package/dist/service/cloudformation/resource/create/sim-cfn-resource-create-operation.js +6 -0
  27. package/dist/service/cloudformation/resource/sim-cfn-resource-record.d.ts +19 -0
  28. package/dist/service/cloudformation/resource/sim-cfn-resource-record.js +26 -0
  29. package/dist/service/cloudformation/resource/sim-cfn-resource.js +1 -0
  30. package/dist/service/cloudformation/resource/unsupported/sim-cfn-named-skip.d.ts +26 -0
  31. package/dist/service/cloudformation/resource/unsupported/sim-cfn-named-skip.js +31 -0
  32. package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.d.ts +47 -0
  33. package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.js +46 -0
  34. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +9 -19
  35. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +12 -26
  36. package/dist/service/cloudformation/stack/sim-cfn-stack.js +2 -1
  37. package/dist/service/cloudformation/stack/sim-cfn-stack.type.d.ts +14 -0
  38. package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.d.ts +5 -2
  39. package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.js +10 -2
  40. package/dist/service/cloudfront/cfn/origin-access-control/sim-cfn-cf-oac-creator.d.ts +5 -2
  41. package/dist/service/cloudfront/cfn/origin-access-control/sim-cfn-cf-oac-creator.js +10 -2
  42. package/dist/service/cloudfront/cfn/origin-request-policy/sim-cfn-cf-orp-creator.d.ts +5 -2
  43. package/dist/service/cloudfront/cfn/origin-request-policy/sim-cfn-cf-orp-creator.js +10 -2
  44. package/dist/service/cloudfront/cfn/policy/sim-cfn-cf-policy-creators.d.ts +33 -0
  45. package/dist/service/cloudfront/cfn/policy/sim-cfn-cf-policy-creators.js +39 -0
  46. package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-creator.d.ts +5 -2
  47. package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-creator.js +10 -2
  48. package/dist/service/cloudfront/cfn/sim-cfn-cf-authorizer.d.ts +40 -0
  49. package/dist/service/cloudfront/cfn/sim-cfn-cf-authorizer.js +50 -0
  50. package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.d.ts +1 -4
  51. package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.js +14 -46
  52. package/dist/service/cloudfront/sim-cloudfront-commands.d.ts +6 -0
  53. package/dist/service/cloudfront/sim-cloudfront-commands.js +7 -0
  54. package/dist/service/cloudfront/sim-cloudfront.d.ts +6 -0
  55. package/dist/service/cloudfront/sim-cloudfront.js +7 -0
  56. package/dist/service/dynamodb/document/sim-dynamodb-document-command-paths.d.ts +8 -0
  57. package/dist/service/dynamodb/document/sim-dynamodb-document-command-paths.js +62 -0
  58. package/dist/service/dynamodb/document/sim-dynamodb-document-routes.d.ts +1 -1
  59. package/dist/service/dynamodb/document/sim-dynamodb-document-routes.js +3 -1
  60. package/dist/service/iam/authorize/sim-iam-action-authorizer.d.ts +8 -3
  61. package/dist/service/iam/authorize/sim-iam-action-authorizer.js +13 -4
  62. package/dist/service/iam/cfn/role/sim-cfn-iam-role-creator.js +1 -0
  63. package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.d.ts +1 -0
  64. package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.js +21 -14
  65. package/dist/service/iam/cfn/{sim-cfn-iam-optional-string.d.ts → sim-cfn-iam-property.d.ts} +10 -2
  66. package/dist/service/iam/cfn/sim-cfn-iam-property.js +31 -0
  67. package/dist/service/iam/cfn/user/sim-cfn-iam-user-properties-parser.js +1 -1
  68. package/dist/service/iam/command/role/create-role/create-role-record-factory.js +3 -0
  69. package/dist/service/iam/command/role/create-role/create-role.command.d.ts +10 -0
  70. package/dist/service/iam/command/role/get-role/get-role.command.d.ts +2 -0
  71. package/dist/service/iam/command/role/get-role/get-role.handler.js +2 -0
  72. package/dist/service/iam/command/role/sim-iam-role-command-handlers.js +15 -1
  73. package/dist/service/iam/role/sim-iam-role-boundary.d.ts +24 -0
  74. package/dist/service/iam/role/sim-iam-role-boundary.js +24 -0
  75. package/dist/service/iam/role/sim-iam-role-with-policy.factory.d.ts +1 -0
  76. package/dist/service/iam/role/sim-iam-role.d.ts +10 -0
  77. package/dist/service/iam/serve/sim-iam-query-entity.d.ts +6 -1
  78. package/dist/service/iam/serve/sim-iam-query-entity.js +10 -4
  79. package/dist/service/iam/serve/sim-iam-query-role-operations.js +15 -3
  80. package/dist/service/lambda/cfn/function/sim-cfn-lambda-runtime-skip.d.ts +6 -0
  81. package/dist/service/lambda/cfn/function/sim-cfn-lambda-runtime-skip.js +9 -2
  82. package/dist/service/route53/command/create-hosted-zone/sim-route53-zone-id.js +23 -1
  83. package/dist/service/s3/bucket/sim-s3-bucket-maker.d.ts +31 -0
  84. package/dist/service/s3/bucket/sim-s3-bucket-maker.js +41 -0
  85. package/dist/service/s3/command/create-bucket/create-bucket.handler.d.ts +2 -2
  86. package/dist/service/s3/command/create-bucket/create-bucket.handler.js +4 -12
  87. package/dist/service/s3/sim-s3-commands.d.ts +6 -0
  88. package/dist/service/s3/sim-s3-commands.js +7 -0
  89. package/dist/service/s3/sim-s3.d.ts +16 -0
  90. package/dist/service/s3/sim-s3.js +25 -0
  91. package/docs/services/cloudformation/README.md +144 -25
  92. package/docs/services/cloudfront/README.md +109 -0
  93. package/docs/services/dynamodb/README.md +128 -8
  94. package/docs/services/iam/README.md +125 -2
  95. package/docs/services/route53/README.md +11 -0
  96. package/package.json +2 -2
  97. 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. Service control policies are, and
1555
- are attached through [simulated Organizations](https://yulinsim.dev/services/organizations/ "Simulated Organizations service control policies usage docs")
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.4",
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": "^72.0.0",
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
- }