@kensio/yulin 1.21.34 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/service/cloudformation/registry/sim-cfn-attribute-reads.d.ts +11 -0
  2. package/dist/service/cloudformation/registry/sim-cfn-attribute-reads.js +64 -0
  3. package/dist/service/cloudformation/registry/sim-cfn-read-handler-authorizer.d.ts +45 -0
  4. package/dist/service/cloudformation/registry/sim-cfn-read-handler-authorizer.js +72 -0
  5. package/dist/service/cloudformation/registry/sim-cfn-read-handler.d.ts +33 -0
  6. package/dist/service/cloudformation/registry/sim-cfn-read-handler.fixture.d.ts +24 -0
  7. package/dist/service/cloudformation/registry/sim-cfn-read-handler.fixture.js +58 -0
  8. package/dist/service/cloudformation/registry/sim-cfn-read-handler.js +36 -0
  9. package/dist/service/cloudformation/registry/sim-cfn-read-handlers.d.ts +10 -0
  10. package/dist/service/cloudformation/registry/sim-cfn-read-handlers.js +23 -0
  11. package/dist/service/cloudformation/registry/sim-cfn-read-handlers.json +7400 -0
  12. package/dist/service/cloudformation/registry/sim-cfn-resource-arn.d.ts +46 -0
  13. package/dist/service/cloudformation/registry/sim-cfn-resource-arn.js +119 -0
  14. package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.d.ts +6 -1
  15. package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.js +3 -0
  16. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +3 -2
  17. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +2 -1
  18. package/dist/service/cloudformation/stack/sim-cfn-stack.js +9 -0
  19. package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.d.ts +11 -0
  20. package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.js +22 -0
  21. package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.d.ts +3 -1
  22. package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.js +2 -1
  23. package/dist/service/stepfunctions/command/execution/sim-states-execution-start.js +1 -0
  24. package/dist/service/stepfunctions/execution/sim-states-run-task.js +1 -0
  25. package/dist/service/stepfunctions/execution/sim-states-state-outcome.d.ts +1 -0
  26. package/dist/service/stepfunctions/execution/sim-states-walks.d.ts +1 -0
  27. package/dist/service/stepfunctions/execution/sim-states-walks.js +1 -0
  28. package/dist/service/stepfunctions/task/sim-aws-states-task-targets.js +6 -1
  29. package/dist/service/stepfunctions/task/sim-states-execution-role.d.ts +2 -1
  30. package/dist/service/stepfunctions/task/sim-states-execution-role.js +2 -1
  31. package/dist/service/stepfunctions/task/sim-states-task-invocation.d.ts +1 -0
  32. package/docs/services/cloudformation/README.md +106 -0
  33. package/package.json +5 -4
@@ -0,0 +1,11 @@
1
+ import type { CfnTemplateBodyRecord } from "../template/sim-cfn-template.js";
2
+ /**
3
+ * The logical IDs of the Resources a template reads an attribute of, through
4
+ * `Fn::GetAtt` or a `${LogicalId.Attribute}` in `Fn::Sub`, anywhere in its
5
+ * Resources or Outputs.
6
+ *
7
+ * This reads the raw template, before conditions are applied. A `Fn::GetAtt`
8
+ * in an `Fn::If` branch the conditions rule out still counts, which can
9
+ * authorize a read real CloudFormation would not make.
10
+ */
11
+ export declare function simCfnAttributeReads(template: CfnTemplateBodyRecord): ReadonlySet<string>;
@@ -0,0 +1,64 @@
1
+ import { isRecord } from "../../../util/type-guard/record.js";
2
+ const subVariablePattern = /\$\{(?<name>[^!}][^}]*)\}/gu;
3
+ /**
4
+ * The logical IDs of the Resources a template reads an attribute of, through
5
+ * `Fn::GetAtt` or a `${LogicalId.Attribute}` in `Fn::Sub`, anywhere in its
6
+ * Resources or Outputs.
7
+ *
8
+ * This reads the raw template, before conditions are applied. A `Fn::GetAtt`
9
+ * in an `Fn::If` branch the conditions rule out still counts, which can
10
+ * authorize a read real CloudFormation would not make.
11
+ */
12
+ export function simCfnAttributeReads(template) {
13
+ const reads = new Set();
14
+ collect(template.Resources, reads);
15
+ collect(template.Outputs ?? {}, reads);
16
+ return reads;
17
+ }
18
+ function collect(value, reads) {
19
+ if (Array.isArray(value)) {
20
+ for (const item of value) {
21
+ collect(item, reads);
22
+ }
23
+ return;
24
+ }
25
+ if (!isRecord(value)) {
26
+ return;
27
+ }
28
+ for (const [key, entry] of Object.entries(value)) {
29
+ if (key === "Fn::GetAtt") {
30
+ addGetAttTarget(entry, reads);
31
+ }
32
+ else if (key === "Fn::Sub") {
33
+ addSubTargets(entry, reads);
34
+ }
35
+ collect(entry, reads);
36
+ }
37
+ }
38
+ /** `["Logical", "Attribute"]`, or the short form `"Logical.Attribute"`. */
39
+ function addGetAttTarget(value, reads) {
40
+ const target = Array.isArray(value) ? value[0] : value;
41
+ if (typeof target === "string") {
42
+ reads.add(target.split(".", 1)[0] ?? target);
43
+ }
44
+ }
45
+ /**
46
+ * A `${Logical.Attribute}` in a `Fn::Sub` string. A name the Sub's own
47
+ * variable map gives is a variable and reads no Resource, and `${!Literal}` is
48
+ * escaped text.
49
+ */
50
+ function addSubTargets(value, reads) {
51
+ const [text, variables] = Array.isArray(value) ? value : [value, undefined];
52
+ if (typeof text !== "string") {
53
+ return;
54
+ }
55
+ for (const match of text.matchAll(subVariablePattern)) {
56
+ const name = match.groups?.["name"] ?? "";
57
+ const [logicalId, attribute] = name.split(".", 2);
58
+ if (logicalId !== undefined &&
59
+ attribute !== undefined &&
60
+ !(isRecord(variables) && Object.hasOwn(variables, name))) {
61
+ reads.add(logicalId);
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,45 @@
1
+ import type { SimCfnResource } from "../resource/sim-cfn-resource.js";
2
+ import type { SimCfnStackDeployContext } from "../stack/sim-cfn-stack-deploy-context.js";
3
+ import type { SimCfnStackUpdatePlan } from "../stack/update/sim-cfn-stack-update-plan.js";
4
+ import type { SimCfnTemplate } from "../template/sim-cfn-template.js";
5
+ interface SimCfnReadHandlerAuthorizerProperties {
6
+ /**
7
+ * Where the simulation and the Stack's caller are read from. The caller is
8
+ * read when the update authorizes, because an update naming a caller of its
9
+ * own takes it on after this is made.
10
+ */
11
+ readonly context: SimCfnStackDeployContext;
12
+ }
13
+ /**
14
+ * Authorizes the calls CloudFormation's read handlers make as the deployment's
15
+ * caller.
16
+ *
17
+ * Real CloudFormation calls a Resource's read handler when it needs the
18
+ * Resource's attributes and holds no fresh model of it. A Stack update that
19
+ * leaves a Resource alone, while the new template reads one of its attributes
20
+ * through `Fn::GetAtt`, is the case simulated here. The handler runs as the
21
+ * Stack's execution role, so a role missing one of its calls fails the update.
22
+ *
23
+ * This needs no model of the Resource's service. A Resource type yulin skips
24
+ * is authorized the same way as one it creates, from the registry snapshot
25
+ * and the Resource's properties.
26
+ */
27
+ export declare class SimCfnReadHandlerAuthorizer {
28
+ private readonly context;
29
+ constructor(properties: SimCfnReadHandlerAuthorizerProperties);
30
+ /**
31
+ * Ensure the caller may make the read handler calls of each Resource an
32
+ * update leaves alone while its new template reads the Resource's
33
+ * attributes.
34
+ */
35
+ authorizeUpdate(plan: SimCfnStackUpdatePlan, update: {
36
+ readonly updated: SimCfnTemplate;
37
+ readonly resources: ReadonlyMap<string, SimCfnResource>;
38
+ }): Promise<void>;
39
+ /**
40
+ * Ensure the caller may make every call each Resource's read handler makes.
41
+ */
42
+ authorize(reading: readonly SimCfnResource[], resources: ReadonlyMap<string, SimCfnResource>): Promise<void>;
43
+ private authorizeOne;
44
+ }
45
+ export {};
@@ -0,0 +1,72 @@
1
+ import { SimIamActionAuthorizer } from "../../iam/authorize/sim-iam-action-authorizer.js";
2
+ import { simScopeIamAuthZ } from "../../iam/authorize/sim-iam-region-auth-z.js";
3
+ import { simCfnReadHandler } from "./sim-cfn-read-handlers.js";
4
+ import { SimCfnResourceArn } from "./sim-cfn-resource-arn.js";
5
+ /**
6
+ * Authorizes the calls CloudFormation's read handlers make as the deployment's
7
+ * caller.
8
+ *
9
+ * Real CloudFormation calls a Resource's read handler when it needs the
10
+ * Resource's attributes and holds no fresh model of it. A Stack update that
11
+ * leaves a Resource alone, while the new template reads one of its attributes
12
+ * through `Fn::GetAtt`, is the case simulated here. The handler runs as the
13
+ * Stack's execution role, so a role missing one of its calls fails the update.
14
+ *
15
+ * This needs no model of the Resource's service. A Resource type yulin skips
16
+ * is authorized the same way as one it creates, from the registry snapshot
17
+ * and the Resource's properties.
18
+ */
19
+ export class SimCfnReadHandlerAuthorizer {
20
+ context;
21
+ constructor(properties) {
22
+ this.context = properties.context;
23
+ }
24
+ /**
25
+ * Ensure the caller may make the read handler calls of each Resource an
26
+ * update leaves alone while its new template reads the Resource's
27
+ * attributes.
28
+ */
29
+ async authorizeUpdate(plan, update) {
30
+ await this.authorize(plan.untouchedReadBy(update.updated.template), update.resources);
31
+ }
32
+ /**
33
+ * Ensure the caller may make every call each Resource's read handler makes.
34
+ */
35
+ async authorize(reading, resources) {
36
+ await Promise.all(reading.map(async (resource) => {
37
+ await this.authorizeOne(resource, resources);
38
+ }));
39
+ }
40
+ async authorizeOne(resource, resources) {
41
+ const handler = simCfnReadHandler(resource.type ?? "");
42
+ if (handler === undefined) {
43
+ return;
44
+ }
45
+ const { simAws, caller } = this.context;
46
+ const resolvedProperties = await resource.resolvedProperties({
47
+ resources,
48
+ simAws,
49
+ caller,
50
+ });
51
+ const resourceArn = new SimCfnResourceArn({
52
+ resource,
53
+ arnFormat: handler.arnFormat,
54
+ resolvedProperties,
55
+ }).value();
56
+ const { accountId, regionName } = resource.accountRegionScope;
57
+ const authorizer = new SimIamActionAuthorizer({
58
+ iam: simScopeIamAuthZ(simAws.accountRegionScope(accountId, regionName)),
59
+ });
60
+ // The denial keeps its AccessDenied name, as a failed creation's does, so a
61
+ // test can match it the way it matches any other refusal.
62
+ try {
63
+ handler.authorize(authorizer, resourceArn, caller);
64
+ }
65
+ catch (error) {
66
+ if (error instanceof Error) {
67
+ error.message = `Sim CloudFormation Resource ${resource.logicalId} read handler failed: ${error.message}`;
68
+ }
69
+ throw error;
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,33 @@
1
+ import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
2
+ import type { SimIamActionAuthorizer } from "../../iam/authorize/sim-iam-action-authorizer.js";
3
+ interface SimCfnReadHandlerProperties {
4
+ readonly resourceType: string;
5
+ readonly arnFormat: string;
6
+ readonly actions: readonly string[];
7
+ readonly anyResourceActions: readonly string[];
8
+ }
9
+ /**
10
+ * The IAM actions one Resource type's CloudFormation read handler calls as
11
+ * the Stack's execution role, and the ARN format they are decided on.
12
+ *
13
+ * Only the actions in the type's own service are held. Each is decided either
14
+ * on the Resource's own ARN or, for an action IAM scopes to no resource type
15
+ * (`batch:DescribeJobQueues`), on `*`.
16
+ */
17
+ export declare class SimCfnReadHandler {
18
+ readonly resourceType: string;
19
+ /**
20
+ * The Resource's ARN with its variables left in, as the Service
21
+ * Authorization Reference writes it (`repository/${DomainName}/...`).
22
+ */
23
+ readonly arnFormat: string;
24
+ private readonly actions;
25
+ private readonly anyResourceActions;
26
+ constructor(properties: SimCfnReadHandlerProperties);
27
+ /**
28
+ * Ensure the caller may make every call the read handler makes on the
29
+ * Resource with this ARN.
30
+ */
31
+ authorize(authorizer: SimIamActionAuthorizer, resourceArn: string, caller: SimAwsCaller | undefined): void;
32
+ }
33
+ export {};
@@ -0,0 +1,24 @@
1
+ import { SimAws } from "../../aws/sim-aws.js";
2
+ import { type SimAwsAccountId } from "../../aws/sim-aws-account.js";
3
+ import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
4
+ export declare const readHandlerRegionName = "eu-west-2";
5
+ /** A Bucket an update adds, so that the update has something to do. */
6
+ export declare const addedBucket: {
7
+ Type: string;
8
+ Properties: {
9
+ BucketName: string;
10
+ };
11
+ };
12
+ /** A simulation in a fresh Account, in the Region the tests read ARNs in. */
13
+ export declare function readHandlerSimulation(): {
14
+ simAws: SimAws;
15
+ accountId: SimAwsAccountId;
16
+ };
17
+ /**
18
+ * Update a Stack, which goes on running as the role it was deployed as.
19
+ */
20
+ export declare function updateStack(simAws: SimAws, stackName: string, template: object): Promise<void>;
21
+ /**
22
+ * A Role a deployment can run as, holding the statements it is given.
23
+ */
24
+ export declare function deployRole(simAws: SimAws, accountId: SimAwsAccountId, statements: readonly object[]): Promise<SimAwsCaller>;
@@ -0,0 +1,58 @@
1
+ import { SimAws } from "../../aws/sim-aws.js";
2
+ import { makeSimAwsAccountId, } from "../../aws/sim-aws-account.js";
3
+ import { jsonStringify } from "../../../util/type-guard/json.js";
4
+ export const readHandlerRegionName = "eu-west-2";
5
+ /** A Bucket an update adds, so that the update has something to do. */
6
+ export const addedBucket = {
7
+ Type: "AWS::S3::Bucket",
8
+ Properties: { BucketName: "chineseboost-sources" },
9
+ };
10
+ /** A simulation in a fresh Account, in the Region the tests read ARNs in. */
11
+ export function readHandlerSimulation() {
12
+ const accountId = makeSimAwsAccountId();
13
+ return {
14
+ simAws: new SimAws({
15
+ defaultAccountId: accountId,
16
+ defaultRegionName: readHandlerRegionName,
17
+ }),
18
+ accountId,
19
+ };
20
+ }
21
+ /**
22
+ * Update a Stack, which goes on running as the role it was deployed as.
23
+ */
24
+ export async function updateStack(simAws, stackName, template) {
25
+ await simAws.cloudFormation().updateStack({
26
+ input: { StackName: stackName, TemplateBody: jsonStringify(template) },
27
+ });
28
+ }
29
+ /**
30
+ * A Role a deployment can run as, holding the statements it is given.
31
+ */
32
+ export async function deployRole(simAws, accountId, statements) {
33
+ const iam = simAws.account(accountId).iam();
34
+ await iam.createRole({
35
+ input: {
36
+ RoleName: "deployer",
37
+ AssumeRolePolicyDocument: jsonStringify({
38
+ Version: "2012-10-17",
39
+ Statement: {
40
+ Effect: "Allow",
41
+ Action: "sts:AssumeRole",
42
+ Principal: { Service: "cloudformation.amazonaws.com" },
43
+ },
44
+ }),
45
+ },
46
+ });
47
+ await iam.putRolePolicy({
48
+ input: {
49
+ RoleName: "deployer",
50
+ PolicyName: "deployer-policy",
51
+ PolicyDocument: jsonStringify({
52
+ Version: "2012-10-17",
53
+ Statement: statements,
54
+ }),
55
+ },
56
+ });
57
+ return { kind: "arn", arn: `arn:aws:iam::${accountId}:role/deployer` };
58
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The IAM actions one Resource type's CloudFormation read handler calls as
3
+ * the Stack's execution role, and the ARN format they are decided on.
4
+ *
5
+ * Only the actions in the type's own service are held. Each is decided either
6
+ * on the Resource's own ARN or, for an action IAM scopes to no resource type
7
+ * (`batch:DescribeJobQueues`), on `*`.
8
+ */
9
+ export class SimCfnReadHandler {
10
+ resourceType;
11
+ /**
12
+ * The Resource's ARN with its variables left in, as the Service
13
+ * Authorization Reference writes it (`repository/${DomainName}/...`).
14
+ */
15
+ arnFormat;
16
+ actions;
17
+ anyResourceActions;
18
+ constructor(properties) {
19
+ this.resourceType = properties.resourceType;
20
+ this.arnFormat = properties.arnFormat;
21
+ this.actions = properties.actions;
22
+ this.anyResourceActions = properties.anyResourceActions;
23
+ }
24
+ /**
25
+ * Ensure the caller may make every call the read handler makes on the
26
+ * Resource with this ARN.
27
+ */
28
+ authorize(authorizer, resourceArn, caller) {
29
+ for (const action of this.actions) {
30
+ authorizer.authorize(action, resourceArn, caller);
31
+ }
32
+ for (const action of this.anyResourceActions) {
33
+ authorizer.authorize(action, "*", caller);
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,10 @@
1
+ import { SimCfnReadHandler } from "./sim-cfn-read-handler.js";
2
+ /**
3
+ * The read handler of each CloudFormation Resource type, from the snapshot
4
+ * `scripts/mts/write-cfn-read-handlers.mts` writes.
5
+ *
6
+ * A type the snapshot leaves out has no read handler sim CloudFormation can
7
+ * authorize. Either the registry publishes none for it, or none of its
8
+ * permissions is decided on a resource type named after it.
9
+ */
10
+ export declare function simCfnReadHandler(resourceType: string): SimCfnReadHandler | undefined;
@@ -0,0 +1,23 @@
1
+ import snapshot from "./sim-cfn-read-handlers.json" with { type: "json" };
2
+ import { SimCfnReadHandler } from "./sim-cfn-read-handler.js";
3
+ const records = new Map(Object.entries(snapshot.types));
4
+ /**
5
+ * The read handler of each CloudFormation Resource type, from the snapshot
6
+ * `scripts/mts/write-cfn-read-handlers.mts` writes.
7
+ *
8
+ * A type the snapshot leaves out has no read handler sim CloudFormation can
9
+ * authorize. Either the registry publishes none for it, or none of its
10
+ * permissions is decided on a resource type named after it.
11
+ */
12
+ export function simCfnReadHandler(resourceType) {
13
+ const record = records.get(resourceType);
14
+ if (record === undefined) {
15
+ return undefined;
16
+ }
17
+ return new SimCfnReadHandler({
18
+ resourceType,
19
+ arnFormat: record.arn,
20
+ actions: record.actions,
21
+ anyResourceActions: record.anyResourceActions,
22
+ });
23
+ }