import boto3
from botocore.exceptions import ClientError
import time
import json
import uuid

# A script to enable AWS Config, including necessary prerequisites,
# and then clean up all resources using Boto3.

# --- Configuration ---
REGION = "us-east-1"
RANDOM_SUFFIX = uuid.uuid4().hex[:8]
CONFIG_BUCKET_NAME = f"my-boto3-config-bucket-{RANDOM_SUFFIX}"
CONFIG_RECORDER_NAME = "default" # Default recorder name
CONFIG_DELIVERY_CHANNEL_NAME = "default" # Default delivery channel name
IAM_ROLE_NAME = "MyBoto3ConfigRole"

s3_client = boto3.client('s3', region_name=REGION)
config_client = boto3.client('config', region_name=REGION)
iam_client = boto3.client('iam', region_name=REGION)

def create_s3_bucket():
    """Creates an S3 bucket for Config recordings."""
    print(f"--- Creating S3 Bucket for Config Recordings: {CONFIG_BUCKET_NAME} ---")
    try:
        s3_client.create_bucket(
            Bucket=CONFIG_BUCKET_NAME,
            CreateBucketConfiguration={'LocationConstraint': REGION} if REGION != 'us-east-1' else {}
        )
        print("S3 Bucket created.")
    except ClientError as e:
        print(f"Error creating S3 bucket: {e}")
        raise

def create_iam_role():
    """Creates an IAM role for AWS Config."""
    print(f"\n--- Creating IAM Role: {IAM_ROLE_NAME} ---")
    trust_policy = {
      "Version": "2012-10-17",
      "Statement": [{"Effect": "Allow", "Principal": {"Service": "config.amazonaws.com"}, "Action": "sts:AssumeRole"}]
    }
    try:
        role_response = iam_client.create_role(
            RoleName=IAM_ROLE_NAME,
            AssumeRolePolicyDocument=json.dumps(trust_policy),
            Description="Role for AWS Config"
        )
        role_arn = role_response['Role']['Arn']
        iam_client.attach_role_policy(
            RoleName=IAM_ROLE_NAME,
            PolicyArn='arn:aws:iam::aws:policy/AWSConfigRole'
        )
        print("IAM Role created and policy attached.")
        print("Waiting for IAM role to propagate...")
        time.sleep(10)
        return role_arn
    except ClientError as e:
        if e.response['Error']['Code'] == 'EntityAlreadyExists':
            print(f"IAM role '{IAM_ROLE_NAME}' already exists. Fetching ARN.")
            return iam_client.get_role(RoleName=IAM_ROLE_NAME)['Role']['Arn']
        else:
            print(f"Error creating IAM role: {e}")
            raise

def create_configuration_recorder(role_arn):
    """Creates a configuration recorder."""
    print(f"\n--- Creating Configuration Recorder: {CONFIG_RECORDER_NAME} ---")
    try:
        config_client.put_configuration_recorder(
            ConfigurationRecorder={'name': CONFIG_RECORDER_NAME, 'roleARN': role_arn}
        )
        print("Configuration Recorder created.")
    except ClientError as e:
        print(f"Error creating configuration recorder: {e}")
        raise

def create_delivery_channel():
    """Creates a delivery channel."""
    print(f"\n--- Creating Delivery Channel: {CONFIG_DELIVERY_CHANNEL_NAME} ---")
    try:
        config_client.put_delivery_channel(
            DeliveryChannel={'name': CONFIG_DELIVERY_CHANNEL_NAME, 's3BucketName': CONFIG_BUCKET_NAME, 's3KeyPrefix': 'config'}
        )
        print("Delivery Channel created.")
    except ClientError as e:
        print(f"Error creating delivery channel: {e}")
        raise

def start_configuration_recorder():
    """Starts the configuration recorder."""
    print(f"\n--- Starting Configuration Recorder ---")
    try:
        config_client.start_configuration_recorder(ConfigurationRecorderName=CONFIG_RECORDER_NAME)
        print("Configuration Recorder started.")
    except ClientError as e:
        print(f"Error starting configuration recorder: {e}")
        raise

def cleanup_resources(role_arn):
    """Cleans up all created resources."""
    print(f"\n--- Cleaning up resources ---")

    # Stop Recorder
    print(f"Stopping Configuration Recorder '{CONFIG_RECORDER_NAME}'...")
    try:
        config_client.stop_configuration_recorder(ConfigurationRecorderName=CONFIG_RECORDER_NAME)
        print("Configuration Recorder stopped.")
    except ClientError as e:
        if e.response['Error']['Code'] == 'NoSuchConfigurationRecorderException':
            print(f"Configuration Recorder '{CONFIG_RECORDER_NAME}' not found, skipping stop.")
        else:
            print(f"Error stopping configuration recorder: {e}")

    # Delete Delivery Channel
    print(f"Deleting Delivery Channel '{CONFIG_DELIVERY_CHANNEL_NAME}'...")
    try:
        config_client.delete_delivery_channel(DeliveryChannelName=CONFIG_DELIVERY_CHANNEL_NAME)
        print("Delivery Channel deleted.")
    except ClientError as e:
        if e.response['Error']['Code'] == 'NoSuchDeliveryChannelException':
            print(f"Delivery Channel '{CONFIG_DELIVERY_CHANNEL_NAME}' not found, skipping deletion.")
        else:
            print(f"Error deleting delivery channel: {e}")

    # Delete Configuration Recorder
    print(f"Deleting Configuration Recorder '{CONFIG_RECORDER_NAME}'...")
    try:
        config_client.delete_configuration_recorder(ConfigurationRecorderName=CONFIG_RECORDER_NAME)
        print("Configuration Recorder deleted.")
    except ClientError as e:
        if e.response['Error']['Code'] == 'NoSuchConfigurationRecorderException':
            print(f"Configuration Recorder '{CONFIG_RECORDER_NAME}' not found, skipping deletion.")
        else:
            print(f"Error deleting configuration recorder: {e}")

    # Detach and Delete IAM Role
    if role_arn:
        print(f"Detaching policy from IAM Role '{IAM_ROLE_NAME}'...")
        try:
            iam_client.detach_role_policy(RoleName=IAM_ROLE_NAME, PolicyArn='arn:aws:iam::aws:policy/AWSConfigRole')
            print(f"Deleting IAM Role '{IAM_ROLE_NAME}'...")
            iam_client.delete_role(RoleName=IAM_ROLE_NAME)
            print("IAM Role deleted.")
        except ClientError as e:
            if e.response['Error']['Code'] == 'NoSuchEntity':
                print(f"IAM Role '{IAM_ROLE_NAME}' not found, skipping deletion.")
            else:
                print(f"Error deleting IAM role: {e}")

    # Delete S3 Bucket
    print(f"Deleting S3 Bucket '{CONFIG_BUCKET_NAME}'...")
    try:
        s3_resource = boto3.resource('s3', region_name=REGION)
        bucket = s3_resource.Bucket(CONFIG_BUCKET_NAME)
        bucket.objects.all().delete() # Delete all objects in the bucket
        bucket.delete()
        print("S3 Bucket deleted.")
    except ClientError as e:
        print(f"Error deleting S3 bucket: {e}")

def main():
    config_role_arn = None
    try:
        create_s3_bucket()
        config_role_arn = create_iam_role()
        create_configuration_recorder(config_role_arn)
        create_delivery_channel()
        start_configuration_recorder()

        print("\n--- AWS Config Enabled Successfully! ---")
        print(f"Configuration Recorder: {CONFIG_RECORDER_NAME}")
        print(f"Configured to deliver to S3 bucket: {CONFIG_BUCKET_NAME}")

        input("Press Enter to stop the recorder and clean up resources...")

    except ClientError as e:
        print(f"An AWS client error occurred: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    finally:
        cleanup_resources(config_role_arn)
        print("\n--- AWS Config demonstration and cleanup complete ---")

if __name__ == "__main__":
    main()
