List all EC2 Instances in all regions with OS and OS version data

If you can’t run Ansible on every EC2 because you don’t have all the SSH keys, and you don’t have AWS SSM installed on every machine, so you can’t do remote code execution with Run Commands, this is your next best option.

This script finds server OS & OS Version data by looping through every region, every reservation in every region, then every instance in every reservation.

To find the OS version, the script makes a call to describe_images for a given instance’s Image ID. The description field will contain the OS version if a default AMI was used to build the EC2. The script will not find an OS version if custom AMIs were used.

Enjoy!

"""
This script retrieves information about all Amazon Elastic Compute Cloud (EC2)
instances in a given list of regions and writes it to a CSV file.

The script uses the boto3 library to connect to the EC2 service and call the
describe_instances method to get a list of all reservations in each region.
It then iterates through the list of reservations and instances, and writes the
following information to a row in the CSV file:

- Instance ID
- Private IP address
- Image ID
- Platform details
- The image's description (if available)

The list of regions is specified in the REGIONS global variable.
"""

import csv

import boto3

REGIONS = [
    "ap-south-1",
    "eu-north-1",
    "eu-west-3",
    "eu-west-2",
    "eu-west-1",
    "ap-northeast-3",
    "ap-northeast-2",
    "ap-northeast-1",
    "ca-central-1",
    "sa-east-1",
    "ap-southeast-1",
    "ap-southeast-2",
    "eu-central-1",
    "us-east-1",
    "us-east-2",
    "us-west-1",
    "us-west-2",
]
FILENAME = "ec2s.csv"

def main():
    # Do The Work
    with open(FILENAME, "w", newline="", encoding="utf-8") as csvfile:
        fieldnames = [
            "Instance ID",
            "Private IP",
            "Image ID",
            "PlatformDetails",
            "Description",
            "Region",
        ]
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()

    for region in REGIONS:
        # Initialize EC2 client with region specified
        ec2 = boto3.client("ec2", region_name=region)

        # Call the describe_instances method to get a list of reservations
        reservations = ec2.describe_instances()["Reservations"]

        # Iterate through the list of reservations
        for reservation in reservations:

            # Iterate through the list of instances
            for instance in reservation["Instances"]:

                # Try to find the OS version through the description field
                try:
                    description = ec2.describe_images(ImageIds=[instance["ImageId"]])[
                        "Images"
                    ][0]["Description"]
                except Exception:
                    description = None

                # Store instance data
                with open(FILENAME, "a", newline="", encoding="utf-8") as csvfile:
                    writer = csv.writer(csvfile)
                    writer.writerow(
                        [
                            instance["InstanceId"],
                            instance["PrivateIpAddress"],
                            instance["ImageId"],
                            instance["PlatformDetails"],
                            description,
                            region,
                        ]
                    )


if __name__ == "__main__":
    main()