Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Gaspillage minimum estimé : ~$25 944/mois
- Détecte le gaspillage IA/ML coûteux : SageMaker, AML, Vertex AI — ressources GPU signalées comme candidats à risque plus élevé (500–23 000 $/mois)
- Fonctionne sur AWS, Azure et GCP en un seul outil
- S'exécute entièrement dans votre environnement — aucun agent, pas de SaaS, aucun credential stocké
- 48 règles de détection sélectives et haut signal, conçues pour éviter les faux positifs en environnements IaC
- 49 règles de détection sélectives et haut signal, conçues pour éviter les faux positifs en environnements IaC
- Prêt pour CI/CD — codes de sortie d'application + sorties JSON/CSV/markdown

### Ce que CleanCloud ne fait PAS
Expand Down Expand Up @@ -434,13 +434,13 @@ Oui. CleanCloud n'a besoin d'accès réseau qu'aux endpoints API de votre cloud

## Ce que CleanCloud détecte

48 règles pour AWS, Azure et GCP — conservatrices, haut signal, conçues pour éviter les faux positifs en environnements IaC.
49 règles pour AWS, Azure et GCP — conservatrices, haut signal, conçues pour éviter les faux positifs en environnements IaC.

**AWS :**
- Compute : instances arrêtées 30+ jours (charges EBS continuent)
- Stockage : volumes EBS non attachés (HIGH), anciens snapshots EBS, anciennes AMIs, anciens snapshots RDS 90+ jours
- Réseau : Elastic IPs non attachées (HIGH), ENI détachées, NAT Gateways inactives, Load Balancers inactifs (HIGH)
- Plateforme : instances RDS inactives (HIGH)
- Plateforme : instances RDS inactives (HIGH), clusters Redshift inactifs (zéro connexion 14+ jours)
- Observabilité : logs CloudWatch à rétention infinie
- Gouvernance : ressources sans tags, security groups inutilisés
- IA/ML *(opt-in : `--category ai`)* : Bedrock Provisioned Throughput (Model Units) inactifs avec zéro invocation depuis 7+ jours ; endpoints SageMaker sans trafic `InvokeEndpoint` observé depuis 14+ jours ; instances Notebook SageMaker avec timestamps de contrôle inactifs depuis 14+ jours ; Domaines SageMaker sans apps en cours d'exécution sur tous les profils et espaces depuis 30+ jours (coût de stockage EFS continu) ; Studio Apps SageMaker (`KernelGateway`/`JupyterLab`/`CodeEditor`) sans signal d'activité récent exploitable depuis 7+ jours ; training jobs SageMaker toujours `InProgress` au-delà du seuil de 24h ; processing jobs SageMaker toujours `InProgress` au-delà du seuil de 24h
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Minimum estimated waste: ~$25,944/month
- Catches expensive idle AI/ML waste: SageMaker, AML, Vertex AI — GPU-backed resources flagged as higher-risk review candidates ($500–$23K/month)
- Works across AWS, Azure, and GCP in one tool
- Runs entirely in your environment — no agents, no SaaS, no credentials stored
- 48 curated, high-signal detection rules designed to avoid false positives in IaC environments
- 49 curated, high-signal detection rules designed to avoid false positives in IaC environments
- CI/CD-ready — enforcement exit codes + JSON/CSV/markdown output

### What CleanCloud does NOT do
Expand Down Expand Up @@ -434,13 +434,13 @@ Yes. CleanCloud only needs network access to your cloud provider's API endpoints

## What CleanCloud Detects

48 rules across AWS, Azure, and GCP — conservative, high-signal, designed to avoid false positives in IaC environments.
49 rules across AWS, Azure, and GCP — conservative, high-signal, designed to avoid false positives in IaC environments.

**AWS:**
- Compute: stopped instances 30+ days (EBS charges continue)
- Storage: unattached EBS volumes (HIGH), old EBS snapshots, old AMIs, old RDS snapshots 90+ days
- Network: unattached Elastic IPs (HIGH), detached ENIs, idle NAT Gateways, idle load balancers (HIGH)
- Platform: idle RDS instances (HIGH)
- Platform: idle RDS instances (HIGH), idle Redshift clusters (zero connections 14+ days)
- Observability: infinite retention CloudWatch Logs
- Governance: untagged resources, unused security groups
- AI/ML *(opt-in: `--category ai`)*: idle Bedrock Provisioned Throughput (Model Units) with zero invocations 7+ days; idle SageMaker endpoints with no observed `InvokeEndpoint` traffic 14+ days; SageMaker Notebook Instances with stale control-plane timestamps 14+ days; SageMaker Domains with no running apps across all user profiles and spaces 30+ days (continuous EFS storage cost); SageMaker Studio apps (`KernelGateway`/`JupyterLab`/`CodeEditor`) with no usable recent activity signal 7+ days; SageMaker training jobs still `InProgress` beyond the 24h threshold; SageMaker processing jobs still `InProgress` beyond the 24h threshold
Expand Down
11 changes: 11 additions & 0 deletions cleancloud/doctor/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ def run_aws_doctor(profile: Optional[str], region: Optional[str] = None) -> None
info(" rds:DescribeDBSnapshots")
info(" rds:DescribeDBSnapshotAttributes")
info(" cloudtrail:LookupEvents")
info(" redshift:DescribeClusters")
info(" elasticloadbalancing:DescribeLoadBalancers")
info(" elasticloadbalancing:DescribeTargetGroups")
info(" logs:DescribeLogGroups")
Expand Down Expand Up @@ -520,6 +521,16 @@ def run_aws_doctor(profile: Optional[str], region: Optional[str] = None) -> None
permissions_tested.append("rds:DescribeDBSnapshotAttributes")
success("rds:DescribeDBSnapshotAttributes")

# Test Redshift permissions
try:
redshift = session.client("redshift", region_name=region)
redshift.describe_clusters(MaxRecords=20)
permissions_tested.append("redshift:DescribeClusters")
success("redshift:DescribeClusters")
except Exception as e:
permissions_failed.append(("redshift:DescribeClusters", str(e)))
warn(f"redshift:DescribeClusters - {e}")

# Test ELB permissions
try:
elbv2 = session.client("elbv2", region_name=region)
Expand Down
Loading
Loading