@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.
@@ -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 {};
@@ -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;