Streamlining AWS EC2 Management: A Python Script for Enhanced Instance Access

In today's cloud-centric world, managing AWS EC2 instances efficiently is paramount for DevOps engineers and system administrators. To streamline this process, I've developed a versatile Python script that not only simplifies listing and managing EC2 instances but also introduces a user-friendly way to filter and access your instances directly. This guide will walk you through the script's features, setup, and usage to help you manage your AWS infrastructure more effectively.

Key Features

  • List All EC2 Instances: Displays both running and stopped instances, providing crucial details at a glance.
  • Optional Filtering: Choose whether to include stopped instances in your list, allowing for a tailored view that matches your current needs.
  • Search Functionality: Quickly find instances by name using a simple search term, perfect for environments with numerous instances.
  • Selective Instance Access: Log into your chosen instance directly from the script, leveraging the correct SSH keys automatically.

Getting Started

Before diving into the script, ensure you have the AWS CLI and Boto3 library installed and configured on your system. These tools provide the necessary foundation to interact with AWS services and execute the script successfully.

  1. AWS CLI Installation: Follow the official AWS documentation to install and configure the AWS CLI, setting up your access ID, secret key, and default region.
  2. Boto3 Installation: Install Boto3 via pip with pip install boto3, ensuring you have Python 3.6 or later.

Script Breakdown

The script is structured into several key functions, each designed to handle specific aspects of the EC2 management process:

  • Instance Listing and Filtering: Users can list all instances or opt to exclude stopped instances. Additionally, a search term can be applied to filter instances by name.
  • Instance Selection: A user-friendly list allows you to select an instance for access, streamlining the login process.
  • SSH Key Handling: The script automatically finds and uses the correct SSH key for the selected instance, based on its associated key name.

Usage

Running the script is straightforward. Execute it in your terminal, and follow the on-screen prompts to filter and select the instance you wish to access:

python manage_ec2.py

You'll first be asked whether to include stopped instances in the listing. Next, you have the option to enter a search term to filter instances by name. Finally, select the instance you wish to access from the presented list, and the script will initiate an SSH connection using the appropriate key.

Conclusion

This Python script enhances your AWS EC2 management capabilities, offering a streamlined and intuitive way to access and manage your instances. By incorporating optional filtering and search functionality, it caters to environments of all sizes, from a handful of instances to large-scale deployments.

Sharing this script on my blog is part of my commitment to not only improve my productivity but also contribute to the wider community. Whether you're a fellow DevOps engineer, a system administrator, or anyone managing AWS EC2 instances, I hope you find this tool as useful as I have in simplifying your cloud management tasks.

Feel free to adapt the script to your specific needs, and I'm eager to hear any feedback or enhancements you might suggest. Happy coding, and here's to a more manageable cloud infrastructure!

import boto3
import subprocess
import os
import time

# Initialize a boto3 EC2 resource
ec2 = boto3.resource('ec2')

def list_all_instances(include_stopped=False, search_term=None):
    """List all EC2 instances, optionally excluding stopped instances and filtering by search term."""
    filters = [{'Name': 'tag:Name', 'Values': ['*'+search_term+'*']} if search_term else {'Name': 'instance-state-name', 'Values': ['running', 'stopped']}]
    
    if not include_stopped:
        filters.append({'Name': 'instance-state-name', 'Values': ['running']})
    
    instances = ec2.instances.filter(Filters=filters)
    return instances

def get_instance_name(instance):
    """Extract the name of the instance from its tags."""
    for tag in instance.tags or []:
        if tag['Key'] == 'Name':
            return tag['Value']
    return "No Name"

def select_instance(instances):
    """Allow the user to select an instance to log into."""
    print("Available instances:")
    if not instances:
        print("No matching instances found.")
        return None

    for i, instance in enumerate(instances, start=1):
        name = get_instance_name(instance)
        print(f"{i}) Name: {name}, Instance ID: {instance.id}, State: {instance.state['Name']}")
    
    selection = input("Enter the number of the instance you want to log into (or 'exit' to quit): ")
    if selection.lower() == 'exit':
        return None
    try:
        selection = int(selection) - 1
        return list(instances)[selection]
    except (ValueError, IndexError):
        print("Invalid selection.")
        return None

def find_key_for_instance(instance):
    """Find the SSH key for the instance based on its KeyName."""
    key_name = instance.key_name
    keys_directory = os.path.expanduser("~/.ssh")
    for key_file in os.listdir(keys_directory):
        if key_file.startswith(key_name) and key_file.endswith(".pem"):
            return os.path.join(keys_directory, key_file)
    return None

def ssh_into_instance(instance, remote_user="ec2-user"):
    """SSH into the selected instance, if any."""
    if instance is None:
        return

    ssh_key_path = find_key_for_instance(instance)
    if not ssh_key_path:
        print(f"No matching SSH key found for instance {instance.id} with KeyName {instance.key_name}")
        return
    
    print(f"Logging into {get_instance_name(instance)} ({instance.id})...")
    private_ip = instance.private_ip_address
    ssh_cmd = f'ssh -o StrictHostKeyChecking=no -i {ssh_key_path} {remote_user}@{private_ip}'
    subprocess.run(ssh_cmd, shell=True)

def main():
    """Main function to list instances and allow user selection for SSH login."""
    include_stopped = input("Include stopped instances? (yes/no): ").lower().startswith('y')
    search_term = input("Enter a search term to filter by instance name (leave empty for no filter): ").strip() or None
    instances = list(list_all_instances(include_stopped, search_term))
    
    selected_instance = select_instance(instances)
    ssh_into_instance(selected_instance)

if __name__ == "__main__":
    main()

Leave a comment

Your email address will not be published. Required fields are marked *