Use Boto3 to find subnets route through virtual private gateway

Viewed 1646

Need to find a way to identify AWS VPC Subnets that route through virtual private gateway by using Python Boto3. In another word, how can I use python boto3 to identify Private Subnets within a VPC?

The goal is to create a Lambda function that will identify private subnets within a given VPC, and then to launch another Lambda function within those Private Subnets.

Below is the code I got so far. It lists all subnets within a VPC that has a Virtual Private Gateway attached.

import boto3

def get_vpn_gateways():
    ec2_client = boto3.client('ec2')
    response = ec2_client.describe_vpn_gateways()
    return response

def get_vpc_subnets(VpcId):
    ec2 = boto3.resource('ec2')
    vpc = ec2.Vpc(VpcId)
    subnets = vpc.subnets.all()
    return subnets

# Get VPC Ids associated with the virtual private gateway
vpc_list = []
virtual_gateways = get_vpn_gateways() 
for virtual_gateway in virtual_gateways["VpnGateways"]:
    vgwId = virtual_gateway["VpnGatewayId"]
    vpcAttach = virtual_gateway["VpcAttachments"]
    vpc_list.append(vpcAttach[0]["VpcId"])
for vpc in vpc_list:
    print(vpc)
    subnets = get_vpc_subnets(vpc)
    for subnet in subnets:
        print(subnet)

The code so far lists all the subnets within the VPC. I am thinking to use routetable as the key identifier for Private subnet. If there are routes going through VGW, then I will deem the subnet as Private. Does that make sense?

2 Answers

I think the routing for 0.0.0.0/0 is not an internet gateway, then that is the private subnet. The private subnet could be routed to NAT gateway or Virtual gateway but not the internet gateway directly. So, I wrote code as below.

import boto3

ec2 = boto3.resource('ec2')
route_tables = ec2.route_tables.all()

for route_table in route_tables:
    for ra in route_table.routes_attribute:
        if ra.get('DestinationCidrBlock') == '0.0.0.0/0' and ra.get('GatewayId') is None:
            for rs in route_table.associations_attribute:
                if rs.get('SubnetId') is not None:
                    print(rs.get('SubnetId'))

Here's the final working code that looks up private subnets within each VPC that has Virtual Private Gateway attached. It checks if the private subnets is in the VPC's subnet list, then proceeds to save it later for another Lambda function. This probably not the most effective/efficient way to achive my goal. Keen to see any other better solutions.

import boto3

def get_vpn_gateways():
    ec2_client = boto3.client('ec2')
    response = ec2_client.describe_vpn_gateways()
    return response

def get_vpc_subnets(VpcId):
    ec2 = boto3.resource('ec2')
    vpc = ec2.Vpc(VpcId)
    subnets = vpc.subnets.all()
    return subnets

def get_private_subnets():
    priv_subnet_list = []
    ec2 = boto3.resource('ec2')
    route_tables = ec2.route_tables.all()
    for route_table in route_tables:
        for ra in route_table.routes_attribute:
            if ra.get('DestinationCidrBlock') == '0.0.0.0/0' and ra.get('GatewayId') is None:
                for rs in route_table.associations_attribute:
                    if rs.get('SubnetId') is not None:
                        priv_subnet_list.append(rs.get('SubnetId'))
    return priv_subnet_list
def lambda_handler(event, context):
    vpc_list = []
    vpc_subnet_list = []
    virtual_gateways = get_vpn_gateways()
    lambda_subnets = []
    # Get VPC Ids associated with the virtual private gateway
    for virtual_gateway in virtual_gateways["VpnGateways"]:
        vgwId = virtual_gateway["VpnGatewayId"]
        vpcAttach = virtual_gateway["VpcAttachments"]
        vpc_list.append(vpcAttach[0]["VpcId"])
    # Get subnets within the VPC
    for vpc in vpc_list:
        subnets = get_vpc_subnets(vpc)
        for subnet in subnets:
            vpc_subnet_list.append(subnet.id)
        # Get Private subnets from the subnet list
        for privsubnet in get_private_subnets():
            if privsubnet in vpc_subnet_list:
                lambda_subnets.append(privsubnet)

Related