@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,45 @@
|
|
|
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 { SimIamAuthZPolicySource } from "../context/sim-iam-auth-z-context.js";
|
|
5
|
+
import { SimIamAllowStatements } from "./sim-iam-allow-statements.js";
|
|
6
|
+
import type { SimIamAllowSides } from "./sim-iam-allow-requirement.js";
|
|
7
|
+
interface SimIamPolicyEvaluationProperties {
|
|
8
|
+
readonly policies: readonly SimIamAuthZPolicySource[];
|
|
9
|
+
readonly policyDocumentParser: SimIamPolicyDocumentParser;
|
|
10
|
+
readonly statementMatcher: SimIamPolicyStatementMatcher;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The statements of the identity and resource policies that matched one
|
|
14
|
+
* request.
|
|
15
|
+
*
|
|
16
|
+
* These are the two sides that can allow a request, so they are read together
|
|
17
|
+
* and kept apart by side afterwards. Which of them has to allow for the
|
|
18
|
+
* request to go ahead belongs to the allow requirement rather than here.
|
|
19
|
+
*/
|
|
20
|
+
export declare class SimIamPolicyEvaluation {
|
|
21
|
+
private readonly explicitDenyStatementRecords;
|
|
22
|
+
private readonly allows;
|
|
23
|
+
constructor(properties: SimIamPolicyEvaluationProperties);
|
|
24
|
+
/**
|
|
25
|
+
* Whether a matching Deny statement was found.
|
|
26
|
+
*/
|
|
27
|
+
get isExplicitDeny(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Matching explicit Deny statements.
|
|
30
|
+
*/
|
|
31
|
+
get explicitDenyStatements(): readonly SimIamPolicyDocumentStatement[];
|
|
32
|
+
/**
|
|
33
|
+
* The matching Allow statements, kept per side.
|
|
34
|
+
*/
|
|
35
|
+
get allowStatements(): SimIamAllowStatements;
|
|
36
|
+
/**
|
|
37
|
+
* Which sides produced a matching Allow.
|
|
38
|
+
*/
|
|
39
|
+
get sides(): SimIamAllowSides;
|
|
40
|
+
/**
|
|
41
|
+
* Record the matching statements of one policy.
|
|
42
|
+
*/
|
|
43
|
+
private evaluate;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { SimIamAllowStatements } from "./sim-iam-allow-statements.js";
|
|
2
|
+
/**
|
|
3
|
+
* The statements of the identity and resource policies that matched one
|
|
4
|
+
* request.
|
|
5
|
+
*
|
|
6
|
+
* These are the two sides that can allow a request, so they are read together
|
|
7
|
+
* and kept apart by side afterwards. Which of them has to allow for the
|
|
8
|
+
* request to go ahead belongs to the allow requirement rather than here.
|
|
9
|
+
*/
|
|
10
|
+
export class SimIamPolicyEvaluation {
|
|
11
|
+
explicitDenyStatementRecords = [];
|
|
12
|
+
allows = new SimIamAllowStatements();
|
|
13
|
+
constructor(properties) {
|
|
14
|
+
for (const policy of properties.policies) {
|
|
15
|
+
this.evaluate(policy, properties);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Whether a matching Deny statement was found.
|
|
20
|
+
*/
|
|
21
|
+
get isExplicitDeny() {
|
|
22
|
+
return this.explicitDenyStatementRecords.length > 0;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Matching explicit Deny statements.
|
|
26
|
+
*/
|
|
27
|
+
get explicitDenyStatements() {
|
|
28
|
+
return this.explicitDenyStatementRecords;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The matching Allow statements, kept per side.
|
|
32
|
+
*/
|
|
33
|
+
get allowStatements() {
|
|
34
|
+
return this.allows;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Which sides produced a matching Allow.
|
|
38
|
+
*/
|
|
39
|
+
get sides() {
|
|
40
|
+
return this.allows.sides;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Record the matching statements of one policy.
|
|
44
|
+
*/
|
|
45
|
+
evaluate(policy, properties) {
|
|
46
|
+
const parsedPolicy = properties.policyDocumentParser.parse(policy.document);
|
|
47
|
+
for (const statement of parsedPolicy.statements) {
|
|
48
|
+
const principal = properties.statementMatcher.matches(policy, statement);
|
|
49
|
+
if (!principal.matched) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (statement.effect === "Deny") {
|
|
53
|
+
this.explicitDenyStatementRecords.push(statement.source);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
this.allows.record(policy, statement.source, principal);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -8,6 +8,7 @@ import type { SimIamCallerConditionSource } from "./sim-iam-caller-condition-sou
|
|
|
8
8
|
import type { SimIamAuthZContext, SimIamAuthZPolicySource, SimIamAuthZPolicySourceType } from "./sim-iam-auth-z-context.js";
|
|
9
9
|
import type { SimAwsCredentialIdentityResolver } from "../../../aws/caller/sim-aws-caller-resolver.js";
|
|
10
10
|
import type { SimIamUser, SimIamUsername } from "../../user/sim-iam-user.js";
|
|
11
|
+
import type { SimIamServiceControlPolicyResolver } from "../scp/sim-iam-scp-resolver.js";
|
|
11
12
|
export interface SimIamResourcePolicyInput {
|
|
12
13
|
readonly document: SimIamPolicyDocument;
|
|
13
14
|
readonly sourceType?: Extract<SimIamAuthZPolicySourceType, "resource" | "trust">;
|
|
@@ -77,6 +78,11 @@ interface SimIamAuthZContextBuilderProperties {
|
|
|
77
78
|
* of a cross-Account request.
|
|
78
79
|
*/
|
|
79
80
|
readonly iamResolver?: SimIamAccountResolver | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Resolves the service control policies in force for an Account. A
|
|
83
|
+
* standalone SimIam has no organization around it and leaves this out.
|
|
84
|
+
*/
|
|
85
|
+
readonly scpResolver?: SimIamServiceControlPolicyResolver | undefined;
|
|
80
86
|
}
|
|
81
87
|
/**
|
|
82
88
|
* Builds the authorization context consumed by SimIamAuthorizer.
|
|
@@ -99,16 +105,21 @@ interface SimIamAuthZContextBuilderProperties {
|
|
|
99
105
|
* They are passed through the authorization input rather than loaded from the
|
|
100
106
|
* IAM role or managed-policy stores.
|
|
101
107
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
108
|
+
* Service control policies come from the organization the caller's Account
|
|
109
|
+
* belongs to, read by SimIamAuthZScpSourceBuilder. They filter and grant
|
|
110
|
+
* nothing, so they travel apart from the sides that can allow a request.
|
|
111
|
+
*
|
|
112
|
+
* Permissions boundaries, session policies, and role trust-policy assume-role
|
|
113
|
+
* semantics are not part of this context assembly path yet. Add those concerns
|
|
114
|
+
* through separate policy-source builders so this class stays focused on
|
|
115
|
+
* composing the authorization request.
|
|
106
116
|
*/
|
|
107
117
|
export declare class SimIamAuthZContextBuilder {
|
|
108
118
|
private readonly callerContextBuilder;
|
|
109
119
|
private readonly identityPolicyCoordinator;
|
|
110
120
|
private readonly callerAccountResolver;
|
|
111
121
|
private readonly allowRequirement;
|
|
122
|
+
private readonly scpSourceBuilder;
|
|
112
123
|
constructor(properties: SimIamAuthZContextBuilderProperties);
|
|
113
124
|
/**
|
|
114
125
|
* Build the context consumed by SimIamAuthorizer.
|
|
@@ -3,6 +3,7 @@ import { SimIamCallerAccountResolver } from "../caller-account/sim-iam-caller-ac
|
|
|
3
3
|
import { SimIamAuthZAllowRequirement } from "./sim-iam-auth-z-allow-requirement.js";
|
|
4
4
|
import { SimIamAuthZIdentityPolicyCoordinator } from "./identity-policy-source/sim-iam-auth-z-id-pol-coordinator.js";
|
|
5
5
|
import { SimIamAuthZCallerContextBuilder, } from "./sim-iam-auth-z-caller-context-builder.js";
|
|
6
|
+
import { SimIamAuthZScpSourceBuilder } from "./sim-iam-auth-z-scp-source-builder.js";
|
|
6
7
|
/**
|
|
7
8
|
* Builds the authorization context consumed by SimIamAuthorizer.
|
|
8
9
|
*
|
|
@@ -24,16 +25,21 @@ import { SimIamAuthZCallerContextBuilder, } from "./sim-iam-auth-z-caller-contex
|
|
|
24
25
|
* They are passed through the authorization input rather than loaded from the
|
|
25
26
|
* IAM role or managed-policy stores.
|
|
26
27
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* Service control policies come from the organization the caller's Account
|
|
29
|
+
* belongs to, read by SimIamAuthZScpSourceBuilder. They filter and grant
|
|
30
|
+
* nothing, so they travel apart from the sides that can allow a request.
|
|
31
|
+
*
|
|
32
|
+
* Permissions boundaries, session policies, and role trust-policy assume-role
|
|
33
|
+
* semantics are not part of this context assembly path yet. Add those concerns
|
|
34
|
+
* through separate policy-source builders so this class stays focused on
|
|
35
|
+
* composing the authorization request.
|
|
31
36
|
*/
|
|
32
37
|
export class SimIamAuthZContextBuilder {
|
|
33
38
|
callerContextBuilder;
|
|
34
39
|
identityPolicyCoordinator;
|
|
35
40
|
callerAccountResolver;
|
|
36
41
|
allowRequirement = new SimIamAuthZAllowRequirement();
|
|
42
|
+
scpSourceBuilder;
|
|
37
43
|
constructor(properties) {
|
|
38
44
|
this.callerContextBuilder = new SimIamAuthZCallerContextBuilder(makeSimAwsAccountRootPrincipal(properties.accountId), properties.credentialIdentityResolver);
|
|
39
45
|
this.identityPolicyCoordinator = new SimIamAuthZIdentityPolicyCoordinator({
|
|
@@ -45,6 +51,10 @@ export class SimIamAuthZContextBuilder {
|
|
|
45
51
|
accountId: properties.accountId,
|
|
46
52
|
iamResolver: properties.iamResolver,
|
|
47
53
|
});
|
|
54
|
+
this.scpSourceBuilder = new SimIamAuthZScpSourceBuilder({
|
|
55
|
+
accountId: properties.accountId,
|
|
56
|
+
scpResolver: properties.scpResolver,
|
|
57
|
+
});
|
|
48
58
|
}
|
|
49
59
|
/**
|
|
50
60
|
* Build the context consumed by SimIamAuthorizer.
|
|
@@ -58,6 +68,7 @@ export class SimIamAuthZContextBuilder {
|
|
|
58
68
|
...callerAccount.identityPolicies,
|
|
59
69
|
],
|
|
60
70
|
resourcePolicies: this.resourcePolicySources(input),
|
|
71
|
+
serviceControlPolicies: this.scpSourceBuilder.build(callerContext.caller),
|
|
61
72
|
allowRequirement: this.allowRequirement.resolve(callerAccount, input.requiresResourcePolicyAllow),
|
|
62
73
|
action: input.action,
|
|
63
74
|
resource: input.resource,
|
|
@@ -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
|
+
}
|