@kensio/yulin 1.21.34 → 1.23.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.
- package/dist/serve/controller/sim-service-controller.d.ts +6 -0
- package/dist/serve/controller/sim-service-controller.js +7 -0
- package/dist/serve/http/request/sim-aws-request-authenticator.js +3 -0
- package/dist/service/apigateway/serve/sim-api-gateway-controller.js +1 -0
- package/dist/service/apigateway/serve/sim-rest-api-web-acl-inspection.d.ts +2 -0
- package/dist/service/apigateway/serve/sim-rest-api-web-acl-inspection.js +1 -0
- package/dist/service/cloudformation/registry/sim-cfn-attribute-reads.d.ts +11 -0
- package/dist/service/cloudformation/registry/sim-cfn-attribute-reads.js +64 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handler-authorizer.d.ts +45 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handler-authorizer.js +72 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handler.d.ts +33 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handler.fixture.d.ts +24 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handler.fixture.js +58 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handler.js +36 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handlers.d.ts +10 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handlers.js +23 -0
- package/dist/service/cloudformation/registry/sim-cfn-read-handlers.json +7400 -0
- package/dist/service/cloudformation/registry/sim-cfn-resource-arn.d.ts +46 -0
- package/dist/service/cloudformation/registry/sim-cfn-resource-arn.js +119 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.d.ts +6 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.js +3 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +3 -2
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +2 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.js +9 -0
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.d.ts +11 -0
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.js +22 -0
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.d.ts +3 -1
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.js +2 -1
- package/dist/service/cognito/serve/sim-cognito-controller.js +4 -3
- package/dist/service/cognito/serve/sim-cognito-domain-controller.js +2 -0
- package/dist/service/cognito/serve/sim-cognito-web-acl-inspection.d.ts +2 -0
- package/dist/service/cognito/serve/sim-cognito-web-acl-inspection.js +1 -0
- package/dist/service/iam/index.d.ts +1 -0
- package/dist/service/iam/index.js +1 -0
- package/dist/service/iam/request/error/sim-aws-request-auth.error.d.ts +1 -1
- package/dist/service/iam/request/error/sim-aws-request-auth.error.js +1 -1
- package/dist/service/iam/request/sim-aws-control-headers.d.ts +2 -1
- package/dist/service/iam/request/sim-aws-control-headers.js +4 -1
- package/dist/service/iam/request/sim-aws-source-ip-header.d.ts +19 -0
- package/dist/service/iam/request/sim-aws-source-ip-header.js +32 -0
- package/dist/service/stepfunctions/command/execution/sim-states-execution-start.js +1 -0
- package/dist/service/stepfunctions/execution/sim-states-run-task.js +1 -0
- package/dist/service/stepfunctions/execution/sim-states-state-outcome.d.ts +1 -0
- package/dist/service/stepfunctions/execution/sim-states-walks.d.ts +1 -0
- package/dist/service/stepfunctions/execution/sim-states-walks.js +1 -0
- package/dist/service/stepfunctions/task/sim-aws-states-task-targets.js +6 -1
- package/dist/service/stepfunctions/task/sim-states-execution-role.d.ts +2 -1
- package/dist/service/stepfunctions/task/sim-states-execution-role.js +2 -1
- package/dist/service/stepfunctions/task/sim-states-task-invocation.d.ts +1 -0
- package/dist/service/wafv2/association/sim-waf-associations.js +1 -1
- package/dist/service/wafv2/association/sim-waf-protection.d.ts +5 -0
- package/dist/service/wafv2/association/sim-waf-request-inspection.d.ts +2 -0
- package/dist/service/wafv2/association/sim-waf-request-inspection.js +7 -2
- package/dist/service/wafv2/evaluate/sim-waf-evaluation-request.d.ts +5 -0
- package/dist/service/wafv2/evaluate/sim-waf-inspected-request.d.ts +12 -1
- package/dist/service/wafv2/evaluate/sim-waf-inspected-request.js +12 -1
- package/dist/service/wafv2/index.d.ts +2 -1
- package/dist/service/wafv2/index.js +1 -0
- package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.d.ts +8 -5
- package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.js +10 -5
- package/dist/service/wafv2/managed/sim-waf-managed-address-declaration.d.ts +32 -0
- package/dist/service/wafv2/managed/sim-waf-managed-address-declaration.js +52 -0
- package/dist/service/wafv2/managed/sim-waf-managed-address-range.d.ts +21 -0
- package/dist/service/wafv2/managed/sim-waf-managed-address-range.js +73 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.d.ts +7 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.js +15 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule.type.d.ts +5 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rules.d.ts +27 -1
- package/dist/service/wafv2/managed/sim-waf-managed-rules.js +33 -13
- package/dist/service/wafv2/sim-wafv2.js +2 -1
- package/dist/service/wafv2/statement/sim-waf-rate-based-input.d.ts +5 -4
- package/dist/service/wafv2/statement/sim-waf-rate-based-input.js +6 -6
- package/docs/services/cloudformation/README.md +106 -0
- package/docs/services/iam/README.md +6 -0
- package/docs/services/wafv2/README.md +105 -14
- package/package.json +5 -4
|
@@ -25,6 +25,7 @@ interface SimAwsServiceRequestProperties {
|
|
|
25
25
|
readonly request: Request;
|
|
26
26
|
readonly caller?: SimAwsRequestCaller | undefined;
|
|
27
27
|
readonly source?: SimAwsRequestSource | undefined;
|
|
28
|
+
readonly sourceIp?: string | undefined;
|
|
28
29
|
readonly body?: Uint8Array | undefined;
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
@@ -49,6 +50,11 @@ export declare class SimAwsServiceRequest {
|
|
|
49
50
|
* conditioned on, and most requests state none.
|
|
50
51
|
*/
|
|
51
52
|
readonly source: SimAwsRequestSource | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The client address the request came from, which is loopback unless the
|
|
55
|
+
* request stated another with `x-sim-aws-source-ip`.
|
|
56
|
+
*/
|
|
57
|
+
readonly sourceIp: string;
|
|
52
58
|
readonly body?: Uint8Array | undefined;
|
|
53
59
|
constructor(properties: SimAwsServiceRequestProperties);
|
|
54
60
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { simAwsProxiedSourceIp } from "../http/sim-aws-proxied-connection.js";
|
|
1
2
|
import { SimAwsRequestCaller } from "../../service/iam/request/sim-aws-request-caller.js";
|
|
2
3
|
/**
|
|
3
4
|
* One HTTP request, routed to a simulated service and attributed to a
|
|
@@ -21,6 +22,11 @@ export class SimAwsServiceRequest {
|
|
|
21
22
|
* conditioned on, and most requests state none.
|
|
22
23
|
*/
|
|
23
24
|
source;
|
|
25
|
+
/**
|
|
26
|
+
* The client address the request came from, which is loopback unless the
|
|
27
|
+
* request stated another with `x-sim-aws-source-ip`.
|
|
28
|
+
*/
|
|
29
|
+
sourceIp;
|
|
24
30
|
body;
|
|
25
31
|
constructor(properties) {
|
|
26
32
|
this.target = properties.target;
|
|
@@ -28,6 +34,7 @@ export class SimAwsServiceRequest {
|
|
|
28
34
|
// An unattributed request is anonymous, never the Account root.
|
|
29
35
|
this.caller = properties.caller ?? SimAwsRequestCaller.anonymous();
|
|
30
36
|
this.source = properties.source;
|
|
37
|
+
this.sourceIp = properties.sourceIp ?? simAwsProxiedSourceIp;
|
|
31
38
|
this.body = properties.body;
|
|
32
39
|
}
|
|
33
40
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { simAwsServiceSigningName } from "../../controller/sim-aws-service-signing-name.js";
|
|
2
2
|
import { SimAwsServiceRequest, } from "../../controller/sim-service-controller.js";
|
|
3
3
|
import { SimAwsRequestSource } from "../../../service/iam/request/sim-aws-request-source.js";
|
|
4
|
+
import { simAwsRequestSourceIp } from "../../../service/iam/request/sim-aws-source-ip-header.js";
|
|
4
5
|
import { SimAwsReceivedRequest } from "./sim-aws-received-request.js";
|
|
5
6
|
/**
|
|
6
7
|
* Turns a received HTTP request into a request a simulated service can serve.
|
|
@@ -40,11 +41,13 @@ export class SimAwsRequestAuthenticator {
|
|
|
40
41
|
},
|
|
41
42
|
});
|
|
42
43
|
const source = SimAwsRequestSource.fromHeaders(request.headers);
|
|
44
|
+
const sourceIp = simAwsRequestSourceIp(request.headers);
|
|
43
45
|
return new SimAwsServiceRequest({
|
|
44
46
|
target,
|
|
45
47
|
request: received.forService(),
|
|
46
48
|
caller,
|
|
47
49
|
...(source !== undefined && { source }),
|
|
50
|
+
sourceIp,
|
|
48
51
|
body: received.body,
|
|
49
52
|
});
|
|
50
53
|
}
|
|
@@ -5,6 +5,8 @@ interface SimRestApiInspectionInput {
|
|
|
5
5
|
/** The first path segment of the request, which names the stage. */
|
|
6
6
|
readonly stageName: string;
|
|
7
7
|
readonly request: Request;
|
|
8
|
+
/** The client address the request came from. */
|
|
9
|
+
readonly sourceIp: string;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Puts a request to the web ACL in front of the stage it reached.
|
|
@@ -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
|
+
}
|