UNPKG

@cloud-copilot/iam-collect

Version:

Collect IAM information from AWS Accounts

180 lines 7.75 kB
#!/usr/bin/env node import { booleanArgument, enumArgument, numberArgument, parseCliArguments, stringArgument, stringArrayArgument } from '@cloud-copilot/cli'; import { conductLogAnalysis } from './analysis/analyze.js'; import { loadConfigFiles } from './config/configFile.js'; import { createDefaultConfiguration } from './config/createConfigFile.js'; import { defaultConfigExists } from './config/defaultConfig.js'; import { iamCollectVersion } from './config/packageVersion.js'; import { downloadData } from './download/download.js'; import { index } from './index/index.js'; import { mergeSqliteDatabases } from './mergeSqlite/mergeSqlite.js'; import {} from './services.js'; import { LogLevels, setLogger, StandardLogger } from '@cloud-copilot/log'; /** * For some reason the AWS SDK v3 looks for AWS_REGION and not AWS_DEFAULT_REGION * even though other SDKs and the CLI use AWS_DEFAULT_REGION. To make things easier * for users, if AWS_DEFAULT_REGION is set and AWS_REGION is not, copy it over. */ if (process.env.AWS_DEFAULT_REGION && !process.env.AWS_REGION) { process.env.AWS_REGION = process.env.AWS_DEFAULT_REGION; } const main = async () => { const cli = await parseCliArguments('iam-collect', { init: { description: 'Initialize the iam-collect configuration file', arguments: { sqlite: booleanArgument({ character: 's', description: 'Initialize configuration file with SQLite storage' }) } }, download: { description: 'Download IAM data and update indexes', arguments: { configFiles: stringArrayArgument({ description: 'The configuration files to use', defaultValue: [] }), accounts: stringArrayArgument({ description: 'The account IDs to download from', defaultValue: [] }), regions: stringArrayArgument({ description: 'The regions to download from', defaultValue: [] }), services: stringArrayArgument({ description: 'The services to download', defaultValue: [] }), concurrency: numberArgument({ description: 'The maximum number of concurrent downloads to allow. Defaults based on your system CPUs' }), noIndex: booleanArgument({ description: 'Skip refreshing the indexes after downloading', character: 'n' }), writeOnly: booleanArgument({ description: 'Only write data for discovered resources and ignore any existing data. May improve performance if you know you have no existing data', character: 'w' }) } }, index: { description: 'Refresh the IAM data indexes', arguments: { configFiles: stringArrayArgument({ description: 'The configuration files to use', defaultValue: [] }), partition: stringArgument({ description: 'The partition to refresh index data for. Defaults to aws', defaultValue: 'aws' }), accounts: stringArrayArgument({ description: 'The account IDs to refresh index data for', defaultValue: [] }), regions: stringArrayArgument({ description: 'The regions to refresh index data for', defaultValue: [] }), services: stringArrayArgument({ description: 'The services to refresh index data for', defaultValue: [] }), concurrency: numberArgument({ description: 'The maximum number of concurrent indexers to run. Defaults based on your system CPUs' }) } }, 'merge-databases': { description: 'Merge multiple iam-collect SQLite databases into one', arguments: { targetDatabase: stringArgument({ description: 'The target database to merge into. If it does not exist, it will be created. If it does exist, new data will be added to existing data' }), sourceDatabases: stringArrayArgument({ description: 'The source databases to merge from' }) } }, 'analyze-logs': { description: 'Analyze iam-collect trace logs and summarize job execution times', arguments: { logFile: stringArgument({ description: 'The path to the log file to analyze' }) } } }, { log: enumArgument({ description: 'The log level to use', validValues: [...LogLevels] // Convert readonly to mutable array }) }, { envPrefix: 'IAM_COLLECT', showHelpIfNoArgs: true, requireSubcommand: true, expectOperands: false, version: { currentVersion: iamCollectVersion, checkForUpdates: '@cloud-copilot/iam-collect' } }); setLogger(new StandardLogger({ logLevel: cli.args.log ?? undefined })); if (cli.subcommand === 'init') { if (defaultConfigExists()) { console.error('Configuration file already exists'); process.exit(1); } console.log('Initializing...'); await createDefaultConfiguration({ type: cli.args.sqlite ? 'sqlite' : 'file' }); } else if (cli.subcommand === 'download') { const defaultConfig = './iam-collect.jsonc'; const configFiles = cli.args.configFiles.length > 0 ? cli.args.configFiles : [defaultConfig]; const configs = loadConfigFiles(configFiles); await downloadData(configs, cli.args.accounts, cli.args.regions, cli.args.services, cli.args.concurrency, cli.args.noIndex, cli.args.writeOnly); } else if (cli.subcommand === 'index') { const defaultConfig = './iam-collect.jsonc'; const configFiles = cli.args.configFiles.length > 0 ? cli.args.configFiles : [defaultConfig]; const configs = loadConfigFiles(configFiles); await index(configs, cli.args.partition || 'aws', cli.args.accounts, cli.args.regions, cli.args.services, cli.args.concurrency); } else if (cli.subcommand === 'merge-databases') { if (!cli.args.targetDatabase) { console.error('You must specify a target database using --target-database'); process.exit(1); } if (!cli.args.sourceDatabases) { console.error('You must specify at least one source database using --source-databases'); process.exit(1); } await mergeSqliteDatabases(cli.args.targetDatabase, cli.args.sourceDatabases); } else if (cli.subcommand === 'analyze-logs') { if (!cli.args.logFile) { console.error('You must specify a log file to analyze using --log-file'); process.exit(1); } const allComplete = await conductLogAnalysis(cli.args.logFile); if (!allComplete) { process.exit(1); } } }; main() .catch((e) => { console.error(e); process.exit(1); }) .then(() => { }) .finally(() => { }); //# sourceMappingURL=cli.js.map