import boto3
from google.cloud import storage
from azure.storage.blob import BlobServiceClient
import requests
from urllib.parse import urlparse, urljoin  # Add urljoin here
import json
import time
import socket
import ssl


class CloudSecurityScanner:
    def __init__(self, target):
        self.target = target
        self.results = []
        self.cloud_provider = self.detect_cloud_provider()

    def detect_cloud_provider(self):
        """Detect the cloud provider based on the target"""
        parsed_url = urlparse(self.target)
        domain = parsed_url.netloc

        if 'amazonaws.com' in domain:
            return 'AWS'
        elif 'azurewebsites.net' in domain or 'blob.core.windows.net' in domain:
            return 'Azure'
        elif 'appspot.com' in domain or 'storage.googleapis.com' in domain:
            return 'GCP'
        return None

    def scan_aws_resources(self):
        """Scan AWS resources for security misconfigurations"""
        # Check for S3 bucket exposure
        if 's3.amazonaws.com' in self.target:
            try:
                bucket_name = self.target.split('//')[1].split('.')[0]
                s3 = boto3.client('s3')

                # Check if bucket is publicly accessible
                try:
                    s3.head_bucket(Bucket=bucket_name)
                    self.results.append({
                        'type': 'S3 Bucket Exposure',
                        'severity': 'High',
                        'description': f"S3 bucket {bucket_name} is publicly accessible",
                        'resource': self.target
                    })
                except Exception as e:
                    if 'AccessDenied' in str(e):
                        print(
                            f"S3 bucket {bucket_name} is not publicly accessible")
            except Exception as e:
                print(f"Error checking S3 bucket: {e}")

        # Check for EC2 metadata service exposure
        try:
            metadata_url = "http://169.254.169.254/latest/meta-data/"
            response = requests.get(metadata_url, timeout=2)
            if response.status_code == 200:
                self.results.append({
                    'type': 'EC2 Metadata Exposure',
                    'severity': 'Critical',
                    'description': 'EC2 metadata service is accessible from the target',
                    'resource': metadata_url
                })
        except:
            pass

    def scan_azure_resources(self):
        """Scan Azure resources for security misconfigurations"""
        # Check for Azure blob storage exposure
        if 'blob.core.windows.net' in self.target:
            try:
                blob_service_client = BlobServiceClient.from_blob_url(
                    self.target)
                container_client = blob_service_client.get_container_client()

                # Try to list blobs
                blobs = container_client.list_blobs()
                self.results.append({
                    'type': 'Azure Blob Exposure',
                    'severity': 'High',
                    'description': f"Azure blob storage is publicly accessible: {self.target}",
                    'resource': self.target
                })
            except Exception as e:
                print(f"Azure blob storage is not publicly accessible: {e}")

    def scan_gcp_resources(self):
        """Scan GCP resources for security misconfigurations"""
        # Check for GCP storage bucket exposure
        if 'storage.googleapis.com' in self.target:
            try:
                bucket_name = self.target.split('//')[1].split('/')[0]
                storage_client = storage.Client()
                bucket = storage_client.bucket(bucket_name)

                # Check if bucket is publicly accessible
                if bucket.make_public():
                    self.results.append({
                        'type': 'GCP Storage Exposure',
                        'severity': 'High',
                        'description': f"GCP storage bucket is publicly accessible: {bucket_name}",
                        'resource': self.target
                    })
            except Exception as e:
                print(f"GCP storage bucket is not publicly accessible: {e}")

    def scan_kubernetes_exposure(self):
        """Scan for Kubernetes API server exposure"""
        k8s_paths = [
            '/api/v1/namespaces',
            '/api/v1/pods',
            '/apis/extensions/v1beta1',
            '/apis/apps/v1',
            '/openapi/v2'
        ]

        for path in k8s_paths:
            url = urljoin(self.target, path)
            try:
                response = requests.get(url, timeout=5)
                if response.status_code == 200:
                    self.results.append({
                        'type': 'Kubernetes API Exposure',
                        'severity': 'Critical',
                        'description': f"Kubernetes API endpoint is exposed: {url}",
                        'resource': url
                    })
            except:
                pass

    def run_scan(self):
        """Run all cloud security scans"""
        if self.cloud_provider == 'AWS':
            self.scan_aws_resources()
        elif self.cloud_provider == 'Azure':
            self.scan_azure_resources()
        elif self.cloud_provider == 'GCP':
            self.scan_gcp_resources()

        # Always check for Kubernetes exposure regardless of cloud provider
        self.scan_kubernetes_exposure()

        return self.results
