@kensio/yulin 1.21.23 → 1.21.25
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/dynamodb/command/authorize/sim-dynamodb-authorizer.d.ts +19 -1
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-authorizer.js +21 -3
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-reached.d.ts +6 -3
- package/dist/service/dynamodb/command/query/sim-dynamodb-query.js +3 -1
- package/dist/service/dynamodb/command/scan/sim-dynamodb-scan.js +3 -1
- package/dist/service/dynamodb/command/table/sim-dynamodb-table-reach.d.ts +4 -0
- package/dist/service/dynamodb/command/table/sim-dynamodb-table-reach.js +1 -0
- package/dist/service/dynamodb/table/sim-dynamodb-table-arn.d.ts +13 -0
- package/dist/service/dynamodb/table/sim-dynamodb-table-arn.js +20 -0
- package/dist/service/wafv2/association/sim-aws-waf-protected-resources.js +4 -0
- package/dist/service/wafv2/association/sim-waf-associations.d.ts +6 -0
- package/dist/service/wafv2/association/sim-waf-associations.js +17 -0
- package/dist/service/wafv2/association/sim-waf-protected-resource.d.ts +13 -8
- package/dist/service/wafv2/association/sim-waf-protected-resource.js +23 -23
- package/dist/service/wafv2/association/sim-waf-protected-resources.d.ts +11 -6
- package/dist/service/wafv2/association/sim-waf-protected-resources.js +10 -7
- package/dist/service/wafv2/association/sim-waf-unsimulated-resource.d.ts +33 -0
- package/dist/service/wafv2/association/sim-waf-unsimulated-resource.js +66 -0
- package/dist/service/wafv2/cfn/association/sim-cfn-waf-association-creator.js +5 -0
- package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-config.js +1 -0
- package/dist/service/wafv2/cfn/ip-set/sim-cfn-waf-ip-set-creator.js +2 -0
- package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-config.js +1 -0
- package/dist/service/wafv2/cfn/regex-pattern-set/sim-cfn-waf-regex-set-creator.js +2 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.d.ts +4 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-resource-config.js +10 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.d.ts +10 -0
- package/dist/service/wafv2/cfn/sim-cfn-waf-unsimulated.js +12 -0
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.d.ts +1 -13
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-config.js +8 -21
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.d.ts +4 -9
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-web-acl-creator.js +7 -15
- package/dist/service/wafv2/command/association/sim-wafv2-association-commands.js +2 -1
- package/dist/service/wafv2/command/association/sim-wafv2-association-input.d.ts +10 -2
- package/dist/service/wafv2/command/association/sim-wafv2-association-input.js +25 -13
- package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.d.ts +3 -3
- package/dist/service/wafv2/command/ip-set/sim-wafv2-ip-set-commands.js +5 -5
- package/dist/service/wafv2/command/managed-rule-group/sim-wafv2-managed-rule-group-commands.js +4 -4
- package/dist/service/wafv2/command/regex-pattern-set/sim-wafv2-regex-pattern-set-commands.js +2 -2
- package/dist/service/wafv2/command/sim-wafv2-input.d.ts +0 -7
- package/dist/service/wafv2/command/sim-wafv2-input.js +1 -13
- package/dist/service/wafv2/command/web-acl/sim-waf-web-acl-output.js +1 -0
- package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.d.ts +9 -12
- package/dist/service/wafv2/command/web-acl/sim-wafv2-unsimulated-web-acl-input.js +27 -28
- package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.d.ts +3 -3
- package/dist/service/wafv2/command/web-acl/sim-wafv2-web-acl-commands.js +6 -6
- package/dist/service/wafv2/command/web-acl/web-acl.command.d.ts +6 -0
- package/dist/service/wafv2/index.d.ts +3 -0
- package/dist/service/wafv2/index.js +1 -0
- package/dist/service/wafv2/managed/group/sim-waf-bot-control.d.ts +27 -0
- package/dist/service/wafv2/managed/group/sim-waf-bot-control.js +68 -0
- package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.d.ts +18 -0
- package/dist/service/wafv2/managed/group/sim-waf-ip-reputation.js +51 -0
- package/dist/service/wafv2/managed/sim-waf-bot-declaration.d.ts +35 -0
- package/dist/service/wafv2/managed/sim-waf-bot-declaration.js +42 -0
- package/dist/service/wafv2/managed/sim-waf-managed-declaration.d.ts +35 -0
- package/dist/service/wafv2/managed/sim-waf-managed-declaration.js +30 -0
- package/dist/service/wafv2/managed/sim-waf-managed-group-configs.d.ts +11 -0
- package/dist/service/wafv2/managed/sim-waf-managed-group-configs.js +42 -0
- package/dist/service/wafv2/managed/sim-waf-managed-group-input.d.ts +5 -4
- package/dist/service/wafv2/managed/sim-waf-managed-group-input.js +7 -9
- package/dist/service/wafv2/managed/sim-waf-managed-group-statement.js +16 -14
- package/dist/service/wafv2/managed/sim-waf-managed-group.type.d.ts +2 -2
- package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.d.ts +30 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule-actions.js +26 -0
- package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.d.ts +5 -3
- package/dist/service/wafv2/managed/sim-waf-managed-rule-groups.js +10 -3
- package/dist/service/wafv2/managed/sim-waf-managed-rule.type.d.ts +11 -2
- package/dist/service/wafv2/managed/sim-waf-managed-rules.d.ts +14 -9
- package/dist/service/wafv2/managed/sim-waf-managed-rules.js +15 -5
- package/dist/service/wafv2/resource/sim-waf-resource.d.ts +10 -0
- package/dist/service/wafv2/resource/sim-waf-resource.js +12 -0
- package/dist/service/wafv2/resource/sim-waf-unsimulated-part.d.ts +24 -0
- package/dist/service/wafv2/resource/sim-waf-unsimulated-part.js +8 -0
- package/dist/service/wafv2/sim-wafv2.d.ts +12 -12
- package/dist/service/wafv2/sim-wafv2.fixture.d.ts +19 -1
- package/dist/service/wafv2/sim-wafv2.fixture.js +29 -0
- package/dist/service/wafv2/sim-wafv2.js +25 -23
- package/dist/service/wafv2/statement/sim-waf-field-to-match.type.d.ts +2 -2
- package/dist/service/wafv2/statement/sim-waf-rule-refusals.d.ts +6 -4
- package/dist/service/wafv2/statement/sim-waf-rule-refusals.js +7 -6
- package/dist/service/wafv2/statement/sim-waf-statement.d.ts +3 -3
- package/dist/service/wafv2/statement/sim-waf-statement.js +3 -3
- package/dist/service/wafv2/statement/sim-waf-statement.type.d.ts +3 -3
- package/dist/service/wafv2/statement/sim-waf-unsimulated-statement.js +1 -1
- package/dist/service/wafv2/web-acl/sim-waf-association-config.d.ts +14 -7
- package/dist/service/wafv2/web-acl/sim-waf-association-config.js +17 -27
- package/dist/service/wafv2/web-acl/sim-waf-rule.d.ts +15 -3
- package/dist/service/wafv2/web-acl/sim-waf-rule.js +46 -10
- package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.d.ts +4 -4
- package/dist/service/wafv2/web-acl/sim-waf-statement-capacity.js +4 -4
- package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.d.ts +6 -0
- package/dist/service/wafv2/web-acl/sim-waf-unsimulated-body-limit.js +23 -0
- package/dist/service/wafv2/web-acl/sim-waf-web-acl-capacity.js +2 -2
- package/dist/service/wafv2/web-acl/sim-waf-web-acl-configuration.d.ts +5 -0
- package/dist/service/wafv2/web-acl/sim-waf-web-acl.d.ts +11 -2
- package/dist/service/wafv2/web-acl/sim-waf-web-acl.js +20 -1
- package/docs/services/dynamodb/README.md +26 -0
- package/docs/services/wafv2/README.md +243 -51
- package/package.json +3 -3
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.d.ts +0 -15
- package/dist/service/wafv2/cfn/web-acl/sim-cfn-waf-evaluatable-rules.js +0 -21
- package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.d.ts +0 -25
- package/dist/service/wafv2/web-acl/sim-waf-unevaluatable-rules.js +0 -33
|
@@ -12,7 +12,8 @@ interface SimDynamoDbAuthorizerProperties {
|
|
|
12
12
|
*
|
|
13
13
|
* AWS maps each DynamoDB API operation to the `dynamodb:` action of the same
|
|
14
14
|
* name, and the resource is the ARN of the table the operation names. ListTables
|
|
15
|
-
* is the exception: it names no table, so it authorizes against `*`.
|
|
15
|
+
* is the exception: it names no table, so it authorizes against `*`. A Query or
|
|
16
|
+
* Scan naming an `IndexName` authorizes against the index's own ARN.
|
|
16
17
|
*/
|
|
17
18
|
export declare class SimDynamoDbAuthorizer {
|
|
18
19
|
private readonly iam;
|
|
@@ -29,6 +30,23 @@ export declare class SimDynamoDbAuthorizer {
|
|
|
29
30
|
* The caller is passed through unchanged so sim IAM can distinguish an
|
|
30
31
|
* omitted caller, which defaults to Account root, from an explicit anonymous
|
|
31
32
|
* caller.
|
|
33
|
+
*
|
|
34
|
+
* A request reaching one of the table's indexes is authorized against the
|
|
35
|
+
* index's ARN. The service authorization reference for DynamoDB gives Query and Scan two
|
|
36
|
+
* resource types, `table` and `index`. The `index` ARN is the table's with
|
|
37
|
+
* `/index/<name>` after it. The developer guide's fine-grained access control
|
|
38
|
+
* page grants index queries on that ARN (its examples 5 and 6). A read naming
|
|
39
|
+
* an index is authorized against the index ARN alone. A statement naming only
|
|
40
|
+
* the table refuses it, and one naming only an index does not reach the
|
|
41
|
+
* table. CDK's `grantReadData` adds `<table ARN>/index/*` only for a table it
|
|
42
|
+
* knows has indexes, and a grant on a table imported by name covers none.
|
|
43
|
+
*
|
|
44
|
+
* The reference also lists `index` for PartiQLSelect, SearchVectors and the
|
|
45
|
+
* contributor insights actions, none of which are simulated. DescribeTable
|
|
46
|
+
* and the item actions take `table` only.
|
|
47
|
+
*
|
|
48
|
+
* The condition keys are the ones the action supplies on the table, with
|
|
49
|
+
* the partition key values read through the index's own key schema.
|
|
32
50
|
*/
|
|
33
51
|
authorizeTable(action: string, tableName: string, caller?: SimAwsCaller, reached?: SimDynamoDbReached): SimAwsResolvedCaller;
|
|
34
52
|
/**
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { SimIamAccessDenied } from "../../../iam/error/sim-iam.error.js";
|
|
2
|
-
import {
|
|
2
|
+
import { simDynamoDbReadArn } from "../../table/sim-dynamodb-table-arn.js";
|
|
3
3
|
import { simDynamoDbConditionContextOf } from "./sim-dynamodb-reached.js";
|
|
4
4
|
/**
|
|
5
5
|
* Applies simulated IAM authorization to DynamoDB requests.
|
|
6
6
|
*
|
|
7
7
|
* AWS maps each DynamoDB API operation to the `dynamodb:` action of the same
|
|
8
8
|
* name, and the resource is the ARN of the table the operation names. ListTables
|
|
9
|
-
* is the exception: it names no table, so it authorizes against `*`.
|
|
9
|
+
* is the exception: it names no table, so it authorizes against `*`. A Query or
|
|
10
|
+
* Scan naming an `IndexName` authorizes against the index's own ARN.
|
|
10
11
|
*/
|
|
11
12
|
export class SimDynamoDbAuthorizer {
|
|
12
13
|
iam;
|
|
@@ -26,9 +27,26 @@ export class SimDynamoDbAuthorizer {
|
|
|
26
27
|
* The caller is passed through unchanged so sim IAM can distinguish an
|
|
27
28
|
* omitted caller, which defaults to Account root, from an explicit anonymous
|
|
28
29
|
* caller.
|
|
30
|
+
*
|
|
31
|
+
* A request reaching one of the table's indexes is authorized against the
|
|
32
|
+
* index's ARN. The service authorization reference for DynamoDB gives Query and Scan two
|
|
33
|
+
* resource types, `table` and `index`. The `index` ARN is the table's with
|
|
34
|
+
* `/index/<name>` after it. The developer guide's fine-grained access control
|
|
35
|
+
* page grants index queries on that ARN (its examples 5 and 6). A read naming
|
|
36
|
+
* an index is authorized against the index ARN alone. A statement naming only
|
|
37
|
+
* the table refuses it, and one naming only an index does not reach the
|
|
38
|
+
* table. CDK's `grantReadData` adds `<table ARN>/index/*` only for a table it
|
|
39
|
+
* knows has indexes, and a grant on a table imported by name covers none.
|
|
40
|
+
*
|
|
41
|
+
* The reference also lists `index` for PartiQLSelect, SearchVectors and the
|
|
42
|
+
* contributor insights actions, none of which are simulated. DescribeTable
|
|
43
|
+
* and the item actions take `table` only.
|
|
44
|
+
*
|
|
45
|
+
* The condition keys are the ones the action supplies on the table, with
|
|
46
|
+
* the partition key values read through the index's own key schema.
|
|
29
47
|
*/
|
|
30
48
|
authorizeTable(action, tableName, caller, reached = {}) {
|
|
31
|
-
return this.authorizeResource(action,
|
|
49
|
+
return this.authorizeResource(action, simDynamoDbReadArn(this.accountRegionScope, tableName, reached.indexName), caller, reached);
|
|
32
50
|
}
|
|
33
51
|
/**
|
|
34
52
|
* Ensure the caller may perform an action on a table's stream.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What one request reaches in the table it names.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* under one of them leaves it out,
|
|
6
|
-
* that reaches nothing it names.
|
|
4
|
+
* The partition key values and attribute names each become a DynamoDB
|
|
5
|
+
* condition key. A request reaching nothing under one of them leaves it out,
|
|
6
|
+
* as AWS leaves a key out for an operation that reaches nothing it names. The
|
|
7
|
+
* index name decides the resource authorized.
|
|
7
8
|
*/
|
|
8
9
|
export interface SimDynamoDbReached {
|
|
10
|
+
/** The index the request reads, when it names one. */
|
|
11
|
+
readonly indexName?: string | undefined;
|
|
9
12
|
/** The partition key values the request reaches. */
|
|
10
13
|
readonly leadingKeys?: readonly string[] | undefined;
|
|
11
14
|
/** The top-level attribute names the request names. */
|
|
@@ -33,11 +33,13 @@ export class SimDynamoDbQuery {
|
|
|
33
33
|
const expressions = readSimDynamoDbQueryExpressions(input);
|
|
34
34
|
// The one partition key the query reads is what authorization needs, and
|
|
35
35
|
// reading it needs the view rather than the table, so it is read again
|
|
36
|
-
// here against whichever of the two the request names.
|
|
36
|
+
// here against whichever of the two the request names. A query naming an
|
|
37
|
+
// index is authorized against the index's own ARN.
|
|
37
38
|
const table = this.access.required("dynamodb:Query", input.TableName, options?.caller, {
|
|
38
39
|
leadingKeys: (reached) => simDynamoDbLeadingKeyOf(expressions.terms.forTable(reached.view(input.IndexName))
|
|
39
40
|
.partitionKeyValue),
|
|
40
41
|
attributes: expressions.attributes,
|
|
42
|
+
indexName: input.IndexName,
|
|
41
43
|
});
|
|
42
44
|
// What is being read is settled here: the table, or one of its indexes. An
|
|
43
45
|
// IndexName the table does not have is refused rather than read as the
|
|
@@ -37,9 +37,11 @@ export class SimDynamoDbScan {
|
|
|
37
37
|
// input DynamoDB would refuse is refused whether or not the table is
|
|
38
38
|
// there. A scan narrows nothing, so unlike a query its filter may name any
|
|
39
39
|
// attribute, including a key attribute, and needs no key schema to check.
|
|
40
|
+
// A scan naming an index of either kind is authorized against the index's
|
|
41
|
+
// own ARN.
|
|
40
42
|
const segment = readSimDynamoDbScanSegment(input);
|
|
41
43
|
const expressions = readSimDynamoDbScanExpressions(input);
|
|
42
|
-
const table = this.access.required("dynamodb:Scan", input.TableName, options?.caller, { attributes: expressions.attributes });
|
|
44
|
+
const table = this.access.required("dynamodb:Scan", input.TableName, options?.caller, { attributes: expressions.attributes, indexName: input.IndexName });
|
|
43
45
|
// What is being read is settled here: the table, or one of its indexes.
|
|
44
46
|
const view = table.view(input.IndexName);
|
|
45
47
|
const scan = view.scan();
|
|
@@ -8,10 +8,14 @@ import type { SimDynamoDbTable } from "../../table/sim-dynamodb-table.js";
|
|
|
8
8
|
* The partition key values need the table to read them, so they arrive as a
|
|
9
9
|
* function of it. The attribute names are read from the request's own
|
|
10
10
|
* parameters before the table is reached, so they arrive as they are.
|
|
11
|
+
*
|
|
12
|
+
* A read naming one of the table's indexes carries the index name. The index
|
|
13
|
+
* is then the resource authorized.
|
|
11
14
|
*/
|
|
12
15
|
export interface SimDynamoDbTableReach {
|
|
13
16
|
readonly leadingKeys?: SimDynamoDbLeadingKeys | undefined;
|
|
14
17
|
readonly attributes?: readonly string[] | undefined;
|
|
18
|
+
readonly indexName?: string | undefined;
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
17
21
|
* Resolve what a request reaches against the table it named.
|
|
@@ -7,3 +7,16 @@ import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-
|
|
|
7
7
|
* about to have, as real IAM does before the service handles the request.
|
|
8
8
|
*/
|
|
9
9
|
export declare function simDynamoDbTableArn(accountRegionScope: SimAwsAccountRegionScope, tableName: string): SimArn;
|
|
10
|
+
/**
|
|
11
|
+
* The ARN an index of a table has in an Account and Region.
|
|
12
|
+
*
|
|
13
|
+
* It is the table's ARN with `/index/` and the index name after it, the form
|
|
14
|
+
* the service authorization reference gives the `index` resource type. Like
|
|
15
|
+
* the table, the index need not exist.
|
|
16
|
+
*/
|
|
17
|
+
export declare function simDynamoDbIndexArn(accountRegionScope: SimAwsAccountRegionScope, tableName: string, indexName: string): SimArn;
|
|
18
|
+
/**
|
|
19
|
+
* The ARN a read is authorized against: the table's, or the index's when the
|
|
20
|
+
* read names one.
|
|
21
|
+
*/
|
|
22
|
+
export declare function simDynamoDbReadArn(accountRegionScope: SimAwsAccountRegionScope, tableName: string, indexName: string | undefined): SimArn;
|
|
@@ -7,3 +7,23 @@
|
|
|
7
7
|
export function simDynamoDbTableArn(accountRegionScope, tableName) {
|
|
8
8
|
return `arn:aws:dynamodb:${accountRegionScope.regionName}:${accountRegionScope.accountId}:table/${tableName}`;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* The ARN an index of a table has in an Account and Region.
|
|
12
|
+
*
|
|
13
|
+
* It is the table's ARN with `/index/` and the index name after it, the form
|
|
14
|
+
* the service authorization reference gives the `index` resource type. Like
|
|
15
|
+
* the table, the index need not exist.
|
|
16
|
+
*/
|
|
17
|
+
export function simDynamoDbIndexArn(accountRegionScope, tableName, indexName) {
|
|
18
|
+
return `${simDynamoDbTableArn(accountRegionScope, tableName)}/index/${indexName}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The ARN a read is authorized against: the table's, or the index's when the
|
|
22
|
+
* read names one.
|
|
23
|
+
*/
|
|
24
|
+
export function simDynamoDbReadArn(accountRegionScope, tableName, indexName) {
|
|
25
|
+
if (indexName === undefined) {
|
|
26
|
+
return simDynamoDbTableArn(accountRegionScope, tableName);
|
|
27
|
+
}
|
|
28
|
+
return simDynamoDbIndexArn(accountRegionScope, tableName, indexName);
|
|
29
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
|
|
1
2
|
/**
|
|
2
3
|
* The resources of one simulated AWS instance a web ACL can be put in front
|
|
3
4
|
* of.
|
|
@@ -19,6 +20,9 @@ export class SimAwsWafProtectedResources {
|
|
|
19
20
|
* Whether the resource an ARN names is one this scope holds.
|
|
20
21
|
*/
|
|
21
22
|
has(resource) {
|
|
23
|
+
if (resource instanceof SimWafUnsimulatedResource) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
22
26
|
if (resource.resourceType === "COGNITO_USER_POOL") {
|
|
23
27
|
return this.hasUserPool(resource);
|
|
24
28
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SimWafDecision } from "../evaluate/sim-waf-decision.js";
|
|
2
|
+
import type { SimWafUnsimulatedPart } from "../resource/sim-waf-unsimulated-part.js";
|
|
2
3
|
import type { SimWafWebAcl } from "../web-acl/sim-waf-web-acl.js";
|
|
3
4
|
import type { SimWafProtectedResource, SimWafProtectedResourceType } from "./sim-waf-protected-resource.js";
|
|
4
5
|
import type { SimWafProtectedRequest, SimWafProtection } from "./sim-waf-protection.js";
|
|
@@ -32,6 +33,11 @@ export declare class SimWafAssociations implements SimWafProtection {
|
|
|
32
33
|
* is what `DeleteWebACL` asks for when it refuses a web ACL still in use.
|
|
33
34
|
*/
|
|
34
35
|
resourceArnsFor(webAcl: SimWafWebAcl, resourceType?: SimWafProtectedResourceType): readonly string[];
|
|
36
|
+
/**
|
|
37
|
+
* The associations of one web ACL that nothing is evaluated through, one
|
|
38
|
+
* part per resource ARN.
|
|
39
|
+
*/
|
|
40
|
+
unsimulatedFor(webAcl: SimWafWebAcl): readonly SimWafUnsimulatedPart[];
|
|
35
41
|
/**
|
|
36
42
|
* Whether a web ACL is in front of one resource.
|
|
37
43
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { simWafInspectedRequest } from "../evaluate/sim-waf-inspected-request.js";
|
|
2
|
+
import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
|
|
2
3
|
/**
|
|
3
4
|
* The web ACLs one Account and Region has in front of things.
|
|
4
5
|
*
|
|
@@ -19,6 +20,9 @@ export class SimWafAssociations {
|
|
|
19
20
|
this.#associations.set(resource.arn, {
|
|
20
21
|
webAcl,
|
|
21
22
|
resourceType: resource.resourceType,
|
|
23
|
+
unsimulatedReason: resource instanceof SimWafUnsimulatedResource
|
|
24
|
+
? resource.reason
|
|
25
|
+
: undefined,
|
|
22
26
|
});
|
|
23
27
|
}
|
|
24
28
|
/**
|
|
@@ -44,6 +48,19 @@ export class SimWafAssociations {
|
|
|
44
48
|
.map(([resourceArn]) => resourceArn)
|
|
45
49
|
.toArray();
|
|
46
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* The associations of one web ACL that nothing is evaluated through, one
|
|
53
|
+
* part per resource ARN.
|
|
54
|
+
*/
|
|
55
|
+
unsimulatedFor(webAcl) {
|
|
56
|
+
return this.#associations
|
|
57
|
+
.entries()
|
|
58
|
+
.filter(([, association]) => association.webAcl === webAcl)
|
|
59
|
+
.flatMap(([resourceArn, { unsimulatedReason }]) => unsimulatedReason === undefined
|
|
60
|
+
? []
|
|
61
|
+
: [{ part: `Association.${resourceArn}`, reason: unsimulatedReason }])
|
|
62
|
+
.toArray();
|
|
63
|
+
}
|
|
47
64
|
/**
|
|
48
65
|
* Whether a web ACL is in front of one resource.
|
|
49
66
|
*/
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { SimWafRestApiStage } from "./sim-waf-rest-api-stage.js";
|
|
2
|
+
import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
|
|
2
3
|
import { SimWafUserPool } from "./sim-waf-user-pool.js";
|
|
3
4
|
/**
|
|
4
5
|
* A resource a `REGIONAL` web ACL can be put in front of.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Requests reach a web ACL through two types here. The rest are held as
|
|
8
|
+
* `SimWafUnsimulatedResource`, associated and listed, with nothing evaluated
|
|
9
|
+
* in front of them. A type that starts serving requests gets a class of its
|
|
10
|
+
* own in this union, and everything that holds an association goes on
|
|
8
11
|
* addressing a resource by its ARN.
|
|
9
12
|
*/
|
|
10
|
-
export type SimWafProtectedResource = SimWafRestApiStage | SimWafUserPool;
|
|
13
|
+
export type SimWafProtectedResource = SimWafRestApiStage | SimWafUserPool | SimWafUnsimulatedResource;
|
|
11
14
|
/**
|
|
12
15
|
* The type ListResourcesForWebACL lists one simulated resource under.
|
|
13
16
|
*/
|
|
@@ -21,17 +24,19 @@ export declare const simWafApiGatewayResourceType = "API_GATEWAY";
|
|
|
21
24
|
*/
|
|
22
25
|
export declare const simWafUserPoolResourceType = "COGNITO_USER_POOL";
|
|
23
26
|
/**
|
|
24
|
-
* The resource types
|
|
27
|
+
* The resource types ListResourcesForWebACL lists, which are all the types
|
|
28
|
+
* an association can hold.
|
|
25
29
|
*/
|
|
26
30
|
export declare const simWafProtectedResourceTypes: readonly SimWafProtectedResourceType[];
|
|
27
31
|
/**
|
|
28
32
|
* Read the resource an association names, refusing anything a web ACL cannot
|
|
29
|
-
* be put in front of
|
|
33
|
+
* be put in front of.
|
|
30
34
|
*
|
|
31
35
|
* The three refusals mean different things. An HTTP API stage is refused
|
|
32
36
|
* because AWS WAF protects no HTTP API, so an association accepted here would
|
|
33
|
-
* let a test cover protection AWS never applies.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
37
|
+
* let a test cover protection AWS never applies. An Amplify app takes a
|
|
38
|
+
* `CLOUDFRONT` web ACL from `us-east-1` for an app in any Region, and a WAFv2
|
|
39
|
+
* here reaches web ACLs in its own Region only. Anything else is not a
|
|
40
|
+
* resource ARN.
|
|
36
41
|
*/
|
|
37
42
|
export declare function simWafProtectedResource(arn: string): SimWafProtectedResource;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SimWafInvalidParameterException, SimWafUnsimulatedInputException, } from "../error/sim-wafv2.error.js";
|
|
2
2
|
import { SimWafRestApiStage } from "./sim-waf-rest-api-stage.js";
|
|
3
|
+
import { SimWafUnsimulatedResource, simWafUnsimulatedResourceTypes, } from "./sim-waf-unsimulated-resource.js";
|
|
3
4
|
import { SimWafUserPool } from "./sim-waf-user-pool.js";
|
|
4
5
|
/**
|
|
5
6
|
* The type ListResourcesForWebACL lists a simulated REST API stage under.
|
|
@@ -10,32 +11,28 @@ export const simWafApiGatewayResourceType = "API_GATEWAY";
|
|
|
10
11
|
*/
|
|
11
12
|
export const simWafUserPoolResourceType = "COGNITO_USER_POOL";
|
|
12
13
|
/**
|
|
13
|
-
* The resource types
|
|
14
|
+
* The resource types ListResourcesForWebACL lists, which are all the types
|
|
15
|
+
* an association can hold.
|
|
14
16
|
*/
|
|
15
|
-
export const simWafProtectedResourceTypes = [
|
|
17
|
+
export const simWafProtectedResourceTypes = [
|
|
18
|
+
simWafApiGatewayResourceType,
|
|
19
|
+
simWafUserPoolResourceType,
|
|
20
|
+
...simWafUnsimulatedResourceTypes,
|
|
21
|
+
];
|
|
16
22
|
const restApiStagePattern = /^arn:aws:apigateway:(?<regionName>[^:]+)::\/restapis\/(?<restApiId>[^/]+)\/stages\/(?<stageName>[^/]+)$/u;
|
|
17
23
|
const httpApiStagePattern = /^arn:aws:apigateway:[^:]+::\/apis\/[^/]+\/stages\/[^/]+$/u;
|
|
18
24
|
const userPoolPattern = /^arn:aws:cognito-idp:(?<regionName>[^:]+):(?<accountId>[^:]+):userpool\/(?<userPoolId>[^/]+)$/u;
|
|
19
|
-
|
|
20
|
-
* The resource types real WAF protects that this simulation does not, by the
|
|
21
|
-
* service in their ARN.
|
|
22
|
-
*/
|
|
23
|
-
const unsimulatedResources = new Map([
|
|
24
|
-
["elasticloadbalancing", "an Application Load Balancer"],
|
|
25
|
-
["appsync", "an AppSync GraphQL API"],
|
|
26
|
-
["apprunner", "an App Runner service"],
|
|
27
|
-
["amplify", "an Amplify app"],
|
|
28
|
-
["ec2", "a Verified Access instance"],
|
|
29
|
-
]);
|
|
25
|
+
const amplifyAppPattern = /^arn:aws:amplify:[^:]+:[^:]+:apps\/[^/]+$/u;
|
|
30
26
|
/**
|
|
31
27
|
* Read the resource an association names, refusing anything a web ACL cannot
|
|
32
|
-
* be put in front of
|
|
28
|
+
* be put in front of.
|
|
33
29
|
*
|
|
34
30
|
* The three refusals mean different things. An HTTP API stage is refused
|
|
35
31
|
* because AWS WAF protects no HTTP API, so an association accepted here would
|
|
36
|
-
* let a test cover protection AWS never applies.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
32
|
+
* let a test cover protection AWS never applies. An Amplify app takes a
|
|
33
|
+
* `CLOUDFRONT` web ACL from `us-east-1` for an app in any Region, and a WAFv2
|
|
34
|
+
* here reaches web ACLs in its own Region only. Anything else is not a
|
|
35
|
+
* resource ARN.
|
|
39
36
|
*/
|
|
40
37
|
export function simWafProtectedResource(arn) {
|
|
41
38
|
const stage = restApiStage(arn);
|
|
@@ -46,6 +43,10 @@ export function simWafProtectedResource(arn) {
|
|
|
46
43
|
if (userPool !== undefined) {
|
|
47
44
|
return userPool;
|
|
48
45
|
}
|
|
46
|
+
const unsimulated = SimWafUnsimulatedResource.read(arn);
|
|
47
|
+
if (unsimulated !== undefined) {
|
|
48
|
+
return unsimulated;
|
|
49
|
+
}
|
|
49
50
|
if (httpApiStagePattern.test(arn)) {
|
|
50
51
|
throw new SimWafInvalidParameterException(`AWS WAF does not protect an API Gateway HTTP API. The resource types ` +
|
|
51
52
|
`it protects cover a REST API stage and not an HTTP API stage, so ` +
|
|
@@ -87,13 +88,12 @@ function simWafUserPool(arn) {
|
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
/**
|
|
90
|
-
* Refuse an
|
|
91
|
+
* Refuse an Amplify app, whose web ACL is out of this WAFv2's reach.
|
|
91
92
|
*/
|
|
92
93
|
function refuseUnsimulatedResource(arn) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`
|
|
97
|
-
`nothing.`);
|
|
94
|
+
if (amplifyAppPattern.test(arn)) {
|
|
95
|
+
throw new SimWafUnsimulatedInputException(`AWS WAF protects an Amplify app with a CLOUDFRONT web ACL held in ` +
|
|
96
|
+
`us-east-1, and a simulated WAFv2 associates web ACLs of its own ` +
|
|
97
|
+
`Region only, so ${arn} is refused.`);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -9,20 +9,25 @@ import type { SimWafProtectedResource } from "./sim-waf-protected-resource.js";
|
|
|
9
9
|
export interface SimWafProtectedResources {
|
|
10
10
|
/**
|
|
11
11
|
* Whether this simulation holds the resource an ARN names.
|
|
12
|
+
*
|
|
13
|
+
* A `SimWafUnsimulatedResource` is held by no simulated service, so there is
|
|
14
|
+
* nothing to look for, and it is taken as named.
|
|
12
15
|
*/
|
|
13
16
|
has(resource: SimWafProtectedResource): boolean;
|
|
14
17
|
}
|
|
15
18
|
/**
|
|
16
19
|
* The resources available to a WAFv2 with nothing around it to ask.
|
|
17
20
|
*
|
|
18
|
-
* Every ARN resolves to nothing, so a standalone simulated
|
|
19
|
-
* web ACL with
|
|
20
|
-
* against a resource no request will ever reach protects
|
|
21
|
-
* so is better than reporting a web ACL in front of
|
|
21
|
+
* Every simulated resource ARN resolves to nothing, so a standalone simulated
|
|
22
|
+
* WAFv2 associates a web ACL with no stage or pool. That is the safe answer:
|
|
23
|
+
* an association held against a resource no request will ever reach protects
|
|
24
|
+
* nothing, and saying so is better than reporting a web ACL in front of
|
|
25
|
+
* something imaginary. A `SimWafUnsimulatedResource` is taken as named here
|
|
26
|
+
* as everywhere else.
|
|
22
27
|
*/
|
|
23
28
|
export declare class SimWafNoProtectedResources implements SimWafProtectedResources {
|
|
24
29
|
/**
|
|
25
|
-
*
|
|
30
|
+
* Whether the resource is one no simulated service holds.
|
|
26
31
|
*/
|
|
27
|
-
has(): boolean;
|
|
32
|
+
has(resource: SimWafProtectedResource): boolean;
|
|
28
33
|
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
import { SimWafUnsimulatedResource } from "./sim-waf-unsimulated-resource.js";
|
|
1
2
|
/**
|
|
2
3
|
* The resources available to a WAFv2 with nothing around it to ask.
|
|
3
4
|
*
|
|
4
|
-
* Every ARN resolves to nothing, so a standalone simulated
|
|
5
|
-
* web ACL with
|
|
6
|
-
* against a resource no request will ever reach protects
|
|
7
|
-
* so is better than reporting a web ACL in front of
|
|
5
|
+
* Every simulated resource ARN resolves to nothing, so a standalone simulated
|
|
6
|
+
* WAFv2 associates a web ACL with no stage or pool. That is the safe answer:
|
|
7
|
+
* an association held against a resource no request will ever reach protects
|
|
8
|
+
* nothing, and saying so is better than reporting a web ACL in front of
|
|
9
|
+
* something imaginary. A `SimWafUnsimulatedResource` is taken as named here
|
|
10
|
+
* as everywhere else.
|
|
8
11
|
*/
|
|
9
12
|
export class SimWafNoProtectedResources {
|
|
10
13
|
/**
|
|
11
|
-
*
|
|
14
|
+
* Whether the resource is one no simulated service holds.
|
|
12
15
|
*/
|
|
13
|
-
has() {
|
|
14
|
-
return
|
|
16
|
+
has(resource) {
|
|
17
|
+
return resource instanceof SimWafUnsimulatedResource;
|
|
15
18
|
}
|
|
16
19
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The resource types AWS WAF protects that no simulated request passes
|
|
3
|
+
* through, as ListResourcesForWebACL lists them.
|
|
4
|
+
*/
|
|
5
|
+
export type SimWafUnsimulatedResourceType = "APPLICATION_LOAD_BALANCER" | "APPSYNC" | "APP_RUNNER_SERVICE" | "VERIFIED_ACCESS_INSTANCE";
|
|
6
|
+
/**
|
|
7
|
+
* The types listed for a resource AWS WAF protects and Yulin does not.
|
|
8
|
+
*/
|
|
9
|
+
export declare const simWafUnsimulatedResourceTypes: readonly SimWafUnsimulatedResourceType[];
|
|
10
|
+
/**
|
|
11
|
+
* A resource AWS WAF protects and no simulated request passes through.
|
|
12
|
+
*
|
|
13
|
+
* An association with one is held, and GetWebACLForResource and
|
|
14
|
+
* ListResourcesForWebACL report it. Nothing is evaluated in front of it,
|
|
15
|
+
* because nothing here serves a request through it. Whether the resource
|
|
16
|
+
* exists is not checked, since no simulated service holds it to ask.
|
|
17
|
+
*/
|
|
18
|
+
export declare class SimWafUnsimulatedResource {
|
|
19
|
+
readonly resourceType: SimWafUnsimulatedResourceType;
|
|
20
|
+
readonly arn: string;
|
|
21
|
+
readonly regionName: string;
|
|
22
|
+
readonly accountId: string;
|
|
23
|
+
/** Why the web ACL in front of this resource evaluates nothing. */
|
|
24
|
+
readonly reason: string;
|
|
25
|
+
private constructor();
|
|
26
|
+
/**
|
|
27
|
+
* The unsimulated resource an ARN names, or nothing when it names none.
|
|
28
|
+
*
|
|
29
|
+
* Every pattern places the Region and the Account where any ARN does, so a
|
|
30
|
+
* match is read for them by position.
|
|
31
|
+
*/
|
|
32
|
+
static read(arn: string): SimWafUnsimulatedResource | undefined;
|
|
33
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ARN shapes AWS documents for each of them.
|
|
3
|
+
*/
|
|
4
|
+
const kinds = [
|
|
5
|
+
{
|
|
6
|
+
resourceType: "APPLICATION_LOAD_BALANCER",
|
|
7
|
+
described: "an Application Load Balancer",
|
|
8
|
+
pattern: /^arn:aws:elasticloadbalancing:[^:]+:[^:]+:loadbalancer\/app\/[^/]+\/[^/]+$/u,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
resourceType: "APPSYNC",
|
|
12
|
+
described: "an AppSync GraphQL API",
|
|
13
|
+
pattern: /^arn:aws:appsync:[^:]+:[^:]+:apis\/[^/]+$/u,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
resourceType: "APP_RUNNER_SERVICE",
|
|
17
|
+
described: "an App Runner service",
|
|
18
|
+
pattern: /^arn:aws:apprunner:[^:]+:[^:]+:service\/[^/]+\/[^/]+$/u,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
resourceType: "VERIFIED_ACCESS_INSTANCE",
|
|
22
|
+
described: "a Verified Access instance",
|
|
23
|
+
pattern: /^arn:aws:ec2:[^:]+:[^:]+:verified-access-instance\/[^/]+$/u,
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* The types listed for a resource AWS WAF protects and Yulin does not.
|
|
28
|
+
*/
|
|
29
|
+
export const simWafUnsimulatedResourceTypes = kinds.map((kind) => kind.resourceType);
|
|
30
|
+
/**
|
|
31
|
+
* A resource AWS WAF protects and no simulated request passes through.
|
|
32
|
+
*
|
|
33
|
+
* An association with one is held, and GetWebACLForResource and
|
|
34
|
+
* ListResourcesForWebACL report it. Nothing is evaluated in front of it,
|
|
35
|
+
* because nothing here serves a request through it. Whether the resource
|
|
36
|
+
* exists is not checked, since no simulated service holds it to ask.
|
|
37
|
+
*/
|
|
38
|
+
export class SimWafUnsimulatedResource {
|
|
39
|
+
resourceType;
|
|
40
|
+
arn;
|
|
41
|
+
regionName;
|
|
42
|
+
accountId;
|
|
43
|
+
/** Why the web ACL in front of this resource evaluates nothing. */
|
|
44
|
+
reason;
|
|
45
|
+
constructor(arn, kind) {
|
|
46
|
+
const [regionName, accountId] = arn.split(":").slice(3, 5);
|
|
47
|
+
this.resourceType = kind.resourceType;
|
|
48
|
+
this.arn = arn;
|
|
49
|
+
this.regionName = String(regionName);
|
|
50
|
+
this.accountId = String(accountId);
|
|
51
|
+
this.reason =
|
|
52
|
+
`AWS WAF protects ${kind.described}, and no simulated request passes ` +
|
|
53
|
+
`through one, so the association with ${arn} is held and nothing in ` +
|
|
54
|
+
`front of it is evaluated`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The unsimulated resource an ARN names, or nothing when it names none.
|
|
58
|
+
*
|
|
59
|
+
* Every pattern places the Region and the Account where any ARN does, so a
|
|
60
|
+
* match is read for them by position.
|
|
61
|
+
*/
|
|
62
|
+
static read(arn) {
|
|
63
|
+
const kind = kinds.find((candidate) => candidate.pattern.test(arn));
|
|
64
|
+
return kind && new SimWafUnsimulatedResource(arn, kind);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SimWafUnsimulatedResource } from "../../association/sim-waf-unsimulated-resource.js";
|
|
1
2
|
import { SimWafUnavailableEntityException } from "../../error/sim-wafv2.error.js";
|
|
2
3
|
import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
|
|
3
4
|
import { wafWebAclAssociationResourceType } from "../sim-cfn-waf-resource-types.js";
|
|
@@ -44,6 +45,10 @@ export class SimCfnWafAssociationCreator {
|
|
|
44
45
|
WebACLArn: association.webAclArn,
|
|
45
46
|
},
|
|
46
47
|
}, options);
|
|
48
|
+
const unsimulated = SimWafUnsimulatedResource.read(association.resourceArn);
|
|
49
|
+
if (unsimulated !== undefined) {
|
|
50
|
+
resource.ignoreProperty("ResourceArn", unsimulated.reason);
|
|
51
|
+
}
|
|
47
52
|
return association;
|
|
48
53
|
});
|
|
49
54
|
}
|
|
@@ -20,6 +20,7 @@ export class SimCfnWafIpSetConfig extends SimCfnWafResourceConfig {
|
|
|
20
20
|
Name: this.name(),
|
|
21
21
|
Scope: this.scope(),
|
|
22
22
|
Description: this.description(),
|
|
23
|
+
Tags: this.tags(),
|
|
23
24
|
IPAddressVersion: this.text("IPAddressVersion"),
|
|
24
25
|
Addresses: this.requiredStrings("Addresses"),
|
|
25
26
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assertDefined } from "../../../../util/type-guard/defined.js";
|
|
2
2
|
import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
|
|
3
|
+
import { simCfnWafRecordUnsimulated } from "../sim-cfn-waf-unsimulated.js";
|
|
3
4
|
import { wafIpSetResourceType } from "../sim-cfn-waf-resource-types.js";
|
|
4
5
|
import { SimCfnWafIpSetConfig } from "./sim-cfn-waf-ip-set-config.js";
|
|
5
6
|
/**
|
|
@@ -29,6 +30,7 @@ export class SimCfnWafIpSetCreator {
|
|
|
29
30
|
assertDefined(arn, `sim WAFv2 IP set ARN for CloudFormation Resource ${resource.logicalId}`);
|
|
30
31
|
const ipSet = this.#wafV2.findIpSetByArn(arn);
|
|
31
32
|
assertDefined(ipSet, `sim WAFv2 IP set ${arn} after CloudFormation creation`);
|
|
33
|
+
simCfnWafRecordUnsimulated(resource, ipSet);
|
|
32
34
|
return ipSet;
|
|
33
35
|
});
|
|
34
36
|
}
|
|
@@ -21,6 +21,7 @@ export class SimCfnWafRegexPatternSetConfig extends SimCfnWafResourceConfig {
|
|
|
21
21
|
Name: this.name(),
|
|
22
22
|
Scope: this.scope(),
|
|
23
23
|
Description: this.description(),
|
|
24
|
+
Tags: this.tags(),
|
|
24
25
|
RegularExpressionList: this.requiredStrings("RegularExpressionList").map((pattern) => ({ RegexString: pattern })),
|
|
25
26
|
};
|
|
26
27
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assertDefined } from "../../../../util/type-guard/defined.js";
|
|
2
2
|
import { simCfnWafResourceCommand } from "../sim-cfn-waf-resource-error.js";
|
|
3
|
+
import { simCfnWafRecordUnsimulated } from "../sim-cfn-waf-unsimulated.js";
|
|
3
4
|
import { wafRegexPatternSetResourceType } from "../sim-cfn-waf-resource-types.js";
|
|
4
5
|
import { SimCfnWafRegexPatternSetConfig } from "./sim-cfn-waf-regex-set-config.js";
|
|
5
6
|
/**
|
|
@@ -29,6 +30,7 @@ export class SimCfnWafRegexPatternSetCreator {
|
|
|
29
30
|
assertDefined(arn, `sim WAFv2 regex pattern set ARN for CloudFormation Resource ${resource.logicalId}`);
|
|
30
31
|
const patternSet = this.#wafV2.findRegexPatternSetByArn(arn);
|
|
31
32
|
assertDefined(patternSet, `sim WAFv2 regex pattern set ${arn} after CloudFormation creation`);
|
|
33
|
+
simCfnWafRecordUnsimulated(resource, patternSet);
|
|
32
34
|
return patternSet;
|
|
33
35
|
});
|
|
34
36
|
}
|
|
@@ -45,6 +45,10 @@ export declare abstract class SimCfnWafResourceConfig {
|
|
|
45
45
|
/**
|
|
46
46
|
* One property of the Resource, whatever shape it is in.
|
|
47
47
|
*/
|
|
48
|
+
/**
|
|
49
|
+
* The tags the template gave the Resource, as written.
|
|
50
|
+
*/
|
|
51
|
+
tags(): readonly unknown[] | undefined;
|
|
48
52
|
protected value(key: string): SimCfnTemplateValue | undefined;
|
|
49
53
|
/**
|
|
50
54
|
* One string property, or nothing when the template left it out.
|