@kensio/yulin 1.20.12 → 1.20.13

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 (132) hide show
  1. package/dist/service/acm/command/delete-certificate/delete-certificate-authorizer.js +1 -0
  2. package/dist/service/acm/command/describe-certificate/describe-certificate-authorizer.js +1 -0
  3. package/dist/service/acm/command/list-certificates/list-certificates-authorizer.js +1 -0
  4. package/dist/service/acm/command/request-certificate/request-certificate-authorizer.js +1 -0
  5. package/dist/service/apigateway/serve/auth/sim-rest-api-authorizer-policy.js +3 -0
  6. package/dist/service/apigatewayv2/serve/auth/sim-http-api-authorizer-policy.js +3 -0
  7. package/dist/service/aws/factory/sim-aws-account-service-cache.d.ts +3 -0
  8. package/dist/service/aws/factory/sim-aws-account-service-cache.js +5 -0
  9. package/dist/service/aws/factory/sim-aws-service-factory.d.ts +9 -0
  10. package/dist/service/aws/factory/sim-aws-service-factory.js +10 -0
  11. package/dist/service/aws/sim-aws.d.ts +18 -0
  12. package/dist/service/aws/sim-aws.js +19 -0
  13. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn-value-adapter.d.ts +6 -0
  14. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn-value-adapter.js +23 -0
  15. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn.d.ts +66 -0
  16. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn.js +136 -0
  17. package/dist/service/cloudformation/resource/cfn/sim-cfn-service-value-adapters.js +2 -0
  18. package/dist/service/cloudformation/resource/resolve/service/sim-cfn-service-factories.js +7 -0
  19. package/dist/service/cloudfront/command/create-distribution/create-distribution-authorizer.js +1 -0
  20. package/dist/service/cloudfront/command/create-function/create-function-authorizer.js +1 -0
  21. package/dist/service/cloudfront/command/delete-distribution/delete-distribution-authorizer.js +1 -0
  22. package/dist/service/cloudfront/command/delete-function/delete-function-authorizer.js +1 -0
  23. package/dist/service/cloudfront/command/get-distribution/get-distribution-authorizer.js +1 -0
  24. package/dist/service/cloudfront/command/update-distribution/update-distribution-authorizer.js +1 -0
  25. package/dist/service/cloudfront/edge/sim-cf-edge-association-auth-z.js +1 -0
  26. package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store-access.js +1 -0
  27. package/dist/service/cloudwatch/command/authorize/sim-cloudwatch-decide.js +1 -0
  28. package/dist/service/cognito/command/authorize/sim-cognito-authorizer.js +1 -0
  29. package/dist/service/dynamodb/command/authorize/sim-dynamodb-authorizer.js +1 -0
  30. package/dist/service/firehose/command/authorize/sim-firehose-authorizer.js +1 -0
  31. package/dist/service/glue/command/authorize/sim-glue-authorize-resources.js +1 -0
  32. package/dist/service/iam/authorize/allow/sim-iam-policy-evaluation.d.ts +45 -0
  33. package/dist/service/iam/authorize/allow/sim-iam-policy-evaluation.js +59 -0
  34. package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.d.ts +15 -4
  35. package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.js +15 -4
  36. package/dist/service/iam/authorize/context/sim-iam-auth-z-context.d.ts +31 -1
  37. package/dist/service/iam/authorize/context/sim-iam-auth-z-context.factory.js +1 -0
  38. package/dist/service/iam/authorize/context/sim-iam-auth-z-scp-source-builder.d.ts +46 -0
  39. package/dist/service/iam/authorize/context/sim-iam-auth-z-scp-source-builder.js +71 -0
  40. package/dist/service/iam/authorize/scp/sim-iam-scp-gate.d.ts +96 -0
  41. package/dist/service/iam/authorize/scp/sim-iam-scp-gate.js +148 -0
  42. package/dist/service/iam/authorize/scp/sim-iam-scp-resolver.d.ts +53 -0
  43. package/dist/service/iam/authorize/scp/sim-iam-scp-resolver.js +1 -0
  44. package/dist/service/iam/authorize/sim-iam-account-auth-z.d.ts +8 -0
  45. package/dist/service/iam/authorize/sim-iam-account-auth-z.js +1 -0
  46. package/dist/service/iam/authorize/sim-iam-action-authorizer.js +1 -0
  47. package/dist/service/iam/authorize/sim-iam-authorizer.d.ts +2 -0
  48. package/dist/service/iam/authorize/sim-iam-authorizer.js +1 -0
  49. package/dist/service/iam/authorize/sim-iam-decision-value.d.ts +13 -0
  50. package/dist/service/iam/authorize/sim-iam-decision-value.js +12 -0
  51. package/dist/service/iam/authorize/sim-iam-decision.d.ts +33 -16
  52. package/dist/service/iam/authorize/sim-iam-decision.js +64 -49
  53. package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.d.ts +8 -0
  54. package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.js +1 -0
  55. package/dist/service/iam/error/sim-iam.error.d.ts +8 -0
  56. package/dist/service/iam/error/sim-iam.error.js +2 -1
  57. package/dist/service/iam/sim-iam-account-parts.d.ts +9 -0
  58. package/dist/service/iam/sim-iam-account-parts.js +1 -0
  59. package/dist/service/kinesis/command/authorize/sim-kinesis-authorizer.js +1 -0
  60. package/dist/service/kms/command/authorize/sim-kms-authorizer.js +2 -0
  61. package/dist/service/lambda/command/create-function/create-function-authorizer.js +1 -0
  62. package/dist/service/lambda/command/delete-function/delete-function-authorizer.js +1 -0
  63. package/dist/service/lambda/command/event-invoke-config/event-invoke-config-authorizer.js +1 -0
  64. package/dist/service/lambda/command/function-url/function-url-authorizer.js +1 -0
  65. package/dist/service/lambda/command/get-function/get-function-authorizer.js +1 -0
  66. package/dist/service/lambda/command/invoke/invoke-authorizer.js +1 -0
  67. package/dist/service/lambda/command/list-functions/list-functions-authorizer.js +1 -0
  68. package/dist/service/lambda/command/update-function-code/update-function-code-authorizer.js +1 -0
  69. package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.js +1 -0
  70. package/dist/service/lambda/command/version/version-authorizer.js +1 -0
  71. package/dist/service/logs/command/authorize/sim-logs-authorizer.js +1 -0
  72. package/dist/service/organizations/cfn/sim-cfn-organization-creator.d.ts +19 -0
  73. package/dist/service/organizations/cfn/sim-cfn-organization-creator.js +25 -0
  74. package/dist/service/organizations/cfn/sim-cfn-organizational-unit-creator.d.ts +16 -0
  75. package/dist/service/organizations/cfn/sim-cfn-organizational-unit-creator.js +21 -0
  76. package/dist/service/organizations/cfn/sim-cfn-organizations-account-creator.d.ts +20 -0
  77. package/dist/service/organizations/cfn/sim-cfn-organizations-account-creator.js +34 -0
  78. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-creator.d.ts +21 -0
  79. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-creator.js +40 -0
  80. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-input.d.ts +20 -0
  81. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-input.js +33 -0
  82. package/dist/service/organizations/cfn/sim-cfn-organizations-properties.d.ts +36 -0
  83. package/dist/service/organizations/cfn/sim-cfn-organizations-properties.js +78 -0
  84. package/dist/service/organizations/cfn/sim-cfn-organizations-record.d.ts +40 -0
  85. package/dist/service/organizations/cfn/sim-cfn-organizations-record.js +54 -0
  86. package/dist/service/organizations/cfn/sim-cfn-organizations-remover.d.ts +17 -0
  87. package/dist/service/organizations/cfn/sim-cfn-organizations-remover.js +40 -0
  88. package/dist/service/organizations/cfn/sim-organizations-cfn-resource-factory.d.ts +24 -0
  89. package/dist/service/organizations/cfn/sim-organizations-cfn-resource-factory.js +50 -0
  90. package/dist/service/organizations/index.d.ts +6 -0
  91. package/dist/service/organizations/index.js +6 -0
  92. package/dist/service/organizations/policy/sim-organizations-effective-policies.d.ts +43 -0
  93. package/dist/service/organizations/policy/sim-organizations-effective-policies.js +58 -0
  94. package/dist/service/organizations/policy/sim-organizations-scp-store.d.ts +61 -0
  95. package/dist/service/organizations/policy/sim-organizations-scp-store.js +103 -0
  96. package/dist/service/organizations/sim-organizations-structure.d.ts +94 -0
  97. package/dist/service/organizations/sim-organizations-structure.js +140 -0
  98. package/dist/service/organizations/sim-organizations.d.ts +95 -0
  99. package/dist/service/organizations/sim-organizations.js +99 -0
  100. package/dist/service/organizations/tree/sim-organizations-node.d.ts +57 -0
  101. package/dist/service/organizations/tree/sim-organizations-node.js +58 -0
  102. package/dist/service/organizations/tree/sim-organizations-tree.d.ts +91 -0
  103. package/dist/service/organizations/tree/sim-organizations-tree.js +154 -0
  104. package/dist/service/route53/command/change-resource-record-sets/change-resource-record-sets-authorizer.js +1 -0
  105. package/dist/service/route53/command/create-hosted-zone/create-hosted-zone-authorizer.js +1 -0
  106. package/dist/service/route53/command/delete-hosted-zone/delete-hosted-zone-authorizer.js +1 -0
  107. package/dist/service/route53/command/dnssec/sim-route53-dnssec-authorizer.js +1 -0
  108. package/dist/service/route53/command/get-hosted-zone/get-hosted-zone-authorizer.js +1 -0
  109. package/dist/service/route53/command/list-hosted-zones-by-name/list-hosted-zones-by-name-authorizer.js +1 -0
  110. package/dist/service/route53/command/list-resource-record-sets/list-resource-record-sets-authorizer.js +1 -0
  111. package/dist/service/s3/command/create-bucket/create-bucket.handler.js +1 -0
  112. package/dist/service/s3/command/delete-bucket/delete-bucket-authorizer.js +1 -0
  113. package/dist/service/s3/command/delete-bucket-policy/delete-bucket-policy-authorizer.js +1 -0
  114. package/dist/service/s3/command/delete-object/delete-object-authorizer.js +1 -0
  115. package/dist/service/s3/command/get-bucket-policy/get-bucket-policy-authorizer.js +1 -0
  116. package/dist/service/s3/command/get-object/get-object-authorizer.js +1 -0
  117. package/dist/service/s3/command/head-bucket/head-bucket-authorizer.js +1 -0
  118. package/dist/service/s3/command/lifecycle/sim-s3-lifecycle-authorizer.js +1 -0
  119. package/dist/service/s3/command/list-buckets/list-buckets-authorizer.js +1 -0
  120. package/dist/service/s3/command/list-objects/list-objects-authorizer.js +1 -0
  121. package/dist/service/s3/command/multipart/sim-s3-multipart-authorizer.js +1 -0
  122. package/dist/service/s3/command/notification/sim-s3-notification-authorizer.js +1 -0
  123. package/dist/service/s3/command/public-access-block/sim-s3-public-access-block-authorizer.js +1 -0
  124. package/dist/service/s3/command/put-bucket-policy/put-bucket-policy-authorizer.js +1 -0
  125. package/dist/service/s3/command/put-bucket-website/put-bucket-website-authorizer.js +1 -0
  126. package/dist/service/s3/command/put-object/put-object-authorizer.js +1 -0
  127. package/dist/service/secretsmanager/command/authorize/sim-secrets-manager-authorizer.js +1 -0
  128. package/dist/service/ses/command/authorize/sim-ses-authorizer.js +1 -0
  129. package/dist/service/sqs/command/authorize/sim-sqs-authorizer.js +1 -0
  130. package/dist/service/ssm/command/authorize/sim-ssm-authorizer.js +1 -0
  131. package/dist/service/wafv2/command/authorize/sim-wafv2-authorizer.js +1 -0
  132. package/package.json +5 -1
@@ -0,0 +1,53 @@
1
+ import type { SimAwsAccountId } from "../../../aws/sim-aws-account.js";
2
+ import type { SimIamPolicyDocument } from "../../policy/sim-iam-policy.js";
3
+ /**
4
+ * One service control policy applying to a simulated Account.
5
+ *
6
+ * The name travels with the document so a denial can say which policy produced
7
+ * it, the way an AWS denial names the policy in the console.
8
+ */
9
+ export interface SimIamServiceControlPolicy {
10
+ readonly document: SimIamPolicyDocument;
11
+ readonly policyName?: string | undefined;
12
+ }
13
+ /**
14
+ * The policies attached at one level of the organization above an Account.
15
+ *
16
+ * AWS requires an Allow at every level between the root and the Account, so
17
+ * which level a policy came from decides the request rather than decorating
18
+ * it. The name is what a denial calls the level.
19
+ */
20
+ export interface SimIamServiceControlPolicyLevel {
21
+ readonly nodeName: string;
22
+ readonly policies: readonly SimIamServiceControlPolicy[];
23
+ }
24
+ /**
25
+ * The service control policies in force for one Account.
26
+ *
27
+ * Whether any apply is a separate fact from how many levels there are. An
28
+ * Account whose every policy has been detached is still inside the
29
+ * organization, and nothing allowing an action there denies it. An Account
30
+ * outside every organization is unrestricted. Both can hold no policy, so the
31
+ * levels alone cannot tell them apart.
32
+ */
33
+ export interface SimIamServiceControlPolicySet {
34
+ readonly applies: boolean;
35
+ readonly levels: readonly SimIamServiceControlPolicyLevel[];
36
+ }
37
+ /**
38
+ * Where sim IAM asks what an Account's organization allows it to do.
39
+ *
40
+ * IAM belongs to one Account and an organization spans several, so the
41
+ * organization is reached through this interface instead of being held by IAM
42
+ * itself. A standalone SimIam has no organization around it and leaves the
43
+ * resolver out, which is the same as an Account outside any organization.
44
+ */
45
+ export interface SimIamServiceControlPolicyResolver {
46
+ /**
47
+ * The service control policies in force for an Account.
48
+ *
49
+ * A set that does not apply leaves the Account's identity and resource
50
+ * policies to decide the request on their own.
51
+ */
52
+ serviceControlPolicySetFor(accountId: SimAwsAccountId): SimIamServiceControlPolicySet;
53
+ }
@@ -10,6 +10,7 @@ import type { SimIamAuthorizationInput } from "./context/sim-iam-auth-z-context-
10
10
  import type { SimIamAuthZPolicySource } from "./context/sim-iam-auth-z-context.js";
11
11
  import type { SimIamAccountIdentityPolicies } from "./identity/sim-iam-account-identity-policies.js";
12
12
  import type { SimIamPolicyDecision } from "./sim-iam-decision.js";
13
+ import type { SimIamServiceControlPolicyResolver } from "./scp/sim-iam-scp-resolver.js";
13
14
  interface SimIamAccountAuthZProperties {
14
15
  readonly accountId: SimAwsAccountId;
15
16
  readonly policies: Map<SimArn, SimIamManagedPolicy>;
@@ -24,6 +25,13 @@ interface SimIamAccountAuthZProperties {
24
25
  * standalone SimIam has no simulation around it and so no resolver.
25
26
  */
26
27
  readonly iamResolver?: SimIamAccountResolver | undefined;
28
+ /**
29
+ * Resolves the service control policies in force for an Account.
30
+ *
31
+ * A simulation with an organization in it supplies this. A standalone SimIam
32
+ * has none, and its Accounts sit outside any organization.
33
+ */
34
+ readonly scpResolver?: SimIamServiceControlPolicyResolver | undefined;
27
35
  }
28
36
  /**
29
37
  * Evaluates IAM authorization attempts against one simulated Account's IAM
@@ -39,6 +39,7 @@ export class SimIamAccountAuthZ {
39
39
  users: this.properties.users,
40
40
  credentialIdentityResolver: this.properties.credentialIdentityResolver,
41
41
  iamResolver: this.properties.iamResolver,
42
+ scpResolver: this.properties.scpResolver,
42
43
  });
43
44
  }
44
45
  }
@@ -25,6 +25,7 @@ export class SimIamActionAuthorizer {
25
25
  if (decision.isDenied) {
26
26
  throw new SimIamAccessDenied({
27
27
  principal: decision.caller.principal,
28
+ reason: decision.denialReason,
28
29
  action,
29
30
  resource,
30
31
  });
@@ -10,6 +10,7 @@ import type { SimAwsAccountId } from "../../aws/sim-aws-account.js";
10
10
  import type { SimIamAccountResolver } from "../registry/sim-iam-account-resolver.js";
11
11
  import type { SimIamAuthZPolicySource } from "./context/sim-iam-auth-z-context.js";
12
12
  import type { SimIamAccountIdentityPolicies } from "./identity/sim-iam-account-identity-policies.js";
13
+ import type { SimIamServiceControlPolicyResolver } from "./scp/sim-iam-scp-resolver.js";
13
14
  interface SimIamAuthorizerProperties {
14
15
  readonly accountId: SimAwsAccountId;
15
16
  readonly policies: ReadonlyMap<SimArn, SimIamPolicy>;
@@ -17,6 +18,7 @@ interface SimIamAuthorizerProperties {
17
18
  readonly users: ReadonlyMap<SimIamUsername, SimIamUser>;
18
19
  readonly credentialIdentityResolver: SimAwsCredentialIdentityResolver;
19
20
  readonly iamResolver?: SimIamAccountResolver | undefined;
21
+ readonly scpResolver?: SimIamServiceControlPolicyResolver | undefined;
20
22
  }
21
23
  /**
22
24
  * Facade for simulated IAM authorization decisions.
@@ -18,6 +18,7 @@ export class SimIamAuthorizer {
18
18
  users: properties.users,
19
19
  credentialIdentityResolver: properties.credentialIdentityResolver,
20
20
  iamResolver: properties.iamResolver,
21
+ scpResolver: properties.scpResolver,
21
22
  });
22
23
  }
23
24
  /**
@@ -0,0 +1,13 @@
1
+ /**
2
+ * What one simulated IAM authorization attempt came to.
3
+ *
4
+ * A denial is one of two things, and which one it is says what to change. An
5
+ * explicit deny means a statement matched and refused. An implicit deny means
6
+ * nothing allowed the request in the first place.
7
+ */
8
+ export declare const SimIamPolicyDecisionValue: {
9
+ readonly ExplicitDeny: "ExplicitDeny";
10
+ readonly Allow: "Allow";
11
+ readonly ImplicitDeny: "ImplicitDeny";
12
+ };
13
+ export type SimIamPolicyDecisionValue = (typeof SimIamPolicyDecisionValue)[keyof typeof SimIamPolicyDecisionValue];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * What one simulated IAM authorization attempt came to.
3
+ *
4
+ * A denial is one of two things, and which one it is says what to change. An
5
+ * explicit deny means a statement matched and refused. An implicit deny means
6
+ * nothing allowed the request in the first place.
7
+ */
8
+ export const SimIamPolicyDecisionValue = {
9
+ ExplicitDeny: "ExplicitDeny",
10
+ Allow: "Allow",
11
+ ImplicitDeny: "ImplicitDeny",
12
+ };
@@ -2,36 +2,37 @@ import type { SimIamPolicyDocumentStatement } from "../policy/sim-iam-policy.js"
2
2
  import type { SimIamAuthZContext } from "./context/sim-iam-auth-z-context.js";
3
3
  import { SimIamPolicyDocumentParser } from "../policy/parse/sim-iam-document-parser.js";
4
4
  import type { SimAwsResolvedCaller } from "../../aws/caller/sim-aws-caller-resolver.js";
5
- export declare const SimIamPolicyDecisionValue: {
6
- readonly ExplicitDeny: "ExplicitDeny";
7
- readonly Allow: "Allow";
8
- readonly ImplicitDeny: "ImplicitDeny";
9
- };
10
- export type SimIamPolicyDecisionValue = (typeof SimIamPolicyDecisionValue)[keyof typeof SimIamPolicyDecisionValue];
5
+ import { SimIamScpGate } from "./scp/sim-iam-scp-gate.js";
6
+ import { SimIamPolicyDecisionValue } from "./sim-iam-decision-value.js";
7
+ export { SimIamPolicyDecisionValue } from "./sim-iam-decision-value.js";
11
8
  /**
12
9
  * Decision for one simulated IAM policy authorization attempt.
13
10
  *
14
- * This evaluates already-discovered identity and resource policy documents. It
15
- * does not fetch attached policies itself, apply trust policy semantics,
16
- * evaluate permissions boundaries, evaluate SCPs, or enforce service command
17
- * access.
11
+ * This evaluates already-discovered identity, resource, and service control
12
+ * policy documents. It does not fetch attached policies itself, apply trust
13
+ * policy semantics, evaluate permissions boundaries, or enforce service
14
+ * command access.
18
15
  *
19
16
  * The simulator currently models the common IAM authorization rules:
20
17
  *
21
18
  * - an explicit Deny in any evaluated policy wins;
19
+ * - the caller's Account has to get past its service control policies, which
20
+ * filter permissions and grant none;
22
21
  * - the Allows found must satisfy the request's allow requirement, which is
23
22
  * either side within one Account and both sides across Accounts;
24
23
  * - otherwise the request is implicitly denied.
25
24
  *
25
+ * Reading the policies belongs to SimIamPolicyEvaluation for the two sides
26
+ * that can allow, and to SimIamScpGate for the Account boundary. This class
27
+ * combines what they found.
28
+ *
26
29
  * Resource policies are expected to be supplied by the service that owns the
27
30
  * target resource.
28
31
  */
29
32
  export declare class SimIamPolicyDecision {
30
33
  private readonly request;
31
- private readonly policyDocumentParser;
32
- private readonly statementMatcher;
33
- private readonly explicitDenyStatementRecords;
34
- private readonly allows;
34
+ private readonly policies;
35
+ private readonly scpGate;
35
36
  constructor(request: SimIamAuthZContext, policyDocumentParser?: SimIamPolicyDocumentParser);
36
37
  /**
37
38
  * Resolved caller against which this authorization decision was evaluated.
@@ -70,6 +71,24 @@ export declare class SimIamPolicyDecision {
70
71
  * Matching explicit Deny statements.
71
72
  */
72
73
  get explicitDenyStatements(): readonly SimIamPolicyDocumentStatement[];
74
+ /**
75
+ * What the caller Account's service control policies said about the request.
76
+ *
77
+ * This is the organization's verdict on its own, apart from the identity and
78
+ * resource sides. It reports whether the Account boundary denied the request
79
+ * and which of its statements matched.
80
+ */
81
+ get serviceControlPolicy(): SimIamScpGate;
82
+ /**
83
+ * How an AccessDenied error should explain this denial, where there is more
84
+ * to say than the action and the resource.
85
+ *
86
+ * A service turns a denied decision into an error and passes this through,
87
+ * so an SCP denial reads the way it does in a real account. A matching Deny
88
+ * in an identity or resource policy is what `value` reports first, and it
89
+ * needs nothing added to the message, so it leaves this absent.
90
+ */
91
+ get denialReason(): string | undefined;
73
92
  /**
74
93
  * Matching Allow statements, from both policy sides.
75
94
  *
@@ -90,6 +109,4 @@ export declare class SimIamPolicyDecision {
90
109
  * Matching Allow statements originating from trust policies.
91
110
  */
92
111
  get trustAllowStatements(): readonly SimIamPolicyDocumentStatement[];
93
- private evaluate;
94
- private evaluatePolicy;
95
112
  }
@@ -1,40 +1,50 @@
1
1
  import { SimIamPolicyDocumentParser } from "../policy/parse/sim-iam-document-parser.js";
2
2
  import { SimIamPolicyStatementMatcher } from "./match/sim-iam-policy-statement-matcher.js";
3
- import { SimIamAllowStatements } from "./allow/sim-iam-allow-statements.js";
4
- export const SimIamPolicyDecisionValue = {
5
- ExplicitDeny: "ExplicitDeny",
6
- Allow: "Allow",
7
- ImplicitDeny: "ImplicitDeny",
8
- };
3
+ import { SimIamPolicyEvaluation } from "./allow/sim-iam-policy-evaluation.js";
4
+ import { SimIamScpGate } from "./scp/sim-iam-scp-gate.js";
5
+ import { SimIamPolicyDecisionValue } from "./sim-iam-decision-value.js";
6
+ export { SimIamPolicyDecisionValue } from "./sim-iam-decision-value.js";
9
7
  /**
10
8
  * Decision for one simulated IAM policy authorization attempt.
11
9
  *
12
- * This evaluates already-discovered identity and resource policy documents. It
13
- * does not fetch attached policies itself, apply trust policy semantics,
14
- * evaluate permissions boundaries, evaluate SCPs, or enforce service command
15
- * access.
10
+ * This evaluates already-discovered identity, resource, and service control
11
+ * policy documents. It does not fetch attached policies itself, apply trust
12
+ * policy semantics, evaluate permissions boundaries, or enforce service
13
+ * command access.
16
14
  *
17
15
  * The simulator currently models the common IAM authorization rules:
18
16
  *
19
17
  * - an explicit Deny in any evaluated policy wins;
18
+ * - the caller's Account has to get past its service control policies, which
19
+ * filter permissions and grant none;
20
20
  * - the Allows found must satisfy the request's allow requirement, which is
21
21
  * either side within one Account and both sides across Accounts;
22
22
  * - otherwise the request is implicitly denied.
23
23
  *
24
+ * Reading the policies belongs to SimIamPolicyEvaluation for the two sides
25
+ * that can allow, and to SimIamScpGate for the Account boundary. This class
26
+ * combines what they found.
27
+ *
24
28
  * Resource policies are expected to be supplied by the service that owns the
25
29
  * target resource.
26
30
  */
27
31
  export class SimIamPolicyDecision {
28
32
  request;
29
- policyDocumentParser;
30
- statementMatcher;
31
- explicitDenyStatementRecords = [];
32
- allows = new SimIamAllowStatements();
33
+ policies;
34
+ scpGate;
33
35
  constructor(request, policyDocumentParser = new SimIamPolicyDocumentParser()) {
36
+ const statementMatcher = new SimIamPolicyStatementMatcher(request);
34
37
  this.request = request;
35
- this.policyDocumentParser = policyDocumentParser;
36
- this.statementMatcher = new SimIamPolicyStatementMatcher(request);
37
- this.evaluate();
38
+ this.policies = new SimIamPolicyEvaluation({
39
+ policies: [...request.identityPolicies, ...request.resourcePolicies],
40
+ policyDocumentParser,
41
+ statementMatcher,
42
+ });
43
+ this.scpGate = new SimIamScpGate({
44
+ serviceControlPolicies: request.serviceControlPolicies,
45
+ policyDocumentParser,
46
+ statementMatcher,
47
+ });
38
48
  }
39
49
  /**
40
50
  * Resolved caller against which this authorization decision was evaluated.
@@ -49,13 +59,15 @@ export class SimIamPolicyDecision {
49
59
  * Final IAM decision value.
50
60
  */
51
61
  get value() {
52
- if (this.explicitDenyStatementRecords.length > 0) {
62
+ if (this.policies.isExplicitDeny) {
53
63
  return SimIamPolicyDecisionValue.ExplicitDeny;
54
64
  }
55
- if (this.request.allowRequirement.isSatisfiedBy(this.allows.sides)) {
56
- return SimIamPolicyDecisionValue.Allow;
65
+ if (this.scpGate.value !== undefined) {
66
+ return this.scpGate.value;
57
67
  }
58
- return SimIamPolicyDecisionValue.ImplicitDeny;
68
+ return this.request.allowRequirement.isSatisfiedBy(this.policies.sides)
69
+ ? SimIamPolicyDecisionValue.Allow
70
+ : SimIamPolicyDecisionValue.ImplicitDeny;
59
71
  }
60
72
  /**
61
73
  * Whether the request is allowed.
@@ -87,13 +99,38 @@ export class SimIamPolicyDecision {
87
99
  * An identity-policy Allow cannot substitute for the target role's trust.
88
100
  */
89
101
  get isAllowedByTrustPolicy() {
90
- return this.allows.trust.length > 0;
102
+ return this.policies.allowStatements.trust.length > 0;
91
103
  }
92
104
  /**
93
105
  * Matching explicit Deny statements.
94
106
  */
95
107
  get explicitDenyStatements() {
96
- return this.explicitDenyStatementRecords;
108
+ return this.policies.explicitDenyStatements;
109
+ }
110
+ /**
111
+ * What the caller Account's service control policies said about the request.
112
+ *
113
+ * This is the organization's verdict on its own, apart from the identity and
114
+ * resource sides. It reports whether the Account boundary denied the request
115
+ * and which of its statements matched.
116
+ */
117
+ get serviceControlPolicy() {
118
+ return this.scpGate;
119
+ }
120
+ /**
121
+ * How an AccessDenied error should explain this denial, where there is more
122
+ * to say than the action and the resource.
123
+ *
124
+ * A service turns a denied decision into an error and passes this through,
125
+ * so an SCP denial reads the way it does in a real account. A matching Deny
126
+ * in an identity or resource policy is what `value` reports first, and it
127
+ * needs nothing added to the message, so it leaves this absent.
128
+ */
129
+ get denialReason() {
130
+ if (this.policies.isExplicitDeny) {
131
+ return undefined;
132
+ }
133
+ return this.scpGate.denialReason(this.request.action);
97
134
  }
98
135
  /**
99
136
  * Matching Allow statements, from both policy sides.
@@ -103,46 +140,24 @@ export class SimIamPolicyDecision {
103
140
  * from each side.
104
141
  */
105
142
  get allowStatements() {
106
- return this.allows.all;
143
+ return this.policies.allowStatements.all;
107
144
  }
108
145
  /**
109
146
  * Matching Allow statements from identity-based policies.
110
147
  */
111
148
  get identityAllowStatements() {
112
- return this.allows.identity;
149
+ return this.policies.allowStatements.identity;
113
150
  }
114
151
  /**
115
152
  * Matching Allow statements from resource-based policies.
116
153
  */
117
154
  get resourceAllowStatements() {
118
- return this.allows.resource;
155
+ return this.policies.allowStatements.resource;
119
156
  }
120
157
  /**
121
158
  * Matching Allow statements originating from trust policies.
122
159
  */
123
160
  get trustAllowStatements() {
124
- return this.allows.trust;
125
- }
126
- evaluate() {
127
- for (const policy of [
128
- ...this.request.identityPolicies,
129
- ...this.request.resourcePolicies,
130
- ]) {
131
- this.evaluatePolicy(policy);
132
- }
133
- }
134
- evaluatePolicy(policy) {
135
- const parsedPolicy = this.policyDocumentParser.parse(policy.document);
136
- for (const statement of parsedPolicy.statements) {
137
- const principal = this.statementMatcher.matches(policy, statement);
138
- if (!principal.matched) {
139
- continue;
140
- }
141
- if (statement.effect === "Deny") {
142
- this.explicitDenyStatementRecords.push(statement.source);
143
- continue;
144
- }
145
- this.allows.record(policy, statement.source, principal);
146
- }
161
+ return this.policies.allowStatements.trust;
147
162
  }
148
163
  }
@@ -15,6 +15,14 @@ export interface SimIamAuthorizationDecision {
15
15
  readonly caller: SimAwsResolvedCaller;
16
16
  readonly isAllowed: boolean;
17
17
  readonly isDenied: boolean;
18
+ /**
19
+ * How an AccessDenied error should explain this denial, where the action and
20
+ * the resource leave something out.
21
+ *
22
+ * A service control policy denial is the case this exists for. Absent for a
23
+ * denial an identity or resource policy accounts for on its own.
24
+ */
25
+ readonly denialReason?: string | undefined;
18
26
  }
19
27
  /**
20
28
  * IAM authorization capability consumed by other simulated AWS services.
@@ -32,6 +32,7 @@ export class SimIamAllowAllAuth {
32
32
  caller,
33
33
  isAllowed: true,
34
34
  isDenied: false,
35
+ denialReason: undefined,
35
36
  };
36
37
  }
37
38
  }
@@ -19,6 +19,14 @@ export interface SimIamAccessDeniedInput {
19
19
  readonly principal: SimAwsPrincipal;
20
20
  readonly action: string;
21
21
  readonly resource: string;
22
+ /**
23
+ * What else the message should say about why the request was denied.
24
+ *
25
+ * AWS names the source of a denial when it is something beyond the caller's
26
+ * own permissions, such as a service control policy. A denial the caller's
27
+ * identity and resource policies account for adds nothing here.
28
+ */
29
+ readonly reason?: string | undefined;
22
30
  }
23
31
  /**
24
32
  * Simulated IAM AccessDenied error.
@@ -27,7 +27,8 @@ export class SimIamAccessDenied extends SimIamError {
27
27
  constructor(input) {
28
28
  const iamCallerIdentifier = new SimIamCallerIdentifier();
29
29
  const callerIdentifier = iamCallerIdentifier.format(input.principal);
30
- super(`User: ${callerIdentifier} is not authorized to perform: ${input.action} on resource: ${input.resource}`, { httpStatusCode: 403 });
30
+ const reason = input.reason === undefined ? "" : ` ${input.reason}`;
31
+ super(`User: ${callerIdentifier} is not authorized to perform: ${input.action} on resource: ${input.resource}${reason}`, { httpStatusCode: 403 });
31
32
  this.caller = input.principal;
32
33
  this.action = input.action;
33
34
  this.resource = input.resource;
@@ -10,6 +10,7 @@ import { SimIamSessionManager } from "./credential/session/sim-iam-session-manag
10
10
  import { type SimIamUserCredentialGenerator } from "./credential/user/sim-iam-user-credential-generator.js";
11
11
  import type { SimIamManagedPolicy } from "./policy/sim-iam-policy.js";
12
12
  import type { SimIamAccountResolver } from "./registry/sim-iam-account-resolver.js";
13
+ import type { SimIamServiceControlPolicyResolver } from "./authorize/scp/sim-iam-scp-resolver.js";
13
14
  import type { SimIamRole, SimIamRoleName } from "./role/sim-iam-role.js";
14
15
  import type { SimIamUser, SimIamUsername } from "./user/sim-iam-user.js";
15
16
  export interface SimIamProperties {
@@ -26,6 +27,14 @@ export interface SimIamProperties {
26
27
  * simulation around it and so leaves this out.
27
28
  */
28
29
  readonly iamResolver?: SimIamAccountResolver;
30
+ /**
31
+ * Resolves the service control policies in force for this Account.
32
+ *
33
+ * Simulated Organizations supplies this when a SimAws builds IAM. A
34
+ * standalone SimIam has no organization around it, which is the same as an
35
+ * Account belonging to none.
36
+ */
37
+ readonly scpResolver?: SimIamServiceControlPolicyResolver;
29
38
  }
30
39
  /**
31
40
  * The state and collaborators of one simulated IAM Account.
@@ -48,6 +48,7 @@ export class SimIamAccountParts {
48
48
  users: this.users,
49
49
  credentialIdentityResolver: credentialRegistry,
50
50
  iamResolver: properties.iamResolver,
51
+ scpResolver: properties.scpResolver,
51
52
  });
52
53
  }
53
54
  /**
@@ -37,6 +37,7 @@ export class SimKinesisAuthorizer {
37
37
  if (decision.isDenied) {
38
38
  throw new SimIamAccessDenied({
39
39
  principal: decision.caller.principal,
40
+ reason: decision.denialReason,
40
41
  action,
41
42
  resource,
42
43
  });
@@ -45,6 +45,7 @@ export class SimKmsAuthorizer {
45
45
  if (decision.isDenied) {
46
46
  throw new SimIamAccessDenied({
47
47
  principal: decision.caller.principal,
48
+ reason: decision.denialReason,
48
49
  action,
49
50
  resource: key.arn,
50
51
  });
@@ -65,6 +66,7 @@ export class SimKmsAuthorizer {
65
66
  if (decision.isDenied) {
66
67
  throw new SimIamAccessDenied({
67
68
  principal: decision.caller.principal,
69
+ reason: decision.denialReason,
68
70
  action,
69
71
  resource,
70
72
  });
@@ -27,6 +27,7 @@ export class CreateFunctionAuthorizer {
27
27
  if (decision.isDenied) {
28
28
  throw new SimIamAccessDenied({
29
29
  principal: decision.caller.principal,
30
+ reason: decision.denialReason,
30
31
  action: CreateFunctionAuthorizer.action,
31
32
  resource: functionArn,
32
33
  });
@@ -23,6 +23,7 @@ export class DeleteFunctionAuthorizer {
23
23
  if (decision.isDenied) {
24
24
  throw new SimIamAccessDenied({
25
25
  principal: decision.caller.principal,
26
+ reason: decision.denialReason,
26
27
  action: DeleteFunctionAuthorizer.action,
27
28
  resource: functionArn,
28
29
  });
@@ -30,6 +30,7 @@ export class EventInvokeConfigAuthorizer {
30
30
  if (decision.isDenied) {
31
31
  throw new SimIamAccessDenied({
32
32
  principal: decision.caller.principal,
33
+ reason: decision.denialReason,
33
34
  action: this.action,
34
35
  resource: functionArn,
35
36
  });
@@ -30,6 +30,7 @@ export class FunctionUrlAuthorizer {
30
30
  if (decision.isDenied) {
31
31
  throw new SimIamAccessDenied({
32
32
  principal: decision.caller.principal,
33
+ reason: decision.denialReason,
33
34
  action: this.action,
34
35
  resource: functionArn,
35
36
  });
@@ -27,6 +27,7 @@ export class GetFunctionAuthorizer {
27
27
  if (decision.isDenied) {
28
28
  throw new SimIamAccessDenied({
29
29
  principal: decision.caller.principal,
30
+ reason: decision.denialReason,
30
31
  action: GetFunctionAuthorizer.action,
31
32
  resource: functionArn,
32
33
  });
@@ -37,6 +37,7 @@ export class InvokeAuthorizer {
37
37
  if (decision.isDenied) {
38
38
  throw new SimIamAccessDenied({
39
39
  principal: decision.caller.principal,
40
+ reason: decision.denialReason,
40
41
  action: InvokeAuthorizer.action,
41
42
  resource: functionArn,
42
43
  });
@@ -32,6 +32,7 @@ export class ListFunctionsAuthorizer {
32
32
  if (decision.isDenied) {
33
33
  throw new SimIamAccessDenied({
34
34
  principal: decision.caller.principal,
35
+ reason: decision.denialReason,
35
36
  action: ListFunctionsAuthorizer.action,
36
37
  resource: ListFunctionsAuthorizer.resource,
37
38
  });
@@ -28,6 +28,7 @@ export class UpdateFunctionCodeAuthorizer {
28
28
  if (decision.isDenied) {
29
29
  throw new SimIamAccessDenied({
30
30
  principal: decision.caller.principal,
31
+ reason: decision.denialReason,
31
32
  action: UpdateFunctionCodeAuthorizer.action,
32
33
  resource: functionArn,
33
34
  });
@@ -29,6 +29,7 @@ export class UpdateFunctionConfigurationAuthorizer {
29
29
  if (decision.isDenied) {
30
30
  throw new SimIamAccessDenied({
31
31
  principal: decision.caller.principal,
32
+ reason: decision.denialReason,
32
33
  action: UpdateFunctionConfigurationAuthorizer.action,
33
34
  resource: functionArn,
34
35
  });
@@ -30,6 +30,7 @@ export class VersionAuthorizer {
30
30
  if (decision.isDenied) {
31
31
  throw new SimIamAccessDenied({
32
32
  principal: decision.caller.principal,
33
+ reason: decision.denialReason,
33
34
  action: this.action,
34
35
  resource: functionArn,
35
36
  });
@@ -52,6 +52,7 @@ export class SimLogsAuthorizer {
52
52
  if (decision.isDenied) {
53
53
  throw new SimIamAccessDenied({
54
54
  principal: decision.caller.principal,
55
+ reason: decision.denialReason,
55
56
  action,
56
57
  resource,
57
58
  });
@@ -0,0 +1,19 @@
1
+ import type { SimAws } from "../../aws/sim-aws.js";
2
+ import type { SimCfnResource } from "../../cloudformation/resource/sim-cfn-resource.js";
3
+ import type { SimCfnTemplateValueRecord } from "../../cloudformation/template/value/sim-cfn-template-value.js";
4
+ import { SimCfnOrganization } from "./sim-cfn-organizations-record.js";
5
+ /**
6
+ * Records the organization an `AWS::Organizations::Organization` declares.
7
+ *
8
+ * A SimAws already has one organization, so this brings nothing into being.
9
+ * The Resource earns its place by answering `RootId`, which is what the rest
10
+ * of a template hangs off.
11
+ */
12
+ export declare class SimCfnOrganizationCreator {
13
+ #private;
14
+ constructor(simAws: SimAws);
15
+ /**
16
+ * Record the organization a template declares.
17
+ */
18
+ create(resource: SimCfnResource, properties: SimCfnTemplateValueRecord): SimCfnOrganization;
19
+ }