zombiehunter 1.0.0
AWS Zombie Hunter - Scan and clean unused/zombie AWS resources (EC2, RDS, VPC, Lambda, etc.)
License: MIT
Requires Python: >=3.12
Keywords: aws, boto3, cloud-cleanup, cost-optimization, zombie-resources

# 🧟 Cloud Zombie Hunter (ZH)

**Cloud Zombie Hunter** is a powerful CLI tool for identifying and tracking unused AWS resources (zombies) and monitoring active infrastructure across your AWS accounts. Save money by finding resources that are costing you without providing value!

---

## 🚀 Features

### 🔍 Zombie Detection (`scan`)
Automatically detect unused, idle, or wasteful AWS resources:
- **EC2**: Stopped instances, unattached volumes, old snapshots, unused AMIs
- **VPC**: Unassociated Elastic IPs, unused NAT Gateways, orphaned security groups
- **VPC Endpoints**: Interface endpoints without ENIs, gateway endpoints without routes
- **ELB**: Load balancers with no healthy targets
- **RDS**: Stopped DB instances, old manual snapshots
- **S3**: Incomplete multipart uploads
- **Lambda**: Functions with no invocations in 30+ days
- **Secrets Manager**: Secrets not accessed in 60+ days
- **DynamoDB**: Tables with no read/write activity in 30 days
- **API Gateway**: REST/HTTP APIs with no traffic in 30 days

### 📊 Resource Monitoring (`show`)
View detailed information about active AWS resources:
- **EC2 Instances**: Type, state, IPs, estimated monthly cost
- **RDS Databases**: Engine, version, storage, Multi-AZ, endpoint, cost
- **ECS Services**: CPU, memory, launch type, task counts, Fargate pricing
- **OpenSearch Domains**: Instance type, count, storage, endpoints
- **ElastiCache Clusters**: Redis/Memcached nodes, endpoints, pricing

### ⚠️ Severity Levels
Resources are categorized by severity to help prioritize cleanup:
- 
- **🟢 LOW**: Low-cost or minor issues
- **🟡 MEDIUM**: Medium-cost or potentially important resources
- **🟡 HIGH**: HIGH cost
- **🔴 CRITICAL**: High-cost resources (e.g., NAT Gateways, large instances)

---

### SORT BY HIGHER COST
The most expensive resources is on top of the table in the output



## 📦 Installation

### Prerequisites
- Python 3.8+
- AWS credentials configured (`~/.aws/credentials` or environment variables)
- Required permissions for read-only access to AWS services

### Install Dependencies
```bash
pip install boto3 typer rich
```

### Setup
```bash
# Clone or download the repository
git clone <your-repo-url>
cd cloud-zombie-hunter

# Make executable (optional)
chmod +x main.py
```

---

## 🎯 Usage

### Basic Commands

#### 1. **Scan for Zombie Resources**

Scan all services:
```bash
python main.py scan all --region us-east-1
```

Scan specific services:
```bash
python main.py scan ec2
python main.py scan vpc
python main.py scan lambda
python main.py scan rds
python main.py scan s3
```

Scan with region specification:
```bash
python main.py scan all --region us-west-2
python main.py scan ec2 -r eu-west-1
```

#### 2. **Show Active Resources**

Show all EC2 instances:
```bash
python main.py show ec2
```

Show only running instances:
```bash
python main.py show ec2 --status running
```

Show only stopped instances:
```bash
python main.py show ec2 --status stopped
```

Show other services:
```bash
python main.py show rds --region us-east-1
python main.py show ecs
python main.py show opensearch
python main.py show elasticache
```

#### 3. **List Available Services**
```bash
python main.py list-services
```

---

## 📋 Command Reference

### `scan` Command
```
python main.py scan [SERVICE] [OPTIONS]

Arguments:
  SERVICE    Service to scan: ec2, vpc, elb, rds, s3, lambda, secrets, 
             dynamodb, apigateway, vpc-endpoints, or "all"

Options:
  --region, -r TEXT    AWS region to scan [default: us-east-1]
```

**Example Output:**
```
🧟 Zombie Resource Report: US-EAST-1
┌─────────┬─────────────────────┬───────────────┬──────────────────────┬────────────────────┐
│ Service │ Type                │ Resource ID   │ Description          │ Est. Monthly Waste │
├─────────┼─────────────────────┼───────────────┼──────────────────────┼────────────────────┤
│ EC2     │ Unattached Volume   │ vol-abc123    │ 100 GB - old-data    │ $8.00              │
│ VPC     │ Idle Elastic IP     │ 52.1.2.3      │ Not attached         │ $3.60              │
│ Lambda  │ Unused Function     │ old-processor │ No invocations 45d   │ $0.00              │
└─────────┴─────────────────────┴───────────────┴──────────────────────┴────────────────────┘

💸 Total Potential Savings: $11.60 / month
Found 3 zombie resource(s)
```

### `show` Command
```
python main.py show [SERVICE] [OPTIONS]

Arguments:
  SERVICE    Service to show: ec2, rds, ecs, opensearch, elasticache

Options:
  --region, -r TEXT     AWS region [default: us-east-1]
  --status, -s TEXT     Filter by status: all, running, stopped [default: all]
```

**Example Output:**
```
EC2 Instances in US-EAST-1 (RUNNING)
┌──────────────┬──────────┬────────────┬─────────┬──────────────┬──────────────┬────────────────────┐
│ Instance ID  │ Name     │ Type       │ State   │ Public IP    │ Private IP   │ Est. Monthly Cost  │
├──────────────┼──────────┼────────────┼─────────┼──────────────┼──────────────┼────────────────────┤
│ i-abc123     │ web-app  │ t3.medium  │ running │ 54.1.2.3     │ 10.0.1.5     │ $30.37             │
│ i-def456     │ api-srv  │ t3.large   │ running │ 54.1.2.4     │ 10.0.1.6     │ $60.74             │
└──────────────┴──────────┴────────────┴─────────┴──────────────┴──────────────┴────────────────────┘

Summary:
  Running: 2 | Stopped: 0
  Total Est. Monthly Cost: $91.11
```

---

## 🏗️ Architecture

### Class Structure

```
BaseScanner (Abstract)
├── EC2Scanner
├── VPCScanner
├── ELBScanner
├── RDSScanner
├── S3Scanner
├── VPCEndpointScanner
├── LambdaScanner
├── SecretsManagerScanner
├── DynamoDBScanner
└── APIGatewayScanner

BaseViewer (Abstract)
├── EC2Viewer
├── RDSViewer
├── ECSViewer
├── OpenSearchViewer
└── ElastiCacheViewer
```

### Design Pattern

**Scanners** (Zombie Detection):
- Each scanner class inherits from `BaseScanner`
- Implements a `scan()` method that returns list of zombie resources
- Uses CloudWatch metrics, API states, and best practices to detect waste

**Viewers** (Active Resource Monitoring):
- Each viewer class inherits from `BaseViewer`
- Implements a `show(status)` method that returns list of active resources
- Fetches current resource state and calculates estimated costs

**Registries**:
```python
SCANNERS = {
    'ec2': EC2Scanner,
    'vpc': VPCScanner,
    # ... etc
}

VIEWERS = {
    'ec2': EC2Viewer,
    'rds': RDSViewer,
    # ... etc
}
```

---

## 💰 Cost Estimation

Cloud Zombie Hunter provides **estimated monthly costs** based on:

- **EC2**: Instance type hourly rates × 730 hours/month
- **RDS**: Instance class + storage (GP2) + Multi-AZ multiplier
- **EBS**: Volume size × storage cost per GB
- **NAT Gateway**: Base hourly cost + data processing estimates
- **ELB**: Application/Network Load Balancer hourly rates
- **Fargate**: vCPU and memory pricing × task count
- **Secrets Manager**: $0.40 per secret per month
- **ElastiCache**: Node type × node count
- **OpenSearch**: Instance cost + storage cost

> **Note**: Pricing is simplified and based on US East (N. Virginia) region. Actual costs may vary by region, reserved instances, savings plans, and specific configurations.

---

## 🔧 Configuration

### AWS Credentials

The tool uses standard AWS credential resolution:
1. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
2. AWS credentials file (`~/.aws/credentials`)
3. IAM role (if running on EC2/ECS)

### Required IAM Permissions

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "rds:Describe*",
        "elasticloadbalancing:Describe*",
        "s3:ListBucket",
        "s3:ListMultipartUploadParts",
        "lambda:List*",
        "lambda:Get*",
        "secretsmanager:List*",
        "secretsmanager:Describe*",
        "dynamodb:Describe*",
        "dynamodb:List*",
        "apigateway:GET",
        "ecs:Describe*",
        "ecs:List*",
        "es:Describe*",
        "es:List*",
        "elasticache:Describe*",
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams"
      ],
      "Resource": "*"
    }
  ]
}
```

---

## 📊 Detection Methods

### How Zombies Are Detected

| Service | Detection Method |
|---------|------------------|
| **EC2 Volumes** | Status = 'available' (unattached) |
| **Elastic IPs** | Not associated with any instance or ENI |
| **EC2 Snapshots** | Older than 90 days |
| **AMIs** | Created more than 180 days ago |
| **Security Groups** | Not attached to any network interface |
| **NAT Gateways** | Listed for review (always cost money) |
| **Load Balancers** | No healthy targets in any target group |
| **Lambda** | CloudWatch Invocations metric = 0 for 30 days |
| **Secrets Manager** | LastAccessedDate > 60 days |
| **DynamoDB** | ConsumedReadCapacity + ConsumedWriteCapacity = 0 for 30 days |
| **API Gateway** | CloudWatch Count metric = 0 for 30 days |
| **RDS Snapshots** | Manual snapshots older than 60 days |
| **S3 Multipart** | Incomplete uploads found |

---

## 🎨 Features Roadmap

### Current Features ✅
- [x] Multi-service zombie detection
- [x] Active resource monitoring
- [x] Cost estimation
- [x] Severity levels
- [x] Region support
- [x] Status filtering (running/stopped)
- [x] Rich CLI output with tables

### Planned Features 🚧
- [ ] Export reports to JSON/CSV
- [ ] Multi-region scanning
- [ ] Automated cleanup (with confirmation)
- [ ] Cost trends over time
- [ ] Slack/Email notifications
- [ ] Custom detection rules
- [ ] Resource tagging analysis
- [ ] CloudWatch dashboard integration

---

## 🤝 Contributing

Contributions are welcome! To add a new service scanner:

1. Create a new scanner class inheriting from `BaseScanner`
2. Implement the `scan()` method
3. Add detection logic for zombie resources
4. Register the scanner in `SCANNERS` dictionary
5. Update this README

Example:
```python
class NewServiceScanner(BaseScanner):
    def __init__(self, region):
        super().__init__(region)
        self.client = get_client('new-service', region)
    
    def scan(self) -> List[Dict]:
        # Your detection logic here
        return self.zombies
```

---

## 📝 License

MIT License - feel free to use and modify!

---

## ⚠️ Disclaimer

This tool provides **estimates** and **recommendations** only. Always:
- Review findings before taking action
- Verify resources are truly unused
- Consider dependencies and integrations
- Test in non-production environments first
- Maintain backups before deletion

**Cloud Zombie Hunter is not responsible for any data loss or service disruptions.**

---

## 🙏 Acknowledgments

Built with:
- [boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) - AWS SDK for Python
- [typer](https://typer.tiangolo.com/) - CLI framework
- [rich](https://rich.readthedocs.io/) - Terminal formatting

---

**Happy Zombie Hunting! 🧟‍♂️💰**