@kensio/yulin 1.20.15 → 1.20.17

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 (355) hide show
  1. package/README.md +13 -0
  2. package/dist/sdk/module/sim-sdk-module-client-interceptor.d.ts +5 -0
  3. package/dist/sdk/module/sim-sdk-module-client-interceptor.js +14 -0
  4. package/dist/sdk/module/sim-sdk-static-client-factory.d.ts +26 -0
  5. package/dist/sdk/module/sim-sdk-static-client-factory.js +59 -0
  6. package/dist/sdk/send-patch.d.ts +8 -0
  7. package/dist/sdk/send-patch.js +11 -0
  8. package/dist/service/aws/caller/sim-aws-ambient-caller.d.ts +23 -0
  9. package/dist/service/aws/caller/sim-aws-ambient-caller.js +12 -0
  10. package/dist/service/aws/caller/sim-aws-caller-resolver.d.ts +39 -6
  11. package/dist/service/aws/caller/sim-aws-caller-resolver.js +32 -30
  12. package/dist/service/aws/caller/sim-aws-caller.d.ts +9 -0
  13. package/dist/service/aws/caller/sim-aws-resolved-caller.d.ts +19 -0
  14. package/dist/service/aws/caller/sim-aws-resolved-caller.js +26 -0
  15. package/dist/service/aws/factory/sim-aws-account-region-service-builder.d.ts +12 -0
  16. package/dist/service/aws/factory/sim-aws-account-region-service-builder.js +6 -0
  17. package/dist/service/aws/factory/sim-aws-account-service-cache.d.ts +12 -0
  18. package/dist/service/aws/factory/sim-aws-account-service-cache.js +9 -0
  19. package/dist/service/aws/factory/sim-aws-registered-service-builder.js +3 -1
  20. package/dist/service/aws/factory/sim-aws-service-factory.d.ts +5 -0
  21. package/dist/service/aws/factory/sim-aws-service-factory.js +14 -0
  22. package/dist/service/aws/sim-aws-properties.d.ts +15 -0
  23. package/dist/service/aws/sim-aws.js +2 -1
  24. package/dist/service/cloudformation/command/create-stack/create-stack.handler.d.ts +4 -0
  25. package/dist/service/cloudformation/command/create-stack/create-stack.handler.js +4 -1
  26. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-deployer.js +2 -1
  27. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.d.ts +11 -2
  28. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.js +2 -1
  29. package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.d.ts +6 -0
  30. package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts +11 -0
  31. package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js +17 -15
  32. package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts +12 -0
  33. package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js +2 -1
  34. package/dist/service/cloudformation/resource/cfn/cloudfront/sim-cloudfront-cache-policy-cfn.d.ts +23 -0
  35. package/dist/service/cloudformation/resource/cfn/cloudfront/sim-cloudfront-cache-policy-cfn.js +30 -0
  36. package/dist/service/cloudformation/resource/cfn/cloudfront/sim-cloudfront-cfn-value-adapter.js +8 -0
  37. package/dist/service/cloudformation/resource/name/sim-cfn-generated-resource-name.d.ts +29 -12
  38. package/dist/service/cloudformation/resource/name/sim-cfn-generated-resource-name.js +51 -20
  39. package/dist/service/cloudformation/stack/deploy/sim-cfn-resource-order.d.ts +19 -0
  40. package/dist/service/cloudformation/stack/deploy/sim-cfn-resource-order.js +6 -0
  41. package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-batch-creator.d.ts +7 -0
  42. package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-batch-creator.js +9 -2
  43. package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-creator.d.ts +2 -0
  44. package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-creator.js +2 -1
  45. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +6 -0
  46. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +4 -1
  47. package/dist/service/cloudformation/stack/sim-cfn-stack.js +2 -1
  48. package/dist/service/cloudformation/stack/sim-cfn-stack.type.d.ts +6 -0
  49. package/dist/service/cloudfront/behaviour/sim-cloud-front-behavior.d.ts +5 -0
  50. package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy-registry.d.ts +37 -0
  51. package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy-registry.js +50 -0
  52. package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy.d.ts +25 -0
  53. package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy.js +21 -0
  54. package/dist/service/cloudfront/cache-policy/sim-cf-managed-cache-policies.d.ts +28 -0
  55. package/dist/service/cloudfront/cache-policy/sim-cf-managed-cache-policies.js +48 -0
  56. package/dist/service/cloudfront/cff/function-code-input/cff-function-code-input.d.ts +8 -0
  57. package/dist/service/cloudfront/cff/function-code-input/cff-function-code-input.js +13 -0
  58. package/dist/service/cloudfront/cff/sim-cf-function-commands.d.ts +52 -0
  59. package/dist/service/cloudfront/cff/sim-cf-function-commands.js +51 -0
  60. package/dist/service/cloudfront/cff/sim-cff-configuration.d.ts +41 -0
  61. package/dist/service/cloudfront/cff/sim-cff-configuration.js +34 -0
  62. package/dist/service/cloudfront/cff/sim-cff-stage.d.ts +23 -0
  63. package/dist/service/cloudfront/cff/sim-cff-stage.js +30 -0
  64. package/dist/service/cloudfront/cff/sim-cloudfront-function.d.ts +6 -1
  65. package/dist/service/cloudfront/cff/sim-cloudfront-function.js +6 -0
  66. package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-config.d.ts +27 -0
  67. package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-config.js +42 -0
  68. package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.d.ts +24 -0
  69. package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.js +32 -0
  70. package/dist/service/cloudfront/cfn/distro/{sim-cfn-cf-distro-response-headers-policy.d.ts → sim-cfn-cf-distro-behavior-policies.d.ts} +8 -7
  71. package/dist/service/cloudfront/cfn/distro/{sim-cfn-cf-distro-response-headers-policy.js → sim-cfn-cf-distro-behavior-policies.js} +11 -37
  72. package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-creator.d.ts +6 -5
  73. package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-creator.js +8 -7
  74. package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-policy-drops.d.ts +23 -0
  75. package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-policy-drops.js +50 -0
  76. package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.d.ts +1 -0
  77. package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.js +10 -0
  78. package/dist/service/cloudfront/command/create-distribution/create-distribution.command.d.ts +1 -0
  79. package/dist/service/cloudfront/command/create-distribution/create-distribution.handler.d.ts +2 -0
  80. package/dist/service/cloudfront/command/create-function/create-function.handler.js +7 -1
  81. package/dist/service/cloudfront/command/function/sim-cf-describe-function.d.ts +22 -0
  82. package/dist/service/cloudfront/command/function/sim-cf-describe-function.js +32 -0
  83. package/dist/service/cloudfront/command/function/sim-cf-function-access.d.ts +48 -0
  84. package/dist/service/cloudfront/command/function/sim-cf-function-access.js +48 -0
  85. package/dist/service/cloudfront/command/function/sim-cf-function-command.types.d.ts +97 -0
  86. package/dist/service/cloudfront/command/function/sim-cf-function-command.types.js +10 -0
  87. package/dist/service/cloudfront/command/function/sim-cf-function-lookup.d.ts +12 -0
  88. package/dist/service/cloudfront/command/function/sim-cf-function-lookup.js +21 -0
  89. package/dist/service/cloudfront/command/function/sim-cf-function-summary.d.ts +11 -0
  90. package/dist/service/cloudfront/command/function/sim-cf-function-summary.js +30 -0
  91. package/dist/service/cloudfront/command/function/sim-cf-get-function.d.ts +23 -0
  92. package/dist/service/cloudfront/command/function/sim-cf-get-function.js +33 -0
  93. package/dist/service/cloudfront/command/function/sim-cf-list-functions.d.ts +22 -0
  94. package/dist/service/cloudfront/command/function/sim-cf-list-functions.js +38 -0
  95. package/dist/service/cloudfront/command/update-distribution/update-distribution.handler.d.ts +2 -0
  96. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-cache-policy.d.ts +18 -0
  97. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-cache-policy.js +30 -0
  98. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-policies.d.ts +28 -0
  99. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-policies.js +41 -0
  100. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-properties.d.ts +2 -2
  101. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-properties.js +6 -3
  102. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-response-headers-policy.d.ts +0 -10
  103. package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-response-headers-policy.js +0 -19
  104. package/dist/service/cloudfront/distribution/configurator/sim-cf-distribution-configurator.factory.d.ts +2 -0
  105. package/dist/service/cloudfront/distribution/configurator/sim-cf-distribution-configurator.factory.js +4 -2
  106. package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-behavior-configurator.d.ts +3 -3
  107. package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-behavior-configurator.js +5 -5
  108. package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-distribution-configurator.d.ts +3 -3
  109. package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-distribution-configurator.js +4 -4
  110. package/dist/service/cloudfront/distribution/sim-cf-distribution-configuration-state.d.ts +3 -1
  111. package/dist/service/cloudfront/distribution/sim-cf-distribution-reconfigurer.d.ts +2 -0
  112. package/dist/service/cloudfront/error/sim-cloudfront.error.d.ts +21 -0
  113. package/dist/service/cloudfront/error/sim-cloudfront.error.js +25 -0
  114. package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store-access.js +2 -10
  115. package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store.js +2 -1
  116. package/dist/service/cloudfront/sdk/sim-cloudfront-sdk-command-router.js +12 -0
  117. package/dist/service/cloudfront/sim-cf-authorize.d.ts +16 -0
  118. package/dist/service/cloudfront/sim-cf-authorize.js +19 -0
  119. package/dist/service/cloudfront/sim-cf-etag.d.ts +7 -0
  120. package/dist/service/cloudfront/sim-cf-etag.js +10 -0
  121. package/dist/service/cloudfront/sim-cloudfront-commands.d.ts +8 -12
  122. package/dist/service/cloudfront/sim-cloudfront-commands.js +8 -17
  123. package/dist/service/cloudfront/sim-cloudfront-policies.d.ts +43 -0
  124. package/dist/service/cloudfront/sim-cloudfront-policies.js +53 -0
  125. package/dist/service/cloudfront/sim-cloudfront.d.ts +13 -17
  126. package/dist/service/cloudfront/sim-cloudfront.js +22 -25
  127. package/dist/service/ecr/authorize/sim-ecr-authorizer.d.ts +31 -0
  128. package/dist/service/ecr/authorize/sim-ecr-authorizer.js +38 -0
  129. package/dist/service/ecr/cfn/repository/sim-cfn-ecr-repository-creator.d.ts +11 -2
  130. package/dist/service/ecr/cfn/repository/sim-cfn-ecr-repository-creator.js +11 -2
  131. package/dist/service/ecr/cfn/sim-ecr-cfn-resource-factory.d.ts +4 -2
  132. package/dist/service/ecr/cfn/sim-ecr-cfn-resource-factory.js +8 -9
  133. package/dist/service/ecr/cfn/sim-ecr-cfn-unsupported-resource.d.ts +7 -0
  134. package/dist/service/ecr/cfn/sim-ecr-cfn-unsupported-resource.js +9 -0
  135. package/dist/service/ecr/sim-ecr.d.ts +7 -0
  136. package/dist/service/ecr/sim-ecr.js +16 -4
  137. package/dist/service/ecs/command/authorize/sim-ecs-authorizer.d.ts +12 -0
  138. package/dist/service/ecs/command/authorize/sim-ecs-authorizer.js +21 -0
  139. package/dist/service/ecs/command/register-task-definition/register-task-definition.handler.js +1 -0
  140. package/dist/service/ecs/sim-ecs-service-principal.d.ts +8 -0
  141. package/dist/service/ecs/sim-ecs-service-principal.js +8 -0
  142. package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.d.ts +12 -0
  143. package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.js +21 -0
  144. package/dist/service/eventbridge/command/rule/sim-event-bridge-rule-access.d.ts +13 -0
  145. package/dist/service/eventbridge/command/rule/sim-event-bridge-rule-access.js +9 -0
  146. package/dist/service/eventbridge/command/target/sim-event-bridge-put-targets.js +1 -0
  147. package/dist/service/firehose/command/authorize/sim-firehose-authorizer.d.ts +12 -0
  148. package/dist/service/firehose/command/authorize/sim-firehose-authorizer.js +20 -0
  149. package/dist/service/firehose/command/sim-firehose-delivery-stream-access.d.ts +4 -0
  150. package/dist/service/firehose/command/sim-firehose-delivery-stream-access.js +6 -0
  151. package/dist/service/firehose/command/stream/sim-firehose-create-delivery-stream.js +3 -1
  152. package/dist/service/firehose/sim-firehose-service-principal.d.ts +8 -0
  153. package/dist/service/firehose/sim-firehose-service-principal.js +8 -0
  154. package/dist/service/firehose/source/sim-firehose-source.d.ts +5 -0
  155. package/dist/service/firehose/source/sim-firehose-source.js +5 -0
  156. package/dist/service/glue/cfn/database/sim-cfn-glue-database-properties.js +2 -2
  157. package/dist/service/glue/cfn/sim-cfn-glue-generated-name.d.ts +10 -0
  158. package/dist/service/glue/cfn/sim-cfn-glue-generated-name.js +25 -0
  159. package/dist/service/glue/cfn/table/sim-cfn-glue-table-properties.js +2 -3
  160. package/dist/service/iam/authorize/allow/sim-iam-allow-requirement.d.ts +33 -2
  161. package/dist/service/iam/authorize/allow/sim-iam-allow-requirement.js +33 -2
  162. package/dist/service/iam/authorize/allow/sim-iam-allow-statements.d.ts +4 -3
  163. package/dist/service/iam/authorize/allow/sim-iam-allow-statements.js +9 -3
  164. package/dist/service/iam/authorize/context/sim-iam-auth-z-allow-requirement.d.ts +14 -5
  165. package/dist/service/iam/authorize/context/sim-iam-auth-z-allow-requirement.js +16 -12
  166. package/dist/service/iam/authorize/context/sim-iam-auth-z-caller-context-builder.d.ts +36 -7
  167. package/dist/service/iam/authorize/context/sim-iam-auth-z-caller-context-builder.js +22 -11
  168. package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.d.ts +10 -71
  169. package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.js +7 -2
  170. package/dist/service/iam/authorize/context/sim-iam-auth-z-input.d.ts +87 -0
  171. package/dist/service/iam/authorize/context/sim-iam-auth-z-input.js +1 -0
  172. package/dist/service/iam/authorize/match/sim-iam-policy-principal-matcher.d.ts +21 -3
  173. package/dist/service/iam/authorize/match/sim-iam-policy-principal-matcher.js +34 -10
  174. package/dist/service/iam/authorize/match/sim-iam-principal-match.d.ts +29 -8
  175. package/dist/service/iam/authorize/match/sim-iam-principal-match.js +38 -13
  176. package/dist/service/iam/authorize/pass-role/sim-iam-pass-role-authorizer.d.ts +74 -0
  177. package/dist/service/iam/authorize/pass-role/sim-iam-pass-role-authorizer.js +92 -0
  178. package/dist/service/iam/authorize/sim-iam-account-auth-z.d.ts +21 -5
  179. package/dist/service/iam/authorize/sim-iam-account-auth-z.js +7 -3
  180. package/dist/service/iam/authorize/sim-iam-authorizer.d.ts +5 -2
  181. package/dist/service/iam/authorize/sim-iam-authorizer.js +3 -1
  182. package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.d.ts +1 -1
  183. package/dist/service/iam/authorize/sim-iam-wildcard.js +39 -4
  184. package/dist/service/iam/cfn/managed-policy/sim-cfn-iam-managed-policy-creator.js +2 -1
  185. package/dist/service/iam/cfn/name/sim-cfn-iam-generated-name.d.ts +16 -0
  186. package/dist/service/iam/cfn/name/sim-cfn-iam-generated-name.js +36 -0
  187. package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.js +9 -8
  188. package/dist/service/iam/cfn/sim-cfn-iam-optional-string.d.ts +17 -0
  189. package/dist/service/iam/cfn/sim-cfn-iam-optional-string.js +17 -0
  190. package/dist/service/iam/cfn/user/sim-cfn-iam-user-properties-parser.js +4 -8
  191. package/dist/service/iam/command/policy/create-policy/create-policy-input-resolver.js +2 -0
  192. package/dist/service/iam/command/policy/put-role-policy/put-role-policy.handler.js +5 -0
  193. package/dist/service/iam/command/policy/put-user-policy/put-user-policy.handler.js +5 -0
  194. package/dist/service/iam/command/role/create-role/create-role.handler.js +4 -1
  195. package/dist/service/iam/error/sim-iam.error.d.ts +11 -0
  196. package/dist/service/iam/error/sim-iam.error.js +13 -0
  197. package/dist/service/iam/index.d.ts +1 -0
  198. package/dist/service/iam/policy/sim-iam-policy-document-of-size.d.ts +18 -0
  199. package/dist/service/iam/policy/sim-iam-policy-document-of-size.js +41 -0
  200. package/dist/service/iam/role/sim-iam-deploy-role.d.ts +56 -0
  201. package/dist/service/iam/role/sim-iam-deploy-role.js +50 -0
  202. package/dist/service/iam/role/sim-iam-role-with-policy.factory.d.ts +11 -0
  203. package/dist/service/iam/role/sim-iam-role-with-policy.factory.js +4 -2
  204. package/dist/service/iam/sim-iam-account-parts.d.ts +16 -0
  205. package/dist/service/iam/sim-iam-account-parts.js +2 -0
  206. package/dist/service/iam/sim-iam.d.ts +12 -2
  207. package/dist/service/iam/sim-iam.js +12 -0
  208. package/dist/service/iam/validate/size/sim-iam-policy-document-size.d.ts +57 -0
  209. package/dist/service/iam/validate/size/sim-iam-policy-document-size.js +71 -0
  210. package/dist/service/kms/command/authorize/sim-kms-authorizer.d.ts +3 -1
  211. package/dist/service/kms/command/authorize/sim-kms-authorizer.js +4 -1
  212. package/dist/service/kms/command/sim-kms-request-options.d.ts +11 -0
  213. package/dist/service/kms/key/sim-kms-key-policy.d.ts +5 -4
  214. package/dist/service/kms/key/sim-kms-key-policy.js +4 -3
  215. package/dist/service/lambda/cfn/function/sim-cfn-lambda-function-properties-parser.d.ts +2 -2
  216. package/dist/service/lambda/cfn/function/sim-cfn-lambda-function-properties-parser.js +4 -3
  217. package/dist/service/lambda/cfn/function/sim-cfn-lambda-generated-function-name.d.ts +10 -0
  218. package/dist/service/lambda/cfn/function/sim-cfn-lambda-generated-function-name.js +25 -0
  219. package/dist/service/lambda/command/authorize/sim-lambda-resource-policies.d.ts +1 -1
  220. package/dist/service/lambda/command/create-function/create-function-authorizer.d.ts +9 -2
  221. package/dist/service/lambda/command/create-function/create-function-authorizer.js +16 -2
  222. package/dist/service/lambda/command/create-function/create-function.handler.js +1 -1
  223. package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.d.ts +7 -2
  224. package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.js +14 -2
  225. package/dist/service/lambda/command/update-function-configuration/update-function-configuration.handler.js +1 -1
  226. package/dist/service/lambda/function/logging/sim-lambda-function-logging.d.ts +10 -1
  227. package/dist/service/lambda/function/logging/sim-lambda-function-logging.js +25 -1
  228. package/dist/service/lambda/function/logging/sim-lambda-invoke-error-log.d.ts +13 -0
  229. package/dist/service/lambda/function/logging/sim-lambda-invoke-error-log.js +18 -0
  230. package/dist/service/lambda/sim-lambda-service-principal.d.ts +7 -0
  231. package/dist/service/lambda/sim-lambda-service-principal.js +7 -0
  232. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-authorization.d.ts +46 -0
  233. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-authorization.js +49 -0
  234. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-creator.d.ts +5 -0
  235. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-creator.js +6 -0
  236. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-destination-creator.d.ts +5 -0
  237. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-destination-creator.js +6 -0
  238. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-source-creator.d.ts +5 -0
  239. package/dist/service/logs/cfn/delivery/sim-cfn-delivery-source-creator.js +6 -0
  240. package/dist/service/logs/cfn/group/sim-cfn-log-group-creator.d.ts +9 -2
  241. package/dist/service/logs/cfn/group/sim-cfn-log-group-creator.js +34 -5
  242. package/dist/service/logs/cfn/sim-logs-cfn-resource-deleter.js +1 -1
  243. package/dist/service/logs/cfn/sim-logs-cfn-resource-factory.d.ts +4 -0
  244. package/dist/service/logs/cfn/sim-logs-cfn-resource-factory.js +9 -4
  245. package/dist/service/logs/sim-logs-commands.d.ts +3 -0
  246. package/dist/service/logs/sim-logs-commands.js +4 -0
  247. package/dist/service/logs/sim-logs.js +6 -1
  248. package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-creator.d.ts +2 -2
  249. package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-creator.js +4 -3
  250. package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-generated-name.d.ts +12 -0
  251. package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-generated-name.js +22 -0
  252. package/dist/service/s3/command/authorize/sim-s3-bucket-resource-policies.d.ts +1 -1
  253. package/dist/service/scheduler/command/authorize/sim-scheduler-authorizer.d.ts +10 -1
  254. package/dist/service/scheduler/command/authorize/sim-scheduler-authorizer.js +19 -1
  255. package/dist/service/scheduler/command/schedule/sim-scheduler-create-schedule.js +1 -0
  256. package/dist/service/scheduler/command/schedule/sim-scheduler-schedule-access.d.ts +8 -0
  257. package/dist/service/scheduler/command/schedule/sim-scheduler-schedule-access.js +9 -0
  258. package/dist/service/scheduler/command/schedule/sim-scheduler-update-schedule.js +1 -0
  259. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-generated-name.d.ts +15 -0
  260. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-generated-name.js +22 -0
  261. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-properties.d.ts +4 -10
  262. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-properties.js +13 -31
  263. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-value.d.ts +17 -0
  264. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-value.js +30 -0
  265. package/dist/service/secretsmanager/secret/sim-secrets-manager-secret-name.d.ts +6 -0
  266. package/dist/service/secretsmanager/secret/sim-secrets-manager-secret-name.js +8 -3
  267. package/dist/service/sns/command/authorize/sim-sns-topic-resource-policies.d.ts +1 -1
  268. package/dist/service/sqs/command/authorize/sim-sqs-queue-resource-policies.d.ts +1 -1
  269. package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-generated-parameter-name.d.ts +16 -0
  270. package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-generated-parameter-name.js +23 -0
  271. package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.d.ts +2 -4
  272. package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.js +5 -5
  273. package/dist/service/ssm/parameter/sim-ssm-kms-crypto.d.ts +6 -4
  274. package/dist/service/ssm/parameter/sim-ssm-kms-crypto.js +4 -4
  275. package/dist/service/ssm/parameter/sim-ssm-parameter-arn.d.ts +17 -0
  276. package/dist/service/ssm/parameter/sim-ssm-parameter-arn.js +20 -0
  277. package/dist/service/ssm/parameter/sim-ssm-parameter-kms.d.ts +15 -9
  278. package/dist/service/ssm/parameter/sim-ssm-parameter-kms.js +20 -10
  279. package/dist/service/ssm/parameter/sim-ssm-parameter-name.js +3 -12
  280. package/dist/service/stepfunctions/command/authorize/sim-step-functions-authorizer.d.ts +41 -0
  281. package/dist/service/stepfunctions/command/authorize/sim-step-functions-authorizer.js +64 -0
  282. package/dist/service/stepfunctions/command/machine/sim-state-machine-create.d.ts +5 -2
  283. package/dist/service/stepfunctions/command/machine/sim-state-machine-create.js +6 -2
  284. package/dist/service/stepfunctions/command/machine/sim-state-machine-delete.d.ts +26 -0
  285. package/dist/service/stepfunctions/command/machine/sim-state-machine-delete.js +29 -0
  286. package/dist/service/stepfunctions/command/machine/sim-state-machine-lookup.d.ts +7 -0
  287. package/dist/service/stepfunctions/command/machine/sim-state-machine-lookup.js +12 -3
  288. package/dist/service/stepfunctions/command/machine/sim-state-machine-update.d.ts +19 -0
  289. package/dist/service/stepfunctions/command/machine/{sim-state-machine-writes.js → sim-state-machine-update.js} +3 -14
  290. package/dist/service/stepfunctions/sim-step-functions.d.ts +8 -2
  291. package/dist/service/stepfunctions/sim-step-functions.js +26 -9
  292. package/dist/service/sts/auth-z/assume-role-auth-z-coordinator.d.ts +9 -2
  293. package/dist/service/sts/auth-z/assume-role-auth-z-coordinator.js +2 -2
  294. package/dist/service/sts/auth-z/assume-role-source-account-auth-z.d.ts +10 -4
  295. package/dist/service/sts/auth-z/assume-role-source-account-auth-z.js +8 -7
  296. package/dist/service/sts/auth-z/assume-role-target-auth-z.d.ts +2 -2
  297. package/dist/service/sts/auth-z/assume-role-trust-policy-authorizer.d.ts +6 -2
  298. package/dist/service/sts/auth-z/assume-role-trust-policy-authorizer.js +14 -11
  299. package/dist/service/sts/command/assume-role/assume-role.handler.d.ts +10 -1
  300. package/dist/service/sts/command/assume-role/assume-role.handler.js +6 -2
  301. package/dist/service/sts/command/get-caller-identity/get-caller-identity.handler.d.ts +10 -1
  302. package/dist/service/sts/command/get-caller-identity/get-caller-identity.handler.js +5 -1
  303. package/dist/service/sts/service-role/sim-service-role.js +5 -1
  304. package/dist/service/sts/sim-sts.d.ts +18 -1
  305. package/dist/service/sts/sim-sts.js +8 -0
  306. package/dist/util/memo/bounded-memo.d.ts +36 -0
  307. package/dist/util/memo/bounded-memo.js +58 -0
  308. package/docs/README.md +54 -0
  309. package/docs/ai-skill/README.md +69 -0
  310. package/docs/cli/README.md +284 -0
  311. package/docs/factories/README.md +140 -0
  312. package/docs/lint/README.md +176 -0
  313. package/docs/non-aws-dependencies/README.md +261 -0
  314. package/docs/sdk/README.md +274 -0
  315. package/docs/serve/README.md +1126 -0
  316. package/docs/services/acm/README.md +823 -0
  317. package/docs/services/apigateway/README.md +1919 -0
  318. package/docs/services/apigatewayv2/README.md +2678 -0
  319. package/docs/services/athena/README.md +1044 -0
  320. package/docs/services/bedrock/README.md +350 -0
  321. package/docs/services/cloudformation/README.md +3625 -0
  322. package/docs/services/cloudfront/README.md +3098 -0
  323. package/docs/services/cloudwatch/README.md +422 -0
  324. package/docs/services/cognito/README.md +4924 -0
  325. package/docs/services/dynamodb/README.md +3785 -0
  326. package/docs/services/ecr/README.md +302 -0
  327. package/docs/services/ecs/README.md +2021 -0
  328. package/docs/services/elbv2/README.md +1901 -0
  329. package/docs/services/eventbridge/README.md +1118 -0
  330. package/docs/services/firehose/README.md +811 -0
  331. package/docs/services/glue/README.md +507 -0
  332. package/docs/services/iam/README.md +1578 -0
  333. package/docs/services/kinesis/README.md +455 -0
  334. package/docs/services/kms/README.md +664 -0
  335. package/docs/services/lambda/README.md +3719 -0
  336. package/docs/services/logs/README.md +882 -0
  337. package/docs/services/organizations/README.md +574 -0
  338. package/docs/services/personalize/README.md +835 -0
  339. package/docs/services/rekognition/README.md +1070 -0
  340. package/docs/services/route53/README.md +1783 -0
  341. package/docs/services/s3/README.md +3029 -0
  342. package/docs/services/scheduler/README.md +814 -0
  343. package/docs/services/secretsmanager/README.md +670 -0
  344. package/docs/services/ses/README.md +1013 -0
  345. package/docs/services/sns/README.md +1904 -0
  346. package/docs/services/sqs/README.md +1185 -0
  347. package/docs/services/ssm/README.md +1096 -0
  348. package/docs/services/stepfunctions/README.md +1341 -0
  349. package/docs/services/sts/README.md +245 -0
  350. package/docs/services/wafv2/README.md +1380 -0
  351. package/docs/terraform/README.md +248 -0
  352. package/docs/time/README.md +284 -0
  353. package/llms.txt +59 -0
  354. package/package.json +7 -4
  355. package/dist/service/stepfunctions/command/machine/sim-state-machine-writes.d.ts +0 -25
@@ -0,0 +1,1578 @@
1
+ # Simulated IAM
2
+
3
+ Yulin includes a simulated IAM service for tests and local development.
4
+
5
+ Sim IAM stores simulated Roles, Users and Policies, and evaluates allow/deny authorization decisions
6
+ for them. Other simulated services use it to authorize their own actions, simulated STS uses it to
7
+ issue temporary Role sessions, and sim CloudFormation can create IAM resources from templates. It can
8
+ also be instantiated on its own as `SimIam` with isolated state.
9
+
10
+ ## Basic usage
11
+
12
+ Create a simulated AWS environment, get simulated IAM, create a Role with an inline policy, and
13
+ authorize an action as that Role.
14
+
15
+ ```typescript sim-iam-role-authorization
16
+ /**
17
+ * Creating a simulated IAM Role and authorizing an action.
18
+ */
19
+
20
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
21
+ import { SimAws } from "@kensio/yulin";
22
+
23
+ const simAws = new SimAws();
24
+ const simIam = simAws.account("123456789012").iam();
25
+
26
+ const roleCreation = await simIam.createRole(
27
+ new CreateRoleCommand({
28
+ RoleName: "ReportReaderRole",
29
+ Description: "Allows reading report objects",
30
+ AssumeRolePolicyDocument: JSON.stringify({
31
+ Version: "2012-10-17",
32
+ Statement: {
33
+ Effect: "Allow",
34
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
35
+ Action: "sts:AssumeRole",
36
+ },
37
+ }),
38
+ }),
39
+ );
40
+
41
+ await simIam.putRolePolicy(
42
+ new PutRolePolicyCommand({
43
+ RoleName: "ReportReaderRole",
44
+ PolicyName: "ReadReports",
45
+ PolicyDocument: JSON.stringify({
46
+ Version: "2012-10-17",
47
+ Statement: {
48
+ Effect: "Allow",
49
+ Action: "s3:GetObject",
50
+ Resource: "arn:aws:s3:::reports-bucket/*",
51
+ },
52
+ }),
53
+ }),
54
+ );
55
+
56
+ const decision = simIam.authorize({
57
+ action: "s3:GetObject",
58
+ resource: "arn:aws:s3:::reports-bucket/2026/summary.csv",
59
+ caller: { kind: "arn", arn: roleCreation.Role.Arn },
60
+ });
61
+
62
+ console.log(decision.isAllowed);
63
+ ```
64
+
65
+ `CreateRoleCommand` validates the trust policy document and stores the Role with an AWS-shaped ARN,
66
+ Role ID, and creation date. Roles can be inspected with `GetRoleCommand` and `ListRolesCommand`.
67
+
68
+ A trust policy alone grants no permissions. A Role with no inline or attached policies is implicitly
69
+ denied for every action.
70
+
71
+ ## Authorization decisions
72
+
73
+ `authorize(...)` returns a decision object. A denied request comes back as a decision too, and a
74
+ test can assert on exactly why it was allowed or denied. The decision models the common IAM
75
+ evaluation rules:
76
+
77
+ - A matching explicit `Deny` statement in any evaluated policy wins
78
+ - Otherwise, within one Account, a matching `Allow` in an identity policy or resource policy allows
79
+ the request
80
+ - Across Accounts, a matching `Allow` is needed from each side. See
81
+ [Cross-Account requests](#cross-account-requests)
82
+ - Otherwise the request is implicitly denied
83
+
84
+ The decision exposes `value` (`"Allow"`, `"ExplicitDeny"`, or `"ImplicitDeny"`), the convenience
85
+ flags `isAllowed`, `isDenied`, `isExplicitDeny`, and `isImplicitDeny`, the matching
86
+ `allowStatements` and `explicitDenyStatements`, and the resolved `caller` for diagnostics. The
87
+ matching Allows are also available per side as `identityAllowStatements` and
88
+ `resourceAllowStatements`. A cross-Account denial is best read from those. Statements the simulator
89
+ could not evaluate are reported by `unevaluatedStatements`, covered under
90
+ [Statements left unevaluated](#statements-left-unevaluated).
91
+
92
+ If the caller is omitted, authorization defaults to the simulation's own
93
+ [default caller](#name-the-caller-a-simulation-uses-by-default), and to the root principal of the
94
+ Account owning the sim IAM instance where the simulation has none. That root principal is allowed
95
+ within its own Account, subject to any service control policy over that Account. An explicit
96
+ `{ kind: "anonymous" }` caller suppresses both fallbacks and is
97
+ evaluated without identity policies.
98
+
99
+ Resource policies live with the service that owns the target resource, such as an S3 Bucket policy,
100
+ and are supplied with the authorization request.
101
+
102
+ ```typescript sim-iam-authorization-decisions
103
+ /**
104
+ * Inspecting simulated IAM authorization decisions.
105
+ */
106
+
107
+ import { SimAws } from "@kensio/yulin";
108
+
109
+ const simAws = new SimAws();
110
+ const simIam = simAws.account("123456789012").iam();
111
+
112
+ const bucketPolicy = {
113
+ document: {
114
+ Version: "2012-10-17",
115
+ Statement: [
116
+ {
117
+ Effect: "Allow",
118
+ Principal: "*",
119
+ Action: "s3:GetObject",
120
+ Resource: "arn:aws:s3:::example-bucket/*",
121
+ },
122
+ {
123
+ Effect: "Deny",
124
+ Principal: "*",
125
+ Action: "s3:GetObject",
126
+ Resource: "arn:aws:s3:::example-bucket/private/*",
127
+ },
128
+ ],
129
+ },
130
+ } as const;
131
+
132
+ const publicDecision = simIam.authorize({
133
+ action: "s3:GetObject",
134
+ resource: "arn:aws:s3:::example-bucket/public/index.html",
135
+ caller: { kind: "anonymous" },
136
+ resourcePolicies: [bucketPolicy],
137
+ });
138
+
139
+ const privateDecision = simIam.authorize({
140
+ action: "s3:GetObject",
141
+ resource: "arn:aws:s3:::example-bucket/private/secrets.txt",
142
+ caller: { kind: "anonymous" },
143
+ resourcePolicies: [bucketPolicy],
144
+ });
145
+
146
+ console.log(publicDecision.value);
147
+ console.log(privateDecision.value);
148
+ console.log(privateDecision.explicitDenyStatements.length);
149
+ ```
150
+
151
+ ## Managed Policies
152
+
153
+ Create standalone managed Policies with `CreatePolicyCommand` and attach them to Roles with
154
+ `AttachRolePolicyCommand`. A managed Policy only grants permissions once it is attached.
155
+
156
+ ```typescript sim-iam-managed-policy
157
+ /**
158
+ * Creating and attaching a simulated IAM managed Policy.
159
+ */
160
+
161
+ import {
162
+ AttachRolePolicyCommand,
163
+ CreatePolicyCommand,
164
+ CreateRoleCommand,
165
+ } from "@aws-sdk/client-iam";
166
+ import { SimAws } from "@kensio/yulin";
167
+
168
+ const simAws = new SimAws();
169
+ const simIam = simAws.account("123456789012").iam();
170
+
171
+ const policyCreation = await simIam.createPolicy(
172
+ new CreatePolicyCommand({
173
+ PolicyName: "ReadOnlyReports",
174
+ Path: "/service-role/",
175
+ PolicyDocument: JSON.stringify({
176
+ Version: "2012-10-17",
177
+ Statement: {
178
+ Effect: "Allow",
179
+ Action: "s3:GetObject",
180
+ Resource: "arn:aws:s3:::reports-bucket/*",
181
+ },
182
+ }),
183
+ }),
184
+ );
185
+
186
+ const roleCreation = await simIam.createRole(
187
+ new CreateRoleCommand({
188
+ RoleName: "ReportingRole",
189
+ AssumeRolePolicyDocument: JSON.stringify({
190
+ Version: "2012-10-17",
191
+ Statement: {
192
+ Effect: "Allow",
193
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
194
+ Action: "sts:AssumeRole",
195
+ },
196
+ }),
197
+ }),
198
+ );
199
+
200
+ await simIam.attachRolePolicy(
201
+ new AttachRolePolicyCommand({
202
+ RoleName: "ReportingRole",
203
+ PolicyArn: policyCreation.Policy.Arn,
204
+ }),
205
+ );
206
+
207
+ const decision = simIam.authorize({
208
+ action: "s3:GetObject",
209
+ resource: "arn:aws:s3:::reports-bucket/2026/summary.csv",
210
+ caller: { kind: "arn", arn: roleCreation.Role.Arn },
211
+ });
212
+
213
+ console.log(policyCreation.Policy.Arn);
214
+ console.log(decision.isAllowed);
215
+ ```
216
+
217
+ Policy paths are normalised into the Policy ARN. A Policy named `ReadOnlyReports` with path
218
+ `/service-role/` gets the ARN `arn:aws:iam::123456789012:policy/service-role/ReadOnlyReports`.
219
+ Creating a duplicate Policy name in the same path throws an error, while the same name in different
220
+ paths is allowed. Stored Policies can be inspected with `GetPolicyCommand` and
221
+ `ListPoliciesCommand`.
222
+
223
+ ## Policy document character limits
224
+
225
+ IAM caps a policy document by where it is going. A managed policy takes 6,144 characters, an inline
226
+ policy on a Role or a User takes 10,240, and a Role trust policy takes 2,048. `CreatePolicy`,
227
+ `PutRolePolicy`, `PutUserPolicy` and `CreateRole` refuse a document past the cap with
228
+ `LimitExceeded`, in IAM's own wording. An `AWS::IAM::ManagedPolicy` or an `AWS::IAM::Policy`
229
+ carrying one fails its Resource.
230
+
231
+ IAM leaves whitespace out of the count, and so does the check here. A document indented for a
232
+ reader measures the same as the one line `JSON.stringify` writes.
233
+
234
+ A policy that has outgrown its cap cannot be deployed. The account keeps whichever version last
235
+ fit, and the permission the policy was grown to grant goes missing weeks later, against a
236
+ repository that still says it is there.
237
+
238
+ ## Policy conditions
239
+
240
+ Policy statements can carry `Condition` blocks. Sim IAM currently supports the `StringEquals`,
241
+ `StringLike`, `ArnLike`, `ArnEquals` and `NumericLessThanEquals` operators, along with the
242
+ `ForAllValues:` and `ForAnyValue:` set variants of `StringEquals` and `StringLike`.
243
+
244
+ The negated operators `StringNotEquals`, `StringNotLike`, `ArnNotEquals` and `ArnNotLike` are
245
+ supported too, each unqualified and in both set forms. A list of policy values under a negated
246
+ operator is an AND (the request value has to differ from every one of them), where the same list
247
+ under a positive operator is an OR. A service control policy writes its carve-outs this way, hanging
248
+ `ArnNotLike` on `aws:PrincipalArn` to deny an action to every principal outside a named set of
249
+ roles.
250
+
251
+ `ArnLike` and `ArnEquals` behave identically, as AWS documents them doing. Both compare the six
252
+ colon-delimited components of an ARN separately, and both accept `*` and `?` wildcards in any of
253
+ them. A wildcard stays inside the component it is written in. `arn:aws:s3:*` matches nothing,
254
+ because a pattern needs as many components as the ARN it is matched against. `ArnNotEquals` and
255
+ `ArnNotLike` compare an ARN the same way and answer the opposite.
256
+
257
+ Condition context values are supplied by the service handling the simulated request, such as S3
258
+ object tags. Sim IAM automatically derives the global values it can work out itself, `aws:PrincipalArn`
259
+ from the resolved caller and `aws:RequestedRegion` from the Region the request was made in. A value a
260
+ service supplies under either name is overwritten by the derived one. Context-key names are matched
261
+ case-insensitively, while string values remain case-sensitive.
262
+
263
+ Every simulated service supplies its own Region. A policy conditioned on `aws:RequestedRegion`
264
+ therefore sees the Region of the service that handled the request, whichever Region the caller was
265
+ in, and a CloudFormation deployment carries the Region of the Stack it is deploying. IAM, CloudFront
266
+ and Route53 are global, with one endpoint between all Regions. Their requests carry `us-east-1`, as
267
+ they do on AWS (which is why a service control policy confining an Account to a list of Regions has
268
+ to leave the global services' actions out of the condition). A request made straight to
269
+ `simIam.authorize(...)` carries no Region unless it is given one, and a statement conditioned on the
270
+ key then matches nothing.
271
+
272
+ ```typescript sim-iam-policy-conditions
273
+ /**
274
+ * Simulated IAM policy conditions.
275
+ */
276
+
277
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
278
+ import { SimAws } from "@kensio/yulin";
279
+
280
+ const simAws = new SimAws();
281
+ const simIam = simAws.account("123456789012").iam();
282
+
283
+ const roleCreation = await simIam.createRole(
284
+ new CreateRoleCommand({
285
+ RoleName: "FinanceReaderRole",
286
+ AssumeRolePolicyDocument: JSON.stringify({
287
+ Version: "2012-10-17",
288
+ Statement: {
289
+ Effect: "Allow",
290
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
291
+ Action: "sts:AssumeRole",
292
+ },
293
+ }),
294
+ }),
295
+ );
296
+
297
+ await simIam.putRolePolicy(
298
+ new PutRolePolicyCommand({
299
+ RoleName: "FinanceReaderRole",
300
+ PolicyName: "ReadFinanceObjects",
301
+ PolicyDocument: JSON.stringify({
302
+ Version: "2012-10-17",
303
+ Statement: {
304
+ Effect: "Allow",
305
+ Action: "s3:GetObject",
306
+ Resource: "arn:aws:s3:::reports-bucket/*",
307
+ Condition: {
308
+ StringEquals: {
309
+ "s3:ExistingObjectTag/department": "finance",
310
+ },
311
+ },
312
+ },
313
+ }),
314
+ }),
315
+ );
316
+
317
+ const decision = simIam.authorize({
318
+ action: "s3:GetObject",
319
+ resource: "arn:aws:s3:::reports-bucket/2026/summary.csv",
320
+ caller: { kind: "arn", arn: roleCreation.Role.Arn },
321
+ conditionContext: {
322
+ "s3:ExistingObjectTag/department": "finance",
323
+ },
324
+ });
325
+
326
+ console.log(decision.isAllowed);
327
+ ```
328
+
329
+ An unqualified positive operator naming a context key the request supplies no value for fails to
330
+ match, leaving the request implicitly denied unless another statement allows it. Its negated form
331
+ matches instead, as AWS documents. With no value in the request there is none for the policy value
332
+ to equal. A `ForAnyValue:` operator answers false for an absent key whatever it wraps, because no
333
+ request value is there to satisfy it.
334
+
335
+ ### Statements left unevaluated
336
+
337
+ An operator from outside the list above fails closed. The statement holding it matches nothing, and
338
+ a `Deny` written that way stops nothing. The request then goes through on whatever else allows it,
339
+ which is how a guardrail comes to report a healthy Allow. `decision.unevaluatedStatements` reports
340
+ each of those statements, with the policy it came from (`policy`), how that policy reached the
341
+ request (`sourceType`), the statement as its document declared it (`statement`), and the operator
342
+ the simulator could not evaluate (`reason`).
343
+
344
+ Every operator in a condition block is read, and an unsupported one leaves the rest of the block
345
+ evaluated as usual. A statement reaches the list once everything else about it has matched. Its
346
+ Principal, Action and Resource applied to the request, and the unsupported operator was the only
347
+ thing standing between the statement and the request. A decision reached over policies the
348
+ simulator read in full reports an empty list, and a test asserting on a guardrail can say so.
349
+
350
+ ```typescript sim-iam-unevaluated-statements
351
+ /**
352
+ * Reporting simulated IAM statements that could not be evaluated.
353
+ */
354
+
355
+ import { SimAws } from "@kensio/yulin";
356
+
357
+ const simAws = new SimAws({ defaultAccountId: "123456789012" });
358
+
359
+ simAws.organizations().attachServiceControlPolicy(
360
+ "123456789012",
361
+ {
362
+ Version: "2012-10-17",
363
+ Statement: {
364
+ Sid: "DenyBucketCreationAfterFreeze",
365
+ Effect: "Deny",
366
+ Action: "s3:CreateBucket",
367
+ Resource: "*",
368
+ Condition: {
369
+ DateGreaterThan: { "aws:CurrentTime": "2026-01-01T00:00:00Z" },
370
+ },
371
+ },
372
+ },
373
+ { policyName: "BucketGuardrail" },
374
+ );
375
+
376
+ const decision = simAws.account("123456789012").iam().authorize({
377
+ action: "s3:CreateBucket",
378
+ resource: "arn:aws:s3:::123456789012-reports",
379
+ });
380
+
381
+ const [unevaluated] = decision.unevaluatedStatements;
382
+
383
+ console.log(decision.isAllowed); // true
384
+ console.log(unevaluated?.policy); // "BucketGuardrail"
385
+ console.log(unevaluated?.reason); // "unsupported condition operator DateGreaterThan"
386
+ ```
387
+
388
+ ## Users and access keys
389
+
390
+ Create Users with `CreateUserCommand`, give them inline policies with `PutUserPolicyCommand`, and
391
+ issue access keys with `CreateAccessKeyCommand`. Access keys are registered with the Account's
392
+ credential registry. Credentials can then be supplied as the caller of an authorization attempt,
393
+ and are authenticated before policy evaluation.
394
+
395
+ `DeleteUserCommand` removes a User. IAM refuses it while the User still holds an inline policy or an
396
+ attached managed policy, the way `DeleteRoleCommand` refuses a Role, and answers `NoSuchEntity` for
397
+ a name the Account does not hold. Real IAM also refuses a User that still has access keys or a login
398
+ profile. Sim IAM serves no way to remove either, and lets the User go.
399
+
400
+ ```typescript sim-iam-user-access-key
401
+ /**
402
+ * Simulated IAM Users, inline policies, and access keys.
403
+ */
404
+
405
+ import {
406
+ CreateAccessKeyCommand,
407
+ CreateUserCommand,
408
+ PutUserPolicyCommand,
409
+ } from "@aws-sdk/client-iam";
410
+ import { SimAws } from "@kensio/yulin";
411
+
412
+ const simAws = new SimAws();
413
+ const simIam = simAws.account("123456789012").iam();
414
+
415
+ await simIam.createUser(
416
+ new CreateUserCommand({
417
+ UserName: "ApplicationUser",
418
+ Path: "/application/",
419
+ }),
420
+ );
421
+
422
+ await simIam.putUserPolicy(
423
+ new PutUserPolicyCommand({
424
+ UserName: "ApplicationUser",
425
+ PolicyName: "ReadAssets",
426
+ PolicyDocument: JSON.stringify({
427
+ Version: "2012-10-17",
428
+ Statement: {
429
+ Effect: "Allow",
430
+ Action: "s3:GetObject",
431
+ Resource: "arn:aws:s3:::assets-bucket/*",
432
+ },
433
+ }),
434
+ }),
435
+ );
436
+
437
+ const accessKeyCreation = await simIam.createAccessKey(
438
+ new CreateAccessKeyCommand({
439
+ UserName: "ApplicationUser",
440
+ }),
441
+ );
442
+
443
+ const decision = simIam.authorize({
444
+ action: "s3:GetObject",
445
+ resource: "arn:aws:s3:::assets-bucket/images/logo.svg",
446
+ caller: {
447
+ kind: "credentials",
448
+ credentials: {
449
+ accessKeyId: accessKeyCreation.AccessKey.AccessKeyId,
450
+ secretAccessKey: accessKeyCreation.AccessKey.SecretAccessKey,
451
+ },
452
+ },
453
+ });
454
+
455
+ console.log(decision.isAllowed);
456
+ console.log(decision.caller.arn);
457
+ ```
458
+
459
+ Invalid credentials throw an AWS-like error before any policies are evaluated, with a diagnostic
460
+ reason such as an unknown access key, a secret access key mismatch, or an expired session.
461
+
462
+ `AttachUserPolicyCommand` attaches a managed Policy to a User by ARN, the way
463
+ `AttachRolePolicyCommand` does for a Role. An ARN with no stored Policy behind it, such as an
464
+ AWS-managed one, attaches and contributes no statements to a decision.
465
+
466
+ `CreateLoginProfileCommand` gives a User a console password. The response describes the profile
467
+ without the password, which is how real IAM behaves. See
468
+ [CloudFormation Users](#users) for reading the password back out of the simulator.
469
+
470
+ ## STS AssumeRole sessions
471
+
472
+ Simulated STS issues temporary credentials for IAM Roles with `AssumeRoleCommand`. The assume
473
+ request is evaluated against the Role's trust policy, and the returned credentials resolve to an
474
+ assumed-role session principal whose permissions come from the underlying Role's policies.
475
+
476
+ A session carries two ARNs, the session's own and the Role's, and a resource policy naming either
477
+ one applies to it. A Bucket policy naming a Role therefore covers every session of that Role, as it
478
+ does in AWS, and `aws:PrincipalArn` holds the Role's ARN throughout.
479
+
480
+ ```typescript sim-iam-sts-assume-role
481
+ /**
482
+ * Assuming a simulated IAM Role through simulated STS.
483
+ */
484
+
485
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
486
+ import { AssumeRoleCommand } from "@aws-sdk/client-sts";
487
+ import { SimAws } from "@kensio/yulin";
488
+
489
+ const simAws = new SimAws();
490
+ const account = simAws.account("123456789012");
491
+ const simIam = account.iam();
492
+
493
+ await simIam.createRole(
494
+ new CreateRoleCommand({
495
+ RoleName: "DeploymentRole",
496
+ AssumeRolePolicyDocument: JSON.stringify({
497
+ Version: "2012-10-17",
498
+ Statement: {
499
+ Effect: "Allow",
500
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
501
+ Action: "sts:AssumeRole",
502
+ },
503
+ }),
504
+ }),
505
+ );
506
+
507
+ await simIam.putRolePolicy(
508
+ new PutRolePolicyCommand({
509
+ RoleName: "DeploymentRole",
510
+ PolicyName: "PutDeploymentObjects",
511
+ PolicyDocument: JSON.stringify({
512
+ Version: "2012-10-17",
513
+ Statement: {
514
+ Effect: "Allow",
515
+ Action: "s3:PutObject",
516
+ Resource: "arn:aws:s3:::deployments-bucket/*",
517
+ },
518
+ }),
519
+ }),
520
+ );
521
+
522
+ const assumeRoleOutput = await account.sts().assumeRole(
523
+ new AssumeRoleCommand({
524
+ RoleArn: "arn:aws:iam::123456789012:role/DeploymentRole",
525
+ RoleSessionName: "deploy-session",
526
+ }),
527
+ );
528
+
529
+ const credentials = assumeRoleOutput.Credentials!;
530
+
531
+ const decision = simIam.authorize({
532
+ action: "s3:PutObject",
533
+ resource: "arn:aws:s3:::deployments-bucket/release.zip",
534
+ caller: {
535
+ kind: "credentials",
536
+ credentials: {
537
+ accessKeyId: credentials.AccessKeyId!,
538
+ secretAccessKey: credentials.SecretAccessKey!,
539
+ sessionToken: credentials.SessionToken!,
540
+ },
541
+ },
542
+ });
543
+
544
+ console.log(decision.isAllowed);
545
+ console.log(decision.caller.arn);
546
+ ```
547
+
548
+ The resolved caller ARN is the STS assumed-role session ARN, such as
549
+ `arn:aws:sts::123456789012:assumed-role/DeploymentRole/deploy-session`, while identity policies and
550
+ the derived `aws:PrincipalArn` come from the underlying Role. A caller that the trust policy does
551
+ not allow is denied the assume request, session credentials require their session token, and
552
+ expired sessions are rejected.
553
+
554
+ ## Name the caller a simulation uses by default
555
+
556
+ Every simulated operation takes a `caller`, and a call that gives none is decided as the root
557
+ principal of the Account it reaches. `defaultCaller` on `SimAws` names a principal for those calls,
558
+ such as the Role an operator would be reading the account through.
559
+
560
+ ```typescript sim-iam-default-caller
561
+ /**
562
+ * Naming who a call that states no caller comes from.
563
+ */
564
+
565
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
566
+ import { SimAws } from "@kensio/yulin";
567
+
568
+ const simAws = new SimAws({
569
+ defaultAccountId: "123456789012",
570
+ defaultCaller: {
571
+ kind: "arn",
572
+ arn: "arn:aws:iam::123456789012:role/Administrator",
573
+ },
574
+ });
575
+
576
+ // The Role is created inside a run as the Account root. A simulation with a
577
+ // default caller attributes these commands to it, and it holds no policy until
578
+ // they are done.
579
+ const simIam = simAws.iam();
580
+
581
+ await simAws.runAs(simAws.account().rootPrincipal, async () => {
582
+ await simIam.createRole(
583
+ new CreateRoleCommand({
584
+ RoleName: "Administrator",
585
+ AssumeRolePolicyDocument: JSON.stringify({
586
+ Version: "2012-10-17",
587
+ Statement: {
588
+ Effect: "Allow",
589
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
590
+ Action: "sts:AssumeRole",
591
+ },
592
+ }),
593
+ }),
594
+ );
595
+
596
+ await simIam.putRolePolicy(
597
+ new PutRolePolicyCommand({
598
+ RoleName: "Administrator",
599
+ PolicyName: "Administer",
600
+ PolicyDocument: JSON.stringify({
601
+ Version: "2012-10-17",
602
+ Statement: { Effect: "Allow", Action: "*", Resource: "*" },
603
+ }),
604
+ }),
605
+ );
606
+ });
607
+
608
+ const decision = simAws.iam().authorize({
609
+ action: "s3:GetObject",
610
+ resource: "arn:aws:s3:::reports-bucket/summary.csv",
611
+ });
612
+
613
+ console.log(decision.caller.arn); // "arn:aws:iam::123456789012:role/Administrator"
614
+ console.log(decision.isAllowed); // true
615
+ ```
616
+
617
+ `defaultCaller` takes a principal or a caller resolved elsewhere, such as an assumed-role session
618
+ carrying the Role its policies come from. Credentials are the one caller it refuses. Only the
619
+ Account that issued a key can authenticate it, and a default is held for a whole simulation.
620
+
621
+ The default reaches a direct sim service call, an intercepted SDK Command, a CloudFormation
622
+ deployment and STS. Three things outrank it, each of them a caller stated for the request in hand.
623
+ An operation's own `caller` wins, as does the ambient caller of a `runAs` block (covered in
624
+ [Run a block of calls as one caller](#run-a-block-of-calls-as-one-caller)) and the `caller` a
625
+ deployment is given.
626
+
627
+ A simulation told no `defaultCaller` decides an unattributed call as the Account root, which is what
628
+ every simulation did before the option existed. The root keeps the identity access sim IAM gives it
629
+ either way, and a test about root behaviour reaches it as `simAws.account().rootPrincipal`. A
630
+ service control policy denying that root still overrides the access.
631
+
632
+ The reason to name one is a service control policy denying the Account root.
633
+ [Simulated Organizations](https://yulinsim.dev/services/organizations/) covers that case, where
634
+ every unattributed read is otherwise denied on a message about the root.
635
+
636
+ ## Run a block of calls as one caller
637
+
638
+ `simAws.runAs(caller, run)` sets an ambient caller for the length of a run. Everything called during
639
+ the run is attributed to that principal, and the code being tested says nothing about it.
640
+
641
+ ```typescript sim-iam-run-as
642
+ /**
643
+ * Attributing a block of calls to one simulated caller.
644
+ */
645
+
646
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
647
+ import { SimAws } from "@kensio/yulin";
648
+
649
+ const simAws = new SimAws({ defaultAccountId: "123456789012" });
650
+ const simIam = simAws.iam();
651
+
652
+ await simIam.createRole(
653
+ new CreateRoleCommand({
654
+ RoleName: "Reporter",
655
+ AssumeRolePolicyDocument: JSON.stringify({
656
+ Version: "2012-10-17",
657
+ Statement: {
658
+ Effect: "Allow",
659
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
660
+ Action: "sts:AssumeRole",
661
+ },
662
+ }),
663
+ }),
664
+ );
665
+
666
+ await simIam.putRolePolicy(
667
+ new PutRolePolicyCommand({
668
+ RoleName: "Reporter",
669
+ PolicyName: "ReadParameters",
670
+ PolicyDocument: JSON.stringify({
671
+ Version: "2012-10-17",
672
+ Statement: { Effect: "Allow", Action: "ssm:GetParameter", Resource: "*" },
673
+ }),
674
+ }),
675
+ );
676
+
677
+ await simAws.ssm().putParameter({
678
+ input: { Name: "/reports/last-run", Type: "String", Value: "done" },
679
+ });
680
+
681
+ const reporter = "arn:aws:iam::123456789012:role/Reporter";
682
+
683
+ await simAws.runAs({ kind: "arn", arn: reporter }, async () => {
684
+ // The read is a direct sim service call, decided as the Reporter Role.
685
+ const read = await simAws
686
+ .ssm()
687
+ .getParameter({ input: { Name: "/reports/last-run" } });
688
+
689
+ const write = simIam.authorize({
690
+ action: "ssm:PutParameter",
691
+ resource: "*",
692
+ });
693
+
694
+ console.log(read.Parameter?.Value); // "done"
695
+ console.log(write.caller.arn); // "arn:aws:iam::123456789012:role/Reporter"
696
+ console.log(write.isDenied); // true
697
+ });
698
+ ```
699
+
700
+ The ambient caller reaches a direct sim service call and an intercepted SDK Command. An operation's
701
+ own `caller` still wins, and `deployTemplate` and `deployCdkOut` take a `caller` of their own. Runs
702
+ nest, and the innermost caller applies.
703
+
704
+ A run belongs to the `SimAws` instance it was started on. Two simulations in one test file are two
705
+ simulated universes, and a run on one leaves the other's calls where they were.
706
+
707
+ Simulated Lambda and ECS set an ambient caller the same way. A Lambda handler runs as the function's
708
+ execution Role and an ECS container runs as its task Role. A direct sim service call from inside
709
+ either is decided as that Role, matching what the deployed code has credentials for.
710
+
711
+ This is also how a simulation bootstraps the principal its own `defaultCaller` names. That Role has
712
+ to be created before it can decide anything, and the creation therefore runs as something else.
713
+ Wrapping it in `runAs(simAws.account().rootPrincipal, ...)` is the shape for that, since sim IAM
714
+ gives the Account root unrestricted access.
715
+
716
+ ## Callers of HTTP requests
717
+
718
+ An in-process SDK call can be told who its caller is. A request arriving over HTTP, through
719
+ `serveSimAws` or through `SimAwsHttp.fetch(...)` in the same process, carries no such thing. Sim IAM
720
+ works the caller out from the request itself, in a fixed order:
721
+
722
+ 1. An `x-sim-aws-caller` header naming the principal directly.
723
+ 2. An `Authorization: AWS4-HMAC-SHA256` header, verified as a SigV4 signature.
724
+ 3. Failing both, **anonymous**.
725
+
726
+ Sim IAM treats an omitted in-process caller as the Account root with unrestricted access, a
727
+ convenience inside a test. Over HTTP the same default would make every unauthenticated request an
728
+ administrator. A served request that says nothing about who sent it is anonymous.
729
+
730
+ ### Naming the caller directly
731
+
732
+ `x-sim-aws-caller` names the principal outright. It is the path for local development and for
733
+ tooling that will not sign requests. A curl one-liner can be a Role without holding any credentials.
734
+
735
+ ```bash
736
+ curl -H 'x-sim-aws-caller: arn:aws:iam::111111111111:role/Reporter' \
737
+ http://abc123.lambda-url.us-east-1.sim-aws.localhost:4566/
738
+ ```
739
+
740
+ The value is one of three forms:
741
+
742
+ | Value | Principal |
743
+ | ---------------- | ------------------------------------------------------------ |
744
+ | An ARN | That IAM User, Role, or assumed-role session |
745
+ | `service:<name>` | An AWS service principal, such as `service:s3.amazonaws.com` |
746
+ | `anonymous` | Explicitly anonymous |
747
+
748
+ The header is always enabled and not configurable, and it takes precedence over a valid signature.
749
+ The ARN it names is taken as given, since naming a principal is a separate thing from claiming it
750
+ was created, exactly as `runAs` behaves. The header is stripped before the request reaches the
751
+ simulated service. A Lambda handler echoing `event.headers` sees none of the simulator's control
752
+ metadata.
753
+
754
+ ```typescript sim-iam-served-request-caller
755
+ /**
756
+ * Naming the caller of an HTTP request into simulated AWS.
757
+ */
758
+
759
+ import {
760
+ CreateFunctionCommand,
761
+ CreateFunctionUrlConfigCommand,
762
+ } from "@aws-sdk/client-lambda";
763
+
764
+ import { SimAws } from "@kensio/yulin";
765
+ import { makeLambdaZipFileInput } from "@kensio/yulin/lambda";
766
+ import { serveSimAws } from "@kensio/yulin/serve";
767
+
768
+ const simAws = new SimAws();
769
+
770
+ await simAws.lambda().createFunction(
771
+ new CreateFunctionCommand({
772
+ FunctionName: "reporter",
773
+ Role: "arn:aws:iam::111111111111:role/ReporterRole",
774
+ Code: { ZipFile: makeLambdaZipFileInput(() => ({ ok: true })) },
775
+ }),
776
+ );
777
+
778
+ const urlConfig = await simAws.lambda().createFunctionUrlConfig(
779
+ new CreateFunctionUrlConfigCommand({
780
+ FunctionName: "reporter",
781
+ AuthType: "NONE",
782
+ }),
783
+ );
784
+
785
+ const srv = await serveSimAws({ simAws });
786
+
787
+ try {
788
+ const response = await fetch(srv.localUrl(urlConfig.FunctionUrl), {
789
+ headers: { "x-sim-aws-caller": "arn:aws:iam::111111111111:role/Reporter" },
790
+ });
791
+
792
+ // arn:aws:iam::111111111111:role/Reporter
793
+ console.log(response.headers.get("x-sim-aws-caller"));
794
+ // caller-header
795
+ console.log(response.headers.get("x-sim-aws-auth"));
796
+ } finally {
797
+ await srv.close();
798
+ }
799
+ ```
800
+
801
+ ### Naming what the request is for
802
+
803
+ When one AWS service calls another it says which of your resources it is calling for, and IAM
804
+ supplies that as `aws:SourceArn` and `aws:SourceAccount`. A resource policy granting a service
805
+ principal is usually conditioned on them, so that a Bucket policy or a function's resource policy
806
+ admits one Distribution rather than every CloudFront customer. Two more headers say the same thing
807
+ over HTTP:
808
+
809
+ | Header | Condition key |
810
+ | -------------------------- | ------------------- |
811
+ | `x-sim-aws-source-arn` | `aws:SourceArn` |
812
+ | `x-sim-aws-source-account` | `aws:SourceAccount` |
813
+
814
+ ```bash
815
+ curl -H 'x-sim-aws-caller: service:cloudfront.amazonaws.com' \
816
+ -H 'x-sim-aws-source-arn: arn:aws:cloudfront::111111111111:distribution/E1EXAMPLE12345' \
817
+ http://abc123.lambda-url.us-east-1.sim-aws.localhost:4566/
818
+ ```
819
+
820
+ A request that supplies neither header leaves both condition keys unset, and an unset key is a
821
+ different thing from an empty one. A statement conditioned on either key fails to match. Both
822
+ headers are stripped before the request reaches the simulated service, as the caller header is.
823
+
824
+ Sim CloudFront sends these itself when a Distribution reaches a custom Origin through an origin
825
+ access control. That is how an `AWS_IAM` Lambda Function URL behind CloudFront is admitted.
826
+ Simulated Lambda Function URLs are the only endpoint evaluating them so far.
827
+
828
+ ### Signed requests
829
+
830
+ A request signed with credentials from `CreateAccessKeyCommand` or from an STS `AssumeRoleCommand`
831
+ session is verified as a SigV4 signature and resolves to the signing principal, with the same
832
+ identity `resolveCredentials` returns in process. For an assumed-role session that means the
833
+ request is attributed to the session while its permissions come from the Role behind it. A policy
834
+ on the Role applies to a request the session signed.
835
+
836
+ Sign the URL you actually call. Serving rewrites AWS endpoint hostnames to local ones, and a
837
+ Function URL is served at `<url-id>.lambda-url.<region>.sim-aws.localhost:<port>`. The `host` header
838
+ is part of what a signature covers. A signature made against the real AWS hostname fails against the
839
+ local one.
840
+
841
+ A signature whose credential scope names a different service or Region than the endpoint it reached
842
+ is refused before anything else is checked, and says so. The scope feeds the signing key. Without
843
+ that check the only symptom would be a bare signature mismatch.
844
+
845
+ ### Presigned URLs
846
+
847
+ A URL carrying its signature in query parameters is verified the same way. `X-Amz-Algorithm` in the
848
+ query is what marks it, and the access key, credential scope, signed headers and signature all come
849
+ from the query string. A presigned URL also states its own lifetime in `X-Amz-Expires`, and that
850
+ _is_ enforced, against simulated time. A frozen clock keeps a URL usable, and advancing past the
851
+ window refuses it with `AccessDenied` and `Request has expired`.
852
+
853
+ URLs built by the real presigner, `getSignedUrl` from `@aws-sdk/s3-request-presigner`, verify here
854
+ without anything simulator-specific. See
855
+ [the sim S3 docs](https://yulinsim.dev/services/s3/#presigned-urls) for the whole path from presigning to fetching.
856
+
857
+ ### What the simulator reports back
858
+
859
+ Every served response carries the simulator's own account of the request in headers, leaving the
860
+ response body the shape the real service returns. Which headers appear depends on whether the
861
+ request was accepted:
862
+
863
+ | Header | On an accepted request | On a refused request |
864
+ | ------------------------ | ---------------------------------------------------------------------------------------- | --------------------------------------------------- |
865
+ | `x-sim-aws-caller` | The principal the request was attributed to, in the same form the request header accepts | Absent, as there is no principal to report |
866
+ | `x-sim-aws-auth` | How that was decided: `caller-header`, `sigv4`, or `none` | `rejected` |
867
+ | `x-sim-aws-error` | Absent | The AWS error code, such as `SignatureDoesNotMatch` |
868
+ | `x-sim-aws-error-detail` | Absent | What the simulator can say about why |
869
+
870
+ A refused request is answered as real AWS answers it. A rejected signature gets `403` with
871
+ `{"Message":"Forbidden"}`. A signature too incomplete to parse, or an `x-sim-aws-caller` value that
872
+ names no principal form, gets `400`. Real AWS has nowhere in that body to explain itself, and this
873
+ follows it. The detail goes in `x-sim-aws-error-detail`, out of the way of a client parsing the
874
+ response.
875
+
876
+ ## Authorizing other simulated services
877
+
878
+ Simulated services use sim IAM to authorize their own actions when used through `SimAws`. Route53
879
+ commands such as `CreateHostedZoneCommand`, `GetHostedZoneCommand`,
880
+ `ChangeResourceRecordSetsCommand`, `ListHostedZonesByNameCommand`, and
881
+ `ListResourceRecordSetsCommand` accept an optional caller, letting tests exercise real allow/deny
882
+ behaviour across services.
883
+
884
+ ```typescript sim-iam-route53-authorization
885
+ /**
886
+ * Simulated IAM authorization of Route53 actions.
887
+ */
888
+
889
+ import { CreateRoleCommand } from "@aws-sdk/client-iam";
890
+ import { CreateHostedZoneCommand } from "@aws-sdk/client-route-53";
891
+ import { SimAws } from "@kensio/yulin";
892
+
893
+ const simAws = new SimAws();
894
+ const account = simAws.account("123456789012");
895
+ const simIam = account.iam();
896
+ const simRoute53 = account.route53();
897
+
898
+ const roleCreation = await simIam.createRole(
899
+ new CreateRoleCommand({
900
+ RoleName: "UnprivilegedRole",
901
+ AssumeRolePolicyDocument: JSON.stringify({
902
+ Version: "2012-10-17",
903
+ Statement: {
904
+ Effect: "Allow",
905
+ Principal: { AWS: "arn:aws:iam::123456789012:root" },
906
+ Action: "sts:AssumeRole",
907
+ },
908
+ }),
909
+ }),
910
+ );
911
+
912
+ try {
913
+ await simRoute53.createHostedZone(
914
+ new CreateHostedZoneCommand({
915
+ Name: "denied.example.test",
916
+ CallerReference: "denied-ref",
917
+ }),
918
+ {
919
+ caller: { kind: "arn", arn: roleCreation.Role.Arn },
920
+ },
921
+ );
922
+ } catch (error) {
923
+ console.error("Hosted Zone creation denied", error);
924
+ }
925
+
926
+ await simRoute53.createHostedZone(
927
+ new CreateHostedZoneCommand({
928
+ Name: "allowed.example.test",
929
+ CallerReference: "allowed-ref",
930
+ }),
931
+ );
932
+ ```
933
+
934
+ A denied action throws an AWS-like access-denied error with a `403` status code and the attempted
935
+ action, resource, and caller for diagnostics, before the service mutates any state. Omitting the
936
+ caller defaults to the Account root. The Account root is allowed within its own Account, and a test
937
+ that never mentions IAM keeps working.
938
+
939
+ ## Passing a Role to a service
940
+
941
+ A simulated service handed a Role keeps it and uses it later, under its own identity. AWS asks two
942
+ questions about that. The first is whether the caller may create the thing. The second is whether the
943
+ caller may hand that Role over, and its resource is the Role.
944
+
945
+ Six simulated services ask the second question. A caller allowed the create action and refused
946
+ `iam:PassRole` fails the request with an access-denied error naming the Role and the caller. A scoped
947
+ deployment role refused `iam:PassRole` is one of the commoner ways a real deployment stops, and a
948
+ deployment through
949
+ [simulated CloudFormation](https://yulinsim.dev/services/cloudformation/ "Simulated CloudFormation usage docs")
950
+ carries the same decision to every Resource it creates.
951
+
952
+ | Request | The Role it hands over | `iam:PassedToService` |
953
+ | ------------------------------------------------------ | ---------------------------------------- | ------------------------- |
954
+ | Lambda `CreateFunction`, `UpdateFunctionConfiguration` | `Role` | `lambda.amazonaws.com` |
955
+ | Scheduler `CreateSchedule`, `UpdateSchedule` | `Target.RoleArn` | `scheduler.amazonaws.com` |
956
+ | EventBridge `PutTargets` | a target's `RoleArn` | `events.amazonaws.com` |
957
+ | Step Functions `CreateStateMachine` | `roleArn` | `states.amazonaws.com` |
958
+ | ECS `RegisterTaskDefinition` | `taskRoleArn` and `executionRoleArn` | `ecs-tasks.amazonaws.com` |
959
+ | Firehose `CreateDeliveryStream` | the destination Role and the source Role | `firehose.amazonaws.com` |
960
+
961
+ Each Role is a separate decision, so a caller allowed one of an ECS task definition's two Roles is
962
+ refused on the other. A request leaving an optional Role out passes nothing and is asked nothing.
963
+
964
+ The condition key `iam:PassedToService` carries the service principal the Role goes to. A
965
+ CDK-generated deployment policy commonly conditions its `iam:PassRole` statement on that key, and a
966
+ policy written that way matches here.
967
+
968
+ ```typescript sim-iam-pass-role
969
+ /**
970
+ * Authorizing the execution role a Lambda function is created with.
971
+ */
972
+
973
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
974
+ import { CreateFunctionCommand } from "@aws-sdk/client-lambda";
975
+ import { SimAws } from "@kensio/yulin";
976
+ import { makeLambdaZipFileInput } from "@kensio/yulin/lambda";
977
+
978
+ const simAws = new SimAws({ defaultAccountId: "123456789012" });
979
+ const simIam = simAws.iam();
980
+
981
+ const deployerCreation = await simIam.createRole(
982
+ new CreateRoleCommand({
983
+ RoleName: "Deployer",
984
+ AssumeRolePolicyDocument: JSON.stringify({
985
+ Version: "2012-10-17",
986
+ Statement: {
987
+ Effect: "Allow",
988
+ Principal: { Service: "cloudformation.amazonaws.com" },
989
+ Action: "sts:AssumeRole",
990
+ },
991
+ }),
992
+ }),
993
+ );
994
+
995
+ await simIam.putRolePolicy(
996
+ new PutRolePolicyCommand({
997
+ RoleName: "Deployer",
998
+ PolicyName: "DeployFunctions",
999
+ PolicyDocument: JSON.stringify({
1000
+ Version: "2012-10-17",
1001
+ Statement: [
1002
+ { Effect: "Allow", Action: "lambda:CreateFunction", Resource: "*" },
1003
+ {
1004
+ Effect: "Allow",
1005
+ Action: "iam:PassRole",
1006
+ Resource: "arn:aws:iam::123456789012:role/ReportsExecutionRole",
1007
+ Condition: {
1008
+ StringEquals: { "iam:PassedToService": "lambda.amazonaws.com" },
1009
+ },
1010
+ },
1011
+ ],
1012
+ }),
1013
+ }),
1014
+ );
1015
+
1016
+ const asDeployer = {
1017
+ caller: { kind: "arn", arn: deployerCreation.Role.Arn },
1018
+ } as const;
1019
+
1020
+ await simAws.lambda().createFunction(
1021
+ new CreateFunctionCommand({
1022
+ FunctionName: "reports",
1023
+ Role: "arn:aws:iam::123456789012:role/ReportsExecutionRole",
1024
+ Code: { ZipFile: makeLambdaZipFileInput(() => null) },
1025
+ }),
1026
+ asDeployer,
1027
+ );
1028
+
1029
+ try {
1030
+ await simAws.lambda().createFunction(
1031
+ new CreateFunctionCommand({
1032
+ FunctionName: "invoices",
1033
+ Role: "arn:aws:iam::123456789012:role/AdminRole",
1034
+ Code: { ZipFile: makeLambdaZipFileInput(() => null) },
1035
+ }),
1036
+ asDeployer,
1037
+ );
1038
+ } catch (error) {
1039
+ console.error("Passing AdminRole to Lambda was refused", error);
1040
+ }
1041
+
1042
+ await simAws.backgroundTasksComplete();
1043
+ ```
1044
+
1045
+ A request naming no caller is decided as the Account root, which may pass any Role. A test that never
1046
+ mentions IAM keeps working.
1047
+
1048
+ ## A Role for a CloudFormation deployment
1049
+
1050
+ `makeDeployRole(...)` creates a Role from a policy document and hands back a caller. Pass it as
1051
+ `caller` to `deployTemplate(...)`, `deployTemplateFile(...)` or `deployCdkOut(...)`, and every
1052
+ resource the deployment creates is authorized against the document.
1053
+
1054
+ ```typescript sim-iam-make-deploy-role
1055
+ /**
1056
+ * Making a deploy Role from a policy document a project already holds.
1057
+ */
1058
+
1059
+ import { SimAws } from "@kensio/yulin";
1060
+
1061
+ const simAws = new SimAws({ defaultAccountId: "123456789012" });
1062
+
1063
+ const deployer = await simAws.iam().makeDeployRole({
1064
+ roleName: "cdk-exec",
1065
+ policyDocument: {
1066
+ Version: "2012-10-17",
1067
+ Statement: {
1068
+ Effect: "Allow",
1069
+ Action: ["s3:*", "kms:*"],
1070
+ Resource: "*",
1071
+ },
1072
+ },
1073
+ });
1074
+
1075
+ console.log(deployer.arn); // "arn:aws:iam::123456789012:role/cdk-exec"
1076
+
1077
+ await simAws
1078
+ .cloudFormation()
1079
+ .deployCdkOut({ directoryPath: "cdk.out", caller: deployer });
1080
+ ```
1081
+
1082
+ The Role trusts `cloudformation.amazonaws.com` and holds the document as an inline policy. A
1083
+ deployment that asks for something the document leaves out fails the resource, with the Role's ARN in
1084
+ the message.
1085
+
1086
+ `policyDocument` also takes the JSON a synthesized policy is carried as, and a list of documents for
1087
+ a policy split in two to stay under IAM's size cap. Each document goes on the Role as its own inline
1088
+ policy, and the Role is allowed the union of them.
1089
+
1090
+ ```typescript sim-iam-deploy-role-documents
1091
+ /**
1092
+ * A deploy Role from a policy split across two documents.
1093
+ */
1094
+
1095
+ import { SimAws } from "@kensio/yulin";
1096
+
1097
+ const simAws = new SimAws({ defaultAccountId: "123456789012" });
1098
+
1099
+ const deployer = await simAws.iam().makeDeployRole({
1100
+ roleName: "cdk-exec",
1101
+ policyDocument: [
1102
+ JSON.stringify({
1103
+ Version: "2012-10-17",
1104
+ Statement: { Effect: "Allow", Action: "s3:*", Resource: "*" },
1105
+ }),
1106
+ {
1107
+ Version: "2012-10-17",
1108
+ Statement: { Effect: "Allow", Action: "kms:*", Resource: "*" },
1109
+ },
1110
+ ],
1111
+ });
1112
+
1113
+ console.log(deployer.kind); // "arn"
1114
+ ```
1115
+
1116
+ Making the Role is two ordinary IAM commands. A simulation with a restrictive default caller has to
1117
+ be allowed them, or the call wrapped in `simAws.runAs(...)`.
1118
+
1119
+ ## CloudFormation IAM resources
1120
+
1121
+ Sim CloudFormation can create IAM resources from `AWS::IAM::Role`, `AWS::IAM::User`,
1122
+ `AWS::IAM::ManagedPolicy`, and `AWS::IAM::Policy`. An `AWS::IAM::Policy` puts its document onto each
1123
+ Role named in `Roles` and each User named in `Users` as an inline policy. That is the shape CDK
1124
+ grants such as `bucket.grantRead(fn)` and `bucket.grantRead(user)` synthesize as a "DefaultPolicy"
1125
+ resource. Every entry names a Role or a User in the Stack's Account. An entry naming no simulated
1126
+ principal fails the resource, and so does a policy naming no principal at all. A `Groups` property
1127
+ still fails the resource.
1128
+
1129
+ A statement value of the wrong type fails the resource too. A `Ref` or an `Fn::GetAtt` naming a
1130
+ Resource the template leaves out survives resolution and reaches IAM as an object where `Action` or
1131
+ `Resource` takes a string. The put refuses it with `MalformedPolicyDocument`, naming the Role or
1132
+ User, the policy and the statement holding it.
1133
+
1134
+ An `AWS::IAM::ManagedPolicy` also carries `Roles`, and attaches itself to each Role it names as it
1135
+ is created (the attachment `AttachRolePolicy` records). A name no simulated Role in the Account
1136
+ answers to fails the resource. Deleting the stack takes the policy back off the Roles still
1137
+ carrying it, and then deletes the policy.
1138
+
1139
+ A Role with no `RoleName`, a User with no `UserName` and a Managed Policy with no
1140
+ `ManagedPolicyName` are each named from the stack name, the logical ID and a tail derived from both.
1141
+ A `ServiceRole` in `iam-stack` becomes `iam-stack-ServiceRole-` and twelve more characters, where
1142
+ real CloudFormation ends the name in twelve random ones. The case is kept as it was written, the way
1143
+ IAM keeps it. A Role name and a User name are trimmed to 64 characters and a policy name to 128, and
1144
+ [the CloudFormation docs](https://yulinsim.dev/services/cloudformation/#names-cloudformation-generates "Names CloudFormation generates")
1145
+ cover how the stack name and the logical ID share what is left.
1146
+
1147
+ That name is what an IAM policy scoped by name prefix matches. A deploy Role allowed `iam:CreateRole`
1148
+ on `arn:aws:iam::123456789012:role/iam-stack-*` covers the Roles its own stack creates, here and in
1149
+ an account.
1150
+
1151
+ ```typescript sim-iam-cloudformation
1152
+ /**
1153
+ * Creating IAM resources through simulated CloudFormation.
1154
+ */
1155
+
1156
+ import { GetRoleCommand } from "@aws-sdk/client-iam";
1157
+ import { SimAws } from "@kensio/yulin";
1158
+
1159
+ const simAws = new SimAws();
1160
+
1161
+ const stack = await simAws.cloudFormation().deployTemplate({
1162
+ stackName: "iam-stack",
1163
+ template: {
1164
+ Resources: {
1165
+ ServiceRole: {
1166
+ Type: "AWS::IAM::Role",
1167
+ Properties: {
1168
+ RoleName: "LambdaExecutionRole",
1169
+ Path: "/service-role/",
1170
+ AssumeRolePolicyDocument: {
1171
+ Version: "2012-10-17",
1172
+ Statement: {
1173
+ Effect: "Allow",
1174
+ Principal: { Service: "lambda.amazonaws.com" },
1175
+ Action: "sts:AssumeRole",
1176
+ },
1177
+ },
1178
+ Policies: [
1179
+ {
1180
+ PolicyName: "ReadReports",
1181
+ PolicyDocument: {
1182
+ Version: "2012-10-17",
1183
+ Statement: {
1184
+ Effect: "Allow",
1185
+ Action: "s3:GetObject",
1186
+ Resource: "arn:aws:s3:::reports-bucket/*",
1187
+ },
1188
+ },
1189
+ },
1190
+ ],
1191
+ },
1192
+ },
1193
+ ReadOnlyPolicy: {
1194
+ Type: "AWS::IAM::ManagedPolicy",
1195
+ Properties: {
1196
+ ManagedPolicyName: "ReadOnlyAccess",
1197
+ Roles: [{ Ref: "ServiceRole" }],
1198
+ PolicyDocument: {
1199
+ Version: "2012-10-17",
1200
+ Statement: {
1201
+ Effect: "Allow",
1202
+ Action: "s3:GetObject",
1203
+ Resource: "*",
1204
+ },
1205
+ },
1206
+ },
1207
+ },
1208
+ },
1209
+ Outputs: {
1210
+ RoleArn: {
1211
+ Value: {
1212
+ "Fn::GetAtt": ["ServiceRole", "Arn"],
1213
+ },
1214
+ },
1215
+ PolicyArn: {
1216
+ Value: {
1217
+ Ref: "ReadOnlyPolicy",
1218
+ },
1219
+ },
1220
+ },
1221
+ },
1222
+ });
1223
+
1224
+ await stack.waitForDeployComplete();
1225
+
1226
+ console.log(stack.output("RoleArn"));
1227
+ console.log(stack.output("PolicyArn"));
1228
+
1229
+ const roleOut = await simAws.iam().getRole(
1230
+ new GetRoleCommand({
1231
+ RoleName: "LambdaExecutionRole",
1232
+ }),
1233
+ );
1234
+
1235
+ console.log(roleOut.Role.Arn);
1236
+ ```
1237
+
1238
+ For `AWS::IAM::Role`, `Ref` returns the Role name and `Fn::GetAtt` supports `Arn` and `RoleId`. For
1239
+ `AWS::IAM::ManagedPolicy`, `Ref` returns the Policy ARN. Both resource types default their name to
1240
+ the logical ID when it is omitted, and inline `Policies` declared on a Role are stored as the
1241
+ Role's inline policies. The `ReadOnlyAccess` policy above is attached to `LambdaExecutionRole`.
1242
+ Authorization for that Role reads the policy document the template gave it.
1243
+
1244
+ ### Users
1245
+
1246
+ An `AWS::IAM::User` creates a User in the Stack's Account. `UserName` names it and falls back to the
1247
+ Resource logical ID. `Path`, the inline `Policies` list and `ManagedPolicyArns` work as they do on a
1248
+ Role, and both policy forms reach the authorization decision made for that User. `Ref` returns the
1249
+ User name and `Fn::GetAtt` supports `Arn` and `UserId`.
1250
+
1251
+ `LoginProfile` gives the User a console password, the way real CloudFormation calls
1252
+ `CreateLoginProfile`. The profile records the password, its creation date and
1253
+ `PasswordResetRequired`. Real IAM never reads a password back, and neither does the simulator. A
1254
+ test asserting on the password reads the User record from `SimIam.users`.
1255
+
1256
+ A separate `AWS::IAM::Policy` naming the User in `Users` puts its document onto the User as another
1257
+ inline policy. That is what a CDK grant against a User synthesizes.
1258
+
1259
+ Group membership is a gap. A `Groups` entry fails the Resource. An empty list still deploys, and CDK
1260
+ leaves `Groups` out of the template for a User that belongs to no group.
1261
+
1262
+ Deleting the Stack deletes the User. Its inline policies and managed policy attachments come off
1263
+ first, as they do for a Role, and the User name is free for the same template to deploy again.
1264
+
1265
+ ```typescript sim-iam-cloudformation-user
1266
+ /**
1267
+ * Creating an IAM User through simulated CloudFormation.
1268
+ */
1269
+
1270
+ import { SimAws } from "@kensio/yulin";
1271
+
1272
+ const simAws = new SimAws();
1273
+
1274
+ const stack = await simAws.cloudFormation().deployTemplate({
1275
+ stackName: "iam-user-stack",
1276
+ template: {
1277
+ Resources: {
1278
+ ReportsReadPolicy: {
1279
+ Type: "AWS::IAM::ManagedPolicy",
1280
+ Properties: {
1281
+ ManagedPolicyName: "ReportsReadPolicy",
1282
+ PolicyDocument: {
1283
+ Version: "2012-10-17",
1284
+ Statement: {
1285
+ Effect: "Allow",
1286
+ Action: "s3:GetObject",
1287
+ Resource: "arn:aws:s3:::reports-bucket/*",
1288
+ },
1289
+ },
1290
+ },
1291
+ },
1292
+ ReportPublisher: {
1293
+ Type: "AWS::IAM::User",
1294
+ Properties: {
1295
+ UserName: "ReportPublisher",
1296
+ Path: "/application/",
1297
+ ManagedPolicyArns: [{ Ref: "ReportsReadPolicy" }],
1298
+ Policies: [
1299
+ {
1300
+ PolicyName: "WriteReports",
1301
+ PolicyDocument: {
1302
+ Version: "2012-10-17",
1303
+ Statement: {
1304
+ Effect: "Allow",
1305
+ Action: "s3:PutObject",
1306
+ Resource: "arn:aws:s3:::reports-bucket/*",
1307
+ },
1308
+ },
1309
+ },
1310
+ ],
1311
+ LoginProfile: {
1312
+ Password: "initial-console-password",
1313
+ PasswordResetRequired: true,
1314
+ },
1315
+ },
1316
+ },
1317
+ },
1318
+ Outputs: {
1319
+ UserArn: {
1320
+ Value: {
1321
+ "Fn::GetAtt": ["ReportPublisher", "Arn"],
1322
+ },
1323
+ },
1324
+ },
1325
+ },
1326
+ });
1327
+
1328
+ await stack.waitForDeployComplete();
1329
+
1330
+ const simIam = simAws.iam();
1331
+
1332
+ const decision = simIam.authorize({
1333
+ action: "s3:PutObject",
1334
+ resource: "arn:aws:s3:::reports-bucket/2026/summary.csv",
1335
+ caller: { kind: "arn", arn: stack.output("UserArn") },
1336
+ });
1337
+
1338
+ console.log(decision.isAllowed);
1339
+
1340
+ const user = simIam.users
1341
+ .values()
1342
+ .find((each) => each.userName === "ReportPublisher");
1343
+
1344
+ console.log(user?.loginProfile?.passwordResetRequired);
1345
+ ```
1346
+
1347
+ ## Accounts
1348
+
1349
+ IAM is account-scoped in AWS, and sim IAM matches that. Every Region scope of the same simulated
1350
+ Account shares one IAM state, while different Accounts are fully isolated from each other.
1351
+
1352
+ ```typescript sim-iam-account-scoping
1353
+ /**
1354
+ * Simulated IAM Account scoping.
1355
+ */
1356
+
1357
+ import { CreateUserCommand } from "@aws-sdk/client-iam";
1358
+ import { SimAws } from "@kensio/yulin";
1359
+
1360
+ const simAws = new SimAws();
1361
+
1362
+ const firstAccountIam = simAws.account("111111111111").iam();
1363
+ const secondAccountIam = simAws.account("222222222222").iam();
1364
+
1365
+ const firstUserOutput = await firstAccountIam.createUser(
1366
+ new CreateUserCommand({ UserName: "DeployUser" }),
1367
+ );
1368
+ const secondUserOutput = await secondAccountIam.createUser(
1369
+ new CreateUserCommand({ UserName: "DeployUser" }),
1370
+ );
1371
+
1372
+ console.log(firstUserOutput.User.Arn);
1373
+ console.log(secondUserOutput.User.Arn);
1374
+ ```
1375
+
1376
+ Principals from one Account get no implicit access to another Account's resources. Authorizing a
1377
+ caller from a different simulated Account results in an implicit deny unless both Accounts allow the
1378
+ request.
1379
+
1380
+ ## Cross-Account requests
1381
+
1382
+ A request whose caller belongs to a different Account from the resource is decided in both
1383
+ Accounts, as it is on AWS:
1384
+
1385
+ - The resource's Account must allow it through a resource policy, such as an S3 Bucket policy or a
1386
+ Lambda permission
1387
+ - The caller's Account must allow it through an identity policy on that principal
1388
+
1389
+ Either one on its own is denied. A resource policy naming another Account's principal delegates to
1390
+ that Account, and an Account cannot grant its own principals access to somebody else's resource. An
1391
+ explicit `Deny` on either side denies. Callers with no
1392
+ identity side, such as a service principal or an anonymous request, are unaffected, and are still
1393
+ allowed by a resource policy alone.
1394
+
1395
+ ```typescript sim-iam-cross-account
1396
+ /**
1397
+ * A cross-Account request needs an allow from both Accounts.
1398
+ */
1399
+
1400
+ import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
1401
+ import { SimAws } from "@kensio/yulin";
1402
+
1403
+ const simAws = new SimAws();
1404
+ const partnerRoleArn = "arn:aws:iam::222222222222:role/Reader";
1405
+
1406
+ // The Bucket's Account grants the partner Account's Role.
1407
+ const bucketPolicy = {
1408
+ document: {
1409
+ Version: "2012-10-17",
1410
+ Statement: {
1411
+ Effect: "Allow",
1412
+ Principal: { AWS: partnerRoleArn },
1413
+ Action: "s3:GetObject",
1414
+ Resource: "arn:aws:s3:::reports-bucket/*",
1415
+ },
1416
+ },
1417
+ } as const;
1418
+
1419
+ const request = {
1420
+ action: "s3:GetObject",
1421
+ resource: "arn:aws:s3:::reports-bucket/summary.csv",
1422
+ caller: { kind: "arn", arn: partnerRoleArn },
1423
+ resourcePolicies: [bucketPolicy],
1424
+ } as const;
1425
+
1426
+ const beforeIdentityPolicy = simAws
1427
+ .account("111111111111")
1428
+ .iam()
1429
+ .authorize(request);
1430
+
1431
+ // false: the partner Account has not allowed its Role to read anything.
1432
+ console.log(beforeIdentityPolicy.isAllowed);
1433
+ console.log(beforeIdentityPolicy.resourceAllowStatements.length); // 1
1434
+ console.log(beforeIdentityPolicy.identityAllowStatements.length); // 0
1435
+
1436
+ // The partner Account allows its own Role.
1437
+ const partnerIam = simAws.account("222222222222").iam();
1438
+
1439
+ await partnerIam.createRole(
1440
+ new CreateRoleCommand({
1441
+ RoleName: "Reader",
1442
+ AssumeRolePolicyDocument: JSON.stringify({
1443
+ Version: "2012-10-17",
1444
+ Statement: {
1445
+ Effect: "Allow",
1446
+ Principal: { AWS: "arn:aws:iam::222222222222:root" },
1447
+ Action: "sts:AssumeRole",
1448
+ },
1449
+ }),
1450
+ }),
1451
+ );
1452
+
1453
+ await partnerIam.putRolePolicy(
1454
+ new PutRolePolicyCommand({
1455
+ RoleName: "Reader",
1456
+ PolicyName: "ReadReports",
1457
+ PolicyDocument: JSON.stringify({
1458
+ Version: "2012-10-17",
1459
+ Statement: {
1460
+ Effect: "Allow",
1461
+ Action: "s3:GetObject",
1462
+ Resource: "arn:aws:s3:::reports-bucket/*",
1463
+ },
1464
+ }),
1465
+ }),
1466
+ );
1467
+
1468
+ // true: both Accounts now allow the request.
1469
+ console.log(simAws.account("111111111111").iam().authorize(request).isAllowed);
1470
+ ```
1471
+
1472
+ The caller's Account is resolved from the principal ARN. For its policies to count, that Account has
1473
+ to belong to the same `SimAws` instance. An Account the simulation was never told about grants
1474
+ nothing. On AWS, a principal ARN that was never given any permissions comes out the same way.
1475
+
1476
+ A standalone `SimIam` has no simulation around it, and so no other Account to ask. A principal whose
1477
+ ARN belongs to another Account is always denied, however permissive the resource policy. Anonymous
1478
+ and service-principal callers carry on as before, since they have no Account either way, and a
1479
+ resource policy still allows them. The Account ID is available as `simIam.accountId`. A test naming
1480
+ its own principals should build their ARNs from that.
1481
+
1482
+ ## Standalone SimIam
1483
+
1484
+ If you only need IAM alone, you can instantiate `SimIam` directly.
1485
+
1486
+ ```typescript sim-iam-standalone
1487
+ /**
1488
+ * Standalone simulated IAM instance.
1489
+ */
1490
+
1491
+ import { CreateRoleCommand } from "@aws-sdk/client-iam";
1492
+ import { SimIam } from "@kensio/yulin/iam";
1493
+
1494
+ const simIam = new SimIam();
1495
+
1496
+ const roleCreation = await simIam.createRole(
1497
+ new CreateRoleCommand({
1498
+ RoleName: "StandaloneRole",
1499
+ AssumeRolePolicyDocument: JSON.stringify({
1500
+ Version: "2012-10-17",
1501
+ Statement: {
1502
+ Effect: "Allow",
1503
+ Principal: { Service: "lambda.amazonaws.com" },
1504
+ Action: "sts:AssumeRole",
1505
+ },
1506
+ }),
1507
+ }),
1508
+ );
1509
+
1510
+ console.log(roleCreation.Role.Arn);
1511
+ ```
1512
+
1513
+ A standalone `SimIam` instance has its own isolated state, scoped to a generated Account ID, and
1514
+ stands apart from any wider `SimAws` environment. Other services instantiated standalone, such as
1515
+ `new SimRoute53()`, fall back to allow-all authorization. Connect services through a shared `SimAws`
1516
+ instance when a test should exercise real IAM enforcement.
1517
+
1518
+ ## Available functionality
1519
+
1520
+ Sim IAM currently supports:
1521
+
1522
+ - `makeDeployRole(...)`, creating a Role for a CloudFormation deployment to run as
1523
+ - `CreateRoleCommand`, including trust-policy validation
1524
+ - `GetRoleCommand` and `ListRolesCommand`, with pagination
1525
+ - `PutRolePolicyCommand`, for inline Role policies
1526
+ - `CreatePolicyCommand`, `GetPolicyCommand` and `ListPoliciesCommand`, for managed Policies
1527
+ - Refusing a policy document over IAM's character limit, with `LimitExceeded`
1528
+ - `AttachRolePolicyCommand`
1529
+ - `CreateUserCommand`, `DeleteUserCommand`, `PutUserPolicyCommand` and `AttachUserPolicyCommand`
1530
+ - `CreateLoginProfileCommand`, for a User's console password
1531
+ - `CreateAccessKeyCommand`, registering access keys for credential authentication
1532
+ - Allow/deny authorization decisions with `authorize(...)`, evaluating identity policies,
1533
+ service-supplied resource policies, and policy conditions with explicit-deny precedence
1534
+ - IAM authorization at simulated service boundaries, such as Route53 actions
1535
+ - `iam:PassRole` authorization of a Role handed to simulated Lambda, Scheduler, EventBridge, Step
1536
+ Functions, ECS or Firehose, with `iam:PassedToService` supplied
1537
+ - Resolving the caller of an HTTP request, from an `x-sim-aws-caller` header or a verified SigV4
1538
+ signature, defaulting to anonymous, and the resource it is made on behalf of from
1539
+ `x-sim-aws-source-arn` and `x-sim-aws-source-account`
1540
+ - Temporary Role sessions through simulated STS `AssumeRoleCommand`, evaluated against Role trust
1541
+ policies
1542
+ - The `AWS::IAM::Role`, `AWS::IAM::User`, `AWS::IAM::ManagedPolicy` and `AWS::IAM::Policy`
1543
+ CloudFormation resources
1544
+
1545
+ Unsupported IAM options may be ignored or may throw errors depending on whether the simulator needs
1546
+ them to model the requested behaviour.
1547
+
1548
+ ## Limitations
1549
+
1550
+ Sim IAM models the policy behaviour that multi-service tests most commonly need. Notable gaps:
1551
+
1552
+ - Groups are absent. An `AWS::IAM::User` naming one fails, and an `AWS::IAM::Policy` naming one
1553
+ 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")
1556
+ - Managed Policies have a single version, and the policy version commands are absent
1557
+ - A policy document is measured against IAM's character limit one document at a time. The
1558
+ 20,480-character cap on the sum of a User's inline policies is absent, and so is the cap on how
1559
+ many managed policies a Role may carry
1560
+ - `DeleteUserPolicy` and `DetachUserPolicy` are absent, along with `DeleteAccessKey` and
1561
+ `DeleteLoginProfile`. `DeleteUserCommand` refuses a User that still holds a policy, and
1562
+ CloudFormation teardown clears a User's policies before deleting it
1563
+ - Only the condition operators listed above are supported. A statement using any other operator
1564
+ fails closed, matching no request. `decision.unevaluatedStatements` names those statements, and a
1565
+ test can assert that a decision was reached over policies read in full
1566
+ - A positive `ForAllValues:` condition fails to match a request carrying no value for the key, and
1567
+ fails to match an empty value set. AWS matches both, and the negated form here matches both
1568
+ - Signature age is deliberately not enforced. `X-Amz-Date` must be present, well formed, and agree
1569
+ with the credential scope date, but is never compared to a clock. A client stamping real time can
1570
+ therefore reach a simulation keeping a different one. Session expiry _is_ enforced, against
1571
+ simulated time
1572
+ - S3 `aws-chunked` streaming signatures and SigV4A are not verified. Presigned query-string
1573
+ authentication is verified, for the `AWS4-HMAC-SHA256` algorithm only
1574
+ - The resolved caller is evaluated by Lambda Function URLs with `AuthType: "AWS_IAM"` and by the S3
1575
+ REST endpoint, but not yet by the other services that serve HTTP. Website-endpoint S3 responses
1576
+ and CloudFront responses perform no authorization
1577
+ - The identity side of a cross-Account request comes from the caller's Account in the same `SimAws`
1578
+ instance. A caller whose Account is absent from the simulation is denied