@kensio/yulin 1.21.5 → 1.21.7
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/cloudformation/resource/cfn/sim-cfn-default-resource-value-adapter.d.ts +8 -1
- package/dist/service/cloudformation/resource/cfn/sim-cfn-default-resource-value-adapter.js +9 -2
- package/dist/service/cloudformation/resource/cfn/sim-cfn-resource-value-adapter.d.ts +6 -1
- package/dist/service/cloudformation/resource/cfn/sim-cfn-resource-value-adapter.js +2 -1
- package/dist/service/cloudformation/resource/create/sim-cfn-resource-create-operation.d.ts +4 -0
- package/dist/service/cloudformation/resource/create/sim-cfn-resource-create-operation.js +6 -0
- package/dist/service/cloudformation/resource/sim-cfn-resource-record.d.ts +19 -0
- package/dist/service/cloudformation/resource/sim-cfn-resource-record.js +26 -0
- package/dist/service/cloudformation/resource/sim-cfn-resource.js +1 -0
- package/dist/service/cloudformation/resource/unsupported/sim-cfn-named-skip.d.ts +26 -0
- package/dist/service/cloudformation/resource/unsupported/sim-cfn-named-skip.js +31 -0
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.js +10 -2
- package/dist/service/cloudfront/cfn/origin-access-control/sim-cfn-cf-oac-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/origin-access-control/sim-cfn-cf-oac-creator.js +10 -2
- package/dist/service/cloudfront/cfn/origin-request-policy/sim-cfn-cf-orp-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/origin-request-policy/sim-cfn-cf-orp-creator.js +10 -2
- package/dist/service/cloudfront/cfn/policy/sim-cfn-cf-policy-creators.d.ts +33 -0
- package/dist/service/cloudfront/cfn/policy/sim-cfn-cf-policy-creators.js +39 -0
- package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-creator.d.ts +5 -2
- package/dist/service/cloudfront/cfn/response-headers-policy/sim-cfn-cf-rh-policy-creator.js +10 -2
- package/dist/service/cloudfront/cfn/sim-cfn-cf-authorizer.d.ts +40 -0
- package/dist/service/cloudfront/cfn/sim-cfn-cf-authorizer.js +50 -0
- package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.d.ts +1 -4
- package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.js +14 -46
- package/dist/service/cloudfront/sim-cloudfront-commands.d.ts +6 -0
- package/dist/service/cloudfront/sim-cloudfront-commands.js +7 -0
- package/dist/service/cloudfront/sim-cloudfront.d.ts +6 -0
- package/dist/service/cloudfront/sim-cloudfront.js +7 -0
- package/dist/service/dynamodb/document/sim-dynamodb-document-command-paths.d.ts +8 -0
- package/dist/service/dynamodb/document/sim-dynamodb-document-command-paths.js +62 -0
- package/dist/service/dynamodb/document/sim-dynamodb-document-routes.d.ts +1 -1
- package/dist/service/dynamodb/document/sim-dynamodb-document-routes.js +3 -1
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-creator.js +1 -0
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.d.ts +4 -0
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.js +26 -1
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-creator.js +3 -1
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-properties.d.ts +0 -7
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-properties.js +0 -20
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-unsimulated-properties.d.ts +13 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-unsimulated-properties.js +59 -0
- package/dist/service/eventbridge/cfn/sim-cfn-event-bridge-resource-error.d.ts +1 -1
- package/dist/service/eventbridge/cfn/sim-cfn-event-bridge-resource-error.js +1 -1
- package/dist/service/iam/authorize/sim-iam-action-authorizer.d.ts +8 -3
- package/dist/service/iam/authorize/sim-iam-action-authorizer.js +13 -4
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-creator.js +1 -0
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.d.ts +1 -0
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.js +21 -14
- package/dist/service/iam/cfn/{sim-cfn-iam-optional-string.d.ts → sim-cfn-iam-property.d.ts} +10 -2
- package/dist/service/iam/cfn/sim-cfn-iam-property.js +31 -0
- package/dist/service/iam/cfn/user/sim-cfn-iam-user-properties-parser.js +1 -1
- package/dist/service/iam/command/role/create-role/create-role-record-factory.js +3 -0
- package/dist/service/iam/command/role/create-role/create-role.command.d.ts +10 -0
- package/dist/service/iam/command/role/get-role/get-role.command.d.ts +2 -0
- package/dist/service/iam/command/role/get-role/get-role.handler.js +2 -0
- package/dist/service/iam/command/role/sim-iam-role-command-handlers.js +15 -1
- package/dist/service/iam/role/sim-iam-role-boundary.d.ts +24 -0
- package/dist/service/iam/role/sim-iam-role-boundary.js +24 -0
- package/dist/service/iam/role/sim-iam-role-with-policy.factory.d.ts +1 -0
- package/dist/service/iam/role/sim-iam-role.d.ts +10 -0
- package/dist/service/iam/serve/sim-iam-query-entity.d.ts +6 -1
- package/dist/service/iam/serve/sim-iam-query-entity.js +10 -4
- package/dist/service/iam/serve/sim-iam-query-role-operations.js +15 -3
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +1 -1
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.d.ts +3 -2
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.js +25 -3
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-runtime-skip.d.ts +6 -0
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-runtime-skip.js +9 -2
- package/dist/service/route53/command/create-hosted-zone/sim-route53-zone-id.js +23 -1
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-creator.js +1 -0
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-properties.d.ts +9 -4
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-properties.js +18 -6
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-property-names.d.ts +10 -0
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-property-names.js +16 -1
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-creator.js +1 -1
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.d.ts +11 -6
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.js +18 -9
- package/docs/README.md +33 -4
- package/docs/ai-skill/README.md +52 -54
- package/docs/cli/README.md +84 -94
- package/docs/factories/README.md +42 -54
- package/docs/lint/README.md +41 -67
- package/docs/non-aws-dependencies/README.md +72 -168
- package/docs/sdk/README.md +97 -98
- package/docs/serve/README.md +192 -898
- package/docs/services/cloudformation/README.md +88 -23
- package/docs/services/cloudfront/README.md +109 -0
- package/docs/services/dynamodb/README.md +128 -8
- package/docs/services/eventbridge/README.md +10 -2
- package/docs/services/iam/README.md +125 -2
- package/docs/services/lambda/README.md +7 -1
- package/docs/services/route53/README.md +11 -0
- package/docs/services/sns/README.md +13 -7
- package/docs/services/ssm/README.md +6 -4
- package/docs/terraform/README.md +108 -126
- package/docs/time/README.md +80 -120
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/dist/service/iam/cfn/sim-cfn-iam-optional-string.js +0 -17
|
@@ -20,6 +20,7 @@ export class SimCfnIamRoleCreator {
|
|
|
20
20
|
Path: roleProperties.path,
|
|
21
21
|
Description: roleProperties.description,
|
|
22
22
|
AssumeRolePolicyDocument: roleProperties.assumeRolePolicyDocument,
|
|
23
|
+
PermissionsBoundary: roleProperties.permissionsBoundary,
|
|
23
24
|
},
|
|
24
25
|
}, options);
|
|
25
26
|
await Promise.all([
|
|
@@ -6,6 +6,7 @@ export interface SimCfnIamRoleProperties {
|
|
|
6
6
|
readonly path: string | undefined;
|
|
7
7
|
readonly description: string | undefined;
|
|
8
8
|
readonly assumeRolePolicyDocument: string;
|
|
9
|
+
readonly permissionsBoundary: string | undefined;
|
|
9
10
|
readonly inlinePolicies: readonly SimCfnIamInlinePolicy[];
|
|
10
11
|
readonly managedPolicyArns: readonly string[];
|
|
11
12
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
/* oxlint-disable security/detect-object-injection -- each lookup here reads a
|
|
2
|
+
template property under the name this parser asks for by literal. */
|
|
1
3
|
import { simCfnIamPrincipalGeneratedName } from "../name/sim-cfn-iam-generated-name.js";
|
|
2
|
-
import { simCfnIamOptionalString } from "../sim-cfn-iam-
|
|
4
|
+
import { simCfnIamJsonObject, simCfnIamOptionalString, } from "../sim-cfn-iam-property.js";
|
|
3
5
|
import { SimCfnIamPoliciesParser, } from "../sim-cfn-iam-policies-parser.js";
|
|
6
|
+
const resourceType = "AWS::IAM::Role";
|
|
4
7
|
/**
|
|
5
8
|
* Parses and validates AWS::IAM::Role CloudFormation properties into the shape
|
|
6
9
|
* the sim IAM Role creator needs.
|
|
@@ -10,34 +13,38 @@ import { SimCfnIamPoliciesParser, } from "../sim-cfn-iam-policies-parser.js";
|
|
|
10
13
|
*/
|
|
11
14
|
export class SimCfnIamRolePropertiesParser {
|
|
12
15
|
policiesParser = new SimCfnIamPoliciesParser({
|
|
13
|
-
resourceType
|
|
16
|
+
resourceType,
|
|
14
17
|
});
|
|
15
18
|
/**
|
|
16
19
|
* Parse the resolved CloudFormation properties for an AWS::IAM::Role.
|
|
17
20
|
*/
|
|
18
21
|
parse(resource, properties) {
|
|
19
22
|
return {
|
|
20
|
-
roleName: this.optionalString(resource, properties
|
|
23
|
+
roleName: this.optionalString(resource, properties, "RoleName") ??
|
|
21
24
|
simCfnIamPrincipalGeneratedName(resource),
|
|
22
|
-
path: this.optionalString(resource, properties
|
|
23
|
-
description: this.optionalString(resource, properties
|
|
24
|
-
assumeRolePolicyDocument: this.jsonObject(resource, properties
|
|
25
|
+
path: this.optionalString(resource, properties, "Path"),
|
|
26
|
+
description: this.optionalString(resource, properties, "Description"),
|
|
27
|
+
assumeRolePolicyDocument: this.jsonObject(resource, properties),
|
|
28
|
+
permissionsBoundary: this.optionalString(resource, properties, "PermissionsBoundary"),
|
|
25
29
|
inlinePolicies: this.policiesParser.inlinePolicies(resource, properties),
|
|
26
30
|
managedPolicyArns: this.policiesParser.managedPolicyArns(resource, properties),
|
|
27
31
|
};
|
|
28
32
|
}
|
|
29
|
-
optionalString(resource,
|
|
33
|
+
optionalString(resource, properties, label) {
|
|
30
34
|
return simCfnIamOptionalString({
|
|
31
|
-
resourceType
|
|
35
|
+
resourceType,
|
|
32
36
|
resource,
|
|
33
|
-
value,
|
|
37
|
+
value: properties[label],
|
|
34
38
|
label,
|
|
35
39
|
});
|
|
36
40
|
}
|
|
37
|
-
jsonObject(resource,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
jsonObject(resource, properties) {
|
|
42
|
+
const label = "AssumeRolePolicyDocument";
|
|
43
|
+
return simCfnIamJsonObject({
|
|
44
|
+
resourceType,
|
|
45
|
+
resource,
|
|
46
|
+
value: properties[label],
|
|
47
|
+
label,
|
|
48
|
+
});
|
|
42
49
|
}
|
|
43
50
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SimCfnResource } from "../../cloudformation/resource/sim-cfn-resource.js";
|
|
2
2
|
import type { SimCfnTemplateValueRecord } from "../../cloudformation/template/value/sim-cfn-template-value.js";
|
|
3
|
-
interface
|
|
3
|
+
interface SimCfnIamPropertyInput {
|
|
4
4
|
readonly resourceType: string;
|
|
5
5
|
readonly resource: SimCfnResource;
|
|
6
6
|
readonly value: SimCfnTemplateValueRecord[string] | undefined;
|
|
@@ -13,5 +13,13 @@ interface SimCfnIamOptionalStringProperties {
|
|
|
13
13
|
* refuse a non-string the same way, naming the Resource type the template
|
|
14
14
|
* declared.
|
|
15
15
|
*/
|
|
16
|
-
export declare function simCfnIamOptionalString(properties:
|
|
16
|
+
export declare function simCfnIamOptionalString(properties: SimCfnIamPropertyInput): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Read a JSON-object property an IAM Resource requires.
|
|
19
|
+
*
|
|
20
|
+
* A Role's trust policy arrives as the object the template wrote, and IAM
|
|
21
|
+
* takes its policy documents as JSON text. A value of any other shape fails
|
|
22
|
+
* the Resource, naming the Resource type the template declared.
|
|
23
|
+
*/
|
|
24
|
+
export declare function simCfnIamJsonObject(properties: SimCfnIamPropertyInput): string;
|
|
17
25
|
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a string property an IAM Resource may leave out.
|
|
3
|
+
*
|
|
4
|
+
* A Role and a User read most of their own properties this way, and both
|
|
5
|
+
* refuse a non-string the same way, naming the Resource type the template
|
|
6
|
+
* declared.
|
|
7
|
+
*/
|
|
8
|
+
export function simCfnIamOptionalString(properties) {
|
|
9
|
+
const { resourceType, resource, value, label } = properties;
|
|
10
|
+
if (value === undefined) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
if (typeof value !== "string") {
|
|
14
|
+
throw new TypeError(`Invalid ${resourceType} ${resource.logicalId}: ${label} must be a string`);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Read a JSON-object property an IAM Resource requires.
|
|
20
|
+
*
|
|
21
|
+
* A Role's trust policy arrives as the object the template wrote, and IAM
|
|
22
|
+
* takes its policy documents as JSON text. A value of any other shape fails
|
|
23
|
+
* the Resource, naming the Resource type the template declared.
|
|
24
|
+
*/
|
|
25
|
+
export function simCfnIamJsonObject(properties) {
|
|
26
|
+
const { resourceType, resource, value, label } = properties;
|
|
27
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
28
|
+
throw new TypeError(`Invalid ${resourceType} ${resource.logicalId}: ${label} must be an object`);
|
|
29
|
+
}
|
|
30
|
+
return JSON.stringify(value);
|
|
31
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { simCfnIamPrincipalGeneratedName } from "../name/sim-cfn-iam-generated-name.js";
|
|
2
|
-
import { simCfnIamOptionalString } from "../sim-cfn-iam-
|
|
2
|
+
import { simCfnIamOptionalString } from "../sim-cfn-iam-property.js";
|
|
3
3
|
import { SimCfnIamPoliciesParser, } from "../sim-cfn-iam-policies-parser.js";
|
|
4
4
|
const resourceType = "AWS::IAM::User";
|
|
5
5
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { makeSimIamRoleId } from "../../../role/sim-iam-role-id.js";
|
|
2
|
+
import { simIamAttachedPermissionsBoundary } from "../../../role/sim-iam-role-boundary.js";
|
|
2
3
|
/**
|
|
3
4
|
* Creates simulated IAM Role records and command outputs.
|
|
4
5
|
*/
|
|
@@ -19,6 +20,7 @@ export class CreateRoleRecordFactory {
|
|
|
19
20
|
assumeRolePolicyDocument: cmd.input.AssumeRolePolicyDocument,
|
|
20
21
|
description: cmd.input.Description,
|
|
21
22
|
creationDate,
|
|
23
|
+
permissionsBoundaryArn: cmd.input.PermissionsBoundary,
|
|
22
24
|
inlinePolicies: new Map(),
|
|
23
25
|
attachedPolicyArns: new Set(),
|
|
24
26
|
};
|
|
@@ -36,6 +38,7 @@ export class CreateRoleRecordFactory {
|
|
|
36
38
|
CreateDate: role.creationDate,
|
|
37
39
|
AssumeRolePolicyDocument: role.assumeRolePolicyDocument,
|
|
38
40
|
Description: role.description,
|
|
41
|
+
PermissionsBoundary: simIamAttachedPermissionsBoundary(role),
|
|
39
42
|
},
|
|
40
43
|
};
|
|
41
44
|
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import type { SimArn } from "../../../../aws/arn.js";
|
|
2
|
+
import type { SimIamAttachedPermissionsBoundary } from "../../../role/sim-iam-role-boundary.js";
|
|
2
3
|
export interface SimCreateRoleCommandInput {
|
|
3
4
|
readonly RoleName?: string | undefined;
|
|
4
5
|
readonly Path?: string | undefined;
|
|
5
6
|
readonly AssumeRolePolicyDocument?: string | undefined;
|
|
6
7
|
readonly Description?: string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* ARN of the managed policy to attach to the new Role as its permissions
|
|
10
|
+
* boundary.
|
|
11
|
+
*
|
|
12
|
+
* The request carries this ARN as `iam:PermissionsBoundary`, which is the
|
|
13
|
+
* key an account requiring a boundary conditions `iam:CreateRole` on.
|
|
14
|
+
*/
|
|
15
|
+
readonly PermissionsBoundary?: string | undefined;
|
|
7
16
|
}
|
|
8
17
|
export interface SimCreateRoleCommand {
|
|
9
18
|
readonly input: SimCreateRoleCommandInput;
|
|
@@ -17,5 +26,6 @@ export interface SimCreateRoleCommandOutput {
|
|
|
17
26
|
readonly CreateDate: Date;
|
|
18
27
|
readonly AssumeRolePolicyDocument?: string | undefined;
|
|
19
28
|
readonly Description?: string | undefined;
|
|
29
|
+
readonly PermissionsBoundary?: SimIamAttachedPermissionsBoundary | undefined;
|
|
20
30
|
};
|
|
21
31
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SimArn } from "../../../../aws/arn.js";
|
|
2
2
|
import type { SimIamRoleName } from "../../../role/sim-iam-role.js";
|
|
3
|
+
import type { SimIamAttachedPermissionsBoundary } from "../../../role/sim-iam-role-boundary.js";
|
|
3
4
|
export interface SimGetRoleCommandInput {
|
|
4
5
|
readonly RoleName?: string | undefined;
|
|
5
6
|
}
|
|
@@ -15,5 +16,6 @@ export interface SimGetRoleCommandOutput {
|
|
|
15
16
|
readonly CreateDate: Date;
|
|
16
17
|
readonly AssumeRolePolicyDocument?: string | undefined;
|
|
17
18
|
readonly Description?: string | undefined;
|
|
19
|
+
readonly PermissionsBoundary?: SimIamAttachedPermissionsBoundary | undefined;
|
|
18
20
|
};
|
|
19
21
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BackgroundTasks, } from "../../../../../util/background/background.js";
|
|
2
2
|
import { SimIamNoSuchEntity } from "../../../error/sim-iam.error.js";
|
|
3
|
+
import { simIamAttachedPermissionsBoundary } from "../../../role/sim-iam-role-boundary.js";
|
|
3
4
|
/**
|
|
4
5
|
* IAM GetRoleCommand handler.
|
|
5
6
|
*
|
|
@@ -36,6 +37,7 @@ export class GetRoleCommandHandler {
|
|
|
36
37
|
CreateDate: role.creationDate,
|
|
37
38
|
AssumeRolePolicyDocument: role.assumeRolePolicyDocument,
|
|
38
39
|
Description: role.description,
|
|
40
|
+
PermissionsBoundary: simIamAttachedPermissionsBoundary(role),
|
|
39
41
|
},
|
|
40
42
|
};
|
|
41
43
|
}
|
|
@@ -31,7 +31,7 @@ export class SimIamRoleCommandHandlers {
|
|
|
31
31
|
* Handle a CreateRole command from the SDK.
|
|
32
32
|
*/
|
|
33
33
|
async createRole(command, options) {
|
|
34
|
-
this.authorizer.authorize("iam:CreateRole", this.roleArn(command.input.RoleName), options?.caller);
|
|
34
|
+
this.authorizer.authorize("iam:CreateRole", this.roleArn(command.input.RoleName), options?.caller, permissionsBoundaryCondition(command.input.PermissionsBoundary));
|
|
35
35
|
const handler = new CreateRoleCommandHandler({
|
|
36
36
|
accountId: this.accountId,
|
|
37
37
|
roles: this.roles,
|
|
@@ -123,3 +123,17 @@ export class SimIamRoleCommandHandlers {
|
|
|
123
123
|
return `arn:aws:iam::${this.accountId}:role/${roleName ?? "*"}`;
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* What a Role-creating request says about the boundary it declares.
|
|
128
|
+
*
|
|
129
|
+
* An account that requires a permissions boundary allows `iam:CreateRole`
|
|
130
|
+
* only under `StringEquals` on `iam:PermissionsBoundary`, and the CDK
|
|
131
|
+
* permissions-boundary guard is written that way. A request declaring no
|
|
132
|
+
* boundary leaves the key out, which is what refuses it: a positive operator
|
|
133
|
+
* over an absent key matches nothing.
|
|
134
|
+
*/
|
|
135
|
+
function permissionsBoundaryCondition(permissionsBoundary) {
|
|
136
|
+
return permissionsBoundary === undefined
|
|
137
|
+
? undefined
|
|
138
|
+
: { "iam:PermissionsBoundary": permissionsBoundary };
|
|
139
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SimArn } from "../../aws/arn.js";
|
|
2
|
+
import type { SimIamRole } from "./sim-iam-role.js";
|
|
3
|
+
/**
|
|
4
|
+
* A permissions boundary attached to a Role, as IAM describes one.
|
|
5
|
+
*
|
|
6
|
+
* IAM answers with the attachment rather than the bare ARN, and the type has
|
|
7
|
+
* only ever taken one value.
|
|
8
|
+
*/
|
|
9
|
+
export interface SimIamAttachedPermissionsBoundary {
|
|
10
|
+
readonly PermissionsBoundaryType: "PermissionsBoundaryPolicy";
|
|
11
|
+
readonly PermissionsBoundaryArn: SimArn;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The member names IAM describes an attached boundary with.
|
|
15
|
+
*/
|
|
16
|
+
export declare const simIamAttachedBoundaryMembers: string[];
|
|
17
|
+
/**
|
|
18
|
+
* How a Role's boundary appears in a CreateRole or GetRole answer.
|
|
19
|
+
*
|
|
20
|
+
* A Role created without one has no attachment to describe, and IAM leaves
|
|
21
|
+
* the field out. `ListRoles` leaves it out whatever the Role carries, along
|
|
22
|
+
* with the Role's tags and last use, and points the caller at `GetRole`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function simIamAttachedPermissionsBoundary(role: SimIamRole): SimIamAttachedPermissionsBoundary | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The member names IAM describes an attached boundary with.
|
|
3
|
+
*/
|
|
4
|
+
export const simIamAttachedBoundaryMembers = [
|
|
5
|
+
"PermissionsBoundaryType",
|
|
6
|
+
"PermissionsBoundaryArn",
|
|
7
|
+
];
|
|
8
|
+
/**
|
|
9
|
+
* How a Role's boundary appears in a CreateRole or GetRole answer.
|
|
10
|
+
*
|
|
11
|
+
* A Role created without one has no attachment to describe, and IAM leaves
|
|
12
|
+
* the field out. `ListRoles` leaves it out whatever the Role carries, along
|
|
13
|
+
* with the Role's tags and last use, and points the caller at `GetRole`.
|
|
14
|
+
*/
|
|
15
|
+
export function simIamAttachedPermissionsBoundary(role) {
|
|
16
|
+
const permissionsBoundaryArn = role.permissionsBoundaryArn;
|
|
17
|
+
if (permissionsBoundaryArn === undefined) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
PermissionsBoundaryType: "PermissionsBoundaryPolicy",
|
|
22
|
+
PermissionsBoundaryArn: permissionsBoundaryArn,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -56,4 +56,5 @@ export declare const simIamRoleWithPolicyFactory: AsyncMappedFactory<SimIamRoleW
|
|
|
56
56
|
readonly CreateDate: Date;
|
|
57
57
|
readonly AssumeRolePolicyDocument?: string | undefined;
|
|
58
58
|
readonly Description?: string | undefined;
|
|
59
|
+
readonly PermissionsBoundary?: import("./sim-iam-role-boundary.js").SimIamAttachedPermissionsBoundary | undefined;
|
|
59
60
|
}, SimAws>;
|
|
@@ -19,6 +19,16 @@ export interface SimIamRole extends SimIamPrincipal {
|
|
|
19
19
|
readonly assumeRolePolicyDocument?: JSONString<SimIamPolicyDocument> | undefined;
|
|
20
20
|
readonly description?: string | undefined;
|
|
21
21
|
readonly creationDate: Date;
|
|
22
|
+
/**
|
|
23
|
+
* ARN of the managed policy attached to this Role as its permissions
|
|
24
|
+
* boundary, where the request creating it declared one.
|
|
25
|
+
*
|
|
26
|
+
* This records what the Role was created with, so that a policy conditioned
|
|
27
|
+
* on `iam:PermissionsBoundary` can be tested against the Roles a deployment
|
|
28
|
+
* makes. The boundary is not yet evaluated as a policy source, so it does
|
|
29
|
+
* not narrow what the Role itself may do.
|
|
30
|
+
*/
|
|
31
|
+
readonly permissionsBoundaryArn?: SimArn | undefined;
|
|
22
32
|
/**
|
|
23
33
|
* Inline identity-based permissions policies stored directly on this role.
|
|
24
34
|
*/
|
|
@@ -7,5 +7,10 @@ import type { SimQueryOutput } from "../../../serve/http/api/query/sim-query-res
|
|
|
7
7
|
* same structures are what a listing repeats. The Query layer writes the
|
|
8
8
|
* members of a structure and the items of a list, and this is the one shape
|
|
9
9
|
* left between them.
|
|
10
|
+
*
|
|
11
|
+
* An entity carrying a member of its own that is a structure passes `nested`,
|
|
12
|
+
* which writes whatever a scalar member cannot. A Role's permissions boundary
|
|
13
|
+
* is the case that exists for, and a listing that leaves it out passes
|
|
14
|
+
* nothing.
|
|
10
15
|
*/
|
|
11
|
-
export declare function iamQueryEntity(output: SimQueryOutput, name: string, members: readonly string[]): string;
|
|
16
|
+
export declare function iamQueryEntity(output: SimQueryOutput, name: string, members: readonly string[], nested?: (entity: SimQueryOutput) => string): string;
|
|
@@ -12,10 +12,16 @@ import { xmlElement } from "../../../util/xml/xml-writer.js";
|
|
|
12
12
|
* same structures are what a listing repeats. The Query layer writes the
|
|
13
13
|
* members of a structure and the items of a list, and this is the one shape
|
|
14
14
|
* left between them.
|
|
15
|
+
*
|
|
16
|
+
* An entity carrying a member of its own that is a structure passes `nested`,
|
|
17
|
+
* which writes whatever a scalar member cannot. A Role's permissions boundary
|
|
18
|
+
* is the case that exists for, and a listing that leaves it out passes
|
|
19
|
+
* nothing.
|
|
15
20
|
*/
|
|
16
|
-
export function iamQueryEntity(output, name, members) {
|
|
21
|
+
export function iamQueryEntity(output, name, members, nested) {
|
|
17
22
|
const entity = output[name];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
if (!isRecord(entity)) {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
return xmlElement(name, queryMembers(entity, members) + (nested?.(entity) ?? ""));
|
|
21
27
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { queryList, queryMembers, } from "../../../serve/http/api/query/sim-query-result.js";
|
|
1
|
+
import { queryList, queryMembers, queryStructure, } from "../../../serve/http/api/query/sim-query-result.js";
|
|
2
|
+
import { simIamAttachedBoundaryMembers } from "../role/sim-iam-role-boundary.js";
|
|
2
3
|
import { iamQueryEntity } from "./sim-iam-query-entity.js";
|
|
3
4
|
import { iamQueryListingInput, iamQueryListingResult, } from "./sim-iam-query-listing.js";
|
|
4
5
|
/**
|
|
@@ -13,6 +14,16 @@ const roleMembers = [
|
|
|
13
14
|
"AssumeRolePolicyDocument",
|
|
14
15
|
"Description",
|
|
15
16
|
];
|
|
17
|
+
/**
|
|
18
|
+
* Write the permissions boundary a Role carries, where it carries one.
|
|
19
|
+
*
|
|
20
|
+
* A boundary is a structure of its own, and `queryMembers` would write it as
|
|
21
|
+
* the JSON text of an object. `ListRoles` leaves the field out altogether, as
|
|
22
|
+
* IAM does, so only the create and the get pass this.
|
|
23
|
+
*/
|
|
24
|
+
function roleBoundary(role) {
|
|
25
|
+
return queryStructure(role, "PermissionsBoundary", (boundary) => queryMembers(boundary, simIamAttachedBoundaryMembers));
|
|
26
|
+
}
|
|
16
27
|
/**
|
|
17
28
|
* The Role operations simulated IAM serves over the Query protocol.
|
|
18
29
|
*
|
|
@@ -30,8 +41,9 @@ export function simIamQueryRoleOperations() {
|
|
|
30
41
|
Path: fields.text("Path"),
|
|
31
42
|
AssumeRolePolicyDocument: fields.text("AssumeRolePolicyDocument"),
|
|
32
43
|
Description: fields.text("Description"),
|
|
44
|
+
PermissionsBoundary: fields.text("PermissionsBoundary"),
|
|
33
45
|
}),
|
|
34
|
-
result: (output) => iamQueryEntity(output, "Role", roleMembers),
|
|
46
|
+
result: (output) => iamQueryEntity(output, "Role", roleMembers, roleBoundary),
|
|
35
47
|
},
|
|
36
48
|
],
|
|
37
49
|
[
|
|
@@ -40,7 +52,7 @@ export function simIamQueryRoleOperations() {
|
|
|
40
52
|
input: (fields) => ({
|
|
41
53
|
RoleName: fields.text("RoleName"),
|
|
42
54
|
}),
|
|
43
|
-
result: (output) => iamQueryEntity(output, "Role", roleMembers),
|
|
55
|
+
result: (output) => iamQueryEntity(output, "Role", roleMembers, roleBoundary),
|
|
44
56
|
},
|
|
45
57
|
],
|
|
46
58
|
[
|
|
@@ -31,7 +31,7 @@ export class SimCfnLambdaEventSourceMappingProperties {
|
|
|
31
31
|
*/
|
|
32
32
|
createInput() {
|
|
33
33
|
const eventSourceArn = this.parser.requiredString(this.resource, this.properties["EventSourceArn"], "EventSourceArn");
|
|
34
|
-
assertSimulatedEventSourceMappingProperties(this.resource
|
|
34
|
+
assertSimulatedEventSourceMappingProperties(this.resource, this.properties);
|
|
35
35
|
return {
|
|
36
36
|
EventSourceArn: eventSourceArn,
|
|
37
37
|
FunctionName: simCfnLambdaTargetFunctionName(this.parser.requiredString(this.resource, this.properties["FunctionName"], "FunctionName")),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SimCfnResource } from "../../../cloudformation/resource/sim-cfn-resource.js";
|
|
1
2
|
import type { SimCfnTemplateValueRecord } from "../../../cloudformation/template/value/sim-cfn-template-value.js";
|
|
2
3
|
/**
|
|
3
4
|
* Build the error a property of an AWS::Lambda::EventSourceMapping Resource is
|
|
@@ -11,6 +12,6 @@ import type { SimCfnTemplateValueRecord } from "../../../cloudformation/template
|
|
|
11
12
|
export declare function eventSourceMappingPropertyError(logicalId: string, reason: string): Error;
|
|
12
13
|
/**
|
|
13
14
|
* Refuse everything about an AWS::Lambda::EventSourceMapping Resource that is
|
|
14
|
-
* not simulated.
|
|
15
|
+
* not simulated, and record what the mapping is created without.
|
|
15
16
|
*/
|
|
16
|
-
export declare function assertSimulatedEventSourceMappingProperties(
|
|
17
|
+
export declare function assertSimulatedEventSourceMappingProperties(resource: SimCfnResource, properties: SimCfnTemplateValueRecord): void;
|
|
@@ -44,10 +44,26 @@ const unsimulatedPropertyNames = new Set([
|
|
|
44
44
|
"SelfManagedEventSource",
|
|
45
45
|
"SelfManagedKafkaEventSourceConfig",
|
|
46
46
|
"SourceAccessConfigurations",
|
|
47
|
-
"Tags",
|
|
48
47
|
"Topics",
|
|
49
48
|
"TumblingWindowInSeconds",
|
|
50
49
|
]);
|
|
50
|
+
/**
|
|
51
|
+
* Real AWS::Lambda::EventSourceMapping properties this simulation has nothing
|
|
52
|
+
* to act on and no reason to fail a stack over.
|
|
53
|
+
*
|
|
54
|
+
* `Tags` is the whole list. The mapping is created without them and the
|
|
55
|
+
* omission is recorded against the Resource. A mapping delivers the same
|
|
56
|
+
* records with a tag and without one, and a CDK app calling
|
|
57
|
+
* `Tags.of(app).add(...)` tags every mapping in it.
|
|
58
|
+
*/
|
|
59
|
+
const ignoredPropertyReasons = new Map([
|
|
60
|
+
[
|
|
61
|
+
"Tags",
|
|
62
|
+
"AWS::Lambda::EventSourceMapping property Tags is not simulated, so the " +
|
|
63
|
+
"mapping is created without them. Nothing reads them back and nothing " +
|
|
64
|
+
"is grouped or billed by them.",
|
|
65
|
+
],
|
|
66
|
+
]);
|
|
51
67
|
/**
|
|
52
68
|
* Build the error a property of an AWS::Lambda::EventSourceMapping Resource is
|
|
53
69
|
* refused with.
|
|
@@ -62,10 +78,16 @@ export function eventSourceMappingPropertyError(logicalId, reason) {
|
|
|
62
78
|
}
|
|
63
79
|
/**
|
|
64
80
|
* Refuse everything about an AWS::Lambda::EventSourceMapping Resource that is
|
|
65
|
-
* not simulated.
|
|
81
|
+
* not simulated, and record what the mapping is created without.
|
|
66
82
|
*/
|
|
67
|
-
export function assertSimulatedEventSourceMappingProperties(
|
|
83
|
+
export function assertSimulatedEventSourceMappingProperties(resource, properties) {
|
|
84
|
+
const logicalId = resource.logicalId;
|
|
68
85
|
for (const name of Object.keys(properties)) {
|
|
86
|
+
const ignoredReason = ignoredPropertyReasons.get(name);
|
|
87
|
+
if (ignoredReason !== undefined) {
|
|
88
|
+
resource.ignoreProperty(name, ignoredReason);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
69
91
|
if (unsimulatedPropertyNames.has(name)) {
|
|
70
92
|
throw eventSourceMappingPropertyError(logicalId, `${name} is a real AWS::Lambda::EventSourceMapping property that ` +
|
|
71
93
|
"this simulation does not simulate, so it is refused rather than " +
|
|
@@ -26,6 +26,12 @@ import type { SimCfnLambdaFunctionProperties } from "./sim-cfn-lambda-function-p
|
|
|
26
26
|
* CloudFormation carries out itself is recorded as inert instead, because this
|
|
27
27
|
* message would otherwise tell a reader to bind a handler to a function that
|
|
28
28
|
* has nothing left to do.
|
|
29
|
+
*
|
|
30
|
+
* The refusal carries the function's name, which the properties parser has
|
|
31
|
+
* already worked out by the time this gate is asked. CDK writes a function's
|
|
32
|
+
* log group name as `/aws/lambda/` joined to a Ref of the function. A refusal
|
|
33
|
+
* carrying no name puts the log group under `/aws/lambda/` and a logical ID,
|
|
34
|
+
* a name no account would hold.
|
|
29
35
|
*/
|
|
30
36
|
export declare class SimCfnLambdaRuntimeSkip {
|
|
31
37
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SimCfnNamedSkip } from "../../../cloudformation/resource/unsupported/sim-cfn-named-skip.js";
|
|
1
2
|
/**
|
|
2
3
|
* Sim Lambda runs handler modules in a Node.js vm, so it simulates the
|
|
3
4
|
* Node.js managed runtimes.
|
|
@@ -29,6 +30,12 @@ const nodeJsRuntimePrefix = "nodejs";
|
|
|
29
30
|
* CloudFormation carries out itself is recorded as inert instead, because this
|
|
30
31
|
* message would otherwise tell a reader to bind a handler to a function that
|
|
31
32
|
* has nothing left to do.
|
|
33
|
+
*
|
|
34
|
+
* The refusal carries the function's name, which the properties parser has
|
|
35
|
+
* already worked out by the time this gate is asked. CDK writes a function's
|
|
36
|
+
* log group name as `/aws/lambda/` joined to a Ref of the function. A refusal
|
|
37
|
+
* carrying no name puts the log group under `/aws/lambda/` and a logical ID,
|
|
38
|
+
* a name no account would hold.
|
|
32
39
|
*/
|
|
33
40
|
export class SimCfnLambdaRuntimeSkip {
|
|
34
41
|
/**
|
|
@@ -42,9 +49,9 @@ export class SimCfnLambdaRuntimeSkip {
|
|
|
42
49
|
runtimeName.startsWith(nodeJsRuntimePrefix)) {
|
|
43
50
|
return undefined;
|
|
44
51
|
}
|
|
45
|
-
return new
|
|
52
|
+
return new SimCfnNamedSkip(`Unsupported sim Lambda CloudFormation Resource ${resource.logicalId}: ` +
|
|
46
53
|
`sim Lambda simulates Node.js runtimes, and this function declares ` +
|
|
47
54
|
`Runtime ${runtimeName}. Bind a real in-process handler to this ` +
|
|
48
|
-
`function to simulate it
|
|
55
|
+
`function to simulate it.`, functionProperties.functionName);
|
|
49
56
|
}
|
|
50
57
|
}
|
|
@@ -34,10 +34,32 @@ export function makeSimRoute53HostedZoneId(existing = new Set()) {
|
|
|
34
34
|
export function normalizeSimRoute53HostedZoneId(value) {
|
|
35
35
|
const hostedZoneId = value?.replace(/^\/?hostedzone\//u, "");
|
|
36
36
|
if (!isSimRoute53HostedZoneId(hostedZoneId)) {
|
|
37
|
-
throw new SimRoute53InvalidInput(
|
|
37
|
+
throw new SimRoute53InvalidInput(rejectedSimRoute53HostedZoneId(value, hostedZoneId));
|
|
38
38
|
}
|
|
39
39
|
return hostedZoneId;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* The literal CDK writes into a synthesized template when
|
|
43
|
+
* `HostedZone.fromLookup` runs against no credentials and no cached context.
|
|
44
|
+
*/
|
|
45
|
+
const cdkUnresolvedLookupHostedZoneId = "DUMMY";
|
|
46
|
+
/**
|
|
47
|
+
* The message for a Hosted Zone ID that fails the shape check.
|
|
48
|
+
*
|
|
49
|
+
* CDK writes its unresolved lookup stand-in into every RecordSet of the
|
|
50
|
+
* synthesized template, and that value arrives here looking like any other
|
|
51
|
+
* malformed ID. Reporting it as one sends the reader to check an ID they never
|
|
52
|
+
* wrote, so the stand-in is named and the synth that produced it is pointed at.
|
|
53
|
+
*/
|
|
54
|
+
function rejectedSimRoute53HostedZoneId(value, hostedZoneId) {
|
|
55
|
+
const reported = `Invalid Route53 Hosted Zone ID: ${value ?? "(missing)"}`;
|
|
56
|
+
if (hostedZoneId !== cdkUnresolvedLookupHostedZoneId) {
|
|
57
|
+
return reported;
|
|
58
|
+
}
|
|
59
|
+
return (`${reported}. CDK fills an unresolved \`HostedZone.fromLookup\` with this ` +
|
|
60
|
+
"stand-in. Run `cdk synth` with credentials for the account holding the " +
|
|
61
|
+
"zone, or commit the `cdk.context.json` a resolved lookup writes.");
|
|
62
|
+
}
|
|
41
63
|
/**
|
|
42
64
|
* Whether a value has the shape of a Route53 Hosted Zone ID.
|
|
43
65
|
*/
|
|
@@ -23,6 +23,7 @@ export class SimCfnSnsTopicCreator {
|
|
|
23
23
|
resource,
|
|
24
24
|
properties,
|
|
25
25
|
});
|
|
26
|
+
topicProperties.recordIgnoredProperties();
|
|
26
27
|
const name = topicProperties.name();
|
|
27
28
|
const attributes = topicProperties.attributes();
|
|
28
29
|
const inline = topicProperties.inlineSubscriptions();
|
|
@@ -43,13 +43,18 @@ export declare class SimCfnSnsTopicProperties {
|
|
|
43
43
|
* The subscriptions the topic declares inside itself.
|
|
44
44
|
*/
|
|
45
45
|
inlineSubscriptions(): readonly SimCfnSnsInlineSubscription[];
|
|
46
|
+
/**
|
|
47
|
+
* Record the properties the topic is created without acting on.
|
|
48
|
+
*/
|
|
49
|
+
recordIgnoredProperties(): void;
|
|
46
50
|
/**
|
|
47
51
|
* Whether a property is handed to CreateTopic as an attribute.
|
|
48
52
|
*
|
|
49
|
-
* The two properties the CloudFormation layer reads itself are not
|
|
50
|
-
* are
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
+
* The two properties the CloudFormation layer reads itself are not, and
|
|
54
|
+
* neither are the ones recorded as ignored. The rest are refused as they are
|
|
55
|
+
* reached: the ones with a reason of their own with that reason, and
|
|
56
|
+
* anything else as a property AWS::SNS::Topic does not have, which is how
|
|
57
|
+
* real CloudFormation answers one too.
|
|
53
58
|
*/
|
|
54
59
|
private isAttributeProperty;
|
|
55
60
|
private propertyError;
|
|
@@ -3,7 +3,7 @@ import { simCfnSnsResourceError } from "../sim-cfn-sns-resource-error.js";
|
|
|
3
3
|
import { snsTopicResourceType } from "../sim-cfn-sns-resource-types.js";
|
|
4
4
|
import { simCfnSnsInlineSubscriptions, } from "./sim-cfn-sns-inline-subscriptions.js";
|
|
5
5
|
import { SimCfnSnsTopicName } from "./sim-cfn-sns-topic-name.js";
|
|
6
|
-
import { attributePropertyNames, topicNamePropertyName, topicSubscriptionPropertyName, unsimulatedPropertyReasons, } from "./sim-cfn-sns-topic-property-names.js";
|
|
6
|
+
import { attributePropertyNames, ignoredPropertyReasons, topicNamePropertyName, topicSubscriptionPropertyName, unsimulatedPropertyReasons, } from "./sim-cfn-sns-topic-property-names.js";
|
|
7
7
|
/**
|
|
8
8
|
* Reads AWS::SNS::Topic CloudFormation properties into the shape CreateTopic
|
|
9
9
|
* takes.
|
|
@@ -63,17 +63,29 @@ export class SimCfnSnsTopicProperties {
|
|
|
63
63
|
inlineSubscriptions() {
|
|
64
64
|
return simCfnSnsInlineSubscriptions(this.resource.logicalId, this.properties.get(topicSubscriptionPropertyName));
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Record the properties the topic is created without acting on.
|
|
68
|
+
*/
|
|
69
|
+
recordIgnoredProperties() {
|
|
70
|
+
for (const [property, reason] of ignoredPropertyReasons) {
|
|
71
|
+
if (this.properties.has(property)) {
|
|
72
|
+
this.resource.ignoreProperty(property, reason);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
66
76
|
/**
|
|
67
77
|
* Whether a property is handed to CreateTopic as an attribute.
|
|
68
78
|
*
|
|
69
|
-
* The two properties the CloudFormation layer reads itself are not
|
|
70
|
-
* are
|
|
71
|
-
*
|
|
72
|
-
*
|
|
79
|
+
* The two properties the CloudFormation layer reads itself are not, and
|
|
80
|
+
* neither are the ones recorded as ignored. The rest are refused as they are
|
|
81
|
+
* reached: the ones with a reason of their own with that reason, and
|
|
82
|
+
* anything else as a property AWS::SNS::Topic does not have, which is how
|
|
83
|
+
* real CloudFormation answers one too.
|
|
73
84
|
*/
|
|
74
85
|
isAttributeProperty(name) {
|
|
75
86
|
if (name === topicNamePropertyName ||
|
|
76
|
-
name === topicSubscriptionPropertyName
|
|
87
|
+
name === topicSubscriptionPropertyName ||
|
|
88
|
+
ignoredPropertyReasons.has(name)) {
|
|
77
89
|
return false;
|
|
78
90
|
}
|
|
79
91
|
if (attributePropertyNames.has(name)) {
|