@jaypie/constructs 1.2.59 → 1.2.60
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/cjs/helpers/index.d.ts +1 -0
- package/dist/cjs/helpers/wafManagedRuleNames.d.ts +33 -0
- package/dist/cjs/index.cjs +148 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/wafManagedRuleNames.d.ts +33 -0
- package/dist/esm/index.js +147 -1
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -19,3 +19,4 @@ export { resolveEnvironment, EnvironmentArrayItem, EnvironmentInput, } from "./r
|
|
|
19
19
|
export { resolveHostedZone } from "./resolveHostedZone";
|
|
20
20
|
export { resolveParamsAndSecrets } from "./resolveParamsAndSecrets";
|
|
21
21
|
export { resolveSecrets, SecretsArrayItem, clearSecretsCache, clearAllSecretsCaches, } from "./resolveSecrets";
|
|
22
|
+
export { assertValidWafRuleNames, AWS_MANAGED_RULE_GROUPS, } from "./wafManagedRuleNames";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as wafv2 from "aws-cdk-lib/aws-wafv2";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical sub-rule names for each AWS managed rule group, as published in the
|
|
4
|
+
* AWS WAF developer guide. Used to validate `waf.allow` and
|
|
5
|
+
* `waf.managedRuleOverrides` rule names at synth time — AWS WAF matches
|
|
6
|
+
* `RuleActionOverride` on the exact rule *name* and silently ignores names that
|
|
7
|
+
* match no rule, so a typo or a label/name casing mismatch (e.g. the label
|
|
8
|
+
* `…:NoUserAgent_Header` vs the rule name `NoUserAgent_HEADER`) becomes an
|
|
9
|
+
* undiagnosable no-op.
|
|
10
|
+
*
|
|
11
|
+
* Groups absent from this map (custom rule groups, or AWS groups not yet
|
|
12
|
+
* mirrored here) are not validated.
|
|
13
|
+
*
|
|
14
|
+
* @see https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html
|
|
15
|
+
*/
|
|
16
|
+
export declare const AWS_MANAGED_RULE_GROUPS: Record<string, readonly string[]>;
|
|
17
|
+
/** One entry in a `waf.allow` list. Mirrors JaypieWafAllowEntry structurally. */
|
|
18
|
+
interface WafAllowEntryLike {
|
|
19
|
+
path: string | string[];
|
|
20
|
+
[ruleGroupKey: string]: string | string[] | undefined;
|
|
21
|
+
}
|
|
22
|
+
interface AssertValidWafRuleNamesOptions {
|
|
23
|
+
allow?: WafAllowEntryLike | WafAllowEntryLike[];
|
|
24
|
+
managedRuleOverrides?: Record<string, wafv2.CfnWebACL.RuleActionOverrideProperty[]>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Throw a ConfigurationError if any `waf.allow` or `waf.managedRuleOverrides`
|
|
28
|
+
* rule name does not exist in its AWS managed rule group. Groups not present in
|
|
29
|
+
* AWS_MANAGED_RULE_GROUPS (custom groups) are skipped. A name that matches no
|
|
30
|
+
* rule would otherwise be silently ignored by AWS WAF.
|
|
31
|
+
*/
|
|
32
|
+
export declare function assertValidWafRuleNames({ allow, managedRuleOverrides, }?: AssertValidWafRuleNamesOptions): void;
|
|
33
|
+
export {};
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1303,6 +1303,148 @@ function clearAllSecretsCaches() {
|
|
|
1303
1303
|
// between test runs. For testing, use clearSecretsCache(scope) instead.
|
|
1304
1304
|
}
|
|
1305
1305
|
|
|
1306
|
+
/**
|
|
1307
|
+
* Canonical sub-rule names for each AWS managed rule group, as published in the
|
|
1308
|
+
* AWS WAF developer guide. Used to validate `waf.allow` and
|
|
1309
|
+
* `waf.managedRuleOverrides` rule names at synth time — AWS WAF matches
|
|
1310
|
+
* `RuleActionOverride` on the exact rule *name* and silently ignores names that
|
|
1311
|
+
* match no rule, so a typo or a label/name casing mismatch (e.g. the label
|
|
1312
|
+
* `…:NoUserAgent_Header` vs the rule name `NoUserAgent_HEADER`) becomes an
|
|
1313
|
+
* undiagnosable no-op.
|
|
1314
|
+
*
|
|
1315
|
+
* Groups absent from this map (custom rule groups, or AWS groups not yet
|
|
1316
|
+
* mirrored here) are not validated.
|
|
1317
|
+
*
|
|
1318
|
+
* @see https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html
|
|
1319
|
+
*/
|
|
1320
|
+
const AWS_MANAGED_RULE_GROUPS = {
|
|
1321
|
+
AWSManagedRulesAdminProtectionRuleSet: ["AdminProtection_URIPATH"],
|
|
1322
|
+
AWSManagedRulesAmazonIpReputationList: [
|
|
1323
|
+
"AWSManagedIPDDoSList",
|
|
1324
|
+
"AWSManagedIPReputationList",
|
|
1325
|
+
"AWSManagedReconnaissanceList",
|
|
1326
|
+
],
|
|
1327
|
+
AWSManagedRulesAnonymousIpList: ["AnonymousIPList", "HostingProviderIPList"],
|
|
1328
|
+
AWSManagedRulesCommonRuleSet: [
|
|
1329
|
+
"CrossSiteScripting_BODY",
|
|
1330
|
+
"CrossSiteScripting_COOKIE",
|
|
1331
|
+
"CrossSiteScripting_QUERYARGUMENTS",
|
|
1332
|
+
"CrossSiteScripting_URIPATH",
|
|
1333
|
+
"EC2MetaDataSSRF_BODY",
|
|
1334
|
+
"EC2MetaDataSSRF_COOKIE",
|
|
1335
|
+
"EC2MetaDataSSRF_QUERYARGUMENTS",
|
|
1336
|
+
"EC2MetaDataSSRF_URIPATH",
|
|
1337
|
+
"GenericLFI_BODY",
|
|
1338
|
+
"GenericLFI_QUERYARGUMENTS",
|
|
1339
|
+
"GenericLFI_URIPATH",
|
|
1340
|
+
"GenericRFI_BODY",
|
|
1341
|
+
"GenericRFI_QUERYARGUMENTS",
|
|
1342
|
+
"GenericRFI_URIPATH",
|
|
1343
|
+
"NoUserAgent_HEADER",
|
|
1344
|
+
"RestrictedExtensions_QUERYARGUMENTS",
|
|
1345
|
+
"RestrictedExtensions_URIPATH",
|
|
1346
|
+
"SizeRestrictions_BODY",
|
|
1347
|
+
"SizeRestrictions_Cookie_HEADER",
|
|
1348
|
+
"SizeRestrictions_QUERYSTRING",
|
|
1349
|
+
"SizeRestrictions_URIPATH",
|
|
1350
|
+
"UserAgent_BadBots_HEADER",
|
|
1351
|
+
],
|
|
1352
|
+
AWSManagedRulesKnownBadInputsRuleSet: [
|
|
1353
|
+
"ExploitablePaths_URIPATH",
|
|
1354
|
+
"Host_localhost_HEADER",
|
|
1355
|
+
"JavaDeserializationRCE_BODY",
|
|
1356
|
+
"JavaDeserializationRCE_HEADER",
|
|
1357
|
+
"JavaDeserializationRCE_QUERYSTRING",
|
|
1358
|
+
"JavaDeserializationRCE_URIPATH",
|
|
1359
|
+
"Log4JRCE_BODY",
|
|
1360
|
+
"Log4JRCE_HEADER",
|
|
1361
|
+
"Log4JRCE_QUERYSTRING",
|
|
1362
|
+
"Log4JRCE_URIPATH",
|
|
1363
|
+
"PROPFIND_METHOD",
|
|
1364
|
+
"ReactJSRCE_BODY",
|
|
1365
|
+
],
|
|
1366
|
+
AWSManagedRulesLinuxRuleSet: ["LFI_HEADER", "LFI_QUERYSTRING", "LFI_URIPATH"],
|
|
1367
|
+
AWSManagedRulesPHPRuleSet: [
|
|
1368
|
+
"PHPHighRiskMethodsVariables_BODY",
|
|
1369
|
+
"PHPHighRiskMethodsVariables_HEADER",
|
|
1370
|
+
"PHPHighRiskMethodsVariables_QUERYSTRING",
|
|
1371
|
+
"PHPHighRiskMethodsVariables_URIPATH",
|
|
1372
|
+
],
|
|
1373
|
+
AWSManagedRulesSQLiRuleSet: [
|
|
1374
|
+
"SQLiExtendedPatterns_BODY",
|
|
1375
|
+
"SQLiExtendedPatterns_HEADER",
|
|
1376
|
+
"SQLiExtendedPatterns_QUERYARGUMENTS",
|
|
1377
|
+
"SQLiExtendedPatterns_URIPATH",
|
|
1378
|
+
"SQLi_BODY",
|
|
1379
|
+
"SQLi_COOKIE",
|
|
1380
|
+
"SQLi_QUERYARGUMENTS",
|
|
1381
|
+
"SQLi_URIPATH",
|
|
1382
|
+
],
|
|
1383
|
+
AWSManagedRulesUnixRuleSet: [
|
|
1384
|
+
"UNIXShellCommandsVariables_BODY",
|
|
1385
|
+
"UNIXShellCommandsVariables_HEADER",
|
|
1386
|
+
"UNIXShellCommandsVariables_QUERYSTRING",
|
|
1387
|
+
],
|
|
1388
|
+
AWSManagedRulesWindowsRuleSet: [
|
|
1389
|
+
"PowerShellCommands_BODY",
|
|
1390
|
+
"PowerShellCommands_COOKIE",
|
|
1391
|
+
"PowerShellCommands_QUERYARGUMENTS",
|
|
1392
|
+
"WindowsShellCommands_BODY",
|
|
1393
|
+
"WindowsShellCommands_HEADER",
|
|
1394
|
+
"WindowsShellCommands_QUERYARGUMENTS",
|
|
1395
|
+
"WindowsShellCommands_QUERYSTRING",
|
|
1396
|
+
"WindowsShellCommands_URIPATH",
|
|
1397
|
+
],
|
|
1398
|
+
AWSManagedRulesWordPressRuleSet: [
|
|
1399
|
+
"WordPressExploitableCommands_QUERYSTRING",
|
|
1400
|
+
"WordPressExploitablePaths_URIPATH",
|
|
1401
|
+
],
|
|
1402
|
+
};
|
|
1403
|
+
/**
|
|
1404
|
+
* Throw a ConfigurationError if any `waf.allow` or `waf.managedRuleOverrides`
|
|
1405
|
+
* rule name does not exist in its AWS managed rule group. Groups not present in
|
|
1406
|
+
* AWS_MANAGED_RULE_GROUPS (custom groups) are skipped. A name that matches no
|
|
1407
|
+
* rule would otherwise be silently ignored by AWS WAF.
|
|
1408
|
+
*/
|
|
1409
|
+
function assertValidWafRuleNames({ allow, managedRuleOverrides, } = {}) {
|
|
1410
|
+
// Collect (group → referenced rule name) pairs from both inputs.
|
|
1411
|
+
const references = [];
|
|
1412
|
+
if (managedRuleOverrides) {
|
|
1413
|
+
for (const [group, overrides] of Object.entries(managedRuleOverrides)) {
|
|
1414
|
+
for (const override of overrides ?? []) {
|
|
1415
|
+
if (override?.name)
|
|
1416
|
+
references.push({ group, ruleName: override.name });
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
const allowEntries = allow ? (Array.isArray(allow) ? allow : [allow]) : [];
|
|
1421
|
+
for (const entry of allowEntries) {
|
|
1422
|
+
for (const key of Object.keys(entry)) {
|
|
1423
|
+
if (key === "path")
|
|
1424
|
+
continue;
|
|
1425
|
+
const raw = entry[key];
|
|
1426
|
+
if (raw == null)
|
|
1427
|
+
continue;
|
|
1428
|
+
const ruleNames = Array.isArray(raw) ? raw : [raw];
|
|
1429
|
+
for (const ruleName of ruleNames) {
|
|
1430
|
+
references.push({ group: key, ruleName });
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
for (const { group, ruleName } of references) {
|
|
1435
|
+
const validNames = AWS_MANAGED_RULE_GROUPS[group];
|
|
1436
|
+
if (!validNames)
|
|
1437
|
+
continue; // Unknown/custom group — cannot validate
|
|
1438
|
+
if (!validNames.includes(ruleName)) {
|
|
1439
|
+
throw new errors.ConfigurationError(`WAF rule "${ruleName}" is not a rule in ${group}. AWS WAF matches ` +
|
|
1440
|
+
`RuleActionOverrides on the exact rule name and silently ignores ` +
|
|
1441
|
+
`unmatched names (note the label/name casing trap, e.g. ` +
|
|
1442
|
+
`"NoUserAgent_HEADER" not "NoUserAgent_Header"). Valid rule names: ` +
|
|
1443
|
+
`${validNames.join(", ")}.`);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1306
1448
|
class JaypieApiGateway extends constructs.Construct {
|
|
1307
1449
|
constructor(scope, id, props) {
|
|
1308
1450
|
super(scope, id);
|
|
@@ -2796,6 +2938,8 @@ class JaypieDistribution extends constructs.Construct {
|
|
|
2796
2938
|
else {
|
|
2797
2939
|
// Create new WebACL
|
|
2798
2940
|
const { allow, managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES$1, rateLimitPerIp = DEFAULT_RATE_LIMIT$1, } = wafConfig;
|
|
2941
|
+
// Fail synth on rule names AWS WAF would silently ignore (#362)
|
|
2942
|
+
assertValidWafRuleNames({ allow, managedRuleOverrides });
|
|
2799
2943
|
const allowEntries = allow
|
|
2800
2944
|
? Array.isArray(allow)
|
|
2801
2945
|
? allow
|
|
@@ -4782,6 +4926,8 @@ class JaypieWebDeploymentBucket extends constructs.Construct {
|
|
|
4782
4926
|
}
|
|
4783
4927
|
else {
|
|
4784
4928
|
const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES, rateLimitPerIp = DEFAULT_RATE_LIMIT, } = wafConfig;
|
|
4929
|
+
// Fail synth on rule names AWS WAF would silently ignore (#362)
|
|
4930
|
+
assertValidWafRuleNames({ managedRuleOverrides });
|
|
4785
4931
|
let priority = 0;
|
|
4786
4932
|
const rules = [];
|
|
4787
4933
|
for (const ruleName of managedRules) {
|
|
@@ -5455,6 +5601,7 @@ class JaypieWebSocketTable extends constructs.Construct {
|
|
|
5455
5601
|
}
|
|
5456
5602
|
}
|
|
5457
5603
|
|
|
5604
|
+
exports.AWS_MANAGED_RULE_GROUPS = AWS_MANAGED_RULE_GROUPS;
|
|
5458
5605
|
exports.CDK = CDK$2;
|
|
5459
5606
|
exports.JaypieAccountLoggingBucket = JaypieAccountLoggingBucket;
|
|
5460
5607
|
exports.JaypieApiGateway = JaypieApiGateway;
|
|
@@ -5491,6 +5638,7 @@ exports.JaypieWebSocket = JaypieWebSocket;
|
|
|
5491
5638
|
exports.JaypieWebSocketLambda = JaypieWebSocketLambda;
|
|
5492
5639
|
exports.JaypieWebSocketTable = JaypieWebSocketTable;
|
|
5493
5640
|
exports.addDatadogLayers = addDatadogLayers;
|
|
5641
|
+
exports.assertValidWafRuleNames = assertValidWafRuleNames;
|
|
5494
5642
|
exports.clearAllCertificateCaches = clearAllCertificateCaches;
|
|
5495
5643
|
exports.clearAllSecretsCaches = clearAllSecretsCaches;
|
|
5496
5644
|
exports.clearCertificateCache = clearCertificateCache;
|