cdk-insights 0.4.6 → 0.4.8-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.
@@ -33691,7 +33691,7 @@ var require_branded_api_example = __commonJS({
33691
33691
  var demonstrateBrandedAPI = () => {
33692
33692
  const env = (0, index_1.getEnvironment)();
33693
33693
  const formatter = (0, index_1.createJsonFormatter)();
33694
- const consoleTransport = (0, index_1.createStroggerConsoleTransport)({
33694
+ const consoleTransport2 = (0, index_1.createStroggerConsoleTransport)({
33695
33695
  formatter,
33696
33696
  level: index_1.LogLevel.DEBUG
33697
33697
  });
@@ -33705,7 +33705,7 @@ var require_branded_api_example = __commonJS({
33705
33705
  serviceName: "branded-api-demo",
33706
33706
  stage: env.stage
33707
33707
  },
33708
- transports: [consoleTransport, dataDogTransport],
33708
+ transports: [consoleTransport2, dataDogTransport],
33709
33709
  formatter,
33710
33710
  env
33711
33711
  });
@@ -33995,23 +33995,26 @@ var import_cdk_nag = require("cdk-nag");
33995
33995
  var import_strogger = __toESM(require_dist());
33996
33996
  var isDevelopment = process.env.NODE_ENV === "development";
33997
33997
  var isDebugEnabled = process.env.CDK_INSIGHTS_DEBUG === "true" || process.env.CDK_INSIGHTS_VERBOSE === "true";
33998
+ var isConsoleLoggingEnabled = isDevelopment || isDebugEnabled || process.env.CDK_INSIGHTS_ENABLE_LOGGING === "true";
33999
+ var defaultLogLevel = isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.ERROR;
34000
+ var consoleTransport = isConsoleLoggingEnabled ? [
34001
+ (0, import_strogger.createConsoleTransport)({
34002
+ formatter: (0, import_strogger.createJsonFormatter)(),
34003
+ level: defaultLogLevel,
34004
+ useColors: !isDevelopment
34005
+ })
34006
+ ] : [];
33998
34007
  var logger3 = (0, import_strogger.createLogger)({
33999
34008
  config: {
34000
- level: isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.WARN,
34009
+ level: defaultLogLevel,
34001
34010
  serviceName: "cdk-insights",
34002
34011
  stage: isDevelopment ? "dev" : "prod"
34003
34012
  },
34004
34013
  formatter: (0, import_strogger.createJsonFormatter)(),
34005
- transports: [
34006
- (0, import_strogger.createConsoleTransport)({
34007
- formatter: (0, import_strogger.createJsonFormatter)(),
34008
- level: isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.WARN,
34009
- useColors: !isDevelopment
34010
- })
34011
- ],
34014
+ transports: consoleTransport,
34012
34015
  env: {
34013
34016
  STAGE: isDevelopment ? "dev" : "prod",
34014
- LOG_LEVEL: isDebugEnabled ? "DEBUG" : isDevelopment ? "INFO" : "WARN"
34017
+ LOG_LEVEL: isDebugEnabled ? "DEBUG" : isDevelopment ? "INFO" : "ERROR"
34015
34018
  }
34016
34019
  });
34017
34020
  var createComponentLogger = (component) => ({
package/dist/cli/entry.js CHANGED
@@ -35831,7 +35831,7 @@ var require_branded_api_example = __commonJS({
35831
35831
  var demonstrateBrandedAPI = () => {
35832
35832
  const env4 = (0, index_1.getEnvironment)();
35833
35833
  const formatter = (0, index_1.createJsonFormatter)();
35834
- const consoleTransport = (0, index_1.createStroggerConsoleTransport)({
35834
+ const consoleTransport2 = (0, index_1.createStroggerConsoleTransport)({
35835
35835
  formatter,
35836
35836
  level: index_1.LogLevel.DEBUG
35837
35837
  });
@@ -35845,7 +35845,7 @@ var require_branded_api_example = __commonJS({
35845
35845
  serviceName: "branded-api-demo",
35846
35846
  stage: env4.stage
35847
35847
  },
35848
- transports: [consoleTransport, dataDogTransport],
35848
+ transports: [consoleTransport2, dataDogTransport],
35849
35849
  formatter,
35850
35850
  env: env4
35851
35851
  });
@@ -78612,23 +78612,26 @@ var getFeatureUpgradeMessage = (feature, tier, context) => {
78612
78612
  var import_strogger = __toESM(require_dist());
78613
78613
  var isDevelopment = process.env.NODE_ENV === "development";
78614
78614
  var isDebugEnabled = process.env.CDK_INSIGHTS_DEBUG === "true" || process.env.CDK_INSIGHTS_VERBOSE === "true";
78615
+ var isConsoleLoggingEnabled = isDevelopment || isDebugEnabled || process.env.CDK_INSIGHTS_ENABLE_LOGGING === "true";
78616
+ var defaultLogLevel = isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.ERROR;
78617
+ var consoleTransport = isConsoleLoggingEnabled ? [
78618
+ (0, import_strogger.createConsoleTransport)({
78619
+ formatter: (0, import_strogger.createJsonFormatter)(),
78620
+ level: defaultLogLevel,
78621
+ useColors: !isDevelopment
78622
+ })
78623
+ ] : [];
78615
78624
  var logger3 = (0, import_strogger.createLogger)({
78616
78625
  config: {
78617
- level: isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.WARN,
78626
+ level: defaultLogLevel,
78618
78627
  serviceName: "cdk-insights",
78619
78628
  stage: isDevelopment ? "dev" : "prod"
78620
78629
  },
78621
78630
  formatter: (0, import_strogger.createJsonFormatter)(),
78622
- transports: [
78623
- (0, import_strogger.createConsoleTransport)({
78624
- formatter: (0, import_strogger.createJsonFormatter)(),
78625
- level: isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.WARN,
78626
- useColors: !isDevelopment
78627
- })
78628
- ],
78631
+ transports: consoleTransport,
78629
78632
  env: {
78630
78633
  STAGE: isDevelopment ? "dev" : "prod",
78631
- LOG_LEVEL: isDebugEnabled ? "DEBUG" : isDevelopment ? "INFO" : "WARN"
78634
+ LOG_LEVEL: isDebugEnabled ? "DEBUG" : isDevelopment ? "INFO" : "ERROR"
78632
78635
  }
78633
78636
  });
78634
78637
  var createComponentLogger = (component) => ({
@@ -78757,6 +78760,107 @@ var recordCacheSet = () => {
78757
78760
  saveCacheStats();
78758
78761
  };
78759
78762
 
78763
+ // src/helpers/serviceSelection/serviceSelection.ts
78764
+ var SPECIFIC_SERVICE_NAMES = [
78765
+ "IAM",
78766
+ "S3",
78767
+ "Lambda",
78768
+ "DynamoDB",
78769
+ "RDS",
78770
+ "EC2",
78771
+ "SNS",
78772
+ "SQS",
78773
+ "StepFunctions",
78774
+ "CloudTrail",
78775
+ "ApiGateway",
78776
+ "SecretsManager",
78777
+ "KMS",
78778
+ "EventBridge"
78779
+ ];
78780
+ var SERVICE_NAME_TO_CHECK_KEYS = {
78781
+ IAM: ["iamPolicies"],
78782
+ S3: ["s3Buckets", "s3IntelligentTiering"],
78783
+ Lambda: ["lambdaEnvironmentVariables", "lambdaMemory"],
78784
+ DynamoDB: ["dynamoDBAutoScaling", "dynamoDBStreams"],
78785
+ RDS: ["rdsEncryption", "rdsMultiAZ"],
78786
+ EC2: ["ec2InstanceType", "natGatewayUsage", "securityGroups", "ebsUnusedVolumes"],
78787
+ SNS: ["sns"],
78788
+ SQS: ["sqs"],
78789
+ StepFunctions: ["stepFunctions"],
78790
+ CloudTrail: ["cloudTrailLogging"],
78791
+ ApiGateway: ["apiGateway"],
78792
+ SecretsManager: ["secretsManager"],
78793
+ KMS: ["kmsKeys"],
78794
+ EventBridge: ["eventBridgeRules"]
78795
+ };
78796
+ var CHECK_KEY_TO_SERVICE_NAME = Object.entries(
78797
+ SERVICE_NAME_TO_CHECK_KEYS
78798
+ ).reduce((acc, [service, keys]) => {
78799
+ for (const key of keys) {
78800
+ acc[key] = service;
78801
+ }
78802
+ return acc;
78803
+ }, {});
78804
+ var dedupe = (items) => {
78805
+ const seen = /* @__PURE__ */ new Set();
78806
+ const result = [];
78807
+ for (const item of items) {
78808
+ if (seen.has(item)) {
78809
+ continue;
78810
+ }
78811
+ seen.add(item);
78812
+ result.push(item);
78813
+ }
78814
+ return result;
78815
+ };
78816
+ var normalizeServiceSelection = (services) => {
78817
+ if (!services || services.length === 0) {
78818
+ return {
78819
+ services: ["All services"],
78820
+ removedAllServices: false,
78821
+ defaultedToAll: true
78822
+ };
78823
+ }
78824
+ const uniqueServices = dedupe(services);
78825
+ const hasAllServices = uniqueServices.includes("All services");
78826
+ const specificServices = uniqueServices.filter(
78827
+ (service) => service !== "All services"
78828
+ );
78829
+ if (hasAllServices && specificServices.length > 0) {
78830
+ return {
78831
+ services: specificServices,
78832
+ removedAllServices: true,
78833
+ defaultedToAll: false
78834
+ };
78835
+ }
78836
+ return {
78837
+ services: hasAllServices ? ["All services"] : uniqueServices,
78838
+ removedAllServices: false,
78839
+ defaultedToAll: false
78840
+ };
78841
+ };
78842
+ var mapServicesToCheckKeys = (services, allCheckKeys) => {
78843
+ if (services.length === 0 || services.includes("All services")) {
78844
+ return dedupe(allCheckKeys);
78845
+ }
78846
+ const resolvedKeys = services.flatMap((service) => {
78847
+ if (service === "All services") {
78848
+ return allCheckKeys;
78849
+ }
78850
+ return SERVICE_NAME_TO_CHECK_KEYS[service] ?? [];
78851
+ });
78852
+ return dedupe(resolvedKeys);
78853
+ };
78854
+ var getServiceLabelForCheckKey = (checkKey) => {
78855
+ return CHECK_KEY_TO_SERVICE_NAME[checkKey];
78856
+ };
78857
+ var isServiceName = (value) => {
78858
+ if (value === "All services") {
78859
+ return true;
78860
+ }
78861
+ return SPECIFIC_SERVICE_NAMES.includes(value);
78862
+ };
78863
+
78760
78864
  // node_modules/axios/lib/helpers/bind.js
78761
78865
  function bind(fn, thisArg) {
78762
78866
  return function wrap2() {
@@ -90323,25 +90427,6 @@ var memoizedServiceChecks = memoize(createAWSServiceChecks, {
90323
90427
  // 10 minutes
90324
90428
  maxSize: 10
90325
90429
  });
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
90430
  var createResourceFilter = (selectedServices) => {
90346
90431
  if (selectedServices.includes("All services")) {
90347
90432
  return (cloudFormationResource) => !cloudFormationResource.Type.startsWith("AWS::CDK::");
@@ -90358,13 +90443,16 @@ var createResourceFilter = (selectedServices) => {
90358
90443
  };
90359
90444
  var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedServices = [], solutionsRegistry = {}) => {
90360
90445
  const serviceChecks = memoizedServiceChecks();
90361
- const allServiceKeys = Object.keys(serviceChecks);
90362
- const servicesToAnalyze = selectedServices.length > 0 && !selectedServices.includes("All services") ? selectedServices : allServiceKeys.filter(
90446
+ const allServiceKeys = Object.keys(serviceChecks).filter(
90363
90447
  (serviceKey) => serviceKey !== "solutionsPatterns"
90364
90448
  );
90365
- const isAllServices = selectedServices.includes("All services") || selectedServices.length === 0;
90449
+ const { services: normalizedServices } = normalizeServiceSelection(selectedServices);
90450
+ const servicesToAnalyze = mapServicesToCheckKeys(
90451
+ normalizedServices,
90452
+ allServiceKeys
90453
+ );
90366
90454
  const analysisFindings = {};
90367
- const resourceFilter = createResourceFilter(selectedServices);
90455
+ const resourceFilter = createResourceFilter(normalizedServices);
90368
90456
  const userResources = Object.entries(cloudformationTemplate.Resources || {}).filter(
90369
90457
  ([, cloudFormationResource]) => resourceFilter(cloudFormationResource)
90370
90458
  ).reduce(
@@ -90374,37 +90462,36 @@ var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedService
90374
90462
  },
90375
90463
  {}
90376
90464
  );
90377
- for (const serviceName of servicesToAnalyze) {
90378
- const checkKeys = isAllServices ? [serviceName] : getServiceCheckKeys(serviceName);
90379
- for (const checkKey of checkKeys) {
90380
- try {
90381
- const serviceCheckFunction = serviceChecks[checkKey];
90382
- if (typeof serviceCheckFunction !== "function") {
90383
- if (checkKeys.indexOf(checkKey) === checkKeys.length - 1) {
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
90465
+ for (const checkKey of servicesToAnalyze) {
90466
+ try {
90467
+ const serviceCheckFunction = serviceChecks[checkKey];
90468
+ if (typeof serviceCheckFunction !== "function") {
90469
+ const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
90470
+ analysisLogger.warn(
90471
+ `\u26A0\uFE0F Service check function for ${serviceLabel} (${checkKey}) is not available`
90394
90472
  );
90395
- for (const [resourceName, resourceFindings] of Object.entries(
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
- });
90473
+ continue;
90407
90474
  }
90475
+ const serviceAnalysisResult = serviceCheckFunction(
90476
+ { Resources: userResources },
90477
+ createFinding2
90478
+ );
90479
+ for (const [resourceName, resourceFindings] of Object.entries(
90480
+ serviceAnalysisResult
90481
+ )) {
90482
+ if (!analysisFindings[resourceName]) {
90483
+ analysisFindings[resourceName] = { issues: [] };
90484
+ }
90485
+ analysisFindings[resourceName].issues.push(...resourceFindings.issues);
90486
+ }
90487
+ } catch (analysisError) {
90488
+ const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
90489
+ analysisLogger.warn(
90490
+ `\u26A0\uFE0F Error in ${serviceLabel} analysis (${checkKey})`,
90491
+ {
90492
+ error: analysisError instanceof Error ? analysisError.message : String(analysisError)
90493
+ }
90494
+ );
90408
90495
  }
90409
90496
  }
90410
90497
  if (Object.keys(solutionsRegistry).length > 0) {
@@ -94079,6 +94166,12 @@ var validateServices = (services) => {
94079
94166
  }
94080
94167
  return [];
94081
94168
  };
94169
+ var validateServiceNames = (services) => {
94170
+ const parsed = validateServices(services);
94171
+ return parsed.map((service) => service.trim()).filter(Boolean).map(
94172
+ (service) => service.toLowerCase() === "all" ? "All services" : service
94173
+ ).filter((service) => isServiceName(service));
94174
+ };
94082
94175
  var validateCacheConfig = (cache3) => {
94083
94176
  if (!cache3 || typeof cache3 !== "object" || Array.isArray(cache3)) {
94084
94177
  return DEFAULT_CONFIG.cache;
@@ -94132,7 +94225,7 @@ var mergeConfigWithArgs = (config2, cliArgs) => {
94132
94225
  output: validatedOutput,
94133
94226
  format: validatedOutput,
94134
94227
  // Keep format in sync with output
94135
- services: validateServices(
94228
+ services: validateServiceNames(
94136
94229
  cliArgs.services ?? config2.services ?? DEFAULT_CONFIG.services
94137
94230
  ),
94138
94231
  withIssue,
@@ -94202,9 +94295,9 @@ var validateConfig = (config2) => {
94202
94295
  );
94203
94296
  }
94204
94297
  if (Array.isArray(raw.services)) {
94205
- validated.services = raw.services.filter(
94206
- (s3) => typeof s3 === "string"
94207
- );
94298
+ validated.services = raw.services.filter((s3) => typeof s3 === "string").map(
94299
+ (service) => service.toLowerCase() === "all" ? "All services" : service
94300
+ ).filter((service) => isServiceName(service));
94208
94301
  }
94209
94302
  if (typeof raw.withIssue === "boolean") {
94210
94303
  validated.withIssue = raw.withIssue;
@@ -94571,12 +94664,14 @@ async function runStackAnalysis(finalConfig, fingerprint, authToken, licenseInfo
94571
94664
  throw refreshError;
94572
94665
  }
94573
94666
  } : void 0;
94574
- let selectedServices = finalConfig.services && finalConfig.services.length > 0 ? finalConfig.services : ["All services"];
94575
- const hasAllServices = selectedServices.includes("All services");
94576
- const hasOtherServices = selectedServices.some((s3) => s3 !== "All services");
94577
- if (hasAllServices && hasOtherServices) {
94578
- selectedServices = selectedServices.filter((s3) => s3 !== "All services");
94579
- cliLogger.debug(`Services normalization: removed "All services", using: ${selectedServices.join(", ")}`);
94667
+ const serviceSelection = normalizeServiceSelection(finalConfig.services);
94668
+ const selectedServices = serviceSelection.services;
94669
+ if (serviceSelection.removedAllServices) {
94670
+ cliLogger.debug(
94671
+ `Services normalization: removed "All services", using: ${selectedServices.join(", ")}`
94672
+ );
94673
+ } else if (serviceSelection.defaultedToAll) {
94674
+ cliLogger.debug('Services normalization: defaulting to "All services"');
94580
94675
  }
94581
94676
  const analysisConfig = {
94582
94677
  stacks,
@@ -94719,14 +94814,6 @@ var analyzeCommand = {
94719
94814
  if (isInteractive2 && !initialConfig.yes) {
94720
94815
  const answers = await promptForConfig(initialConfig, stackChoices);
94721
94816
  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
94817
  }
94731
94818
  if (finalConfig.all) {
94732
94819
  finalConfig.stackName = "All stacks";
@@ -95107,7 +95194,14 @@ var handleConfigSetup = async () => {
95107
95194
  `Services to scan (comma-separated, or "all") [${cfg.services?.join(",") || "all"}]: `
95108
95195
  );
95109
95196
  if (services.trim()) {
95110
- cfg.services = services.trim().toLowerCase() === "all" ? [] : services.trim().split(",").map((s3) => s3.trim());
95197
+ if (services.trim().toLowerCase() === "all") {
95198
+ cfg.services = [];
95199
+ } else {
95200
+ const parsedServices = services.trim().split(",").map((s3) => s3.trim()).map(
95201
+ (service) => service.toLowerCase() === "all" ? "All services" : service
95202
+ ).filter((service) => isServiceName(service));
95203
+ cfg.services = parsedServices;
95204
+ }
95111
95205
  }
95112
95206
  console.log("\n\u{1F4BE} Cache configuration:");
95113
95207
  const cacheEnabled = await question(
@@ -6,7 +6,7 @@ export interface AnalyzeCommandArgs {
6
6
  withIssue?: boolean;
7
7
  output?: string;
8
8
  all?: boolean;
9
- services?: string[];
9
+ services?: ServiceName[];
10
10
  format?: string;
11
11
  yes?: boolean;
12
12
  reset?: boolean;
@@ -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;
package/dist/index.js CHANGED
@@ -45306,7 +45306,7 @@ var require_branded_api_example = __commonJS({
45306
45306
  var demonstrateBrandedAPI = () => {
45307
45307
  const env2 = (0, index_1.getEnvironment)();
45308
45308
  const formatter = (0, index_1.createJsonFormatter)();
45309
- const consoleTransport = (0, index_1.createStroggerConsoleTransport)({
45309
+ const consoleTransport2 = (0, index_1.createStroggerConsoleTransport)({
45310
45310
  formatter,
45311
45311
  level: index_1.LogLevel.DEBUG
45312
45312
  });
@@ -45320,7 +45320,7 @@ var require_branded_api_example = __commonJS({
45320
45320
  serviceName: "branded-api-demo",
45321
45321
  stage: env2.stage
45322
45322
  },
45323
- transports: [consoleTransport, dataDogTransport],
45323
+ transports: [consoleTransport2, dataDogTransport],
45324
45324
  formatter,
45325
45325
  env: env2
45326
45326
  });
@@ -54682,27 +54682,109 @@ 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";
54688
54767
  var isDebugEnabled = process.env.CDK_INSIGHTS_DEBUG === "true" || process.env.CDK_INSIGHTS_VERBOSE === "true";
54768
+ var isConsoleLoggingEnabled = isDevelopment || isDebugEnabled || process.env.CDK_INSIGHTS_ENABLE_LOGGING === "true";
54769
+ var defaultLogLevel = isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.ERROR;
54770
+ var consoleTransport = isConsoleLoggingEnabled ? [
54771
+ (0, import_strogger.createConsoleTransport)({
54772
+ formatter: (0, import_strogger.createJsonFormatter)(),
54773
+ level: defaultLogLevel,
54774
+ useColors: !isDevelopment
54775
+ })
54776
+ ] : [];
54689
54777
  var logger3 = (0, import_strogger.createLogger)({
54690
54778
  config: {
54691
- level: isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.WARN,
54779
+ level: defaultLogLevel,
54692
54780
  serviceName: "cdk-insights",
54693
54781
  stage: isDevelopment ? "dev" : "prod"
54694
54782
  },
54695
54783
  formatter: (0, import_strogger.createJsonFormatter)(),
54696
- transports: [
54697
- (0, import_strogger.createConsoleTransport)({
54698
- formatter: (0, import_strogger.createJsonFormatter)(),
54699
- level: isDebugEnabled ? import_strogger.LogLevel.DEBUG : isDevelopment ? import_strogger.LogLevel.INFO : import_strogger.LogLevel.WARN,
54700
- useColors: !isDevelopment
54701
- })
54702
- ],
54784
+ transports: consoleTransport,
54703
54785
  env: {
54704
54786
  STAGE: isDevelopment ? "dev" : "prod",
54705
- LOG_LEVEL: isDebugEnabled ? "DEBUG" : isDevelopment ? "INFO" : "WARN"
54787
+ LOG_LEVEL: isDebugEnabled ? "DEBUG" : isDevelopment ? "INFO" : "ERROR"
54706
54788
  }
54707
54789
  });
54708
54790
  var createComponentLogger = (component) => ({
@@ -54729,25 +54811,6 @@ var memoizedServiceChecks = memoize(createAWSServiceChecks, {
54729
54811
  // 10 minutes
54730
54812
  maxSize: 10
54731
54813
  });
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
54814
  var createResourceFilter = (selectedServices) => {
54752
54815
  if (selectedServices.includes("All services")) {
54753
54816
  return (cloudFormationResource) => !cloudFormationResource.Type.startsWith("AWS::CDK::");
@@ -54764,13 +54827,16 @@ var createResourceFilter = (selectedServices) => {
54764
54827
  };
54765
54828
  var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedServices = [], solutionsRegistry = {}) => {
54766
54829
  const serviceChecks = memoizedServiceChecks();
54767
- const allServiceKeys = Object.keys(serviceChecks);
54768
- const servicesToAnalyze = selectedServices.length > 0 && !selectedServices.includes("All services") ? selectedServices : allServiceKeys.filter(
54830
+ const allServiceKeys = Object.keys(serviceChecks).filter(
54769
54831
  (serviceKey) => serviceKey !== "solutionsPatterns"
54770
54832
  );
54771
- const isAllServices = selectedServices.includes("All services") || selectedServices.length === 0;
54833
+ const { services: normalizedServices } = normalizeServiceSelection(selectedServices);
54834
+ const servicesToAnalyze = mapServicesToCheckKeys(
54835
+ normalizedServices,
54836
+ allServiceKeys
54837
+ );
54772
54838
  const analysisFindings = {};
54773
- const resourceFilter = createResourceFilter(selectedServices);
54839
+ const resourceFilter = createResourceFilter(normalizedServices);
54774
54840
  const userResources = Object.entries(cloudformationTemplate.Resources || {}).filter(
54775
54841
  ([, cloudFormationResource]) => resourceFilter(cloudFormationResource)
54776
54842
  ).reduce(
@@ -54780,37 +54846,36 @@ var runStaticAnalysis = (cloudformationTemplate, createFinding2, selectedService
54780
54846
  },
54781
54847
  {}
54782
54848
  );
54783
- for (const serviceName of servicesToAnalyze) {
54784
- const checkKeys = isAllServices ? [serviceName] : getServiceCheckKeys(serviceName);
54785
- for (const checkKey of checkKeys) {
54786
- try {
54787
- const serviceCheckFunction = serviceChecks[checkKey];
54788
- if (typeof serviceCheckFunction !== "function") {
54789
- if (checkKeys.indexOf(checkKey) === checkKeys.length - 1) {
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
54849
+ for (const checkKey of servicesToAnalyze) {
54850
+ try {
54851
+ const serviceCheckFunction = serviceChecks[checkKey];
54852
+ if (typeof serviceCheckFunction !== "function") {
54853
+ const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
54854
+ analysisLogger.warn(
54855
+ `\u26A0\uFE0F Service check function for ${serviceLabel} (${checkKey}) is not available`
54800
54856
  );
54801
- for (const [resourceName, resourceFindings] of Object.entries(
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
- });
54857
+ continue;
54813
54858
  }
54859
+ const serviceAnalysisResult = serviceCheckFunction(
54860
+ { Resources: userResources },
54861
+ createFinding2
54862
+ );
54863
+ for (const [resourceName, resourceFindings] of Object.entries(
54864
+ serviceAnalysisResult
54865
+ )) {
54866
+ if (!analysisFindings[resourceName]) {
54867
+ analysisFindings[resourceName] = { issues: [] };
54868
+ }
54869
+ analysisFindings[resourceName].issues.push(...resourceFindings.issues);
54870
+ }
54871
+ } catch (analysisError) {
54872
+ const serviceLabel = getServiceLabelForCheckKey(checkKey) ?? checkKey;
54873
+ analysisLogger.warn(
54874
+ `\u26A0\uFE0F Error in ${serviceLabel} analysis (${checkKey})`,
54875
+ {
54876
+ error: analysisError instanceof Error ? analysisError.message : String(analysisError)
54877
+ }
54878
+ );
54814
54879
  }
54815
54880
  }
54816
54881
  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 ServiceName = Exclude<keyof AWSServiceChecks, 'solutionsPatterns'> | 'All services';
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[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdk-insights",
3
- "version": "0.4.6",
3
+ "version": "0.4.8-beta.0",
4
4
  "description": "AWS CDK security and cost analysis tool with AI-powered insights",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",