@kensio/yulin 1.20.11 → 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 (150) 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/athena/engine/sim-athena-regexp-flags.d.ts +22 -0
  8. package/dist/service/athena/engine/sim-athena-regexp-flags.js +34 -0
  9. package/dist/service/athena/engine/sim-athena-regexp-shims.js +3 -1
  10. package/dist/service/athena/engine/sim-athena-url-parts.d.ts +24 -0
  11. package/dist/service/athena/engine/sim-athena-url-parts.js +76 -0
  12. package/dist/service/athena/engine/sim-athena-url-shims.d.ts +3 -2
  13. package/dist/service/athena/engine/sim-athena-url-shims.js +57 -25
  14. package/dist/service/athena/table/sim-athena-negated-columns.d.ts +17 -0
  15. package/dist/service/athena/table/sim-athena-negated-columns.js +80 -0
  16. package/dist/service/athena/table/sim-athena-partition-filters.d.ts +7 -4
  17. package/dist/service/athena/table/sim-athena-partition-filters.js +12 -5
  18. package/dist/service/aws/factory/sim-aws-account-service-cache.d.ts +3 -0
  19. package/dist/service/aws/factory/sim-aws-account-service-cache.js +5 -0
  20. package/dist/service/aws/factory/sim-aws-service-factory.d.ts +9 -0
  21. package/dist/service/aws/factory/sim-aws-service-factory.js +10 -0
  22. package/dist/service/aws/sim-aws.d.ts +18 -0
  23. package/dist/service/aws/sim-aws.js +19 -0
  24. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn-value-adapter.d.ts +6 -0
  25. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn-value-adapter.js +23 -0
  26. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn.d.ts +66 -0
  27. package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn.js +136 -0
  28. package/dist/service/cloudformation/resource/cfn/sim-cfn-service-value-adapters.js +2 -0
  29. package/dist/service/cloudformation/resource/resolve/service/sim-cfn-service-factories.js +7 -0
  30. package/dist/service/cloudfront/command/create-distribution/create-distribution-authorizer.js +1 -0
  31. package/dist/service/cloudfront/command/create-function/create-function-authorizer.js +1 -0
  32. package/dist/service/cloudfront/command/delete-distribution/delete-distribution-authorizer.js +1 -0
  33. package/dist/service/cloudfront/command/delete-function/delete-function-authorizer.js +1 -0
  34. package/dist/service/cloudfront/command/get-distribution/get-distribution-authorizer.js +1 -0
  35. package/dist/service/cloudfront/command/update-distribution/update-distribution-authorizer.js +1 -0
  36. package/dist/service/cloudfront/edge/sim-cf-edge-association-auth-z.js +1 -0
  37. package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store-access.js +1 -0
  38. package/dist/service/cloudwatch/command/authorize/sim-cloudwatch-decide.js +1 -0
  39. package/dist/service/cognito/command/authorize/sim-cognito-authorizer.js +1 -0
  40. package/dist/service/dynamodb/command/authorize/sim-dynamodb-authorizer.js +1 -0
  41. package/dist/service/firehose/command/authorize/sim-firehose-authorizer.js +1 -0
  42. package/dist/service/glue/command/authorize/sim-glue-authorize-resources.js +1 -0
  43. package/dist/service/iam/authorize/allow/sim-iam-policy-evaluation.d.ts +45 -0
  44. package/dist/service/iam/authorize/allow/sim-iam-policy-evaluation.js +59 -0
  45. package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.d.ts +15 -4
  46. package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.js +15 -4
  47. package/dist/service/iam/authorize/context/sim-iam-auth-z-context.d.ts +31 -1
  48. package/dist/service/iam/authorize/context/sim-iam-auth-z-context.factory.js +1 -0
  49. package/dist/service/iam/authorize/context/sim-iam-auth-z-scp-source-builder.d.ts +46 -0
  50. package/dist/service/iam/authorize/context/sim-iam-auth-z-scp-source-builder.js +71 -0
  51. package/dist/service/iam/authorize/scp/sim-iam-scp-gate.d.ts +96 -0
  52. package/dist/service/iam/authorize/scp/sim-iam-scp-gate.js +148 -0
  53. package/dist/service/iam/authorize/scp/sim-iam-scp-resolver.d.ts +53 -0
  54. package/dist/service/iam/authorize/scp/sim-iam-scp-resolver.js +1 -0
  55. package/dist/service/iam/authorize/sim-iam-account-auth-z.d.ts +8 -0
  56. package/dist/service/iam/authorize/sim-iam-account-auth-z.js +1 -0
  57. package/dist/service/iam/authorize/sim-iam-action-authorizer.js +1 -0
  58. package/dist/service/iam/authorize/sim-iam-authorizer.d.ts +2 -0
  59. package/dist/service/iam/authorize/sim-iam-authorizer.js +1 -0
  60. package/dist/service/iam/authorize/sim-iam-decision-value.d.ts +13 -0
  61. package/dist/service/iam/authorize/sim-iam-decision-value.js +12 -0
  62. package/dist/service/iam/authorize/sim-iam-decision.d.ts +33 -16
  63. package/dist/service/iam/authorize/sim-iam-decision.js +64 -49
  64. package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.d.ts +8 -0
  65. package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.js +1 -0
  66. package/dist/service/iam/error/sim-iam.error.d.ts +8 -0
  67. package/dist/service/iam/error/sim-iam.error.js +2 -1
  68. package/dist/service/iam/sim-iam-account-parts.d.ts +9 -0
  69. package/dist/service/iam/sim-iam-account-parts.js +1 -0
  70. package/dist/service/kinesis/command/authorize/sim-kinesis-authorizer.js +1 -0
  71. package/dist/service/kms/command/authorize/sim-kms-authorizer.js +2 -0
  72. package/dist/service/lambda/command/create-function/create-function-authorizer.js +1 -0
  73. package/dist/service/lambda/command/delete-function/delete-function-authorizer.js +1 -0
  74. package/dist/service/lambda/command/event-invoke-config/event-invoke-config-authorizer.js +1 -0
  75. package/dist/service/lambda/command/function-url/function-url-authorizer.js +1 -0
  76. package/dist/service/lambda/command/get-function/get-function-authorizer.js +1 -0
  77. package/dist/service/lambda/command/invoke/invoke-authorizer.js +1 -0
  78. package/dist/service/lambda/command/list-functions/list-functions-authorizer.js +1 -0
  79. package/dist/service/lambda/command/update-function-code/update-function-code-authorizer.js +1 -0
  80. package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.js +1 -0
  81. package/dist/service/lambda/command/version/version-authorizer.js +1 -0
  82. package/dist/service/logs/command/authorize/sim-logs-authorizer.js +1 -0
  83. package/dist/service/organizations/cfn/sim-cfn-organization-creator.d.ts +19 -0
  84. package/dist/service/organizations/cfn/sim-cfn-organization-creator.js +25 -0
  85. package/dist/service/organizations/cfn/sim-cfn-organizational-unit-creator.d.ts +16 -0
  86. package/dist/service/organizations/cfn/sim-cfn-organizational-unit-creator.js +21 -0
  87. package/dist/service/organizations/cfn/sim-cfn-organizations-account-creator.d.ts +20 -0
  88. package/dist/service/organizations/cfn/sim-cfn-organizations-account-creator.js +34 -0
  89. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-creator.d.ts +21 -0
  90. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-creator.js +40 -0
  91. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-input.d.ts +20 -0
  92. package/dist/service/organizations/cfn/sim-cfn-organizations-policy-input.js +33 -0
  93. package/dist/service/organizations/cfn/sim-cfn-organizations-properties.d.ts +36 -0
  94. package/dist/service/organizations/cfn/sim-cfn-organizations-properties.js +78 -0
  95. package/dist/service/organizations/cfn/sim-cfn-organizations-record.d.ts +40 -0
  96. package/dist/service/organizations/cfn/sim-cfn-organizations-record.js +54 -0
  97. package/dist/service/organizations/cfn/sim-cfn-organizations-remover.d.ts +17 -0
  98. package/dist/service/organizations/cfn/sim-cfn-organizations-remover.js +40 -0
  99. package/dist/service/organizations/cfn/sim-organizations-cfn-resource-factory.d.ts +24 -0
  100. package/dist/service/organizations/cfn/sim-organizations-cfn-resource-factory.js +50 -0
  101. package/dist/service/organizations/index.d.ts +6 -0
  102. package/dist/service/organizations/index.js +6 -0
  103. package/dist/service/organizations/policy/sim-organizations-effective-policies.d.ts +43 -0
  104. package/dist/service/organizations/policy/sim-organizations-effective-policies.js +58 -0
  105. package/dist/service/organizations/policy/sim-organizations-scp-store.d.ts +61 -0
  106. package/dist/service/organizations/policy/sim-organizations-scp-store.js +103 -0
  107. package/dist/service/organizations/sim-organizations-structure.d.ts +94 -0
  108. package/dist/service/organizations/sim-organizations-structure.js +140 -0
  109. package/dist/service/organizations/sim-organizations.d.ts +95 -0
  110. package/dist/service/organizations/sim-organizations.js +99 -0
  111. package/dist/service/organizations/tree/sim-organizations-node.d.ts +57 -0
  112. package/dist/service/organizations/tree/sim-organizations-node.js +58 -0
  113. package/dist/service/organizations/tree/sim-organizations-tree.d.ts +91 -0
  114. package/dist/service/organizations/tree/sim-organizations-tree.js +154 -0
  115. package/dist/service/route53/command/change-resource-record-sets/change-resource-record-sets-authorizer.js +1 -0
  116. package/dist/service/route53/command/create-hosted-zone/create-hosted-zone-authorizer.js +1 -0
  117. package/dist/service/route53/command/delete-hosted-zone/delete-hosted-zone-authorizer.js +1 -0
  118. package/dist/service/route53/command/dnssec/sim-route53-dnssec-authorizer.js +1 -0
  119. package/dist/service/route53/command/get-hosted-zone/get-hosted-zone-authorizer.js +1 -0
  120. package/dist/service/route53/command/list-hosted-zones-by-name/list-hosted-zones-by-name-authorizer.js +1 -0
  121. package/dist/service/route53/command/list-resource-record-sets/list-resource-record-sets-authorizer.js +1 -0
  122. package/dist/service/s3/command/create-bucket/create-bucket.handler.js +1 -0
  123. package/dist/service/s3/command/delete-bucket/delete-bucket-authorizer.js +1 -0
  124. package/dist/service/s3/command/delete-bucket-policy/delete-bucket-policy-authorizer.js +1 -0
  125. package/dist/service/s3/command/delete-object/delete-object-authorizer.js +1 -0
  126. package/dist/service/s3/command/get-bucket-policy/get-bucket-policy-authorizer.js +1 -0
  127. package/dist/service/s3/command/get-object/get-object-authorizer.js +1 -0
  128. package/dist/service/s3/command/head-bucket/head-bucket-authorizer.js +1 -0
  129. package/dist/service/s3/command/lifecycle/sim-s3-lifecycle-authorizer.js +1 -0
  130. package/dist/service/s3/command/list-buckets/list-buckets-authorizer.js +1 -0
  131. package/dist/service/s3/command/list-objects/list-objects-authorizer.js +1 -0
  132. package/dist/service/s3/command/multipart/sim-s3-multipart-authorizer.js +1 -0
  133. package/dist/service/s3/command/notification/sim-s3-notification-authorizer.js +1 -0
  134. package/dist/service/s3/command/public-access-block/sim-s3-public-access-block-authorizer.js +1 -0
  135. package/dist/service/s3/command/put-bucket-policy/put-bucket-policy-authorizer.js +1 -0
  136. package/dist/service/s3/command/put-bucket-website/put-bucket-website-authorizer.js +1 -0
  137. package/dist/service/s3/command/put-object/put-object-authorizer.js +1 -0
  138. package/dist/service/secretsmanager/command/authorize/sim-secrets-manager-authorizer.js +1 -0
  139. package/dist/service/ses/command/authorize/sim-ses-authorizer.js +1 -0
  140. package/dist/service/sqs/command/authorize/sim-sqs-authorizer.js +1 -0
  141. package/dist/service/ssm/command/authorize/sim-ssm-authorizer.js +1 -0
  142. package/dist/service/wafv2/command/authorize/sim-wafv2-authorizer.js +1 -0
  143. package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.js +4 -3
  144. package/dist/service/wafv2/command/regex-pattern-set/sim-wafv2-regex-pattern-set-commands.js +4 -3
  145. package/dist/service/wafv2/command/sim-wafv2-input.d.ts +15 -0
  146. package/dist/service/wafv2/command/sim-wafv2-input.js +66 -1
  147. package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.js +7 -5
  148. package/dist/service/wafv2/error/sim-wafv2.error.d.ts +11 -0
  149. package/dist/service/wafv2/error/sim-wafv2.error.js +13 -0
  150. package/package.json +5 -1
@@ -2,7 +2,7 @@ import type { SimArn } from "../../../aws/arn.js";
2
2
  import type { SimIamConditionValue, SimIamPolicyDocument } from "../../policy/sim-iam-policy.js";
3
3
  import type { SimAwsResolvedCaller } from "../../../aws/caller/sim-aws-caller-resolver.js";
4
4
  import type { SimIamAllowRequirement } from "../allow/sim-iam-allow-requirement.js";
5
- export type SimIamAuthZPolicySourceType = "identity-inline" | "identity-managed" | "resource" | "trust" | "permissions-boundary" | "session";
5
+ export type SimIamAuthZPolicySourceType = "identity-inline" | "identity-managed" | "resource" | "trust" | "permissions-boundary" | "session" | "service-control";
6
6
  export interface SimIamAuthZPolicySource {
7
7
  readonly sourceType: SimIamAuthZPolicySourceType;
8
8
  readonly document: SimIamPolicyDocument;
@@ -16,6 +16,29 @@ export interface SimIamAuthZPolicySource {
16
16
  export type SimIamAuthZResourcePolicySource = Omit<SimIamAuthZPolicySource, "sourceType"> & {
17
17
  readonly sourceType: Extract<SimIamAuthZPolicySourceType, "resource" | "trust">;
18
18
  };
19
+ /**
20
+ * The service control policies attached at one level above the caller's
21
+ * Account, which is the root, an organizational unit, or the Account itself.
22
+ *
23
+ * Each level has to allow the action on its own. A level allowing nothing
24
+ * denies the request whatever another level allows, which is why the sources
25
+ * stay grouped rather than being read as one list.
26
+ */
27
+ export interface SimIamAuthZServiceControlPolicyLevel {
28
+ readonly nodeName: string;
29
+ readonly sources: readonly SimIamAuthZPolicySource[];
30
+ }
31
+ /**
32
+ * The service control policies in force for an authorization request.
33
+ *
34
+ * `applies` is a separate fact from how many levels there are. An Account
35
+ * inside an organization holding no policy allows nothing, while an Account
36
+ * outside every organization is unrestricted, and both can carry no levels.
37
+ */
38
+ export interface SimIamAuthZServiceControlPolicies {
39
+ readonly applies: boolean;
40
+ readonly levels: readonly SimIamAuthZServiceControlPolicyLevel[];
41
+ }
19
42
  export interface SimIamAuthZContext {
20
43
  /**
21
44
  * Identity-based policies that grant permissions to the principal.
@@ -29,6 +52,13 @@ export interface SimIamAuthZContext {
29
52
  * Resource policies are not gathered from IAM's managed policy store.
30
53
  */
31
54
  readonly resourcePolicies: readonly SimIamAuthZPolicySource[];
55
+ /**
56
+ * Service control policies in force for the caller's Account.
57
+ *
58
+ * These filter what the Account's principals may do and grant nothing, so
59
+ * they are kept apart from the two sides that can allow a request.
60
+ */
61
+ readonly serviceControlPolicies: SimIamAuthZServiceControlPolicies;
32
62
  /**
33
63
  * How an Allow from each policy side combines into the final decision.
34
64
  *
@@ -6,6 +6,7 @@ import { SimIamEitherSideAllowRequirement } from "../allow/sim-iam-allow-require
6
6
  export const simIamAuthZContextFactory = new StaticFactory({
7
7
  identityPolicies: [],
8
8
  resourcePolicies: [],
9
+ serviceControlPolicies: { applies: false, levels: [] },
9
10
  allowRequirement: new SimIamEitherSideAllowRequirement(),
10
11
  action: "s3:GetObject",
11
12
  resource: "arn:aws:s3:::test-bucket/test-key",
@@ -0,0 +1,46 @@
1
+ import type { SimAwsAccountId } from "../../../aws/sim-aws-account.js";
2
+ import type { SimAwsResolvedCaller } from "../../../aws/caller/sim-aws-caller-resolver.js";
3
+ import type { SimIamServiceControlPolicyResolver } from "../scp/sim-iam-scp-resolver.js";
4
+ import type { SimIamAuthZServiceControlPolicies } from "./sim-iam-auth-z-context.js";
5
+ interface SimIamAuthZScpSourceBuilderProperties {
6
+ /**
7
+ * The Account whose IAM is evaluating the request.
8
+ */
9
+ readonly accountId: SimAwsAccountId;
10
+ readonly scpResolver?: SimIamServiceControlPolicyResolver | undefined;
11
+ }
12
+ /**
13
+ * Finds the service control policies that apply to one request.
14
+ *
15
+ * An SCP belongs to the caller's own Account, which is the Account whose
16
+ * principal is asking. For a request within one Account that is the Account
17
+ * evaluating it. For a cross-Account request it is the other one, because AWS
18
+ * filters a principal by the organization its own account sits in and leaves
19
+ * the resource's organization to say nothing about it.
20
+ *
21
+ * A caller with no Account in its ARN, which means a service principal or an
22
+ * anonymous request, belongs to no Account and is subject to no SCP.
23
+ */
24
+ export declare class SimIamAuthZScpSourceBuilder {
25
+ /**
26
+ * What a caller no organization reaches is subject to.
27
+ */
28
+ private static readonly unrestricted;
29
+ private readonly accountId;
30
+ private readonly scpResolver?;
31
+ constructor(properties: SimIamAuthZScpSourceBuilderProperties);
32
+ /**
33
+ * The service control policies in force for a resolved caller.
34
+ */
35
+ build(caller: SimAwsResolvedCaller): SimIamAuthZServiceControlPolicies;
36
+ /**
37
+ * The Account whose organization decides this request.
38
+ *
39
+ * A caller identified only by a service name or by nothing at all has no
40
+ * Account of its own. The Account root fallback IAM applies to a request
41
+ * with no caller carries this Account's id, so a CloudFormation deployment
42
+ * is filtered like any other principal in it.
43
+ */
44
+ private callerAccountId;
45
+ }
46
+ export {};
@@ -0,0 +1,71 @@
1
+ import { isSimAwsAccountId } from "../../../aws/sim-aws-account.js";
2
+ /**
3
+ * Finds the service control policies that apply to one request.
4
+ *
5
+ * An SCP belongs to the caller's own Account, which is the Account whose
6
+ * principal is asking. For a request within one Account that is the Account
7
+ * evaluating it. For a cross-Account request it is the other one, because AWS
8
+ * filters a principal by the organization its own account sits in and leaves
9
+ * the resource's organization to say nothing about it.
10
+ *
11
+ * A caller with no Account in its ARN, which means a service principal or an
12
+ * anonymous request, belongs to no Account and is subject to no SCP.
13
+ */
14
+ export class SimIamAuthZScpSourceBuilder {
15
+ /**
16
+ * What a caller no organization reaches is subject to.
17
+ */
18
+ static unrestricted = {
19
+ applies: false,
20
+ levels: [],
21
+ };
22
+ accountId;
23
+ scpResolver;
24
+ constructor(properties) {
25
+ this.accountId = properties.accountId;
26
+ this.scpResolver = properties.scpResolver;
27
+ }
28
+ /**
29
+ * The service control policies in force for a resolved caller.
30
+ */
31
+ build(caller) {
32
+ const scpResolver = this.scpResolver;
33
+ if (scpResolver === undefined) {
34
+ return SimIamAuthZScpSourceBuilder.unrestricted;
35
+ }
36
+ const accountId = this.callerAccountId(caller);
37
+ if (accountId === undefined) {
38
+ return SimIamAuthZScpSourceBuilder.unrestricted;
39
+ }
40
+ const set = scpResolver.serviceControlPolicySetFor(accountId);
41
+ return {
42
+ applies: set.applies,
43
+ levels: set.levels.map((level) => ({
44
+ nodeName: level.nodeName,
45
+ sources: level.policies.map((policy) => ({
46
+ sourceType: "service-control",
47
+ document: policy.document,
48
+ policyName: policy.policyName,
49
+ })),
50
+ })),
51
+ };
52
+ }
53
+ /**
54
+ * The Account whose organization decides this request.
55
+ *
56
+ * A caller identified only by a service name or by nothing at all has no
57
+ * Account of its own. The Account root fallback IAM applies to a request
58
+ * with no caller carries this Account's id, so a CloudFormation deployment
59
+ * is filtered like any other principal in it.
60
+ */
61
+ callerAccountId(caller) {
62
+ if (caller.principal.kind === "anonymous" || caller.service !== undefined) {
63
+ return undefined;
64
+ }
65
+ const callerAccountId = caller.accountId;
66
+ if (callerAccountId === undefined) {
67
+ return this.accountId;
68
+ }
69
+ return isSimAwsAccountId(callerAccountId) ? callerAccountId : undefined;
70
+ }
71
+ }
@@ -0,0 +1,96 @@
1
+ import type { SimIamPolicyDocumentStatement } from "../../policy/sim-iam-policy.js";
2
+ import type { SimIamPolicyDocumentParser } from "../../policy/parse/sim-iam-document-parser.js";
3
+ import type { SimIamPolicyStatementMatcher } from "../match/sim-iam-policy-statement-matcher.js";
4
+ import type { SimIamAuthZServiceControlPolicies } from "../context/sim-iam-auth-z-context.js";
5
+ import { SimIamPolicyDecisionValue } from "../sim-iam-decision-value.js";
6
+ interface SimIamScpGateProperties {
7
+ readonly serviceControlPolicies: SimIamAuthZServiceControlPolicies;
8
+ readonly policyDocumentParser: SimIamPolicyDocumentParser;
9
+ readonly statementMatcher: SimIamPolicyStatementMatcher;
10
+ }
11
+ /**
12
+ * What an Account's service control policies say about one request.
13
+ *
14
+ * An SCP is a filter on the permissions an Account's principals can be given.
15
+ * It grants nothing, so this runs as a gate in front of the identity and
16
+ * resource policy evaluation instead of contributing Allows to it. The rules
17
+ * are the ones AWS applies at the Account boundary:
18
+ *
19
+ * - a matching Deny at any level ends the request;
20
+ * - every level between the root and the Account has to produce a matching
21
+ * Allow of its own.
22
+ *
23
+ * The second rule is what makes the levels worth keeping apart. A root
24
+ * allowing S3 and an organizational unit allowing DynamoDB leave an Account
25
+ * beneath them able to do neither, because each level is asked separately.
26
+ *
27
+ * An Account outside any organization's reach is unrestricted, and this gate
28
+ * stands open for it. An Account inside one that holds no policy is a
29
+ * different case: nothing allows it anything, so the gate is shut.
30
+ */
31
+ export declare class SimIamScpGate {
32
+ private readonly applies;
33
+ private readonly denyStatementRecords;
34
+ private readonly allowStatementRecords;
35
+ private readonly unallowedLevelNames;
36
+ constructor(properties: SimIamScpGateProperties);
37
+ /**
38
+ * Whether any service control policy applied to this request at all.
39
+ */
40
+ get isApplied(): boolean;
41
+ /**
42
+ * Whether an attached policy explicitly denied the request.
43
+ */
44
+ get isExplicitDeny(): boolean;
45
+ /**
46
+ * Whether a level left the request unallowed.
47
+ *
48
+ * A Deny is reported by `isExplicitDeny` and leaves this false, so the two
49
+ * name different denials and a reader can tell them apart.
50
+ */
51
+ get isImplicitDeny(): boolean;
52
+ /**
53
+ * Whether the service control policies denied the request either way.
54
+ */
55
+ get isDenied(): boolean;
56
+ /**
57
+ * The decision this gate forces, where it forces one.
58
+ *
59
+ * Undefined leaves the request to the identity and resource policies, which
60
+ * is what an open gate means.
61
+ */
62
+ get value(): SimIamPolicyDecisionValue | undefined;
63
+ /**
64
+ * Matching Deny statements from the attached policies.
65
+ */
66
+ get denyStatements(): readonly SimIamPolicyDocumentStatement[];
67
+ /**
68
+ * Matching Allow statements from the attached policies, across every level.
69
+ */
70
+ get allowStatements(): readonly SimIamPolicyDocumentStatement[];
71
+ /**
72
+ * The levels that allowed nothing matching the request, root first.
73
+ *
74
+ * This is what a test reads to find which node in the organization is in the
75
+ * way, which is the part of an SCP denial AWS makes hardest to work out.
76
+ */
77
+ get unallowedLevels(): readonly string[];
78
+ /**
79
+ * How an AWS error explains this denial, if this gate is what denied it.
80
+ *
81
+ * The wording follows the AccessDenied messages AWS returns for the two
82
+ * cases, so a test asserting on the message reads what it would in a real
83
+ * account.
84
+ */
85
+ denialReason(action: string): string | undefined;
86
+ /**
87
+ * Record what one level of the organization said.
88
+ */
89
+ private evaluateLevel;
90
+ /**
91
+ * Record the matching statements of one attached policy, and say whether it
92
+ * allowed the request.
93
+ */
94
+ private evaluatePolicy;
95
+ }
96
+ export {};
@@ -0,0 +1,148 @@
1
+ import { SimIamPolicyDecisionValue } from "../sim-iam-decision-value.js";
2
+ /**
3
+ * What an Account's service control policies say about one request.
4
+ *
5
+ * An SCP is a filter on the permissions an Account's principals can be given.
6
+ * It grants nothing, so this runs as a gate in front of the identity and
7
+ * resource policy evaluation instead of contributing Allows to it. The rules
8
+ * are the ones AWS applies at the Account boundary:
9
+ *
10
+ * - a matching Deny at any level ends the request;
11
+ * - every level between the root and the Account has to produce a matching
12
+ * Allow of its own.
13
+ *
14
+ * The second rule is what makes the levels worth keeping apart. A root
15
+ * allowing S3 and an organizational unit allowing DynamoDB leave an Account
16
+ * beneath them able to do neither, because each level is asked separately.
17
+ *
18
+ * An Account outside any organization's reach is unrestricted, and this gate
19
+ * stands open for it. An Account inside one that holds no policy is a
20
+ * different case: nothing allows it anything, so the gate is shut.
21
+ */
22
+ export class SimIamScpGate {
23
+ applies;
24
+ denyStatementRecords = [];
25
+ allowStatementRecords = [];
26
+ unallowedLevelNames = [];
27
+ constructor(properties) {
28
+ this.applies = properties.serviceControlPolicies.applies;
29
+ for (const level of properties.serviceControlPolicies.levels) {
30
+ this.evaluateLevel(level, properties);
31
+ }
32
+ if (this.applies && properties.serviceControlPolicies.levels.length === 0) {
33
+ this.unallowedLevelNames.push("the organization");
34
+ }
35
+ }
36
+ /**
37
+ * Whether any service control policy applied to this request at all.
38
+ */
39
+ get isApplied() {
40
+ return this.applies;
41
+ }
42
+ /**
43
+ * Whether an attached policy explicitly denied the request.
44
+ */
45
+ get isExplicitDeny() {
46
+ return this.denyStatementRecords.length > 0;
47
+ }
48
+ /**
49
+ * Whether a level left the request unallowed.
50
+ *
51
+ * A Deny is reported by `isExplicitDeny` and leaves this false, so the two
52
+ * name different denials and a reader can tell them apart.
53
+ */
54
+ get isImplicitDeny() {
55
+ return (this.applies &&
56
+ !this.isExplicitDeny &&
57
+ this.unallowedLevelNames.length > 0);
58
+ }
59
+ /**
60
+ * Whether the service control policies denied the request either way.
61
+ */
62
+ get isDenied() {
63
+ return this.isExplicitDeny || this.isImplicitDeny;
64
+ }
65
+ /**
66
+ * The decision this gate forces, where it forces one.
67
+ *
68
+ * Undefined leaves the request to the identity and resource policies, which
69
+ * is what an open gate means.
70
+ */
71
+ get value() {
72
+ if (this.isExplicitDeny) {
73
+ return SimIamPolicyDecisionValue.ExplicitDeny;
74
+ }
75
+ return this.isImplicitDeny
76
+ ? SimIamPolicyDecisionValue.ImplicitDeny
77
+ : undefined;
78
+ }
79
+ /**
80
+ * Matching Deny statements from the attached policies.
81
+ */
82
+ get denyStatements() {
83
+ return this.denyStatementRecords;
84
+ }
85
+ /**
86
+ * Matching Allow statements from the attached policies, across every level.
87
+ */
88
+ get allowStatements() {
89
+ return this.allowStatementRecords;
90
+ }
91
+ /**
92
+ * The levels that allowed nothing matching the request, root first.
93
+ *
94
+ * This is what a test reads to find which node in the organization is in the
95
+ * way, which is the part of an SCP denial AWS makes hardest to work out.
96
+ */
97
+ get unallowedLevels() {
98
+ return this.unallowedLevelNames;
99
+ }
100
+ /**
101
+ * How an AWS error explains this denial, if this gate is what denied it.
102
+ *
103
+ * The wording follows the AccessDenied messages AWS returns for the two
104
+ * cases, so a test asserting on the message reads what it would in a real
105
+ * account.
106
+ */
107
+ denialReason(action) {
108
+ if (this.isExplicitDeny) {
109
+ return "with an explicit deny in a service control policy";
110
+ }
111
+ if (this.isImplicitDeny) {
112
+ return `because no service control policy allows the ${action} action`;
113
+ }
114
+ return undefined;
115
+ }
116
+ /**
117
+ * Record what one level of the organization said.
118
+ */
119
+ evaluateLevel(level, properties) {
120
+ let allowed = false;
121
+ for (const policy of level.sources) {
122
+ allowed = this.evaluatePolicy(policy, properties) || allowed;
123
+ }
124
+ if (!allowed) {
125
+ this.unallowedLevelNames.push(level.nodeName);
126
+ }
127
+ }
128
+ /**
129
+ * Record the matching statements of one attached policy, and say whether it
130
+ * allowed the request.
131
+ */
132
+ evaluatePolicy(policy, properties) {
133
+ const parsedPolicy = properties.policyDocumentParser.parse(policy.document);
134
+ let allowed = false;
135
+ for (const statement of parsedPolicy.statements) {
136
+ if (!properties.statementMatcher.matches(policy, statement).matched) {
137
+ continue;
138
+ }
139
+ if (statement.effect === "Deny") {
140
+ this.denyStatementRecords.push(statement.source);
141
+ continue;
142
+ }
143
+ this.allowStatementRecords.push(statement.source);
144
+ allowed = true;
145
+ }
146
+ return allowed;
147
+ }
148
+ }
@@ -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
  }