@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
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { SimCfnResource } from "../resource/sim-cfn-resource.js";
|
|
2
|
+
import type { SimCfnTemplateValueRecord } from "../template/value/sim-cfn-template-value.js";
|
|
3
|
+
interface SimCfnResourceArnProperties {
|
|
4
|
+
readonly resource: SimCfnResource;
|
|
5
|
+
readonly arnFormat: string;
|
|
6
|
+
readonly resolvedProperties: SimCfnTemplateValueRecord;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The ARN a read handler's calls on one Resource are authorized on.
|
|
10
|
+
*
|
|
11
|
+
* The ARN format's variables are filled from the Stack's scope and from the
|
|
12
|
+
* Resource's own properties, which is the whole of it for a Resource whose
|
|
13
|
+
* template names it (`DomainName` and `RepositoryName` on a CodeArtifact
|
|
14
|
+
* repository). A Resource whose name CloudFormation generated holds no such
|
|
15
|
+
* property. Its ARN comes from its `Arn` attribute, from a Ref that is an ARN, or
|
|
16
|
+
* from its Ref where the format has one variable left, all of which a service answers once it has
|
|
17
|
+
* created the Resource.
|
|
18
|
+
*
|
|
19
|
+
* An ARN that cannot be built is refused. Authorizing the calls on a guessed
|
|
20
|
+
* ARN would let a policy scoped to the real one pass or fail by accident.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SimCfnResourceArn {
|
|
23
|
+
private readonly resource;
|
|
24
|
+
private readonly arnFormat;
|
|
25
|
+
private readonly resolvedProperties;
|
|
26
|
+
constructor(properties: SimCfnResourceArnProperties);
|
|
27
|
+
/** The Resource's ARN, or a refusal saying which variable could not be filled. */
|
|
28
|
+
value(): string;
|
|
29
|
+
private filled;
|
|
30
|
+
private unfilledVariables;
|
|
31
|
+
private variable;
|
|
32
|
+
private property;
|
|
33
|
+
/**
|
|
34
|
+
* The property an ARN variable is held in under another name. The Service
|
|
35
|
+
* Authorization Reference names a CodeBuild project's `${ProjectName}`,
|
|
36
|
+
* which `AWS::CodeBuild::Project` calls `Name`.
|
|
37
|
+
*/
|
|
38
|
+
private namePropertyFor;
|
|
39
|
+
/**
|
|
40
|
+
* A value the Resource answers once a service has created it. A Resource
|
|
41
|
+
* that was skipped answers with a stand-in naming itself, which is no part
|
|
42
|
+
* of an ARN.
|
|
43
|
+
*/
|
|
44
|
+
private deployedValue;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const variablePattern = /\$\{(?<name>[^}]+)\}/gu;
|
|
2
|
+
/**
|
|
3
|
+
* The ARN a read handler's calls on one Resource are authorized on.
|
|
4
|
+
*
|
|
5
|
+
* The ARN format's variables are filled from the Stack's scope and from the
|
|
6
|
+
* Resource's own properties, which is the whole of it for a Resource whose
|
|
7
|
+
* template names it (`DomainName` and `RepositoryName` on a CodeArtifact
|
|
8
|
+
* repository). A Resource whose name CloudFormation generated holds no such
|
|
9
|
+
* property. Its ARN comes from its `Arn` attribute, from a Ref that is an ARN, or
|
|
10
|
+
* from its Ref where the format has one variable left, all of which a service answers once it has
|
|
11
|
+
* created the Resource.
|
|
12
|
+
*
|
|
13
|
+
* An ARN that cannot be built is refused. Authorizing the calls on a guessed
|
|
14
|
+
* ARN would let a policy scoped to the real one pass or fail by accident.
|
|
15
|
+
*/
|
|
16
|
+
export class SimCfnResourceArn {
|
|
17
|
+
resource;
|
|
18
|
+
arnFormat;
|
|
19
|
+
resolvedProperties;
|
|
20
|
+
constructor(properties) {
|
|
21
|
+
this.resource = properties.resource;
|
|
22
|
+
this.arnFormat = properties.arnFormat;
|
|
23
|
+
this.resolvedProperties = new Map(Object.entries(properties.resolvedProperties));
|
|
24
|
+
}
|
|
25
|
+
/** The Resource's ARN, or a refusal saying which variable could not be filled. */
|
|
26
|
+
value() {
|
|
27
|
+
const unfilled = this.unfilledVariables();
|
|
28
|
+
if (unfilled.length === 0) {
|
|
29
|
+
return this.filled();
|
|
30
|
+
}
|
|
31
|
+
const arnAttribute = this.deployedValue(() => {
|
|
32
|
+
return this.resource.attributeValue("Arn");
|
|
33
|
+
});
|
|
34
|
+
if (arnAttribute?.startsWith("arn:") === true) {
|
|
35
|
+
return arnAttribute;
|
|
36
|
+
}
|
|
37
|
+
const refValue = this.deployedValue(() => this.resource.refValue);
|
|
38
|
+
// An SNS topic's Ref is its whole ARN, where a hosted zone's is the one
|
|
39
|
+
// identifier its ARN format lacks.
|
|
40
|
+
if (refValue?.startsWith("arn:") === true) {
|
|
41
|
+
return refValue;
|
|
42
|
+
}
|
|
43
|
+
const [onlyUnfilled] = unfilled;
|
|
44
|
+
if (refValue !== undefined && unfilled.length === 1) {
|
|
45
|
+
return this.filled(new Map([[onlyUnfilled, refValue]]));
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`Sim CloudFormation cannot authorize the read handler of Resource ${this.resource.logicalId} (${String(this.resource.type)}): its ARN format ${this.arnFormat} needs ${unfilled.join(", ")}, which neither its properties nor its attributes give`);
|
|
48
|
+
}
|
|
49
|
+
filled(extra = new Map()) {
|
|
50
|
+
return this.arnFormat.replaceAll(variablePattern, (_match, name) => {
|
|
51
|
+
return extra.get(name) ?? this.variable(name) ?? "";
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
unfilledVariables() {
|
|
55
|
+
return this.arnFormat
|
|
56
|
+
.matchAll(variablePattern)
|
|
57
|
+
.map((match) => match.groups?.["name"] ?? "")
|
|
58
|
+
.filter((name) => this.variable(name) === undefined)
|
|
59
|
+
.toArray();
|
|
60
|
+
}
|
|
61
|
+
variable(name) {
|
|
62
|
+
const { accountId, regionName } = this.resource.accountRegionScope;
|
|
63
|
+
switch (name) {
|
|
64
|
+
case "Partition": {
|
|
65
|
+
return "aws";
|
|
66
|
+
}
|
|
67
|
+
case "Region": {
|
|
68
|
+
return regionName;
|
|
69
|
+
}
|
|
70
|
+
case "Account": {
|
|
71
|
+
return accountId;
|
|
72
|
+
}
|
|
73
|
+
default: {
|
|
74
|
+
return this.property(name) ?? this.property(this.namePropertyFor(name));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
property(name) {
|
|
79
|
+
return stringValue(this.resolvedProperties.get(name));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The property an ARN variable is held in under another name. The Service
|
|
83
|
+
* Authorization Reference names a CodeBuild project's `${ProjectName}`,
|
|
84
|
+
* which `AWS::CodeBuild::Project` calls `Name`.
|
|
85
|
+
*/
|
|
86
|
+
namePropertyFor(variable) {
|
|
87
|
+
const typeName = this.resource.type?.split("::").at(-1);
|
|
88
|
+
if (variable === `${String(typeName)}Name`) {
|
|
89
|
+
return "Name";
|
|
90
|
+
}
|
|
91
|
+
return variable;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A value the Resource answers once a service has created it. A Resource
|
|
95
|
+
* that was skipped answers with a stand-in naming itself, which is no part
|
|
96
|
+
* of an ARN.
|
|
97
|
+
*/
|
|
98
|
+
deployedValue(read) {
|
|
99
|
+
const { createComplete, skipped, inert } = this.resource;
|
|
100
|
+
if (!createComplete || skipped || inert) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
// A Resource type with no Arn attribute refuses to answer for one, which
|
|
104
|
+
// here only means the ARN has to come from somewhere else.
|
|
105
|
+
try {
|
|
106
|
+
return stringValue(read());
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** The value where it is a string, which is all an ARN can be made of. */
|
|
114
|
+
function stringValue(value) {
|
|
115
|
+
if (typeof value === "string") {
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SimAws } from "../../aws/sim-aws.js";
|
|
1
2
|
import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
|
|
2
3
|
import type { SimCdkOutContext } from "../cdk/sim-cdk-out-context.js";
|
|
3
4
|
/**
|
|
@@ -18,13 +19,17 @@ export interface SimCfnStackUpdateContext {
|
|
|
18
19
|
* values the deployment started with.
|
|
19
20
|
*/
|
|
20
21
|
export declare class SimCfnStackDeployContext {
|
|
22
|
+
/** The simulation the Stack deploys into, which an update never moves. */
|
|
23
|
+
readonly simAws: SimAws;
|
|
21
24
|
/** The CDK cloud assembly the Stack's template was synthesized into. */
|
|
22
25
|
cdkOutContext: SimCdkOutContext | undefined;
|
|
23
26
|
/** The principal the Stack's Resource work is authorized as. */
|
|
24
27
|
caller: SimAwsCaller | undefined;
|
|
25
28
|
/** The principal the Stack's CDK file assets are published as. */
|
|
26
29
|
assetsCaller: SimAwsCaller | undefined;
|
|
27
|
-
constructor(properties: SimCfnStackUpdateContext
|
|
30
|
+
constructor(properties: SimCfnStackUpdateContext & {
|
|
31
|
+
readonly simAws: SimAws;
|
|
32
|
+
});
|
|
28
33
|
/**
|
|
29
34
|
* Take on what an update brings with it, for this and every later operation.
|
|
30
35
|
*
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* values the deployment started with.
|
|
8
8
|
*/
|
|
9
9
|
export class SimCfnStackDeployContext {
|
|
10
|
+
/** The simulation the Stack deploys into, which an update never moves. */
|
|
11
|
+
simAws;
|
|
10
12
|
/** The CDK cloud assembly the Stack's template was synthesized into. */
|
|
11
13
|
cdkOutContext;
|
|
12
14
|
/** The principal the Stack's Resource work is authorized as. */
|
|
@@ -14,6 +16,7 @@ export class SimCfnStackDeployContext {
|
|
|
14
16
|
/** The principal the Stack's CDK file assets are published as. */
|
|
15
17
|
assetsCaller;
|
|
16
18
|
constructor(properties) {
|
|
19
|
+
this.simAws = properties.simAws;
|
|
17
20
|
this.cdkOutContext = properties.cdkOutContext;
|
|
18
21
|
this.caller = properties.caller;
|
|
19
22
|
this.assetsCaller = properties.assetsCaller;
|
|
@@ -4,7 +4,7 @@ import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
|
|
|
4
4
|
import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-scope.js";
|
|
5
5
|
import type { SimCfnBinding } from "../bind/sim-cfn-binding.js";
|
|
6
6
|
import type { SimCdkOutContext } from "../cdk/sim-cdk-out-context.js";
|
|
7
|
-
import { type SimCfnStackUpdateContext } from "./sim-cfn-stack-deploy-context.js";
|
|
7
|
+
import { SimCfnStackDeployContext, type SimCfnStackUpdateContext } from "./sim-cfn-stack-deploy-context.js";
|
|
8
8
|
import type { SimCfnResource } from "../resource/sim-cfn-resource.js";
|
|
9
9
|
import { SimCfnResourceRetention } from "../resource/delete/sim-cfn-resource-retention.js";
|
|
10
10
|
import type { SimCfnTemplate } from "../template/sim-cfn-template.js";
|
|
@@ -53,12 +53,13 @@ interface SimCfnStackResourceOperationsProperties {
|
|
|
53
53
|
* ordering of the work itself.
|
|
54
54
|
*/
|
|
55
55
|
export declare class SimCfnStackResourceOperations {
|
|
56
|
+
/** What the Stack deploys from, into and as. */
|
|
57
|
+
readonly context: SimCfnStackDeployContext;
|
|
56
58
|
private readonly simAws;
|
|
57
59
|
private readonly accountRegionScope;
|
|
58
60
|
private readonly stackName;
|
|
59
61
|
private readonly bindings;
|
|
60
62
|
private readonly resourceOrder;
|
|
61
|
-
private readonly context;
|
|
62
63
|
/**
|
|
63
64
|
* Resources an update kept in simulated AWS.
|
|
64
65
|
*
|
|
@@ -20,12 +20,13 @@ import { SimCfnStackResourceUpdates } from "./update/sim-cfn-stack-resource-upda
|
|
|
20
20
|
* ordering of the work itself.
|
|
21
21
|
*/
|
|
22
22
|
export class SimCfnStackResourceOperations {
|
|
23
|
+
/** What the Stack deploys from, into and as. */
|
|
24
|
+
context;
|
|
23
25
|
simAws;
|
|
24
26
|
accountRegionScope;
|
|
25
27
|
stackName;
|
|
26
28
|
bindings;
|
|
27
29
|
resourceOrder;
|
|
28
|
-
context;
|
|
29
30
|
/**
|
|
30
31
|
* Resources an update kept in simulated AWS.
|
|
31
32
|
*
|
|
@@ -3,6 +3,7 @@ import { makeSimCfnStackResourceMap } from "./resource-map/sim-cfn-stack-resourc
|
|
|
3
3
|
import { SimCfnStackResourceLookup } from "./resource-map/sim-cfn-stack-resource-lookup.js";
|
|
4
4
|
import { SimCfnStackDeploymentLifecycle } from "./deploy/sim-cfn-stack-deployment-lifecycle.js";
|
|
5
5
|
import { SimCfnStackResourceOperations } from "./sim-cfn-stack-resource-operations.js";
|
|
6
|
+
import { SimCfnReadHandlerAuthorizer } from "../registry/sim-cfn-read-handler-authorizer.js";
|
|
6
7
|
import { SimCfnStackUpdateLifecycle } from "./update/sim-cfn-stack-update-lifecycle.js";
|
|
7
8
|
import { SimCfnStackOutputs } from "./output/sim-cfn-stack-outputs.js";
|
|
8
9
|
import { SimCfnStackOutputLookup } from "./output/sim-cfn-stack-output-lookup.js";
|
|
@@ -148,6 +149,14 @@ export class SimCfnStack {
|
|
|
148
149
|
await this.updating.update({
|
|
149
150
|
apply: async () => {
|
|
150
151
|
await updater.apply();
|
|
152
|
+
// Resolving an output reads an untouched Resource through its read
|
|
153
|
+
// handler. A rollback makes no such call, so it has no step here.
|
|
154
|
+
await new SimCfnReadHandlerAuthorizer({
|
|
155
|
+
context: this.operations.context,
|
|
156
|
+
}).authorizeUpdate(updater.plan, {
|
|
157
|
+
updated: template,
|
|
158
|
+
resources: this.resourceMap,
|
|
159
|
+
});
|
|
151
160
|
this.resolveOutputs();
|
|
152
161
|
},
|
|
153
162
|
rollBack: async () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SimCfnResource } from "../../resource/sim-cfn-resource.js";
|
|
2
2
|
import { SimCfnResourceRetention } from "../../resource/delete/sim-cfn-resource-retention.js";
|
|
3
|
+
import type { CfnTemplateBodyRecord } from "../../template/sim-cfn-template.js";
|
|
3
4
|
import { type SimCfnStackInPlaceUpdates } from "./sim-cfn-stack-resource-changes.js";
|
|
4
5
|
import { type SimCfnStackResourceChange } from "./sim-cfn-stack-resource-change-pairs.js";
|
|
5
6
|
interface SimCfnStackUpdatePlanProperties {
|
|
@@ -39,6 +40,11 @@ export declare class SimCfnStackUpdatePlan {
|
|
|
39
40
|
*/
|
|
40
41
|
readonly creations: readonly SimCfnResource[];
|
|
41
42
|
readonly updated: ReadonlyMap<string, SimCfnResource>;
|
|
43
|
+
/**
|
|
44
|
+
* The deployed Resources the new template describes unchanged, which the
|
|
45
|
+
* update leaves where they are.
|
|
46
|
+
*/
|
|
47
|
+
readonly untouched: readonly SimCfnResource[];
|
|
42
48
|
constructor(properties: SimCfnStackUpdatePlanProperties);
|
|
43
49
|
/**
|
|
44
50
|
* What the update's deletions are to leave in simulated AWS.
|
|
@@ -49,6 +55,11 @@ export declare class SimCfnStackUpdatePlan {
|
|
|
49
55
|
* deletes that Resource.
|
|
50
56
|
*/
|
|
51
57
|
retention(): SimCfnResourceRetention;
|
|
58
|
+
/**
|
|
59
|
+
* The untouched Resources whose attributes the template reads, through
|
|
60
|
+
* `Fn::GetAtt` or `Fn::Sub`.
|
|
61
|
+
*/
|
|
62
|
+
untouchedReadBy(template: CfnTemplateBodyRecord): SimCfnResource[];
|
|
52
63
|
/**
|
|
53
64
|
* Whether the update changes any Resource at all.
|
|
54
65
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SimCfnResourceRetention } from "../../resource/delete/sim-cfn-resource-retention.js";
|
|
2
|
+
import { simCfnAttributeReads } from "../../registry/sim-cfn-attribute-reads.js";
|
|
2
3
|
import { simCfnStackResourceChanges, } from "./sim-cfn-stack-resource-changes.js";
|
|
3
4
|
import { simCfnStackResourceChangePairs, } from "./sim-cfn-stack-resource-change-pairs.js";
|
|
4
5
|
/**
|
|
@@ -33,6 +34,11 @@ export class SimCfnStackUpdatePlan {
|
|
|
33
34
|
*/
|
|
34
35
|
creations;
|
|
35
36
|
updated;
|
|
37
|
+
/**
|
|
38
|
+
* The deployed Resources the new template describes unchanged, which the
|
|
39
|
+
* update leaves where they are.
|
|
40
|
+
*/
|
|
41
|
+
untouched;
|
|
36
42
|
constructor(properties) {
|
|
37
43
|
const { current, updated, inPlaceUpdates } = properties;
|
|
38
44
|
const { replaced, updatedInPlace } = simCfnStackResourceChanges({
|
|
@@ -57,6 +63,14 @@ export class SimCfnStackUpdatePlan {
|
|
|
57
63
|
return (!current.has(resource.logicalId) || replaced.has(resource.logicalId));
|
|
58
64
|
})
|
|
59
65
|
.toArray();
|
|
66
|
+
this.untouched = current
|
|
67
|
+
.values()
|
|
68
|
+
.filter(({ logicalId }) => {
|
|
69
|
+
return (updated.has(logicalId) &&
|
|
70
|
+
!replaced.has(logicalId) &&
|
|
71
|
+
!updatedInPlace.has(logicalId));
|
|
72
|
+
})
|
|
73
|
+
.toArray();
|
|
60
74
|
}
|
|
61
75
|
/**
|
|
62
76
|
* What the update's deletions are to leave in simulated AWS.
|
|
@@ -74,6 +88,14 @@ export class SimCfnStackUpdatePlan {
|
|
|
74
88
|
])),
|
|
75
89
|
});
|
|
76
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* The untouched Resources whose attributes the template reads, through
|
|
93
|
+
* `Fn::GetAtt` or `Fn::Sub`.
|
|
94
|
+
*/
|
|
95
|
+
untouchedReadBy(template) {
|
|
96
|
+
const reads = simCfnAttributeReads(template);
|
|
97
|
+
return this.untouched.filter(({ logicalId }) => reads.has(logicalId));
|
|
98
|
+
}
|
|
77
99
|
/**
|
|
78
100
|
* Whether the update changes any Resource at all.
|
|
79
101
|
*
|
|
@@ -3,6 +3,7 @@ import type { SimAwsAccountRegionScope } from "../../../aws/sim-aws-account-regi
|
|
|
3
3
|
import type { SimCfnResource } from "../../resource/sim-cfn-resource.js";
|
|
4
4
|
import type { SimCfnTemplate } from "../../template/sim-cfn-template.js";
|
|
5
5
|
import type { SimCfnStackResourceOperations } from "../sim-cfn-stack-resource-operations.js";
|
|
6
|
+
import { SimCfnStackUpdatePlan } from "./sim-cfn-stack-update-plan.js";
|
|
6
7
|
/**
|
|
7
8
|
* What CloudFormation answers an update that would change nothing.
|
|
8
9
|
*
|
|
@@ -34,8 +35,9 @@ interface SimCfnStackUpdaterProperties {
|
|
|
34
35
|
* SimCfnStackUpdateLifecycle owns the first and SimCfnStack the second.
|
|
35
36
|
*/
|
|
36
37
|
export declare class SimCfnStackUpdater {
|
|
38
|
+
/** What the update does to the Stack's Resources. */
|
|
39
|
+
readonly plan: SimCfnStackUpdatePlan;
|
|
37
40
|
private readonly properties;
|
|
38
|
-
private readonly plan;
|
|
39
41
|
constructor(properties: SimCfnStackUpdaterProperties);
|
|
40
42
|
/**
|
|
41
43
|
* Refuse an update that would do nothing, the way CloudFormation refuses one.
|
|
@@ -25,8 +25,9 @@ export const simCfnNoUpdatesMessage = "No updates are to be performed.";
|
|
|
25
25
|
* SimCfnStackUpdateLifecycle owns the first and SimCfnStack the second.
|
|
26
26
|
*/
|
|
27
27
|
export class SimCfnStackUpdater {
|
|
28
|
-
|
|
28
|
+
/** What the update does to the Stack's Resources. */
|
|
29
29
|
plan;
|
|
30
|
+
properties;
|
|
30
31
|
constructor(properties) {
|
|
31
32
|
const { accountRegionScope, background, resources, updated } = properties;
|
|
32
33
|
this.properties = properties;
|
|
@@ -69,7 +69,7 @@ export class SimCognitoServiceController {
|
|
|
69
69
|
// The web ACL sits in front of the endpoint rather than behind it, so a
|
|
70
70
|
// request it blocks is answered before the method is judged. A write the
|
|
71
71
|
// rules turned away gets WAF's 403 and never learns the endpoint reads.
|
|
72
|
-
const blocked = await this.blocked(pool, segment,
|
|
72
|
+
const blocked = await this.blocked(pool, segment, serviceRequest);
|
|
73
73
|
if (blocked !== undefined) {
|
|
74
74
|
return blocked;
|
|
75
75
|
}
|
|
@@ -90,14 +90,15 @@ export class SimCognitoServiceController {
|
|
|
90
90
|
* A blocked request is answered before the document is read, so a verifier
|
|
91
91
|
* the rules turn away gets 403 and no keys.
|
|
92
92
|
*/
|
|
93
|
-
async blocked(pool, segment,
|
|
93
|
+
async blocked(pool, segment, serviceRequest) {
|
|
94
94
|
if (!simCognitoProtectedSegment(segment)) {
|
|
95
95
|
return undefined;
|
|
96
96
|
}
|
|
97
97
|
const inspected = await this.webAcl.inspect({
|
|
98
98
|
pool,
|
|
99
99
|
cognito: simCognitoPoolScope(this.simAws, pool),
|
|
100
|
-
request,
|
|
100
|
+
request: serviceRequest.request,
|
|
101
|
+
sourceIp: serviceRequest.sourceIp,
|
|
101
102
|
});
|
|
102
103
|
return inspected.blocked;
|
|
103
104
|
}
|
|
@@ -44,6 +44,7 @@ export class SimCognitoDomainController {
|
|
|
44
44
|
pool,
|
|
45
45
|
cognito,
|
|
46
46
|
request: serviceRequest.request,
|
|
47
|
+
sourceIp: serviceRequest.sourceIp,
|
|
47
48
|
});
|
|
48
49
|
if (inspected.blocked !== undefined) {
|
|
49
50
|
return inspected.blocked;
|
|
@@ -95,6 +96,7 @@ function forwarded(serviceRequest, request) {
|
|
|
95
96
|
request,
|
|
96
97
|
caller: serviceRequest.caller,
|
|
97
98
|
source: serviceRequest.source,
|
|
99
|
+
sourceIp: serviceRequest.sourceIp,
|
|
98
100
|
body: serviceRequest.body,
|
|
99
101
|
});
|
|
100
102
|
}
|
|
@@ -6,6 +6,8 @@ interface SimCognitoInspectionInput {
|
|
|
6
6
|
/** The simulated Cognito scope the pool belongs to. */
|
|
7
7
|
readonly cognito: SimCognitoIdentityProvider;
|
|
8
8
|
readonly request: Request;
|
|
9
|
+
/** The client address the request came from. */
|
|
10
|
+
readonly sourceIp: string;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* Puts a request to the web ACL in front of the pool it reached.
|
|
@@ -9,4 +9,5 @@ export type { SimIamSigV4ExpectedScope } from "./sigv4/sim-iam-sigv4-expected-sc
|
|
|
9
9
|
export { simAwsCallerHeaderName, simAwsCallerHeaderPrincipal, simAwsCallerHeaderValue, } from "./request/sim-aws-caller-header.js";
|
|
10
10
|
export { type SimAwsRequestAuthMethod, SimAwsRequestCaller, } from "./request/sim-aws-request-caller.js";
|
|
11
11
|
export { SimAwsRequestSource, simAwsSourceAccountHeaderName, simAwsSourceArnHeaderName, } from "./request/sim-aws-request-source.js";
|
|
12
|
+
export { simAwsRequestSourceIp, simAwsSourceIpHeaderName, } from "./request/sim-aws-source-ip-header.js";
|
|
12
13
|
export { isSimAwsRequestAuthFailure, SimAwsInvalidCallerHeader, type SimAwsRequestAuthFailure, } from "./request/error/sim-aws-request-auth.error.js";
|
|
@@ -4,4 +4,5 @@ export { SimIamCredentialScopeMismatch, SimIamExpiredToken, SimIamIncompleteSign
|
|
|
4
4
|
export { simAwsCallerHeaderName, simAwsCallerHeaderPrincipal, simAwsCallerHeaderValue, } from "./request/sim-aws-caller-header.js";
|
|
5
5
|
export { SimAwsRequestCaller, } from "./request/sim-aws-request-caller.js";
|
|
6
6
|
export { SimAwsRequestSource, simAwsSourceAccountHeaderName, simAwsSourceArnHeaderName, } from "./request/sim-aws-request-source.js";
|
|
7
|
+
export { simAwsRequestSourceIp, simAwsSourceIpHeaderName, } from "./request/sim-aws-source-ip-header.js";
|
|
7
8
|
export { isSimAwsRequestAuthFailure, SimAwsInvalidCallerHeader, } from "./request/error/sim-aws-request-auth.error.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SimIamSigV4Error } from "../../sigv4/error/sim-iam-sigv4.error.js";
|
|
2
2
|
/**
|
|
3
3
|
* Raised when the `x-sim-aws-caller` header does not name a principal the
|
|
4
|
-
* simulator understands.
|
|
4
|
+
* simulator understands, or `x-sim-aws-source-ip` names no address.
|
|
5
5
|
*
|
|
6
6
|
* This is a simulator control header rather than anything real AWS defines, so
|
|
7
7
|
* a bad value is the caller's mistake in using Yulin, not a failed AWS
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SimIamSigV4Error } from "../../sigv4/error/sim-iam-sigv4.error.js";
|
|
2
2
|
/**
|
|
3
3
|
* Raised when the `x-sim-aws-caller` header does not name a principal the
|
|
4
|
-
* simulator understands.
|
|
4
|
+
* simulator understands, or `x-sim-aws-source-ip` names no address.
|
|
5
5
|
*
|
|
6
6
|
* This is a simulator control header rather than anything real AWS defines, so
|
|
7
7
|
* a bad value is the caller's mistake in using Yulin, not a failed AWS
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Header names that are instructions to the simulator rather than part of the
|
|
3
3
|
* request being simulated.
|
|
4
4
|
*
|
|
5
|
-
* They state who a request is from and what it is for, so
|
|
5
|
+
* They state who a request is from, where it came from and what it is for, so
|
|
6
|
+
* anything passing a
|
|
6
7
|
* request on to a simulated service has to decide what to do with them rather
|
|
7
8
|
* than forward them by accident: the HTTP boundary strips them once the
|
|
8
9
|
* request has been attributed, and sim CloudFront strips a viewer's before
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { simAwsCallerHeaderName } from "./sim-aws-caller-header.js";
|
|
2
|
+
import { simAwsSourceIpHeaderName } from "./sim-aws-source-ip-header.js";
|
|
2
3
|
import { simAwsSourceAccountHeaderName, simAwsSourceArnHeaderName, } from "./sim-aws-request-source.js";
|
|
3
4
|
/**
|
|
4
5
|
* Header names that are instructions to the simulator rather than part of the
|
|
5
6
|
* request being simulated.
|
|
6
7
|
*
|
|
7
|
-
* They state who a request is from and what it is for, so
|
|
8
|
+
* They state who a request is from, where it came from and what it is for, so
|
|
9
|
+
* anything passing a
|
|
8
10
|
* request on to a simulated service has to decide what to do with them rather
|
|
9
11
|
* than forward them by accident: the HTTP boundary strips them once the
|
|
10
12
|
* request has been attributed, and sim CloudFront strips a viewer's before
|
|
@@ -14,6 +16,7 @@ export const simAwsControlHeaderNames = [
|
|
|
14
16
|
simAwsCallerHeaderName,
|
|
15
17
|
simAwsSourceArnHeaderName,
|
|
16
18
|
simAwsSourceAccountHeaderName,
|
|
19
|
+
simAwsSourceIpHeaderName,
|
|
17
20
|
];
|
|
18
21
|
/**
|
|
19
22
|
* Remove the simulator's control headers from a set of request headers.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The header naming the client address a request into simulated AWS comes
|
|
3
|
+
* from.
|
|
4
|
+
*
|
|
5
|
+
* A request arrives in process or over loopback, so there is no remote address
|
|
6
|
+
* for the simulation to read. Whatever decides by where a request came from,
|
|
7
|
+
* such as a web ACL's IP reputation and anonymous IP rules, reads this instead,
|
|
8
|
+
* and a test sends it to say which client a request stands for.
|
|
9
|
+
*/
|
|
10
|
+
export declare const simAwsSourceIpHeaderName = "x-sim-aws-source-ip";
|
|
11
|
+
/**
|
|
12
|
+
* Read the client address a request states, or the loopback address when it
|
|
13
|
+
* states none.
|
|
14
|
+
*
|
|
15
|
+
* The header holds one IPv4 or IPv6 address. A value that is neither is
|
|
16
|
+
* refused rather than read as loopback, since a test that misspelt an address
|
|
17
|
+
* would otherwise pass for the wrong reason.
|
|
18
|
+
*/
|
|
19
|
+
export declare function simAwsRequestSourceIp(headers: Headers): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { simAwsProxiedSourceIp } from "../../../serve/http/sim-aws-proxied-connection.js";
|
|
3
|
+
import { SimAwsInvalidCallerHeader } from "./error/sim-aws-request-auth.error.js";
|
|
4
|
+
/**
|
|
5
|
+
* The header naming the client address a request into simulated AWS comes
|
|
6
|
+
* from.
|
|
7
|
+
*
|
|
8
|
+
* A request arrives in process or over loopback, so there is no remote address
|
|
9
|
+
* for the simulation to read. Whatever decides by where a request came from,
|
|
10
|
+
* such as a web ACL's IP reputation and anonymous IP rules, reads this instead,
|
|
11
|
+
* and a test sends it to say which client a request stands for.
|
|
12
|
+
*/
|
|
13
|
+
export const simAwsSourceIpHeaderName = "x-sim-aws-source-ip";
|
|
14
|
+
/**
|
|
15
|
+
* Read the client address a request states, or the loopback address when it
|
|
16
|
+
* states none.
|
|
17
|
+
*
|
|
18
|
+
* The header holds one IPv4 or IPv6 address. A value that is neither is
|
|
19
|
+
* refused rather than read as loopback, since a test that misspelt an address
|
|
20
|
+
* would otherwise pass for the wrong reason.
|
|
21
|
+
*/
|
|
22
|
+
export function simAwsRequestSourceIp(headers) {
|
|
23
|
+
const value = headers.get(simAwsSourceIpHeaderName)?.trim();
|
|
24
|
+
if (value === undefined || value === "") {
|
|
25
|
+
return simAwsProxiedSourceIp;
|
|
26
|
+
}
|
|
27
|
+
if (isIP(value) === 0) {
|
|
28
|
+
throw new SimAwsInvalidCallerHeader(`${simAwsSourceIpHeaderName} value ${value} must be one IPv4 or IPv6 ` +
|
|
29
|
+
`address`);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
@@ -14,6 +14,7 @@ export async function runSimStatesTask(state, input, context) {
|
|
|
14
14
|
target: state.target,
|
|
15
15
|
payload: simStatesEffectiveInput(input, state, context.contextObject),
|
|
16
16
|
roleArn: context.roleArn,
|
|
17
|
+
stateMachineArn: context.stateMachineArn,
|
|
17
18
|
});
|
|
18
19
|
const output = simStatesEffectiveOutput(input, result, state, context.contextObject);
|
|
19
20
|
return state.Next === undefined
|
|
@@ -71,6 +71,7 @@ export interface SimStatesWalkContext {
|
|
|
71
71
|
* The state machine's execution role, which a task assumes.
|
|
72
72
|
*/
|
|
73
73
|
readonly roleArn: string;
|
|
74
|
+
readonly stateMachineArn: string;
|
|
74
75
|
/**
|
|
75
76
|
* What the walk is recording itself on, which a `Parallel` state's branch
|
|
76
77
|
* hangs off.
|
|
@@ -11,6 +11,7 @@ interface SimStatesWalksProperties {
|
|
|
11
11
|
* The state machine's execution role, which a task assumes.
|
|
12
12
|
*/
|
|
13
13
|
readonly roleArn: string;
|
|
14
|
+
readonly stateMachineArn: string;
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
17
|
* How one execution walks a set of states, its `Parallel` branches included.
|
|
@@ -16,6 +16,7 @@ export function simStatesWalks(properties) {
|
|
|
16
16
|
contextObject: child.contextObject,
|
|
17
17
|
tasks: properties.tasks,
|
|
18
18
|
roleArn: properties.roleArn,
|
|
19
|
+
stateMachineArn: properties.stateMachineArn,
|
|
19
20
|
walkChild: walks,
|
|
20
21
|
},
|
|
21
22
|
...(child.onSettled !== undefined && { onSettled: child.onSettled }),
|
|
@@ -30,7 +30,12 @@ export class SimAwsStatesTaskTargets {
|
|
|
30
30
|
const { stateName, target } = invocation;
|
|
31
31
|
const role = simStatesExecutionRoleTarget(invocation.roleArn, stateName);
|
|
32
32
|
const roleScope = this.#simAws.accountRegionScope(role.accountId, this.#accountRegionScope.regionName);
|
|
33
|
-
|
|
33
|
+
// Step Functions supplies the state machine as the trust policy source.
|
|
34
|
+
// https://docs.aws.amazon.com/step-functions/latest/dg/procedure-create-iam-role.html
|
|
35
|
+
const caller = await assumeSimStatesExecutionRole(role, roleScope, {
|
|
36
|
+
arn: invocation.stateMachineArn,
|
|
37
|
+
accountId: this.#accountRegionScope.accountId,
|
|
38
|
+
});
|
|
34
39
|
return await target.run({
|
|
35
40
|
stateName,
|
|
36
41
|
payload: invocation.payload,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
|
|
2
2
|
import type { SimAwsAccountRegionContainer } from "../../aws/sim-aws-account-region-scope.js";
|
|
3
3
|
import { type SimServiceRoleTarget } from "../../sts/service-role/sim-service-role-target.js";
|
|
4
|
+
import type { SimServiceRoleSource } from "../../sts/service-role/sim-service-role-source.js";
|
|
4
5
|
/**
|
|
5
6
|
* The service principal a state machine's execution role trusts.
|
|
6
7
|
*/
|
|
@@ -21,4 +22,4 @@ export declare function simStatesExecutionRoleTarget(roleArn: string, stateName:
|
|
|
21
22
|
* rule, which reaches a function as a service principal and is admitted by the
|
|
22
23
|
* function's resource policy.
|
|
23
24
|
*/
|
|
24
|
-
export declare function assumeSimStatesExecutionRole(target: SimServiceRoleTarget, scope: SimAwsAccountRegionContainer): Promise<SimAwsCaller>;
|
|
25
|
+
export declare function assumeSimStatesExecutionRole(target: SimServiceRoleTarget, scope: SimAwsAccountRegionContainer, source: SimServiceRoleSource): Promise<SimAwsCaller>;
|