@jaypie/constructs 1.2.59 → 1.2.61
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/jaypieLambdaEnv.d.ts +1 -0
- package/dist/cjs/helpers/wafManagedRuleNames.d.ts +33 -0
- package/dist/cjs/index.cjs +155 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/jaypieLambdaEnv.d.ts +1 -0
- package/dist/esm/helpers/wafManagedRuleNames.d.ts +33 -0
- package/dist/esm/index.js +154 -3
- 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/esm/index.js
CHANGED
|
@@ -702,7 +702,7 @@ function isValidSubdomain(subdomain) {
|
|
|
702
702
|
}
|
|
703
703
|
|
|
704
704
|
function jaypieLambdaEnv(options = {}) {
|
|
705
|
-
const { initialEnvironment = {} } = options;
|
|
705
|
+
const { initialEnvironment = {}, serviceTag } = options;
|
|
706
706
|
// Start with empty environment - we'll only add valid values
|
|
707
707
|
let environment = {};
|
|
708
708
|
// First, add all valid string values from initialEnvironment
|
|
@@ -731,6 +731,11 @@ function jaypieLambdaEnv(options = {}) {
|
|
|
731
731
|
environment[key] = defaultValue;
|
|
732
732
|
}
|
|
733
733
|
});
|
|
734
|
+
// Apply serviceTag as PROJECT_SERVICE unless explicitly overridden.
|
|
735
|
+
// Precedence: explicit environment > serviceTag > process.env.PROJECT_SERVICE
|
|
736
|
+
if (serviceTag && !environment.PROJECT_SERVICE) {
|
|
737
|
+
environment.PROJECT_SERVICE = serviceTag;
|
|
738
|
+
}
|
|
734
739
|
// Default environment variables from process.env if present
|
|
735
740
|
const defaultEnvVars = [
|
|
736
741
|
"DATADOG_API_KEY_ARN",
|
|
@@ -1267,6 +1272,148 @@ function clearAllSecretsCaches() {
|
|
|
1267
1272
|
// between test runs. For testing, use clearSecretsCache(scope) instead.
|
|
1268
1273
|
}
|
|
1269
1274
|
|
|
1275
|
+
/**
|
|
1276
|
+
* Canonical sub-rule names for each AWS managed rule group, as published in the
|
|
1277
|
+
* AWS WAF developer guide. Used to validate `waf.allow` and
|
|
1278
|
+
* `waf.managedRuleOverrides` rule names at synth time — AWS WAF matches
|
|
1279
|
+
* `RuleActionOverride` on the exact rule *name* and silently ignores names that
|
|
1280
|
+
* match no rule, so a typo or a label/name casing mismatch (e.g. the label
|
|
1281
|
+
* `…:NoUserAgent_Header` vs the rule name `NoUserAgent_HEADER`) becomes an
|
|
1282
|
+
* undiagnosable no-op.
|
|
1283
|
+
*
|
|
1284
|
+
* Groups absent from this map (custom rule groups, or AWS groups not yet
|
|
1285
|
+
* mirrored here) are not validated.
|
|
1286
|
+
*
|
|
1287
|
+
* @see https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html
|
|
1288
|
+
*/
|
|
1289
|
+
const AWS_MANAGED_RULE_GROUPS = {
|
|
1290
|
+
AWSManagedRulesAdminProtectionRuleSet: ["AdminProtection_URIPATH"],
|
|
1291
|
+
AWSManagedRulesAmazonIpReputationList: [
|
|
1292
|
+
"AWSManagedIPDDoSList",
|
|
1293
|
+
"AWSManagedIPReputationList",
|
|
1294
|
+
"AWSManagedReconnaissanceList",
|
|
1295
|
+
],
|
|
1296
|
+
AWSManagedRulesAnonymousIpList: ["AnonymousIPList", "HostingProviderIPList"],
|
|
1297
|
+
AWSManagedRulesCommonRuleSet: [
|
|
1298
|
+
"CrossSiteScripting_BODY",
|
|
1299
|
+
"CrossSiteScripting_COOKIE",
|
|
1300
|
+
"CrossSiteScripting_QUERYARGUMENTS",
|
|
1301
|
+
"CrossSiteScripting_URIPATH",
|
|
1302
|
+
"EC2MetaDataSSRF_BODY",
|
|
1303
|
+
"EC2MetaDataSSRF_COOKIE",
|
|
1304
|
+
"EC2MetaDataSSRF_QUERYARGUMENTS",
|
|
1305
|
+
"EC2MetaDataSSRF_URIPATH",
|
|
1306
|
+
"GenericLFI_BODY",
|
|
1307
|
+
"GenericLFI_QUERYARGUMENTS",
|
|
1308
|
+
"GenericLFI_URIPATH",
|
|
1309
|
+
"GenericRFI_BODY",
|
|
1310
|
+
"GenericRFI_QUERYARGUMENTS",
|
|
1311
|
+
"GenericRFI_URIPATH",
|
|
1312
|
+
"NoUserAgent_HEADER",
|
|
1313
|
+
"RestrictedExtensions_QUERYARGUMENTS",
|
|
1314
|
+
"RestrictedExtensions_URIPATH",
|
|
1315
|
+
"SizeRestrictions_BODY",
|
|
1316
|
+
"SizeRestrictions_Cookie_HEADER",
|
|
1317
|
+
"SizeRestrictions_QUERYSTRING",
|
|
1318
|
+
"SizeRestrictions_URIPATH",
|
|
1319
|
+
"UserAgent_BadBots_HEADER",
|
|
1320
|
+
],
|
|
1321
|
+
AWSManagedRulesKnownBadInputsRuleSet: [
|
|
1322
|
+
"ExploitablePaths_URIPATH",
|
|
1323
|
+
"Host_localhost_HEADER",
|
|
1324
|
+
"JavaDeserializationRCE_BODY",
|
|
1325
|
+
"JavaDeserializationRCE_HEADER",
|
|
1326
|
+
"JavaDeserializationRCE_QUERYSTRING",
|
|
1327
|
+
"JavaDeserializationRCE_URIPATH",
|
|
1328
|
+
"Log4JRCE_BODY",
|
|
1329
|
+
"Log4JRCE_HEADER",
|
|
1330
|
+
"Log4JRCE_QUERYSTRING",
|
|
1331
|
+
"Log4JRCE_URIPATH",
|
|
1332
|
+
"PROPFIND_METHOD",
|
|
1333
|
+
"ReactJSRCE_BODY",
|
|
1334
|
+
],
|
|
1335
|
+
AWSManagedRulesLinuxRuleSet: ["LFI_HEADER", "LFI_QUERYSTRING", "LFI_URIPATH"],
|
|
1336
|
+
AWSManagedRulesPHPRuleSet: [
|
|
1337
|
+
"PHPHighRiskMethodsVariables_BODY",
|
|
1338
|
+
"PHPHighRiskMethodsVariables_HEADER",
|
|
1339
|
+
"PHPHighRiskMethodsVariables_QUERYSTRING",
|
|
1340
|
+
"PHPHighRiskMethodsVariables_URIPATH",
|
|
1341
|
+
],
|
|
1342
|
+
AWSManagedRulesSQLiRuleSet: [
|
|
1343
|
+
"SQLiExtendedPatterns_BODY",
|
|
1344
|
+
"SQLiExtendedPatterns_HEADER",
|
|
1345
|
+
"SQLiExtendedPatterns_QUERYARGUMENTS",
|
|
1346
|
+
"SQLiExtendedPatterns_URIPATH",
|
|
1347
|
+
"SQLi_BODY",
|
|
1348
|
+
"SQLi_COOKIE",
|
|
1349
|
+
"SQLi_QUERYARGUMENTS",
|
|
1350
|
+
"SQLi_URIPATH",
|
|
1351
|
+
],
|
|
1352
|
+
AWSManagedRulesUnixRuleSet: [
|
|
1353
|
+
"UNIXShellCommandsVariables_BODY",
|
|
1354
|
+
"UNIXShellCommandsVariables_HEADER",
|
|
1355
|
+
"UNIXShellCommandsVariables_QUERYSTRING",
|
|
1356
|
+
],
|
|
1357
|
+
AWSManagedRulesWindowsRuleSet: [
|
|
1358
|
+
"PowerShellCommands_BODY",
|
|
1359
|
+
"PowerShellCommands_COOKIE",
|
|
1360
|
+
"PowerShellCommands_QUERYARGUMENTS",
|
|
1361
|
+
"WindowsShellCommands_BODY",
|
|
1362
|
+
"WindowsShellCommands_HEADER",
|
|
1363
|
+
"WindowsShellCommands_QUERYARGUMENTS",
|
|
1364
|
+
"WindowsShellCommands_QUERYSTRING",
|
|
1365
|
+
"WindowsShellCommands_URIPATH",
|
|
1366
|
+
],
|
|
1367
|
+
AWSManagedRulesWordPressRuleSet: [
|
|
1368
|
+
"WordPressExploitableCommands_QUERYSTRING",
|
|
1369
|
+
"WordPressExploitablePaths_URIPATH",
|
|
1370
|
+
],
|
|
1371
|
+
};
|
|
1372
|
+
/**
|
|
1373
|
+
* Throw a ConfigurationError if any `waf.allow` or `waf.managedRuleOverrides`
|
|
1374
|
+
* rule name does not exist in its AWS managed rule group. Groups not present in
|
|
1375
|
+
* AWS_MANAGED_RULE_GROUPS (custom groups) are skipped. A name that matches no
|
|
1376
|
+
* rule would otherwise be silently ignored by AWS WAF.
|
|
1377
|
+
*/
|
|
1378
|
+
function assertValidWafRuleNames({ allow, managedRuleOverrides, } = {}) {
|
|
1379
|
+
// Collect (group → referenced rule name) pairs from both inputs.
|
|
1380
|
+
const references = [];
|
|
1381
|
+
if (managedRuleOverrides) {
|
|
1382
|
+
for (const [group, overrides] of Object.entries(managedRuleOverrides)) {
|
|
1383
|
+
for (const override of overrides ?? []) {
|
|
1384
|
+
if (override?.name)
|
|
1385
|
+
references.push({ group, ruleName: override.name });
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
const allowEntries = allow ? (Array.isArray(allow) ? allow : [allow]) : [];
|
|
1390
|
+
for (const entry of allowEntries) {
|
|
1391
|
+
for (const key of Object.keys(entry)) {
|
|
1392
|
+
if (key === "path")
|
|
1393
|
+
continue;
|
|
1394
|
+
const raw = entry[key];
|
|
1395
|
+
if (raw == null)
|
|
1396
|
+
continue;
|
|
1397
|
+
const ruleNames = Array.isArray(raw) ? raw : [raw];
|
|
1398
|
+
for (const ruleName of ruleNames) {
|
|
1399
|
+
references.push({ group: key, ruleName });
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
for (const { group, ruleName } of references) {
|
|
1404
|
+
const validNames = AWS_MANAGED_RULE_GROUPS[group];
|
|
1405
|
+
if (!validNames)
|
|
1406
|
+
continue; // Unknown/custom group — cannot validate
|
|
1407
|
+
if (!validNames.includes(ruleName)) {
|
|
1408
|
+
throw new ConfigurationError(`WAF rule "${ruleName}" is not a rule in ${group}. AWS WAF matches ` +
|
|
1409
|
+
`RuleActionOverrides on the exact rule name and silently ignores ` +
|
|
1410
|
+
`unmatched names (note the label/name casing trap, e.g. ` +
|
|
1411
|
+
`"NoUserAgent_HEADER" not "NoUserAgent_Header"). Valid rule names: ` +
|
|
1412
|
+
`${validNames.join(", ")}.`);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1270
1417
|
class JaypieApiGateway extends Construct {
|
|
1271
1418
|
constructor(scope, id, props) {
|
|
1272
1419
|
super(scope, id);
|
|
@@ -1460,7 +1607,7 @@ class JaypieLambda extends Construct {
|
|
|
1460
1607
|
// Resolve environment from array or object syntax
|
|
1461
1608
|
const initialEnvironment = resolveEnvironment(environmentInput);
|
|
1462
1609
|
// Get base environment with defaults
|
|
1463
|
-
const environment = jaypieLambdaEnv({ initialEnvironment });
|
|
1610
|
+
const environment = jaypieLambdaEnv({ initialEnvironment, serviceTag });
|
|
1464
1611
|
// Resolve secrets from mixed array (strings and JaypieSecret instances)
|
|
1465
1612
|
// Use Stack.of(this) to ensure secrets are shared at stack level across all constructs
|
|
1466
1613
|
const secrets = resolveSecrets(Stack.of(this), secretsInput);
|
|
@@ -2760,6 +2907,8 @@ class JaypieDistribution extends Construct {
|
|
|
2760
2907
|
else {
|
|
2761
2908
|
// Create new WebACL
|
|
2762
2909
|
const { allow, managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES$1, rateLimitPerIp = DEFAULT_RATE_LIMIT$1, } = wafConfig;
|
|
2910
|
+
// Fail synth on rule names AWS WAF would silently ignore (#362)
|
|
2911
|
+
assertValidWafRuleNames({ allow, managedRuleOverrides });
|
|
2763
2912
|
const allowEntries = allow
|
|
2764
2913
|
? Array.isArray(allow)
|
|
2765
2914
|
? allow
|
|
@@ -4746,6 +4895,8 @@ class JaypieWebDeploymentBucket extends Construct {
|
|
|
4746
4895
|
}
|
|
4747
4896
|
else {
|
|
4748
4897
|
const { managedRuleOverrides, managedRuleScopeDowns, managedRules = DEFAULT_MANAGED_RULES, rateLimitPerIp = DEFAULT_RATE_LIMIT, } = wafConfig;
|
|
4898
|
+
// Fail synth on rule names AWS WAF would silently ignore (#362)
|
|
4899
|
+
assertValidWafRuleNames({ managedRuleOverrides });
|
|
4749
4900
|
let priority = 0;
|
|
4750
4901
|
const rules = [];
|
|
4751
4902
|
for (const ruleName of managedRules) {
|
|
@@ -5419,5 +5570,5 @@ class JaypieWebSocketTable extends Construct {
|
|
|
5419
5570
|
}
|
|
5420
5571
|
}
|
|
5421
5572
|
|
|
5422
|
-
export { CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieCertificate, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieDynamoDb, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMigration, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSecret, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieStaticWebBucket, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, JaypieWebSocket, JaypieWebSocketLambda, JaypieWebSocketTable, addDatadogLayers, clearAllCertificateCaches, clearAllSecretsCaches, clearCertificateCache, clearSecretsCache, constructEnvName, constructStackName, constructTagger, constructWafLogBucketName, ensureRoute53QueryLoggingPolicy, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveCertificate, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveEnvironment, resolveHostedZone, resolveParamsAndSecrets, resolveSecrets };
|
|
5573
|
+
export { AWS_MANAGED_RULE_GROUPS, CDK$2 as CDK, JaypieAccountLoggingBucket, JaypieApiGateway, JaypieAppStack, JaypieBucketQueuedLambda, JaypieCertificate, JaypieDatadogBucket, JaypieDatadogForwarder, JaypieDatadogSecret, JaypieDistribution, JaypieDnsRecord, JaypieDynamoDb, JaypieEnvSecret, JaypieEventsRule, JaypieExpressLambda, JaypieGitHubDeployRole, JaypieHostedZone, JaypieInfrastructureStack, JaypieLambda, JaypieMigration, JaypieMongoDbSecret, JaypieNextJs, JaypieOpenAiSecret, JaypieOrganizationTrail, JaypieQueuedLambda, JaypieSecret, JaypieSsoPermissions, JaypieSsoSyncApplication, JaypieStack, JaypieStaticWebBucket, JaypieTraceSigningKeySecret, JaypieWebDeploymentBucket, JaypieWebSocket, JaypieWebSocketLambda, JaypieWebSocketTable, addDatadogLayers, assertValidWafRuleNames, clearAllCertificateCaches, clearAllSecretsCaches, clearCertificateCache, clearSecretsCache, constructEnvName, constructStackName, constructTagger, constructWafLogBucketName, ensureRoute53QueryLoggingPolicy, envHostname, extendDatadogRole, isEnv, isProductionEnv, isSandboxEnv, isValidHostname$1 as isValidHostname, isValidSubdomain, jaypieLambdaEnv, mergeDomain, resolveCertificate, resolveDatadogForwarderFunction, resolveDatadogLayers, resolveDatadogLoggingDestination, resolveEnvironment, resolveHostedZone, resolveParamsAndSecrets, resolveSecrets };
|
|
5423
5574
|
//# sourceMappingURL=index.js.map
|