container-image-scanner
Version:
Enterprise Container Image Scanner with AWS Security Best Practices. Scan EKS clusters for Bitnami container image dependencies and generate migration guidance for AWS ECR alternatives.
222 lines (192 loc) ⢠7.28 kB
JavaScript
const chalk = require('chalk');
class TechnicalAlternativesAnalyzer {
constructor() {
this.serviceMatrix = {
'mysql': {
type: 'Database',
aws: ['Amazon RDS for MySQL', 'Amazon Aurora MySQL'],
partners: ['PlanetScale (if available)'],
upstream: ['mysql'],
engagement: 'AWS Database Specialist SA'
},
'postgresql': {
type: 'Database',
aws: ['Amazon RDS for PostgreSQL', 'Amazon Aurora PostgreSQL'],
partners: ['Neon', 'Supabase'],
upstream: ['postgres'],
engagement: 'AWS Database Specialist SA'
},
'mongodb': {
type: 'Database',
aws: ['Amazon DocumentDB'],
partners: ['MongoDB Atlas'],
upstream: ['mongo'],
engagement: 'AWS Database Specialist SA'
},
'redis': {
type: 'Cache',
aws: ['Amazon ElastiCache for Redis'],
partners: ['Redis Enterprise'],
upstream: ['redis'],
engagement: 'AWS Database Specialist SA'
},
'elasticsearch': {
type: 'Analytics',
aws: ['Amazon OpenSearch Service'],
partners: ['Elastic Cloud'],
upstream: ['elasticsearch'],
engagement: 'AWS Analytics Specialist SA'
},
'kafka': {
type: 'Messaging',
aws: ['Amazon MSK'],
partners: ['Confluent Platform'],
upstream: ['apache/kafka'],
engagement: 'AWS Integration Specialist SA'
},
'rabbitmq': {
type: 'Messaging',
aws: ['Amazon MQ'],
partners: ['CloudAMQP'],
upstream: ['rabbitmq'],
engagement: 'AWS Integration Specialist SA'
},
'grafana': {
type: 'Monitoring',
aws: ['Amazon Managed Grafana'],
partners: ['Grafana Cloud'],
upstream: ['grafana/grafana'],
engagement: 'AWS Analytics Specialist SA'
},
'prometheus': {
type: 'Monitoring',
aws: ['Amazon Managed Prometheus'],
partners: ['Grafana Cloud'],
upstream: ['prom/prometheus'],
engagement: 'AWS Analytics Specialist SA'
}
};
}
analyzeImage(imageName) {
const [name, tag] = imageName.split(':');
const service = name.split('/')[1]?.split(':')[0];
if (!name.includes('bitnami') || !this.serviceMatrix[service]) {
return { applicable: false };
}
const isVersioned = tag && tag !== 'latest' && /^\d+\.\d+/.test(tag);
const serviceInfo = this.serviceMatrix[service];
return {
applicable: true,
imageName,
service,
type: serviceInfo.type,
tag: tag || 'latest',
isVersioned,
migrationComplexity: this.assessComplexity(isVersioned, service),
alternatives: {
aws: serviceInfo.aws,
partners: serviceInfo.partners,
upstream: serviceInfo.upstream,
bitnamiPremium: `bitnamiprem/${service}:${tag || 'latest'}`
},
engagement: serviceInfo.engagement
};
}
assessComplexity(isVersioned, service) {
const complexServices = ['elasticsearch', 'kafka', 'mongodb'];
const baseComplexity = complexServices.includes(service) ? 'HIGH' : 'MEDIUM';
// Versioned images add complexity
if (isVersioned) {
return baseComplexity === 'HIGH' ? 'HIGH' : 'HIGH';
}
return baseComplexity === 'HIGH' ? 'MEDIUM' : 'LOW';
}
generateTechnicalReport(images) {
console.log(chalk.bold.blue('š Technical Alternatives Analysis'));
console.log(chalk.gray('Bitnami Container Migration Options\n'));
const analyses = images
.map(img => this.analyzeImage(img))
.filter(analysis => analysis.applicable);
if (analyses.length === 0) {
console.log(chalk.yellow('No Bitnami images found in provided list.'));
return;
}
// Group by complexity
const highComplexity = analyses.filter(a => a.migrationComplexity === 'HIGH');
const mediumComplexity = analyses.filter(a => a.migrationComplexity === 'MEDIUM');
const lowComplexity = analyses.filter(a => a.migrationComplexity === 'LOW');
if (highComplexity.length > 0) {
console.log(chalk.red.bold('šØ HIGH COMPLEXITY MIGRATIONS'));
highComplexity.forEach(analysis => this.displayAnalysis(analysis));
console.log('');
}
if (mediumComplexity.length > 0) {
console.log(chalk.yellow.bold('ā ļø MEDIUM COMPLEXITY MIGRATIONS'));
mediumComplexity.forEach(analysis => this.displayAnalysis(analysis));
console.log('');
}
if (lowComplexity.length > 0) {
console.log(chalk.green.bold('ā
LOW COMPLEXITY MIGRATIONS'));
lowComplexity.forEach(analysis => this.displayAnalysis(analysis));
console.log('');
}
// Summary
console.log(chalk.bold('š Technical Summary:'));
console.log(` High Complexity: ${chalk.red(highComplexity.length)}`);
console.log(` Medium Complexity: ${chalk.yellow(mediumComplexity.length)}`);
console.log(` Low Complexity: ${chalk.green(lowComplexity.length)}`);
// Engagement routing
const engagements = [...new Set(analyses.map(a => a.engagement))];
console.log(chalk.bold('\nšÆ AWS Engagement Required:'));
engagements.forEach(engagement => {
const count = analyses.filter(a => a.engagement === engagement).length;
console.log(` ${engagement}: ${count} services`);
});
}
displayAnalysis(analysis) {
console.log(chalk.bold(` š¦ ${analysis.imageName}`));
console.log(` Type: ${analysis.type}`);
console.log(` Version: ${analysis.isVersioned ? chalk.red('Pinned') : chalk.green('Latest')}`);
console.log(` Complexity: ${this.getComplexityColor(analysis.migrationComplexity)}`);
console.log(chalk.blue(' AWS Managed Services:'));
analysis.alternatives.aws.forEach(service => {
console.log(chalk.blue(` ⢠${service}`));
});
console.log(chalk.magenta(' AWS Marketplace Partners:'));
analysis.alternatives.partners.forEach(partner => {
console.log(chalk.magenta(` ⢠${partner}`));
});
console.log(chalk.cyan(' Open Source Upstream:'));
analysis.alternatives.upstream.forEach(upstream => {
console.log(chalk.cyan(` ⢠${upstream}`));
});
console.log(chalk.gray(' Bitnami Premium:'));
console.log(chalk.gray(` ⢠${analysis.alternatives.bitnamiPremium}`));
console.log(chalk.yellow(` ā Engage: ${analysis.engagement}`));
console.log('');
}
getComplexityColor(complexity) {
switch(complexity) {
case 'LOW': return chalk.green(complexity);
case 'MEDIUM': return chalk.yellow(complexity);
case 'HIGH': return chalk.red(complexity);
default: return chalk.gray(complexity);
}
}
}
// Test with sample images
if (require.main === module) {
const analyzer = new TechnicalAlternativesAnalyzer();
const testImages = [
'bitnami/mysql:8.0.35',
'bitnami/postgresql:15.4.0',
'bitnami/mongodb:6.0.8',
'bitnami/redis:latest',
'bitnami/elasticsearch:8.8.0',
'bitnami/kafka:3.5.0',
'nginx:latest'
];
analyzer.generateTechnicalReport(testImages);
}
module.exports = { TechnicalAlternativesAnalyzer };