@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.
- package/dist/service/acm/command/delete-certificate/delete-certificate-authorizer.js +1 -0
- package/dist/service/acm/command/describe-certificate/describe-certificate-authorizer.js +1 -0
- package/dist/service/acm/command/list-certificates/list-certificates-authorizer.js +1 -0
- package/dist/service/acm/command/request-certificate/request-certificate-authorizer.js +1 -0
- package/dist/service/apigateway/serve/auth/sim-rest-api-authorizer-policy.js +3 -0
- package/dist/service/apigatewayv2/serve/auth/sim-http-api-authorizer-policy.js +3 -0
- package/dist/service/aws/factory/sim-aws-account-service-cache.d.ts +3 -0
- package/dist/service/aws/factory/sim-aws-account-service-cache.js +5 -0
- package/dist/service/aws/factory/sim-aws-service-factory.d.ts +9 -0
- package/dist/service/aws/factory/sim-aws-service-factory.js +10 -0
- package/dist/service/aws/sim-aws.d.ts +18 -0
- package/dist/service/aws/sim-aws.js +19 -0
- package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn-value-adapter.d.ts +6 -0
- package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn-value-adapter.js +23 -0
- package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn.d.ts +66 -0
- package/dist/service/cloudformation/resource/cfn/organizations/sim-organizations-cfn.js +136 -0
- package/dist/service/cloudformation/resource/cfn/sim-cfn-service-value-adapters.js +2 -0
- package/dist/service/cloudformation/resource/resolve/service/sim-cfn-service-factories.js +7 -0
- package/dist/service/cloudfront/command/create-distribution/create-distribution-authorizer.js +1 -0
- package/dist/service/cloudfront/command/create-function/create-function-authorizer.js +1 -0
- package/dist/service/cloudfront/command/delete-distribution/delete-distribution-authorizer.js +1 -0
- package/dist/service/cloudfront/command/delete-function/delete-function-authorizer.js +1 -0
- package/dist/service/cloudfront/command/get-distribution/get-distribution-authorizer.js +1 -0
- package/dist/service/cloudfront/command/update-distribution/update-distribution-authorizer.js +1 -0
- package/dist/service/cloudfront/edge/sim-cf-edge-association-auth-z.js +1 -0
- package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store-access.js +1 -0
- package/dist/service/cloudwatch/command/authorize/sim-cloudwatch-decide.js +1 -0
- package/dist/service/cognito/command/authorize/sim-cognito-authorizer.js +1 -0
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-authorizer.js +1 -0
- package/dist/service/firehose/command/authorize/sim-firehose-authorizer.js +1 -0
- package/dist/service/glue/command/authorize/sim-glue-authorize-resources.js +1 -0
- package/dist/service/iam/authorize/allow/sim-iam-policy-evaluation.d.ts +45 -0
- package/dist/service/iam/authorize/allow/sim-iam-policy-evaluation.js +59 -0
- package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.d.ts +15 -4
- package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.js +15 -4
- package/dist/service/iam/authorize/context/sim-iam-auth-z-context.d.ts +31 -1
- package/dist/service/iam/authorize/context/sim-iam-auth-z-context.factory.js +1 -0
- package/dist/service/iam/authorize/context/sim-iam-auth-z-scp-source-builder.d.ts +46 -0
- package/dist/service/iam/authorize/context/sim-iam-auth-z-scp-source-builder.js +71 -0
- package/dist/service/iam/authorize/scp/sim-iam-scp-gate.d.ts +96 -0
- package/dist/service/iam/authorize/scp/sim-iam-scp-gate.js +148 -0
- package/dist/service/iam/authorize/scp/sim-iam-scp-resolver.d.ts +53 -0
- package/dist/service/iam/authorize/scp/sim-iam-scp-resolver.js +1 -0
- package/dist/service/iam/authorize/sim-iam-account-auth-z.d.ts +8 -0
- package/dist/service/iam/authorize/sim-iam-account-auth-z.js +1 -0
- package/dist/service/iam/authorize/sim-iam-action-authorizer.js +1 -0
- package/dist/service/iam/authorize/sim-iam-authorizer.d.ts +2 -0
- package/dist/service/iam/authorize/sim-iam-authorizer.js +1 -0
- package/dist/service/iam/authorize/sim-iam-decision-value.d.ts +13 -0
- package/dist/service/iam/authorize/sim-iam-decision-value.js +12 -0
- package/dist/service/iam/authorize/sim-iam-decision.d.ts +33 -16
- package/dist/service/iam/authorize/sim-iam-decision.js +64 -49
- package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.d.ts +8 -0
- package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.js +1 -0
- package/dist/service/iam/error/sim-iam.error.d.ts +8 -0
- package/dist/service/iam/error/sim-iam.error.js +2 -1
- package/dist/service/iam/sim-iam-account-parts.d.ts +9 -0
- package/dist/service/iam/sim-iam-account-parts.js +1 -0
- package/dist/service/kinesis/command/authorize/sim-kinesis-authorizer.js +1 -0
- package/dist/service/kms/command/authorize/sim-kms-authorizer.js +2 -0
- package/dist/service/lambda/command/create-function/create-function-authorizer.js +1 -0
- package/dist/service/lambda/command/delete-function/delete-function-authorizer.js +1 -0
- package/dist/service/lambda/command/event-invoke-config/event-invoke-config-authorizer.js +1 -0
- package/dist/service/lambda/command/function-url/function-url-authorizer.js +1 -0
- package/dist/service/lambda/command/get-function/get-function-authorizer.js +1 -0
- package/dist/service/lambda/command/invoke/invoke-authorizer.js +1 -0
- package/dist/service/lambda/command/list-functions/list-functions-authorizer.js +1 -0
- package/dist/service/lambda/command/update-function-code/update-function-code-authorizer.js +1 -0
- package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.js +1 -0
- package/dist/service/lambda/command/version/version-authorizer.js +1 -0
- package/dist/service/logs/command/authorize/sim-logs-authorizer.js +1 -0
- package/dist/service/organizations/cfn/sim-cfn-organization-creator.d.ts +19 -0
- package/dist/service/organizations/cfn/sim-cfn-organization-creator.js +25 -0
- package/dist/service/organizations/cfn/sim-cfn-organizational-unit-creator.d.ts +16 -0
- package/dist/service/organizations/cfn/sim-cfn-organizational-unit-creator.js +21 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-account-creator.d.ts +20 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-account-creator.js +34 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-policy-creator.d.ts +21 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-policy-creator.js +40 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-policy-input.d.ts +20 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-policy-input.js +33 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-properties.d.ts +36 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-properties.js +78 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-record.d.ts +40 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-record.js +54 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-remover.d.ts +17 -0
- package/dist/service/organizations/cfn/sim-cfn-organizations-remover.js +40 -0
- package/dist/service/organizations/cfn/sim-organizations-cfn-resource-factory.d.ts +24 -0
- package/dist/service/organizations/cfn/sim-organizations-cfn-resource-factory.js +50 -0
- package/dist/service/organizations/index.d.ts +6 -0
- package/dist/service/organizations/index.js +6 -0
- package/dist/service/organizations/policy/sim-organizations-effective-policies.d.ts +43 -0
- package/dist/service/organizations/policy/sim-organizations-effective-policies.js +58 -0
- package/dist/service/organizations/policy/sim-organizations-scp-store.d.ts +61 -0
- package/dist/service/organizations/policy/sim-organizations-scp-store.js +103 -0
- package/dist/service/organizations/sim-organizations-structure.d.ts +94 -0
- package/dist/service/organizations/sim-organizations-structure.js +140 -0
- package/dist/service/organizations/sim-organizations.d.ts +95 -0
- package/dist/service/organizations/sim-organizations.js +99 -0
- package/dist/service/organizations/tree/sim-organizations-node.d.ts +57 -0
- package/dist/service/organizations/tree/sim-organizations-node.js +58 -0
- package/dist/service/organizations/tree/sim-organizations-tree.d.ts +91 -0
- package/dist/service/organizations/tree/sim-organizations-tree.js +154 -0
- package/dist/service/route53/command/change-resource-record-sets/change-resource-record-sets-authorizer.js +1 -0
- package/dist/service/route53/command/create-hosted-zone/create-hosted-zone-authorizer.js +1 -0
- package/dist/service/route53/command/delete-hosted-zone/delete-hosted-zone-authorizer.js +1 -0
- package/dist/service/route53/command/dnssec/sim-route53-dnssec-authorizer.js +1 -0
- package/dist/service/route53/command/get-hosted-zone/get-hosted-zone-authorizer.js +1 -0
- package/dist/service/route53/command/list-hosted-zones-by-name/list-hosted-zones-by-name-authorizer.js +1 -0
- package/dist/service/route53/command/list-resource-record-sets/list-resource-record-sets-authorizer.js +1 -0
- package/dist/service/s3/command/create-bucket/create-bucket.handler.js +1 -0
- package/dist/service/s3/command/delete-bucket/delete-bucket-authorizer.js +1 -0
- package/dist/service/s3/command/delete-bucket-policy/delete-bucket-policy-authorizer.js +1 -0
- package/dist/service/s3/command/delete-object/delete-object-authorizer.js +1 -0
- package/dist/service/s3/command/get-bucket-policy/get-bucket-policy-authorizer.js +1 -0
- package/dist/service/s3/command/get-object/get-object-authorizer.js +1 -0
- package/dist/service/s3/command/head-bucket/head-bucket-authorizer.js +1 -0
- package/dist/service/s3/command/lifecycle/sim-s3-lifecycle-authorizer.js +1 -0
- package/dist/service/s3/command/list-buckets/list-buckets-authorizer.js +1 -0
- package/dist/service/s3/command/list-objects/list-objects-authorizer.js +1 -0
- package/dist/service/s3/command/multipart/sim-s3-multipart-authorizer.js +1 -0
- package/dist/service/s3/command/notification/sim-s3-notification-authorizer.js +1 -0
- package/dist/service/s3/command/public-access-block/sim-s3-public-access-block-authorizer.js +1 -0
- package/dist/service/s3/command/put-bucket-policy/put-bucket-policy-authorizer.js +1 -0
- package/dist/service/s3/command/put-bucket-website/put-bucket-website-authorizer.js +1 -0
- package/dist/service/s3/command/put-object/put-object-authorizer.js +1 -0
- package/dist/service/secretsmanager/command/authorize/sim-secrets-manager-authorizer.js +1 -0
- package/dist/service/ses/command/authorize/sim-ses-authorizer.js +1 -0
- package/dist/service/sqs/command/authorize/sim-sqs-authorizer.js +1 -0
- package/dist/service/ssm/command/authorize/sim-ssm-authorizer.js +1 -0
- package/dist/service/wafv2/command/authorize/sim-wafv2-authorizer.js +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Works out which service control policies an Account is actually subject to.
|
|
3
|
+
*
|
|
4
|
+
* The tree says which nodes lie above an Account and the store says what hangs
|
|
5
|
+
* on each of them. Putting the two together is the whole of what sim IAM asks
|
|
6
|
+
* an organization, so it lives here rather than in the facade.
|
|
7
|
+
*/
|
|
8
|
+
export class SimOrganizationsEffectivePolicies {
|
|
9
|
+
tree;
|
|
10
|
+
scpStore;
|
|
11
|
+
managementAccountId;
|
|
12
|
+
constructor(properties) {
|
|
13
|
+
this.tree = properties.tree;
|
|
14
|
+
this.scpStore = properties.scpStore;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Name the Account AWS exempts from every service control policy.
|
|
18
|
+
*/
|
|
19
|
+
setManagementAccount(accountId) {
|
|
20
|
+
this.managementAccountId = accountId;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The policies in force for an Account, level by level, root first.
|
|
24
|
+
*/
|
|
25
|
+
setFor(accountId) {
|
|
26
|
+
if (accountId === this.managementAccountId) {
|
|
27
|
+
return { applies: false, levels: [] };
|
|
28
|
+
}
|
|
29
|
+
const path = this.pathFor(accountId);
|
|
30
|
+
if (path.length === 0) {
|
|
31
|
+
return { applies: false, levels: [] };
|
|
32
|
+
}
|
|
33
|
+
return { applies: true, levels: path.map((node) => this.levelAt(node)) };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The nodes filtering an Account's requests.
|
|
37
|
+
*
|
|
38
|
+
* An Account placed in the organization is filtered by the path down to it.
|
|
39
|
+
* An Account only ever named by having a policy attached to it is filtered
|
|
40
|
+
* by that policy alone, which is what attaching to an Account meant before
|
|
41
|
+
* the organization had a shape.
|
|
42
|
+
*/
|
|
43
|
+
pathFor(accountId) {
|
|
44
|
+
if (this.tree.holds(accountId)) {
|
|
45
|
+
return this.tree.pathTo(accountId);
|
|
46
|
+
}
|
|
47
|
+
return this.scpStore.holds(accountId) ? [accountId] : [];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* What one node contributes to an Account's decision.
|
|
51
|
+
*/
|
|
52
|
+
levelAt(nodeId) {
|
|
53
|
+
return {
|
|
54
|
+
nodeName: this.tree.nameOf(nodeId),
|
|
55
|
+
policies: this.scpStore.policiesAt(nodeId),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { SimIamServiceControlPolicy } from "../../iam/authorize/scp/sim-iam-scp-resolver.js";
|
|
2
|
+
import type { SimIamPolicyDocument } from "../../iam/policy/sim-iam-policy.js";
|
|
3
|
+
import type { SimOrganizationsNodeId } from "../tree/sim-organizations-node.js";
|
|
4
|
+
/**
|
|
5
|
+
* The AWS-managed policy attached to every organization node by default.
|
|
6
|
+
*
|
|
7
|
+
* Turning service control policies on in an organization leaves every
|
|
8
|
+
* account's permissions as they were, because this policy comes with them. A
|
|
9
|
+
* simulated node gets the same treatment, so attaching one Deny statement
|
|
10
|
+
* denies that one action and leaves the rest working.
|
|
11
|
+
*/
|
|
12
|
+
export declare const SIM_ORGANIZATIONS_FULL_AWS_ACCESS: SimIamServiceControlPolicy;
|
|
13
|
+
/**
|
|
14
|
+
* The service control policies attached to each node of an organization.
|
|
15
|
+
*
|
|
16
|
+
* A node holds FullAWSAccess along with whatever was attached to it, until a
|
|
17
|
+
* test detaches FullAWSAccess to write an allow list at that node. A node
|
|
18
|
+
* nothing was attached to still holds FullAWSAccess, so an organizational unit
|
|
19
|
+
* a test never mentions allows everything through it.
|
|
20
|
+
*/
|
|
21
|
+
export declare class SimOrganizationsScpStore {
|
|
22
|
+
private readonly byNodeId;
|
|
23
|
+
/**
|
|
24
|
+
* Attach a service control policy to a node under an id of its own.
|
|
25
|
+
*
|
|
26
|
+
* The id is what takes the policy off again. One policy attached to several
|
|
27
|
+
* nodes carries the same id at each of them, the way an AWS policy attached
|
|
28
|
+
* to several targets is one policy.
|
|
29
|
+
*/
|
|
30
|
+
attach(nodeId: SimOrganizationsNodeId, policyId: string, document: SimIamPolicyDocument, policyName?: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Take one service control policy off a node, leaving the rest.
|
|
33
|
+
*
|
|
34
|
+
* A node can hold policies from more than one source, so taking the wrong
|
|
35
|
+
* ones off would change what an Account may do behind the caller's back.
|
|
36
|
+
*/
|
|
37
|
+
detach(nodeId: SimOrganizationsNodeId, policyId: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Take the AWS-managed FullAWSAccess policy off a node.
|
|
40
|
+
*
|
|
41
|
+
* What remains at that node has to allow an action for a request through it
|
|
42
|
+
* to go ahead, which is how a level is turned into an allow list.
|
|
43
|
+
*/
|
|
44
|
+
detachFullAwsAccess(nodeId: SimOrganizationsNodeId): void;
|
|
45
|
+
/**
|
|
46
|
+
* Put a node back to holding FullAWSAccess and nothing else.
|
|
47
|
+
*/
|
|
48
|
+
detachAll(nodeId: SimOrganizationsNodeId): void;
|
|
49
|
+
/**
|
|
50
|
+
* The policies in force at one node, FullAWSAccess first.
|
|
51
|
+
*/
|
|
52
|
+
policiesAt(nodeId: SimOrganizationsNodeId): readonly SimIamServiceControlPolicy[];
|
|
53
|
+
/**
|
|
54
|
+
* Whether anything has been attached to or detached from a node.
|
|
55
|
+
*/
|
|
56
|
+
holds(nodeId: SimOrganizationsNodeId): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The record for a node, created on first use.
|
|
59
|
+
*/
|
|
60
|
+
private nodePolicies;
|
|
61
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AWS-managed policy attached to every organization node by default.
|
|
3
|
+
*
|
|
4
|
+
* Turning service control policies on in an organization leaves every
|
|
5
|
+
* account's permissions as they were, because this policy comes with them. A
|
|
6
|
+
* simulated node gets the same treatment, so attaching one Deny statement
|
|
7
|
+
* denies that one action and leaves the rest working.
|
|
8
|
+
*/
|
|
9
|
+
export const SIM_ORGANIZATIONS_FULL_AWS_ACCESS = {
|
|
10
|
+
policyName: "FullAWSAccess",
|
|
11
|
+
document: {
|
|
12
|
+
Version: "2012-10-17",
|
|
13
|
+
Statement: { Effect: "Allow", Action: "*", Resource: "*" },
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The service control policies attached to each node of an organization.
|
|
18
|
+
*
|
|
19
|
+
* A node holds FullAWSAccess along with whatever was attached to it, until a
|
|
20
|
+
* test detaches FullAWSAccess to write an allow list at that node. A node
|
|
21
|
+
* nothing was attached to still holds FullAWSAccess, so an organizational unit
|
|
22
|
+
* a test never mentions allows everything through it.
|
|
23
|
+
*/
|
|
24
|
+
export class SimOrganizationsScpStore {
|
|
25
|
+
byNodeId = new Map();
|
|
26
|
+
/**
|
|
27
|
+
* Attach a service control policy to a node under an id of its own.
|
|
28
|
+
*
|
|
29
|
+
* The id is what takes the policy off again. One policy attached to several
|
|
30
|
+
* nodes carries the same id at each of them, the way an AWS policy attached
|
|
31
|
+
* to several targets is one policy.
|
|
32
|
+
*/
|
|
33
|
+
attach(nodeId, policyId, document, policyName) {
|
|
34
|
+
this.nodePolicies(nodeId).attached.push({
|
|
35
|
+
policyId,
|
|
36
|
+
policy: { document, policyName },
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Take one service control policy off a node, leaving the rest.
|
|
41
|
+
*
|
|
42
|
+
* A node can hold policies from more than one source, so taking the wrong
|
|
43
|
+
* ones off would change what an Account may do behind the caller's back.
|
|
44
|
+
*/
|
|
45
|
+
detach(nodeId, policyId) {
|
|
46
|
+
const node = this.byNodeId.get(nodeId);
|
|
47
|
+
if (node === undefined) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const remaining = node.attached.filter((attached) => attached.policyId !== policyId);
|
|
51
|
+
node.attached.length = 0;
|
|
52
|
+
node.attached.push(...remaining);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Take the AWS-managed FullAWSAccess policy off a node.
|
|
56
|
+
*
|
|
57
|
+
* What remains at that node has to allow an action for a request through it
|
|
58
|
+
* to go ahead, which is how a level is turned into an allow list.
|
|
59
|
+
*/
|
|
60
|
+
detachFullAwsAccess(nodeId) {
|
|
61
|
+
this.nodePolicies(nodeId).fullAwsAccess = false;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Put a node back to holding FullAWSAccess and nothing else.
|
|
65
|
+
*/
|
|
66
|
+
detachAll(nodeId) {
|
|
67
|
+
this.byNodeId.delete(nodeId);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The policies in force at one node, FullAWSAccess first.
|
|
71
|
+
*/
|
|
72
|
+
policiesAt(nodeId) {
|
|
73
|
+
const node = this.byNodeId.get(nodeId);
|
|
74
|
+
if (node === undefined) {
|
|
75
|
+
return [SIM_ORGANIZATIONS_FULL_AWS_ACCESS];
|
|
76
|
+
}
|
|
77
|
+
const attached = node.attached.map((entry) => entry.policy);
|
|
78
|
+
return node.fullAwsAccess
|
|
79
|
+
? [SIM_ORGANIZATIONS_FULL_AWS_ACCESS, ...attached]
|
|
80
|
+
: attached;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether anything has been attached to or detached from a node.
|
|
84
|
+
*/
|
|
85
|
+
holds(nodeId) {
|
|
86
|
+
return this.byNodeId.has(nodeId);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The record for a node, created on first use.
|
|
90
|
+
*/
|
|
91
|
+
nodePolicies(nodeId) {
|
|
92
|
+
const existing = this.byNodeId.get(nodeId);
|
|
93
|
+
if (existing !== undefined) {
|
|
94
|
+
return existing;
|
|
95
|
+
}
|
|
96
|
+
const created = {
|
|
97
|
+
attached: [],
|
|
98
|
+
fullAwsAccess: true,
|
|
99
|
+
};
|
|
100
|
+
this.byNodeId.set(nodeId, created);
|
|
101
|
+
return created;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { SimOrganizationsEffectivePolicies } from "./policy/sim-organizations-effective-policies.js";
|
|
2
|
+
import { SimOrganizationsScpStore } from "./policy/sim-organizations-scp-store.js";
|
|
3
|
+
import { type SimOrganizationsNodeId, type SimOrganizationsOrganizationalUnit, type SimOrganizationsRoot, type SimOrganizationsTarget } from "./tree/sim-organizations-node.js";
|
|
4
|
+
import { SimOrganizationsTree } from "./tree/sim-organizations-tree.js";
|
|
5
|
+
/**
|
|
6
|
+
* The shape of one simulated organization: its root, the organizational units
|
|
7
|
+
* under it, and where its Accounts sit.
|
|
8
|
+
*
|
|
9
|
+
* SimOrganizations is the facade a test reaches through, and this is the half
|
|
10
|
+
* of it concerned with structure. The policies that hang on that structure are
|
|
11
|
+
* the other half.
|
|
12
|
+
*/
|
|
13
|
+
export declare abstract class SimOrganizationsStructure {
|
|
14
|
+
protected readonly scpStore: SimOrganizationsScpStore;
|
|
15
|
+
protected readonly tree: SimOrganizationsTree;
|
|
16
|
+
protected readonly effectivePolicies: SimOrganizationsEffectivePolicies;
|
|
17
|
+
/**
|
|
18
|
+
* The root of this organization, which every Account sits under.
|
|
19
|
+
*/
|
|
20
|
+
root(): SimOrganizationsRoot;
|
|
21
|
+
/**
|
|
22
|
+
* Create an organizational unit, under the root unless a parent unit is
|
|
23
|
+
* given.
|
|
24
|
+
*/
|
|
25
|
+
createOrganizationalUnit(name: string, parent?: SimOrganizationsTarget): SimOrganizationsOrganizationalUnit;
|
|
26
|
+
/**
|
|
27
|
+
* Put an Account in the organization, under an organizational unit or under
|
|
28
|
+
* the root.
|
|
29
|
+
*/
|
|
30
|
+
moveAccount(accountId: string, parent?: SimOrganizationsTarget): void;
|
|
31
|
+
/**
|
|
32
|
+
* Name the Account that pays the organization's bills.
|
|
33
|
+
*
|
|
34
|
+
* AWS exempts the management account from every service control policy, and
|
|
35
|
+
* so does this. An Account named here is decided by its identity and
|
|
36
|
+
* resource policies alone, whatever is attached above it.
|
|
37
|
+
*/
|
|
38
|
+
setManagementAccount(accountId: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Every Account this organization holds.
|
|
41
|
+
*
|
|
42
|
+
* A test tracking down where a denial came from reads this to see which
|
|
43
|
+
* Accounts the organization is filtering at all.
|
|
44
|
+
*/
|
|
45
|
+
accountIds(): readonly string[];
|
|
46
|
+
/**
|
|
47
|
+
* Take an Account out of the organization.
|
|
48
|
+
*
|
|
49
|
+
* Nothing then filters its requests, whatever is attached above where it
|
|
50
|
+
* sat. This is how an Account leaves an organization, and it is a different
|
|
51
|
+
* thing from taking the policies off it.
|
|
52
|
+
*/
|
|
53
|
+
removeAccount(accountId: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Take an organizational unit out of the organization.
|
|
56
|
+
*
|
|
57
|
+
* Anything still under it moves up to its parent, so every Account keeps a
|
|
58
|
+
* path back to the root.
|
|
59
|
+
*/
|
|
60
|
+
removeOrganizationalUnit(target: SimOrganizationsTarget): void;
|
|
61
|
+
/**
|
|
62
|
+
* The node a target names.
|
|
63
|
+
*
|
|
64
|
+
* An Account is named by its twelve-digit id and needs no place in the
|
|
65
|
+
* organization yet, because attaching a policy to one is what puts it there.
|
|
66
|
+
* A root or organizational unit, whether given as a handle or as the `r-` or
|
|
67
|
+
* `ou-` id a template carries, has to be this organization's own. One from
|
|
68
|
+
* another organization is refused rather than attached to and never read.
|
|
69
|
+
*/
|
|
70
|
+
protected nodeIdOf(target: SimOrganizationsTarget): SimOrganizationsNodeId;
|
|
71
|
+
/**
|
|
72
|
+
* Refuse the whole set unless every target names a node this organization
|
|
73
|
+
* has.
|
|
74
|
+
*
|
|
75
|
+
* Attaching one policy to several nodes is one act, so it either reaches all
|
|
76
|
+
* of them or none. Failing partway would leave a policy attached where
|
|
77
|
+
* nothing knows to take it off.
|
|
78
|
+
*/
|
|
79
|
+
requireTargets(targets: readonly SimOrganizationsTarget[]): void;
|
|
80
|
+
/**
|
|
81
|
+
* The node a target names, or nothing where this organization has no such
|
|
82
|
+
* node.
|
|
83
|
+
*
|
|
84
|
+
* Taking something off a node that has already gone is what a Stack teardown
|
|
85
|
+
* asks for when a unit came down before the policy pointing at it. There is
|
|
86
|
+
* nothing to take off, and refusing would fail a teardown over work already
|
|
87
|
+
* done.
|
|
88
|
+
*/
|
|
89
|
+
protected knownNodeIdOf(target: SimOrganizationsTarget): SimOrganizationsNodeId | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* The node something sits under, defaulting to the root.
|
|
92
|
+
*/
|
|
93
|
+
private parentIdOf;
|
|
94
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { simAwsAccountId } from "../aws/sim-aws-account.js";
|
|
2
|
+
import { SimOrganizationsEffectivePolicies } from "./policy/sim-organizations-effective-policies.js";
|
|
3
|
+
import { SimOrganizationsScpStore } from "./policy/sim-organizations-scp-store.js";
|
|
4
|
+
import { isSimOrganizationsUnitId, } from "./tree/sim-organizations-node.js";
|
|
5
|
+
import { SimOrganizationsTree } from "./tree/sim-organizations-tree.js";
|
|
6
|
+
/**
|
|
7
|
+
* The shape of one simulated organization: its root, the organizational units
|
|
8
|
+
* under it, and where its Accounts sit.
|
|
9
|
+
*
|
|
10
|
+
* SimOrganizations is the facade a test reaches through, and this is the half
|
|
11
|
+
* of it concerned with structure. The policies that hang on that structure are
|
|
12
|
+
* the other half.
|
|
13
|
+
*/
|
|
14
|
+
export class SimOrganizationsStructure {
|
|
15
|
+
scpStore = new SimOrganizationsScpStore();
|
|
16
|
+
tree = new SimOrganizationsTree();
|
|
17
|
+
effectivePolicies = new SimOrganizationsEffectivePolicies({
|
|
18
|
+
tree: this.tree,
|
|
19
|
+
scpStore: this.scpStore,
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* The root of this organization, which every Account sits under.
|
|
23
|
+
*/
|
|
24
|
+
root() {
|
|
25
|
+
return this.tree.root;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create an organizational unit, under the root unless a parent unit is
|
|
29
|
+
* given.
|
|
30
|
+
*/
|
|
31
|
+
createOrganizationalUnit(name, parent) {
|
|
32
|
+
return this.tree.createOrganizationalUnit(name, this.parentIdOf(parent));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Put an Account in the organization, under an organizational unit or under
|
|
36
|
+
* the root.
|
|
37
|
+
*/
|
|
38
|
+
moveAccount(accountId, parent) {
|
|
39
|
+
this.tree.placeAccount(simAwsAccountId(accountId), this.parentIdOf(parent));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Name the Account that pays the organization's bills.
|
|
43
|
+
*
|
|
44
|
+
* AWS exempts the management account from every service control policy, and
|
|
45
|
+
* so does this. An Account named here is decided by its identity and
|
|
46
|
+
* resource policies alone, whatever is attached above it.
|
|
47
|
+
*/
|
|
48
|
+
setManagementAccount(accountId) {
|
|
49
|
+
const account = simAwsAccountId(accountId);
|
|
50
|
+
this.effectivePolicies.setManagementAccount(account);
|
|
51
|
+
this.tree.placeAccount(account);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Every Account this organization holds.
|
|
55
|
+
*
|
|
56
|
+
* A test tracking down where a denial came from reads this to see which
|
|
57
|
+
* Accounts the organization is filtering at all.
|
|
58
|
+
*/
|
|
59
|
+
accountIds() {
|
|
60
|
+
return this.tree.accountIds();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Take an Account out of the organization.
|
|
64
|
+
*
|
|
65
|
+
* Nothing then filters its requests, whatever is attached above where it
|
|
66
|
+
* sat. This is how an Account leaves an organization, and it is a different
|
|
67
|
+
* thing from taking the policies off it.
|
|
68
|
+
*/
|
|
69
|
+
removeAccount(accountId) {
|
|
70
|
+
this.tree.removeAccount(simAwsAccountId(accountId));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Take an organizational unit out of the organization.
|
|
74
|
+
*
|
|
75
|
+
* Anything still under it moves up to its parent, so every Account keeps a
|
|
76
|
+
* path back to the root.
|
|
77
|
+
*/
|
|
78
|
+
removeOrganizationalUnit(target) {
|
|
79
|
+
const nodeId = this.knownNodeIdOf(target);
|
|
80
|
+
if (nodeId !== undefined) {
|
|
81
|
+
this.tree.removeOrganizationalUnit(nodeId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The node a target names.
|
|
86
|
+
*
|
|
87
|
+
* An Account is named by its twelve-digit id and needs no place in the
|
|
88
|
+
* organization yet, because attaching a policy to one is what puts it there.
|
|
89
|
+
* A root or organizational unit, whether given as a handle or as the `r-` or
|
|
90
|
+
* `ou-` id a template carries, has to be this organization's own. One from
|
|
91
|
+
* another organization is refused rather than attached to and never read.
|
|
92
|
+
*/
|
|
93
|
+
nodeIdOf(target) {
|
|
94
|
+
if (typeof target !== "string") {
|
|
95
|
+
this.tree.requireNode(target.id);
|
|
96
|
+
return target.id;
|
|
97
|
+
}
|
|
98
|
+
if (!isSimOrganizationsUnitId(target)) {
|
|
99
|
+
return simAwsAccountId(target);
|
|
100
|
+
}
|
|
101
|
+
const nodeId = target;
|
|
102
|
+
this.tree.requireNode(nodeId);
|
|
103
|
+
return nodeId;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Refuse the whole set unless every target names a node this organization
|
|
107
|
+
* has.
|
|
108
|
+
*
|
|
109
|
+
* Attaching one policy to several nodes is one act, so it either reaches all
|
|
110
|
+
* of them or none. Failing partway would leave a policy attached where
|
|
111
|
+
* nothing knows to take it off.
|
|
112
|
+
*/
|
|
113
|
+
requireTargets(targets) {
|
|
114
|
+
for (const target of targets) {
|
|
115
|
+
this.nodeIdOf(target);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The node a target names, or nothing where this organization has no such
|
|
120
|
+
* node.
|
|
121
|
+
*
|
|
122
|
+
* Taking something off a node that has already gone is what a Stack teardown
|
|
123
|
+
* asks for when a unit came down before the policy pointing at it. There is
|
|
124
|
+
* nothing to take off, and refusing would fail a teardown over work already
|
|
125
|
+
* done.
|
|
126
|
+
*/
|
|
127
|
+
knownNodeIdOf(target) {
|
|
128
|
+
if (typeof target === "string" && !isSimOrganizationsUnitId(target)) {
|
|
129
|
+
return simAwsAccountId(target);
|
|
130
|
+
}
|
|
131
|
+
const nodeId = (typeof target === "string" ? target : target.id);
|
|
132
|
+
return this.tree.hasNode(nodeId) ? nodeId : undefined;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The node something sits under, defaulting to the root.
|
|
136
|
+
*/
|
|
137
|
+
parentIdOf(parent) {
|
|
138
|
+
return parent === undefined ? undefined : this.nodeIdOf(parent);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type SimAwsAccountId } from "../aws/sim-aws-account.js";
|
|
2
|
+
import type { SimIamPolicyDocument } from "../iam/policy/sim-iam-policy.js";
|
|
3
|
+
import type { SimIamServiceControlPolicy, SimIamServiceControlPolicyResolver, SimIamServiceControlPolicySet } from "../iam/authorize/scp/sim-iam-scp-resolver.js";
|
|
4
|
+
import { SimOrganizationsStructure } from "./sim-organizations-structure.js";
|
|
5
|
+
import { type SimOrganizationsTarget } from "./tree/sim-organizations-node.js";
|
|
6
|
+
/**
|
|
7
|
+
* Options for one attached service control policy.
|
|
8
|
+
*/
|
|
9
|
+
export interface SimOrganizationsAttachOptions {
|
|
10
|
+
/**
|
|
11
|
+
* What to call the policy in a denial. Defaults to `ServiceControlPolicy`.
|
|
12
|
+
*/
|
|
13
|
+
readonly policyName?: string | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* The id to attach the policy under, for taking it off again later.
|
|
16
|
+
*
|
|
17
|
+
* One policy attached to several nodes takes the same id at each of them.
|
|
18
|
+
* Defaults to an id of this attachment's own.
|
|
19
|
+
*/
|
|
20
|
+
readonly policyId?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Simulated AWS Organizations, holding the organization structure and the
|
|
24
|
+
* service control policies that decide what its Accounts may do.
|
|
25
|
+
*
|
|
26
|
+
* An organization spans Accounts, so one of these belongs to a SimAws rather
|
|
27
|
+
* than to an Account scope, and it is reached as `simAws.organizations()`.
|
|
28
|
+
*
|
|
29
|
+
* A service control policy filters permissions and grants none. Every level
|
|
30
|
+
* between the root and an Account has to allow an action for the Account to be
|
|
31
|
+
* allowed it, and a Deny at any level ends the request whatever else allows
|
|
32
|
+
* it. That applies to the Account root as well as to its Roles and Users, so
|
|
33
|
+
* it catches a CloudFormation deployment and an intercepted SDK call alike.
|
|
34
|
+
*
|
|
35
|
+
* The root, the organizational units and where the Accounts sit come from
|
|
36
|
+
* SimOrganizationsStructure, which this extends.
|
|
37
|
+
*/
|
|
38
|
+
export declare class SimOrganizations extends SimOrganizationsStructure implements SimIamServiceControlPolicyResolver {
|
|
39
|
+
/**
|
|
40
|
+
* Attach a service control policy to the root, an organizational unit, or an
|
|
41
|
+
* Account.
|
|
42
|
+
*
|
|
43
|
+
* The node also holds AWS's own FullAWSAccess policy, as it would in a real
|
|
44
|
+
* organization, so one Deny statement denies that action and leaves the rest
|
|
45
|
+
* of the node's Accounts working.
|
|
46
|
+
*/
|
|
47
|
+
attachServiceControlPolicy(target: SimOrganizationsTarget, document: SimIamPolicyDocument, options?: SimOrganizationsAttachOptions): string;
|
|
48
|
+
/**
|
|
49
|
+
* Take one service control policy off a node, leaving whatever else is
|
|
50
|
+
* attached there.
|
|
51
|
+
*
|
|
52
|
+
* This is what a CloudFormation teardown uses, because a node can hold
|
|
53
|
+
* policies from more than one Stack and clearing it would take another
|
|
54
|
+
* Stack's guardrail away.
|
|
55
|
+
*/
|
|
56
|
+
detachServiceControlPolicy(target: SimOrganizationsTarget, policyId: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Take AWS's FullAWSAccess policy off a node, leaving only the policies
|
|
59
|
+
* attached to it to allow anything through that level.
|
|
60
|
+
*
|
|
61
|
+
* This turns the node into an allow list. An action no policy attached there
|
|
62
|
+
* allows is denied for every Account beneath it.
|
|
63
|
+
*/
|
|
64
|
+
detachFullAwsAccess(target: SimOrganizationsTarget): void;
|
|
65
|
+
/**
|
|
66
|
+
* Remove every service control policy attached to a node.
|
|
67
|
+
*
|
|
68
|
+
* Only that node is cleared. An Account sitting in an organizational unit
|
|
69
|
+
* goes on inheriting what the levels above it say, as it does in AWS, where
|
|
70
|
+
* detaching a policy from an account leaves the account where it is. Take an
|
|
71
|
+
* Account out of the organization with `removeAccount`.
|
|
72
|
+
*
|
|
73
|
+
* A node that has already gone leaves nothing to take off, so this does
|
|
74
|
+
* nothing rather than refusing. A Stack teardown reaches that case whenever
|
|
75
|
+
* a unit came down before the policy pointing at it.
|
|
76
|
+
*/
|
|
77
|
+
detachServiceControlPolicies(target: SimOrganizationsTarget): void;
|
|
78
|
+
/**
|
|
79
|
+
* The service control policies in force for an Account, root level first.
|
|
80
|
+
*
|
|
81
|
+
* This flattens the levels, so it says what was evaluated without saying
|
|
82
|
+
* which level each policy came from. `serviceControlPolicySetFor` keeps that
|
|
83
|
+
* apart, and a denial needs it, because a level allowing nothing denies the
|
|
84
|
+
* Account whatever another level allows.
|
|
85
|
+
*/
|
|
86
|
+
serviceControlPoliciesFor(accountId: SimAwsAccountId | string): readonly SimIamServiceControlPolicy[];
|
|
87
|
+
/**
|
|
88
|
+
* The policies in force for an Account, level by level, along with whether
|
|
89
|
+
* the Account is inside this organization at all.
|
|
90
|
+
*
|
|
91
|
+
* Sim IAM reads this rather than the flattened list, because each level has
|
|
92
|
+
* to allow an action on its own.
|
|
93
|
+
*/
|
|
94
|
+
serviceControlPolicySetFor(accountId: SimAwsAccountId | string): SimIamServiceControlPolicySet;
|
|
95
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { simAwsAccountId, } from "../aws/sim-aws-account.js";
|
|
2
|
+
import { SimOrganizationsStructure } from "./sim-organizations-structure.js";
|
|
3
|
+
import { makeSimOrganizationsPolicyId, } from "./tree/sim-organizations-node.js";
|
|
4
|
+
/**
|
|
5
|
+
* Simulated AWS Organizations, holding the organization structure and the
|
|
6
|
+
* service control policies that decide what its Accounts may do.
|
|
7
|
+
*
|
|
8
|
+
* An organization spans Accounts, so one of these belongs to a SimAws rather
|
|
9
|
+
* than to an Account scope, and it is reached as `simAws.organizations()`.
|
|
10
|
+
*
|
|
11
|
+
* A service control policy filters permissions and grants none. Every level
|
|
12
|
+
* between the root and an Account has to allow an action for the Account to be
|
|
13
|
+
* allowed it, and a Deny at any level ends the request whatever else allows
|
|
14
|
+
* it. That applies to the Account root as well as to its Roles and Users, so
|
|
15
|
+
* it catches a CloudFormation deployment and an intercepted SDK call alike.
|
|
16
|
+
*
|
|
17
|
+
* The root, the organizational units and where the Accounts sit come from
|
|
18
|
+
* SimOrganizationsStructure, which this extends.
|
|
19
|
+
*/
|
|
20
|
+
export class SimOrganizations extends SimOrganizationsStructure {
|
|
21
|
+
/**
|
|
22
|
+
* Attach a service control policy to the root, an organizational unit, or an
|
|
23
|
+
* Account.
|
|
24
|
+
*
|
|
25
|
+
* The node also holds AWS's own FullAWSAccess policy, as it would in a real
|
|
26
|
+
* organization, so one Deny statement denies that action and leaves the rest
|
|
27
|
+
* of the node's Accounts working.
|
|
28
|
+
*/
|
|
29
|
+
attachServiceControlPolicy(target, document, options = {}) {
|
|
30
|
+
const policyName = options.policyName ?? "ServiceControlPolicy";
|
|
31
|
+
const policyId = options.policyId ?? makeSimOrganizationsPolicyId();
|
|
32
|
+
this.scpStore.attach(this.nodeIdOf(target), policyId, document, policyName);
|
|
33
|
+
return policyId;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Take one service control policy off a node, leaving whatever else is
|
|
37
|
+
* attached there.
|
|
38
|
+
*
|
|
39
|
+
* This is what a CloudFormation teardown uses, because a node can hold
|
|
40
|
+
* policies from more than one Stack and clearing it would take another
|
|
41
|
+
* Stack's guardrail away.
|
|
42
|
+
*/
|
|
43
|
+
detachServiceControlPolicy(target, policyId) {
|
|
44
|
+
const nodeId = this.knownNodeIdOf(target);
|
|
45
|
+
if (nodeId !== undefined) {
|
|
46
|
+
this.scpStore.detach(nodeId, policyId);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Take AWS's FullAWSAccess policy off a node, leaving only the policies
|
|
51
|
+
* attached to it to allow anything through that level.
|
|
52
|
+
*
|
|
53
|
+
* This turns the node into an allow list. An action no policy attached there
|
|
54
|
+
* allows is denied for every Account beneath it.
|
|
55
|
+
*/
|
|
56
|
+
detachFullAwsAccess(target) {
|
|
57
|
+
this.scpStore.detachFullAwsAccess(this.nodeIdOf(target));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Remove every service control policy attached to a node.
|
|
61
|
+
*
|
|
62
|
+
* Only that node is cleared. An Account sitting in an organizational unit
|
|
63
|
+
* goes on inheriting what the levels above it say, as it does in AWS, where
|
|
64
|
+
* detaching a policy from an account leaves the account where it is. Take an
|
|
65
|
+
* Account out of the organization with `removeAccount`.
|
|
66
|
+
*
|
|
67
|
+
* A node that has already gone leaves nothing to take off, so this does
|
|
68
|
+
* nothing rather than refusing. A Stack teardown reaches that case whenever
|
|
69
|
+
* a unit came down before the policy pointing at it.
|
|
70
|
+
*/
|
|
71
|
+
detachServiceControlPolicies(target) {
|
|
72
|
+
const nodeId = this.knownNodeIdOf(target);
|
|
73
|
+
if (nodeId !== undefined) {
|
|
74
|
+
this.scpStore.detachAll(nodeId);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The service control policies in force for an Account, root level first.
|
|
79
|
+
*
|
|
80
|
+
* This flattens the levels, so it says what was evaluated without saying
|
|
81
|
+
* which level each policy came from. `serviceControlPolicySetFor` keeps that
|
|
82
|
+
* apart, and a denial needs it, because a level allowing nothing denies the
|
|
83
|
+
* Account whatever another level allows.
|
|
84
|
+
*/
|
|
85
|
+
serviceControlPoliciesFor(accountId) {
|
|
86
|
+
const set = this.serviceControlPolicySetFor(accountId);
|
|
87
|
+
return set.levels.flatMap((level) => level.policies);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The policies in force for an Account, level by level, along with whether
|
|
91
|
+
* the Account is inside this organization at all.
|
|
92
|
+
*
|
|
93
|
+
* Sim IAM reads this rather than the flattened list, because each level has
|
|
94
|
+
* to allow an action on its own.
|
|
95
|
+
*/
|
|
96
|
+
serviceControlPolicySetFor(accountId) {
|
|
97
|
+
return this.effectivePolicies.setFor(simAwsAccountId(accountId));
|
|
98
|
+
}
|
|
99
|
+
}
|