cdk-insights 0.4.6 → 0.4.7-beta.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/cli/entry.js +162 -71
- package/dist/cli/types/cli.types.d.ts +1 -1
- package/dist/helpers/serviceSelection/serviceSelection.d.ts +10 -0
- package/dist/helpers/serviceSelection/serviceSelection.test.d.ts +1 -0
- package/dist/index.js +114 -52
- package/dist/types/analysis.types.d.ts +3 -1
- package/package.json +1 -1
package/dist/cli/entry.js
CHANGED
|
@@ -78757,6 +78757,107 @@ var recordCacheSet = () => {
|
|
|
78757
78757
|
saveCacheStats();
|
|
78758
78758
|
};
|
|
78759
78759
|
|
|
78760
|
+
// src/helpers/serviceSelection/serviceSelection.ts
|
|
78761
|
+
var SPECIFIC_SERVICE_NAMES = [
|
|
78762
|
+
"IAM",
|
|
78763
|
+
"S3",
|
|
78764
|
+
"Lambda",
|
|
78765
|
+
"DynamoDB",
|
|
78766
|
+
"RDS",
|
|
78767
|
+
"EC2",
|
|
78768
|
+
"SNS",
|
|
78769
|
+
"SQS",
|
|
78770
|
+
"StepFunctions",
|
|
78771
|
+
"CloudTrail",
|
|
78772
|
+
"ApiGateway",
|
|
78773
|
+
"SecretsManager",
|
|
78774
|
+
"KMS",
|
|
78775
|
+
"EventBridge"
|
|
78776
|
+
];
|
|
78777
|
+
var SERVICE_NAME_TO_CHECK_KEYS = {
|
|
78778
|
+
IAM: ["iamPolicies"],
|
|
78779
|
+
S3: ["s3Buckets", "s3IntelligentTiering"],
|
|
78780
|
+
Lambda: ["lambdaEnvironmentVariables", "lambdaMemory"],
|
|
78781
|
+
DynamoDB: ["dynamoDBAutoScaling", "dynamoDBStreams"],
|
|
78782
|
+
RDS: ["rdsEncryption", "rdsMultiAZ"],
|
|
78783
|
+
EC2: ["ec2InstanceType", "natGatewayUsage", "securityGroups", "ebsUnusedVolumes"],
|
|
78784
|
+
SNS: ["sns"],
|
|
78785
|
+
SQS: ["sqs"],
|
|
78786
|
+
StepFunctions: ["stepFunctions"],
|
|
78787
|
+
CloudTrail: ["cloudTrailLogging"],
|
|
78788
|
+
ApiGateway: ["apiGateway"],
|
|
78789
|
+
SecretsManager: ["secretsManager"],
|
|
78790
|
+
KMS: ["kmsKeys"],
|
|
78791
|
+
EventBridge: ["eventBridgeRules"]
|
|
78792
|
+
};
|
|
78793
|
+
var CHECK_KEY_TO_SERVICE_NAME = Object.entries(
|
|
78794
|
+
SERVICE_NAME_TO_CHECK_KEYS
|
|
78795
|
+
).reduce((acc, [service, keys]) => {
|
|
78796
|
+
for (const key of keys) {
|
|
78797
|
+
acc[key] = service;
|
|
78798
|
+
}
|
|
78799
|
+
return acc;
|
|
78800
|
+
}, {});
|
|
78801
|
+
var dedupe = (items) => {
|
|
78802
|
+
const seen = /* @__PURE__ */ new Set();
|
|
78803
|
+
const result = [];
|
|
78804
|
+
for (const item of items) {
|
|
78805
|
+
if (seen.has(item)) {
|
|
78806
|
+
continue;
|
|
78807
|
+
}
|
|
78808
|
+
seen.add(item);
|
|
78809
|
+
result.push(item);
|
|
78810
|
+
}
|
|
78811
|
+
return result;
|
|
78812
|
+
};
|
|
78813
|
+
var normalizeServiceSelection = (services) => {
|
|
78814
|
+
if (!services || services.length === 0) {
|
|
78815
|
+
return {
|
|
78816
|
+
services: ["All services"],
|
|
78817
|
+
removedAllServices: false,
|
|
78818
|
+
defaultedToAll: true
|
|
78819
|
+
};
|
|
78820
|
+
}
|
|
78821
|
+
const uniqueServices = dedupe(services);
|
|
78822
|
+
const hasAllServices = uniqueServices.includes("All services");
|
|
78823
|
+
const specificServices = uniqueServices.filter(
|
|
78824
|
+
(service) => service !== "All services"
|
|
78825
|
+
);
|
|
78826
|
+
if (hasAllServices && specificServices.length > 0) {
|
|
78827
|
+
return {
|
|
78828
|
+
services: specificServices,
|
|
78829
|
+
removedAllServices: true,
|
|
78830
|
+
defaultedToAll: false
|
|
78831
|
+
};
|
|
78832
|
+
}
|
|
78833
|
+
return {
|
|
78834
|
+
services: hasAllServices ? ["All services"] : uniqueServices,
|
|
78835
|
+
removedAllServices: false,
|
|
78836
|
+
defaultedToAll: false
|
|
78837
|
+
};
|
|
78838
|
+
};
|
|
78839
|
+
var mapServicesToCheckKeys = (services, allCheckKeys) => {
|
|
78840
|
+
if (services.length === 0 || services.includes("All services")) {
|
|
78841
|
+
return dedupe(allCheckKeys);
|
|
78842
|
+
}
|
|
78843
|
+
const resolvedKeys = services.flatMap((service) => {
|
|
78844
|
+
if (service === "All services") {
|
|
78845
|
+
return allCheckKeys;
|
|
78846
|
+
}
|
|
78847
|
+
return SERVICE_NAME_TO_CHECK_KEYS[service] ?? [];
|
|
78848
|
+
});
|
|
78849
|
+
return dedupe(resolvedKeys);
|
|
78850
|
+
};
|
|
78851
|
+
var getServiceLabelForCheckKey = (checkKey) => {
|
|
78852
|
+
return CHECK_KEY_TO_SERVICE_NAME[checkKey];
|
|
78853
|
+
};
|
|
78854
|
+
var isServiceName = (value) => {
|
|
78855
|
+
if (value === "All services") {
|
|
78856
|
+
return true;
|
|
78857
|
+
}
|
|
78858
|
+
return SPECIFIC_SERVICE_NAMES.includes(value);
|
|
78859
|
+
};
|
|
78860
|
+
|
|
78760
78861
|
// node_modules/axios/lib/helpers/bind.js
|
|
78761
78862
|
function bind(fn, thisArg) {
|
|
78762
78863
|
return function wrap2() {
|
|
@@ -90323,25 +90424,6 @@ var memoizedServiceChecks = memoize(createAWSServiceChecks, {
|
|
|
90323
90424
|
// 10 minutes
|
|
90324
90425
|
maxSize: 10
|
|
90325
90426
|
});
|
|
90326
|
-
var getServiceCheckKeys = (serviceName) => {
|
|
90327
|
-
const serviceMapping = {
|
|
90328
|
-
"Lambda": ["lambdaEnvironmentVariables", "lambdaMemory"],
|
|
90329
|
-
"S3": ["s3Buckets", "s3IntelligentTiering"],
|
|
90330
|
-
"DynamoDB": ["dynamoDBAutoScaling", "dynamoDBStreams"],
|
|
90331
|
-
"RDS": ["rdsEncryption", "rdsMultiAZ"],
|
|
90332
|
-
"EC2": ["ec2InstanceType", "natGatewayUsage", "securityGroups", "ebsUnusedVolumes"],
|
|
90333
|
-
"IAM": ["iamPolicies"],
|
|
90334
|
-
"SNS": ["sns"],
|
|
90335
|
-
"SQS": ["sqs"],
|
|
90336
|
-
"StepFunctions": ["stepFunctions"],
|
|
90337
|
-
"CloudTrail": ["cloudTrailLogging"],
|
|
90338
|
-
"ApiGateway": ["apiGateway"],
|
|
90339
|
-
"SecretsManager": ["secretsManager"],
|
|
90340
|
-
"KMS": ["kmsKeys"],
|
|
90341
|
-
"EventBridge": ["eventBridgeRules"]
|
|
90342
|
-
};
|
|
90343
|
-
return serviceMapping[serviceName] || [serviceName];
|
|
90344
|
-
};
|
|
90345
90427
|
var createResourceFilter = (selectedServices) => {
|
|
90346
90428
|
if (selectedServices.includes("All services")) {
|
|
90347
90429
|
return (cloudFormationResource) => !cloudFormationResource.Type.startsWith("AWS::CDK::");
|
|
@@ -90358,13 +90440,16 @@ var createResourceFilter = (selectedServices) => {
|
|
|
90358
90440
|
};
|
|
90359
90441
|
var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedServices = [], solutionsRegistry = {}) => {
|
|
90360
90442
|
const serviceChecks = memoizedServiceChecks();
|
|
90361
|
-
const allServiceKeys = Object.keys(serviceChecks)
|
|
90362
|
-
const servicesToAnalyze = selectedServices.length > 0 && !selectedServices.includes("All services") ? selectedServices : allServiceKeys.filter(
|
|
90443
|
+
const allServiceKeys = Object.keys(serviceChecks).filter(
|
|
90363
90444
|
(serviceKey) => serviceKey !== "solutionsPatterns"
|
|
90364
90445
|
);
|
|
90365
|
-
const
|
|
90446
|
+
const { services: normalizedServices } = normalizeServiceSelection(selectedServices);
|
|
90447
|
+
const servicesToAnalyze = mapServicesToCheckKeys(
|
|
90448
|
+
normalizedServices,
|
|
90449
|
+
allServiceKeys
|
|
90450
|
+
);
|
|
90366
90451
|
const analysisFindings = {};
|
|
90367
|
-
const resourceFilter = createResourceFilter(
|
|
90452
|
+
const resourceFilter = createResourceFilter(normalizedServices);
|
|
90368
90453
|
const userResources = Object.entries(cloudformationTemplate.Resources || {}).filter(
|
|
90369
90454
|
([, cloudFormationResource]) => resourceFilter(cloudFormationResource)
|
|
90370
90455
|
).reduce(
|
|
@@ -90374,37 +90459,36 @@ var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedService
|
|
|
90374
90459
|
},
|
|
90375
90460
|
{}
|
|
90376
90461
|
);
|
|
90377
|
-
for (const
|
|
90378
|
-
|
|
90379
|
-
|
|
90380
|
-
|
|
90381
|
-
const
|
|
90382
|
-
|
|
90383
|
-
|
|
90384
|
-
analysisLogger.warn(
|
|
90385
|
-
`\u26A0\uFE0F Service check function for ${serviceName} is not available`
|
|
90386
|
-
);
|
|
90387
|
-
}
|
|
90388
|
-
continue;
|
|
90389
|
-
}
|
|
90390
|
-
const typedServiceCheckFunction = serviceCheckFunction;
|
|
90391
|
-
const serviceAnalysisResult = typedServiceCheckFunction(
|
|
90392
|
-
{ Resources: userResources },
|
|
90393
|
-
createFinding2
|
|
90462
|
+
for (const checkKey of servicesToAnalyze) {
|
|
90463
|
+
try {
|
|
90464
|
+
const serviceCheckFunction = serviceChecks[checkKey];
|
|
90465
|
+
if (typeof serviceCheckFunction !== "function") {
|
|
90466
|
+
const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
|
|
90467
|
+
analysisLogger.warn(
|
|
90468
|
+
`\u26A0\uFE0F Service check function for ${serviceLabel} (${checkKey}) is not available`
|
|
90394
90469
|
);
|
|
90395
|
-
|
|
90396
|
-
serviceAnalysisResult
|
|
90397
|
-
)) {
|
|
90398
|
-
if (!analysisFindings[resourceName]) {
|
|
90399
|
-
analysisFindings[resourceName] = { issues: [] };
|
|
90400
|
-
}
|
|
90401
|
-
analysisFindings[resourceName].issues.push(...resourceFindings.issues);
|
|
90402
|
-
}
|
|
90403
|
-
} catch (analysisError) {
|
|
90404
|
-
analysisLogger.warn(`\u26A0\uFE0F Error in ${serviceName} analysis (${checkKey})`, {
|
|
90405
|
-
error: analysisError instanceof Error ? analysisError.message : String(analysisError)
|
|
90406
|
-
});
|
|
90470
|
+
continue;
|
|
90407
90471
|
}
|
|
90472
|
+
const serviceAnalysisResult = serviceCheckFunction(
|
|
90473
|
+
{ Resources: userResources },
|
|
90474
|
+
createFinding2
|
|
90475
|
+
);
|
|
90476
|
+
for (const [resourceName, resourceFindings] of Object.entries(
|
|
90477
|
+
serviceAnalysisResult
|
|
90478
|
+
)) {
|
|
90479
|
+
if (!analysisFindings[resourceName]) {
|
|
90480
|
+
analysisFindings[resourceName] = { issues: [] };
|
|
90481
|
+
}
|
|
90482
|
+
analysisFindings[resourceName].issues.push(...resourceFindings.issues);
|
|
90483
|
+
}
|
|
90484
|
+
} catch (analysisError) {
|
|
90485
|
+
const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
|
|
90486
|
+
analysisLogger.warn(
|
|
90487
|
+
`\u26A0\uFE0F Error in ${serviceLabel} analysis (${checkKey})`,
|
|
90488
|
+
{
|
|
90489
|
+
error: analysisError instanceof Error ? analysisError.message : String(analysisError)
|
|
90490
|
+
}
|
|
90491
|
+
);
|
|
90408
90492
|
}
|
|
90409
90493
|
}
|
|
90410
90494
|
if (Object.keys(solutionsRegistry).length > 0) {
|
|
@@ -94079,6 +94163,12 @@ var validateServices = (services) => {
|
|
|
94079
94163
|
}
|
|
94080
94164
|
return [];
|
|
94081
94165
|
};
|
|
94166
|
+
var validateServiceNames = (services) => {
|
|
94167
|
+
const parsed = validateServices(services);
|
|
94168
|
+
return parsed.map((service) => service.trim()).filter(Boolean).map(
|
|
94169
|
+
(service) => service.toLowerCase() === "all" ? "All services" : service
|
|
94170
|
+
).filter((service) => isServiceName(service));
|
|
94171
|
+
};
|
|
94082
94172
|
var validateCacheConfig = (cache3) => {
|
|
94083
94173
|
if (!cache3 || typeof cache3 !== "object" || Array.isArray(cache3)) {
|
|
94084
94174
|
return DEFAULT_CONFIG.cache;
|
|
@@ -94132,7 +94222,7 @@ var mergeConfigWithArgs = (config2, cliArgs) => {
|
|
|
94132
94222
|
output: validatedOutput,
|
|
94133
94223
|
format: validatedOutput,
|
|
94134
94224
|
// Keep format in sync with output
|
|
94135
|
-
services:
|
|
94225
|
+
services: validateServiceNames(
|
|
94136
94226
|
cliArgs.services ?? config2.services ?? DEFAULT_CONFIG.services
|
|
94137
94227
|
),
|
|
94138
94228
|
withIssue,
|
|
@@ -94202,9 +94292,9 @@ var validateConfig = (config2) => {
|
|
|
94202
94292
|
);
|
|
94203
94293
|
}
|
|
94204
94294
|
if (Array.isArray(raw.services)) {
|
|
94205
|
-
validated.services = raw.services.filter(
|
|
94206
|
-
(
|
|
94207
|
-
);
|
|
94295
|
+
validated.services = raw.services.filter((s3) => typeof s3 === "string").map(
|
|
94296
|
+
(service) => service.toLowerCase() === "all" ? "All services" : service
|
|
94297
|
+
).filter((service) => isServiceName(service));
|
|
94208
94298
|
}
|
|
94209
94299
|
if (typeof raw.withIssue === "boolean") {
|
|
94210
94300
|
validated.withIssue = raw.withIssue;
|
|
@@ -94571,12 +94661,14 @@ async function runStackAnalysis(finalConfig, fingerprint, authToken, licenseInfo
|
|
|
94571
94661
|
throw refreshError;
|
|
94572
94662
|
}
|
|
94573
94663
|
} : void 0;
|
|
94574
|
-
|
|
94575
|
-
const
|
|
94576
|
-
|
|
94577
|
-
|
|
94578
|
-
|
|
94579
|
-
|
|
94664
|
+
const serviceSelection = normalizeServiceSelection(finalConfig.services);
|
|
94665
|
+
const selectedServices = serviceSelection.services;
|
|
94666
|
+
if (serviceSelection.removedAllServices) {
|
|
94667
|
+
cliLogger.debug(
|
|
94668
|
+
`Services normalization: removed "All services", using: ${selectedServices.join(", ")}`
|
|
94669
|
+
);
|
|
94670
|
+
} else if (serviceSelection.defaultedToAll) {
|
|
94671
|
+
cliLogger.debug('Services normalization: defaulting to "All services"');
|
|
94580
94672
|
}
|
|
94581
94673
|
const analysisConfig = {
|
|
94582
94674
|
stacks,
|
|
@@ -94719,14 +94811,6 @@ var analyzeCommand = {
|
|
|
94719
94811
|
if (isInteractive2 && !initialConfig.yes) {
|
|
94720
94812
|
const answers = await promptForConfig(initialConfig, stackChoices);
|
|
94721
94813
|
finalConfig = { ...initialConfig, ...answers };
|
|
94722
|
-
if (finalConfig.services && finalConfig.services.length > 0) {
|
|
94723
|
-
const hasAllServices = finalConfig.services.includes("All services");
|
|
94724
|
-
const hasOtherServices = finalConfig.services.some((s3) => s3 !== "All services");
|
|
94725
|
-
if (hasAllServices && hasOtherServices) {
|
|
94726
|
-
finalConfig.services = finalConfig.services.filter((s3) => s3 !== "All services");
|
|
94727
|
-
cliLogger.debug(`Normalized services: removed "All services", using specific services: ${finalConfig.services.join(", ")}`);
|
|
94728
|
-
}
|
|
94729
|
-
}
|
|
94730
94814
|
}
|
|
94731
94815
|
if (finalConfig.all) {
|
|
94732
94816
|
finalConfig.stackName = "All stacks";
|
|
@@ -95107,7 +95191,14 @@ var handleConfigSetup = async () => {
|
|
|
95107
95191
|
`Services to scan (comma-separated, or "all") [${cfg.services?.join(",") || "all"}]: `
|
|
95108
95192
|
);
|
|
95109
95193
|
if (services.trim()) {
|
|
95110
|
-
|
|
95194
|
+
if (services.trim().toLowerCase() === "all") {
|
|
95195
|
+
cfg.services = [];
|
|
95196
|
+
} else {
|
|
95197
|
+
const parsedServices = services.trim().split(",").map((s3) => s3.trim()).map(
|
|
95198
|
+
(service) => service.toLowerCase() === "all" ? "All services" : service
|
|
95199
|
+
).filter((service) => isServiceName(service));
|
|
95200
|
+
cfg.services = parsedServices;
|
|
95201
|
+
}
|
|
95111
95202
|
}
|
|
95112
95203
|
console.log("\n\u{1F4BE} Cache configuration:");
|
|
95113
95204
|
const cacheEnabled = await question(
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ServiceCheckKey, ServiceName, SpecificServiceName } from '../../types/analysis.types';
|
|
2
|
+
export declare const SPECIFIC_SERVICE_NAMES: readonly ["IAM", "S3", "Lambda", "DynamoDB", "RDS", "EC2", "SNS", "SQS", "StepFunctions", "CloudTrail", "ApiGateway", "SecretsManager", "KMS", "EventBridge"];
|
|
3
|
+
export declare const normalizeServiceSelection: (services?: ServiceName[]) => {
|
|
4
|
+
services: ServiceName[];
|
|
5
|
+
removedAllServices: boolean;
|
|
6
|
+
defaultedToAll: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare const mapServicesToCheckKeys: (services: ServiceName[], allCheckKeys: ServiceCheckKey[]) => ServiceCheckKey[];
|
|
9
|
+
export declare const getServiceLabelForCheckKey: (checkKey: ServiceCheckKey) => SpecificServiceName | undefined;
|
|
10
|
+
export declare const isServiceName: (value: string) => value is ServiceName;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -54682,6 +54682,85 @@ var memoize = (functionToMemoize, options = {}) => {
|
|
|
54682
54682
|
};
|
|
54683
54683
|
};
|
|
54684
54684
|
|
|
54685
|
+
// src/helpers/serviceSelection/serviceSelection.ts
|
|
54686
|
+
var SERVICE_NAME_TO_CHECK_KEYS = {
|
|
54687
|
+
IAM: ["iamPolicies"],
|
|
54688
|
+
S3: ["s3Buckets", "s3IntelligentTiering"],
|
|
54689
|
+
Lambda: ["lambdaEnvironmentVariables", "lambdaMemory"],
|
|
54690
|
+
DynamoDB: ["dynamoDBAutoScaling", "dynamoDBStreams"],
|
|
54691
|
+
RDS: ["rdsEncryption", "rdsMultiAZ"],
|
|
54692
|
+
EC2: ["ec2InstanceType", "natGatewayUsage", "securityGroups", "ebsUnusedVolumes"],
|
|
54693
|
+
SNS: ["sns"],
|
|
54694
|
+
SQS: ["sqs"],
|
|
54695
|
+
StepFunctions: ["stepFunctions"],
|
|
54696
|
+
CloudTrail: ["cloudTrailLogging"],
|
|
54697
|
+
ApiGateway: ["apiGateway"],
|
|
54698
|
+
SecretsManager: ["secretsManager"],
|
|
54699
|
+
KMS: ["kmsKeys"],
|
|
54700
|
+
EventBridge: ["eventBridgeRules"]
|
|
54701
|
+
};
|
|
54702
|
+
var CHECK_KEY_TO_SERVICE_NAME = Object.entries(
|
|
54703
|
+
SERVICE_NAME_TO_CHECK_KEYS
|
|
54704
|
+
).reduce((acc, [service, keys]) => {
|
|
54705
|
+
for (const key of keys) {
|
|
54706
|
+
acc[key] = service;
|
|
54707
|
+
}
|
|
54708
|
+
return acc;
|
|
54709
|
+
}, {});
|
|
54710
|
+
var dedupe = (items) => {
|
|
54711
|
+
const seen = /* @__PURE__ */ new Set();
|
|
54712
|
+
const result = [];
|
|
54713
|
+
for (const item of items) {
|
|
54714
|
+
if (seen.has(item)) {
|
|
54715
|
+
continue;
|
|
54716
|
+
}
|
|
54717
|
+
seen.add(item);
|
|
54718
|
+
result.push(item);
|
|
54719
|
+
}
|
|
54720
|
+
return result;
|
|
54721
|
+
};
|
|
54722
|
+
var normalizeServiceSelection = (services) => {
|
|
54723
|
+
if (!services || services.length === 0) {
|
|
54724
|
+
return {
|
|
54725
|
+
services: ["All services"],
|
|
54726
|
+
removedAllServices: false,
|
|
54727
|
+
defaultedToAll: true
|
|
54728
|
+
};
|
|
54729
|
+
}
|
|
54730
|
+
const uniqueServices = dedupe(services);
|
|
54731
|
+
const hasAllServices = uniqueServices.includes("All services");
|
|
54732
|
+
const specificServices = uniqueServices.filter(
|
|
54733
|
+
(service) => service !== "All services"
|
|
54734
|
+
);
|
|
54735
|
+
if (hasAllServices && specificServices.length > 0) {
|
|
54736
|
+
return {
|
|
54737
|
+
services: specificServices,
|
|
54738
|
+
removedAllServices: true,
|
|
54739
|
+
defaultedToAll: false
|
|
54740
|
+
};
|
|
54741
|
+
}
|
|
54742
|
+
return {
|
|
54743
|
+
services: hasAllServices ? ["All services"] : uniqueServices,
|
|
54744
|
+
removedAllServices: false,
|
|
54745
|
+
defaultedToAll: false
|
|
54746
|
+
};
|
|
54747
|
+
};
|
|
54748
|
+
var mapServicesToCheckKeys = (services, allCheckKeys) => {
|
|
54749
|
+
if (services.length === 0 || services.includes("All services")) {
|
|
54750
|
+
return dedupe(allCheckKeys);
|
|
54751
|
+
}
|
|
54752
|
+
const resolvedKeys = services.flatMap((service) => {
|
|
54753
|
+
if (service === "All services") {
|
|
54754
|
+
return allCheckKeys;
|
|
54755
|
+
}
|
|
54756
|
+
return SERVICE_NAME_TO_CHECK_KEYS[service] ?? [];
|
|
54757
|
+
});
|
|
54758
|
+
return dedupe(resolvedKeys);
|
|
54759
|
+
};
|
|
54760
|
+
var getServiceLabelForCheckKey = (checkKey) => {
|
|
54761
|
+
return CHECK_KEY_TO_SERVICE_NAME[checkKey];
|
|
54762
|
+
};
|
|
54763
|
+
|
|
54685
54764
|
// src/shared/logger.ts
|
|
54686
54765
|
var import_strogger = __toESM(require_dist());
|
|
54687
54766
|
var isDevelopment = process.env.NODE_ENV === "development";
|
|
@@ -54729,25 +54808,6 @@ var memoizedServiceChecks = memoize(createAWSServiceChecks, {
|
|
|
54729
54808
|
// 10 minutes
|
|
54730
54809
|
maxSize: 10
|
|
54731
54810
|
});
|
|
54732
|
-
var getServiceCheckKeys = (serviceName) => {
|
|
54733
|
-
const serviceMapping = {
|
|
54734
|
-
"Lambda": ["lambdaEnvironmentVariables", "lambdaMemory"],
|
|
54735
|
-
"S3": ["s3Buckets", "s3IntelligentTiering"],
|
|
54736
|
-
"DynamoDB": ["dynamoDBAutoScaling", "dynamoDBStreams"],
|
|
54737
|
-
"RDS": ["rdsEncryption", "rdsMultiAZ"],
|
|
54738
|
-
"EC2": ["ec2InstanceType", "natGatewayUsage", "securityGroups", "ebsUnusedVolumes"],
|
|
54739
|
-
"IAM": ["iamPolicies"],
|
|
54740
|
-
"SNS": ["sns"],
|
|
54741
|
-
"SQS": ["sqs"],
|
|
54742
|
-
"StepFunctions": ["stepFunctions"],
|
|
54743
|
-
"CloudTrail": ["cloudTrailLogging"],
|
|
54744
|
-
"ApiGateway": ["apiGateway"],
|
|
54745
|
-
"SecretsManager": ["secretsManager"],
|
|
54746
|
-
"KMS": ["kmsKeys"],
|
|
54747
|
-
"EventBridge": ["eventBridgeRules"]
|
|
54748
|
-
};
|
|
54749
|
-
return serviceMapping[serviceName] || [serviceName];
|
|
54750
|
-
};
|
|
54751
54811
|
var createResourceFilter = (selectedServices) => {
|
|
54752
54812
|
if (selectedServices.includes("All services")) {
|
|
54753
54813
|
return (cloudFormationResource) => !cloudFormationResource.Type.startsWith("AWS::CDK::");
|
|
@@ -54764,13 +54824,16 @@ var createResourceFilter = (selectedServices) => {
|
|
|
54764
54824
|
};
|
|
54765
54825
|
var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedServices = [], solutionsRegistry = {}) => {
|
|
54766
54826
|
const serviceChecks = memoizedServiceChecks();
|
|
54767
|
-
const allServiceKeys = Object.keys(serviceChecks)
|
|
54768
|
-
const servicesToAnalyze = selectedServices.length > 0 && !selectedServices.includes("All services") ? selectedServices : allServiceKeys.filter(
|
|
54827
|
+
const allServiceKeys = Object.keys(serviceChecks).filter(
|
|
54769
54828
|
(serviceKey) => serviceKey !== "solutionsPatterns"
|
|
54770
54829
|
);
|
|
54771
|
-
const
|
|
54830
|
+
const { services: normalizedServices } = normalizeServiceSelection(selectedServices);
|
|
54831
|
+
const servicesToAnalyze = mapServicesToCheckKeys(
|
|
54832
|
+
normalizedServices,
|
|
54833
|
+
allServiceKeys
|
|
54834
|
+
);
|
|
54772
54835
|
const analysisFindings = {};
|
|
54773
|
-
const resourceFilter = createResourceFilter(
|
|
54836
|
+
const resourceFilter = createResourceFilter(normalizedServices);
|
|
54774
54837
|
const userResources = Object.entries(cloudformationTemplate.Resources || {}).filter(
|
|
54775
54838
|
([, cloudFormationResource]) => resourceFilter(cloudFormationResource)
|
|
54776
54839
|
).reduce(
|
|
@@ -54780,37 +54843,36 @@ var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedService
|
|
|
54780
54843
|
},
|
|
54781
54844
|
{}
|
|
54782
54845
|
);
|
|
54783
|
-
for (const
|
|
54784
|
-
|
|
54785
|
-
|
|
54786
|
-
|
|
54787
|
-
const
|
|
54788
|
-
|
|
54789
|
-
|
|
54790
|
-
analysisLogger.warn(
|
|
54791
|
-
`\u26A0\uFE0F Service check function for ${serviceName} is not available`
|
|
54792
|
-
);
|
|
54793
|
-
}
|
|
54794
|
-
continue;
|
|
54795
|
-
}
|
|
54796
|
-
const typedServiceCheckFunction = serviceCheckFunction;
|
|
54797
|
-
const serviceAnalysisResult = typedServiceCheckFunction(
|
|
54798
|
-
{ Resources: userResources },
|
|
54799
|
-
createFinding2
|
|
54846
|
+
for (const checkKey of servicesToAnalyze) {
|
|
54847
|
+
try {
|
|
54848
|
+
const serviceCheckFunction = serviceChecks[checkKey];
|
|
54849
|
+
if (typeof serviceCheckFunction !== "function") {
|
|
54850
|
+
const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
|
|
54851
|
+
analysisLogger.warn(
|
|
54852
|
+
`\u26A0\uFE0F Service check function for ${serviceLabel} (${checkKey}) is not available`
|
|
54800
54853
|
);
|
|
54801
|
-
|
|
54802
|
-
serviceAnalysisResult
|
|
54803
|
-
)) {
|
|
54804
|
-
if (!analysisFindings[resourceName]) {
|
|
54805
|
-
analysisFindings[resourceName] = { issues: [] };
|
|
54806
|
-
}
|
|
54807
|
-
analysisFindings[resourceName].issues.push(...resourceFindings.issues);
|
|
54808
|
-
}
|
|
54809
|
-
} catch (analysisError) {
|
|
54810
|
-
analysisLogger.warn(`\u26A0\uFE0F Error in ${serviceName} analysis (${checkKey})`, {
|
|
54811
|
-
error: analysisError instanceof Error ? analysisError.message : String(analysisError)
|
|
54812
|
-
});
|
|
54854
|
+
continue;
|
|
54813
54855
|
}
|
|
54856
|
+
const serviceAnalysisResult = serviceCheckFunction(
|
|
54857
|
+
{ Resources: userResources },
|
|
54858
|
+
createFinding2
|
|
54859
|
+
);
|
|
54860
|
+
for (const [resourceName, resourceFindings] of Object.entries(
|
|
54861
|
+
serviceAnalysisResult
|
|
54862
|
+
)) {
|
|
54863
|
+
if (!analysisFindings[resourceName]) {
|
|
54864
|
+
analysisFindings[resourceName] = { issues: [] };
|
|
54865
|
+
}
|
|
54866
|
+
analysisFindings[resourceName].issues.push(...resourceFindings.issues);
|
|
54867
|
+
}
|
|
54868
|
+
} catch (analysisError) {
|
|
54869
|
+
const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
|
|
54870
|
+
analysisLogger.warn(
|
|
54871
|
+
`\u26A0\uFE0F Error in ${serviceLabel} analysis (${checkKey})`,
|
|
54872
|
+
{
|
|
54873
|
+
error: analysisError instanceof Error ? analysisError.message : String(analysisError)
|
|
54874
|
+
}
|
|
54875
|
+
);
|
|
54814
54876
|
}
|
|
54815
54877
|
}
|
|
54816
54878
|
if (Object.keys(solutionsRegistry).length > 0) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ConstructMetadata } from '../analysis/static/solutionConstructs/loadConstructMetadata';
|
|
2
2
|
import type { AWSServiceChecks } from '../functions/factories/awsServices';
|
|
3
|
-
export type
|
|
3
|
+
export type ServiceCheckKey = Exclude<keyof AWSServiceChecks, 'solutionsPatterns'>;
|
|
4
|
+
export type SpecificServiceName = 'IAM' | 'S3' | 'Lambda' | 'DynamoDB' | 'RDS' | 'EC2' | 'SNS' | 'SQS' | 'StepFunctions' | 'CloudTrail' | 'ApiGateway' | 'SecretsManager' | 'KMS' | 'EventBridge';
|
|
5
|
+
export type ServiceName = 'All services' | SpecificServiceName;
|
|
4
6
|
export type RunAnalysisTypes = {
|
|
5
7
|
stacks: Record<string, CloudFormationStack>;
|
|
6
8
|
inlineFindings: Issue[];
|