Navigazione docs

Quick Start

Prerequisiti

  • Node.js 20+ — verifica con node --version
  • Credenziali AWS con permessi in sola lettura (vedi Permessi IAM sotto)

Installazione

npm install -g @cloudrift/cli
# oppure eseguilo una tantum, senza installarlo:
npx @cloudrift/cli analyze

macOS/Linux via Homebrew:

brew install elleVas/cloudrift/cloudrift

Dai sorgenti (per contribuire, o per eseguire modifiche non ancora rilasciate):

git clone https://github.com/elleVas/cloudrift.git
cd cloudrift
pnpm install
pnpm nx build cli   # output compilato in apps/cli/dist/

Gli esempi qui sotto usano il comando cloudrift (installazione da npm). Esegui dai sorgenti? Sostituisci cloudrift con node apps/cli/dist/main.js.

Configurazione credenziali AWS

cloudrift usa la chain standard di credenziali AWS SDK v3. Tre opzioni, in ordine di preferenza:

Opzione A — AWS CLI (consigliato)

aws configure
# inserisci: Access Key ID, Secret Access Key, regione default (es. us-east-1), output format (json)

Questo crea ~/.aws/credentials con il profilo default.

Opzione B — File ~/.aws/credentials manuale

[default]
aws_access_key_id     = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Opzione C — Variabili d’ambiente

export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_DEFAULT_REGION=us-east-1

Verifica: aws sts get-caller-identity deve restituire il tuo account ID senza errori.

Permessi IAM necessari

L’utente/ruolo AWS deve avere questa policy in sola lettura:

{
  "Effect": "Allow",
  "Action": [
    "ec2:DescribeVolumes",
    "ec2:DescribeAddresses",
    "ec2:DescribeInstances",
    "ec2:DescribeSnapshots",
    "ec2:DescribeImages",
    "ec2:DescribeNatGateways",
    "ec2:DescribeNetworkInterfaces",
    "ec2:DescribeLaunchTemplates",
    "ec2:DescribeLaunchTemplateVersions",
    "cloudwatch:GetMetricStatistics",
    "rds:DescribeDBInstances",
    "rds:DescribeDBClusters",
    "rds:DescribeDBSnapshots",
    "elasticloadbalancing:DescribeLoadBalancers",
    "elasticloadbalancing:DescribeTargetGroups",
    "elasticloadbalancing:DescribeTargetHealth",
    "logs:DescribeLogGroups",
    "s3:ListAllMyBuckets",
    "s3:GetBucketLifecycleConfiguration",
    "s3:ListMultipartUploadParts",
    "s3:ListBucketMultipartUploads",
    "ecr:DescribeRepositories",
    "ecr:DescribeImages",
    "codepipeline:ListPipelines",
    "codepipeline:ListPipelineExecutions",
    "secretsmanager:ListSecrets",
    "lambda:ListFunctions",
    "elasticfilesystem:DescribeFileSystems",
    "dynamodb:ListTables",
    "dynamodb:DescribeTable",
    "elasticache:DescribeCacheClusters",
    "sagemaker:ListNotebookInstances",
    "sagemaker:ListEndpoints",
    "sagemaker:DescribeEndpoint",
    "sagemaker:DescribeEndpointConfig",
    "sagemaker:ListEndpointConfigs",
    "sagemaker:ListModels",
    "sagemaker:DescribeModel",
    "sagemaker:ListTags",
    "sqs:ListQueues",
    "sqs:GetQueueAttributes",
    "sqs:ListDeadLetterSourceQueues",
    "sqs:ListQueueTags",
    "tag:GetResources",
    "eks:ListClusters",
    "eks:ListNodegroups",
    "eks:DescribeNodegroup",
    "sts:GetCallerIdentity"
  ],
  "Resource": "*"
}

--live-pricing richiede in più pricing:GetProducts (AWS Pricing API). Non serve per il pricing statico di default.

Primo utilizzo

# Scansione della regione di default (us-east-1)
# L'account ID viene rilevato automaticamente via STS
cloudrift analyze

# Scansione di più regioni
cloudrift analyze -r us-east-1 eu-west-1 ap-southeast-1

# Solo servizi specifici (salta il picker interattivo)
cloudrift analyze --scanners ebs-volume elastic-ip

# Tutti gli scanner senza picker interattivo
cloudrift analyze --all-services

# Disattiva il periodo di grazia (segnala risorse di qualsiasi età)
cloudrift analyze --min-age-days 0

Il picker interattivo

Lanciando analyze in un vero terminale (fuori da CI), appare un picker interattivo — una checklist di tutti gli scanner, tutti pre-selezionati. Premi Invio per scansionare tutto, oppure deseleziona quelli che non ti servono.

Il picker non appare mai quando:

  • stdout non è un TTY (piped output)
  • La variabile CI=true è settata
  • Usi --silent, --scanners <kinds...> o --all-services

In questi casi tutti gli scanner vengono eseguiti automaticamente.

Formati di output

# Tabella console (default)
cloudrift analyze

# Output JSON (machine-readable, ideale per piping)
cloudrift analyze --format json | jq '.totalWasteMonthlyUsd'

# Filtra findings con jq
cloudrift analyze --format json | jq '.findings[] | select(.category=="waste")'

# Markdown per GitHub Actions step summary
cloudrift analyze --format markdown >> "$GITHUB_STEP_SUMMARY"

Nei formati machine-readable (json, markdown) tutti i messaggi umani vanno su stderr, così su stdout resta solo il report — ideale per il piping.

Report PDF

# PDF con nome automatico (cloudrift-reports/AWS_report_YYYY_MM_DD.pdf)
cloudrift analyze --pdf

# PDF con nome personalizzato, nessun output a terminale
cloudrift analyze --pdf ./report.pdf --silent

Il report PDF contiene:

  • Executive summary — totale mensile e annuale, numero risorse, breakdown per tipo
  • Top raccomandazioni — fino a 8 voci ordinate per impatto, con risparmio annuale
  • Pagine di dettaglio — una tabella per ogni tipo di risorsa trovata
  • Scan warnings — elencati se alcuni tipi non hanno potuto essere scansionati

Ordine dei flag: il filename di --pdf è opzionale, quindi viene raccolto solo se segue immediatamente il flag. Usa --pdf=./report.pdf --silent per evitare ambiguità di ordine.

Report JSON su file

# Scrive anche un file JSON su disco (indipendente da --format)
cloudrift analyze --json

# Con nome personalizzato
cloudrift analyze --json ./report.json --silent

Gestione errori parziali

Se la scansione di un tipo di risorsa fallisce (es. permessi mancanti su CloudWatch per i NAT Gateway), il tool:

  • Restituisce comunque tutti gli altri risultati
  • Mostra una sezione “Scan Warnings” con i dettagli dell’errore
  • Indica il totale come (incomplete — see warnings above)
  ⚠ Scan Warnings
  • NAT Gateways: Access denied to CloudWatch metrics

  Total estimated waste: $56.20/month (incomplete — see warnings above)

L’exit code resta guidato solo dalla soglia di costo, mai dagli errori di scansione.

Tutte le opzioni

Flag Descrizione Default
-r, --regions <regioni...> Regioni AWS da scansionare us-east-1
--format <format> Formato stdout: table, json, markdown table
--config <path> Percorso del file di config auto-rilevato
--live-pricing Prezzi correnti dall’AWS Pricing API off
--scanners <kinds...> Solo questi servizi (salta picker)
--all-services Tutti gli scanner senza picker on in CI/non-TTY
--account-id <id> Override account ID (auto-rilevato via STS) auto
--assume-role-arn <arn> Assume questo ruolo IAM per accesso cross-account
--external-id <id> External ID per --assume-role-arn
--min-age-days <giorni> Periodo di grazia in giorni 7
--ignore-tag <tag> Tag di esclusione cloudrift:ignore
--pdf [filename] Genera report PDF
--json [filename] Genera report JSON su disco
--silent Nessun output su stdout off
--notify-slack Notifica Slack se lo spreco supera costAlertThresholdUsd (legge SLACK_WEBHOOK_URL dall’env) off
--notify-webhook POST di un riepilogo JSON a un webhook (legge CLOUDRIFT_WEBHOOK_URL dall’env) off
--notify-email <indirizzo> Email con un riepilogo (legge CLOUDRIFT_SMTP_* dall’env) off
-h, --help Mostra l’help

Notifiche: disponibili anche su dead-resources, resource-security e history --compare (condizioni di trigger diverse — vedi ciascun comando sotto). Best-effort: un webhook rotto o un SMTP mal configurato loggano un warning e non fanno fallire lo scan. Ogni credenziale viene letta dall’ambiente, mai da un flag — impostale nel profilo della shell o come secret di CI, mai in un file committato.

Scansione cross-account

cloudrift può scansionare un account diverso da quello a cui appartengono le tue credenziali, assumendo un ruolo IAM via STS:

# Scansiona un account diverso assumendo un ruolo al suo interno
cloudrift analyze --assume-role-arn arn:aws:iam::222222222222:role/cloudrift-scanner

# Con external ID (se la trust policy lo richiede)
cloudrift analyze --assume-role-arn arn:aws:iam::222222222222:role/cloudrift-scanner --external-id il-mio-secret

# Scansiona più account da un loop di shell
for account in 111111111111 222222222222; do
  cloudrift analyze \
    --assume-role-arn "arn:aws:iam::${account}:role/cloudrift-scanner" \
    --format json > "report-${account}.json"
done

Tutti i comandi (analyze, cost, trend, dead-resources, resource-security) accettano --assume-role-arn e --external-id.

Comandi cost e trend

Oltre alla waste detection, cloudrift offre due comandi per confrontare e tracciare la spesa AWS via Cost Explorer:

# Confronta spesa di questo mese con gli stessi giorni del mese scorso
cloudrift cost

# Trend mensile degli ultimi 12 mesi
cloudrift trend --months 12

# Solo EC2 e S3, salta la conferma di fatturazione
cloudrift trend --months 12 --services ec2 s3 --yes

# Fallisce in CI se la spesa è aumentata più del 20%
cloudrift cost --fail-on-increase 20 --format json

⚠️ cost e trend chiamano AWS Cost Explorer, che fattura $0.01 a richiesta — gli unici comandi di cloudrift che possono generare un costo AWS. Entrambi chiedono conferma interattiva prima della prima chiamata (saltabile con -y/--yes, --silent, o in CI). I periodi chiusi vengono cachati su disco.

Comando dead-resources

Trova risorse lasciate morte o inutilizzate nell’account con costo AWS diretto pari a $0 (invisibili alla waste detection): key pair EC2 inutilizzate, security group orfani, utenti/ruoli IAM inattivi, access key non ruotate, e altro — 18 check in totale.

# Tutti i check, regione di default
cloudrift dead-resources

# Più regioni
cloudrift dead-resources -r us-east-1 eu-west-1

# Solo i check IAM
cloudrift dead-resources --scanners iam-user-inactive iam-policy-unattached

# Output machine-readable
cloudrift dead-resources --format json | jq '.findings[] | select(.severity=="warning")'

# Report PDF
cloudrift dead-resources --pdf ./hygiene.pdf --silent

I finding portano una severity (info / warning / critical) invece di una stima $/mese. Richiede permessi IAM aggiuntivi — vedi la policy completa con cloudrift iam-policy.

Comando resource-security

Scansiona la postura di sicurezza dell’account: MFA disabilitata, access key non ruotate, security group aperti su internet, bucket S3 pubblici, EBS/RDS non cifrati, GuardDuty/Config/Security Hub non abilitati, VPC Flow Logs disabilitati, rotazione delle chiavi KMS, policy IAM admin wildcard, certificati ACM in scadenza, resource policy pubbliche su Lambda/SNS/SQS/ECR/Secrets Manager, e altro — 29 check in totale.

# Ogni check, regione di default
cloudrift resource-security

# Solo i check IAM
cloudrift resource-security --scanners iam-root-mfa-disabled iam-user-mfa-disabled

# Output machine-readable
cloudrift resource-security --format json | jq '.findings[] | select(.severity=="critical")'

# Report PDF
cloudrift resource-security --pdf ./sicurezza.pdf --silent

Anche qui i finding portano una severity. Richiede permessi IAM aggiuntivi — vedi la policy completa con cloudrift iam-policy.

Comando history

Visualizza lo storico locale delle scansioni. Ogni esecuzione di analyze, dead-resources e resource-security salva un snapshot in un file SQLite locale (~/.cloudrift/trends/<account-id>.db) — in modalità best-effort, senza mai bloccare la scansione.

# Tutti gli snapshot registrati, dal più recente
cloudrift history

# Solo lo storico cost-waste, ultime 10 esecuzioni
cloudrift history --domain cloud-cost --limit 10

# Output machine-readable
cloudrift history --format json | jq '.[0].payload'

# Report HTML autocontenuto (grafici per dominio, stat tiles, previsione lineare)
cloudrift history --html

# Report HTML per un singolo dominio
cloudrift history --domain cloud-cost --html

# Confronta due snapshot specifici
cloudrift history --compare

Il report --html cambia in base al dominio: cloud-cost mostra una linea di spreco in dollari con previsione lineare e una lista “top resource type per spreco”; dead-resources/resource-security mostrano critical/warning/info come tre linee separate. Il report combinato apre con 3 stat tile esecutivi pensati per un pubblico CTO/CEO.

Nessun dato viene mai caricato da nessuna parte: il file non lascia mai la tua macchina.

Comando iam-policy

Stampa la policy IAM read-only completa richiesta da cloudrift come JSON pronto da incollare:

cloudrift iam-policy

Nessuna chiamata AWS, utile per copiarla direttamente nella console IAM, in Terraform o CDK.

Output di esempio

  Scanning us-east-1 (account 123456789012) for wasted cloud resources...

  EBS Volumes — Unattached
  ┌────────────────────┬───────────┬────────┬──────┬────────────┬────────────┐
  │ Volume ID          │ Region    │ Size   │ Type │ Created    │ Est. Cost  │
  ├────────────────────┼───────────┼────────┼──────┼────────────┼────────────┤
  │ vol-0abc123def456  │ us-east-1 │ 500 GB │ gp3  │ 2025-01-15 │ $40.00/mo  │
  └────────────────────┴───────────┴────────┴──────┴────────────┴────────────┘

  Total estimated waste: $40.00/month

Prezzi per regione

I prezzi sono region-aware. Regioni con listino specifico: us-east-1, us-west-2, eu-west-1, eu-central-1, ap-southeast-1, ap-northeast-1. Le altre usano il fallback di us-east-1.

Ogni report mostra prices as of con la data di ultima verifica del listino.