DEV Community

Jake Howering
Jake Howering

Posted on

Simple Python Code to get all VM Names, IPs, and FQDN's in the AWS Organization

Getting your AWS VM Name, IP address and FQDN from your AWS Organization should be simple. But...

AWS has made it ridiculously hard to get a consolidated list of all Virtual Machine Names, IP's and Fully-Qualified Domain Names across your AWS Organization. There is no single command to do it. You must iterate through all accounts individually, making API calls within each account. It can be tricky.

Using Python, I've made it simple. Keep reading to learn how I did it.

Background: The AWS Organization must be setup to allow users to assume roles from the Management Account to the individual Member Accounts. Start here with more information on this.

Program Logic:
1) Input the Management Account ID into the program. We'll use it later

print("******************************************************************")
print("Welcome to the AWS Organization EC2 Name, IP and FQDN Report")
print("To get started, please enter the AWS Organization Main Account ID: ")
orgMainAccountID = input()
Enter fullscreen mode Exit fullscreen mode

2) Get the list of all the accounts in the AWS Organization

orgClient = boto3.client('organizations')
response = orgClient.list_accounts()
Enter fullscreen mode Exit fullscreen mode

3) We'll iterate over all the accounts found in the "response" variable. For each of the accounts, we'll use the AWS Security Token Service (STS) to create temporary tokens to access the Member accounts from the Management account. Except, we won't create a temporary token for the Management account since we are accessing it directly.

for account in response['Accounts']:
Enter fullscreen mode Exit fullscreen mode

4) Using AWS STS, create the token and the session

stsClient = boto3.client('sts')
roleArn = "arn:aws:iam::" + account['Id'] + ":role/OrganizationAccountAccessRole"
stsresponse = stsClient.assume_role(RoleArn=roleArn, RoleSessionName='newsession')
# Save the details from assumed role into vars
newsession_id = stsresponse["Credentials"]["AccessKeyId"]
newsession_key = stsresponse["Credentials"]["SecretAccessKey"]
newsession_token = stsresponse["Credentials"]["SessionToken"]
Enter fullscreen mode Exit fullscreen mode

5) Using the assume_role variables, create an ec2client to get information from our virtual machines and store in the "response" variable

# Use the assumed session vars to create a new boto3 client with the assumed role creds
ec2Client = boto3.client('ec2', 
  region_name=region['RegionName'],
  aws_access_key_id=newsession_id, 
  aws_secret_access_key=newsession_key, 
  aws_session_token=newsession_token)
response = ec2Client.describe_instances()
Enter fullscreen mode Exit fullscreen mode

6) Loop through all responses and get the VM Name, IP, and FDQN.

for reservation in response["Reservations"]:
  for instance in reservation["Instances"]:
    try:
      if instance["State"]["Name"] == "running":
        print("Account Name:",account['Name']+",", "Region: 
        {}, Name: {}, Private IP: {}, Public IP: {}, FQDN: 
        {}".format( region['RegionName'],
        # get instance name from Tag Name
        [tag['Value'] for tag in instance['Tags'] if tag['Key'] == 'Name'][0], instance["PrivateIpAddress"],instance["PublicIpAddress"], instance["PublicDnsName"]))
     except KeyError as missing_key:
     # Used as missing_key for readability purposes only
       print(f"Trying to access a <dict> with a missing key {missing_key}") 
Enter fullscreen mode Exit fullscreen mode

7) Back to the Management account ID we input in step 1. The code contains a condition to make sure we don't try to "assume_role" into the Management account, since we are accessing it directly.

A final note. The complete code can be found here. Feel free to improve with better error handling, readability or execution speed.

Top comments (0)