UNPKG

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
#!/usr/bin/env node 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 };