Last active
June 18, 2024 10:12
-
-
Save amgill/353225152495d2dce52501fa70c2528a to your computer and use it in GitHub Desktop.
Generate AWS Security Groups Rules Report of all the Security Groups, as Seen via AWS Web Console. Uses python 3 with boto3 to generate CSV.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/python3 | |
###################################################################################################################### | |
# Purpose: Generate rules report of all the security groups # | |
# Input Params: None [Make sure to set AWS CLI session by populating env. vars. with keys.] # | |
# Usage: ./ec2_sg_rules.py > account-date.csv [python ./ec2_sg_rules.py > gill-dev-sg-2018-04-11.csv] # | |
# Author: Abdul Gill # | |
# Doc. Ref: http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.describe_security_groups# | |
###################################################################################################################### | |
from __future__ import print_function | |
import json | |
import boto3 | |
#Explicitly declaring variables here grants them global scope | |
cidr_block = "" | |
ip_protpcol = "" | |
from_port = "" | |
to_port = "" | |
from_source = "" | |
print("%s,%s,%s,%s,%s,%s" % ("Group-Name","Group-ID","In/Out","Protocol","Port","Source/Destination")) | |
for region in ["us-east-1","us-west-1", "us-west-2"]: | |
ec2=boto3.client('ec2', region ) | |
sgs = ec2.describe_security_groups()["SecurityGroups"] | |
for sg in sgs: | |
group_name = sg['GroupName'] | |
group_id = sg['GroupId'] | |
print("%s,%s" % (group_name,group_id)) | |
# InBound permissions ########################################## | |
inbound = sg['IpPermissions'] | |
print("%s,%s,%s" % ("","","Inbound")) | |
for rule in inbound: | |
if rule['IpProtocol'] == "-1": | |
traffic_type="All Trafic" | |
ip_protpcol="All" | |
to_port="All" | |
else: | |
ip_protpcol = rule['IpProtocol'] | |
from_port=rule['FromPort'] | |
to_port=rule['ToPort'] | |
#If ICMP, report "N/A" for port # | |
if to_port == -1: | |
to_port = "N/A" | |
#Is source/target an IP v4? | |
if len(rule['IpRanges']) > 0: | |
for ip_range in rule['IpRanges']: | |
cidr_block = ip_range['CidrIp'] | |
print("%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port, cidr_block)) | |
#Is source/target an IP v6? | |
if len(rule['Ipv6Ranges']) > 0: | |
for ip_range in rule['Ipv6Ranges']: | |
cidr_block = ip_range['CidrIpv6'] | |
print("%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port, cidr_block)) | |
#Is source/target a security group? | |
if len(rule['UserIdGroupPairs']) > 0: | |
for source in rule['UserIdGroupPairs']: | |
from_source = source['GroupId'] | |
print("%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port, from_source)) | |
# OutBound permissions ########################################## | |
outbound = sg['IpPermissionsEgress'] | |
print("%s,%s,%s" % ("","","Outbound")) | |
for rule in outbound: | |
if rule['IpProtocol'] == "-1": | |
traffic_type="All Trafic" | |
ip_protpcol="All" | |
to_port="All" | |
else: | |
ip_protpcol = rule['IpProtocol'] | |
from_port=rule['FromPort'] | |
to_port=rule['ToPort'] | |
#If ICMP, report "N/A" for port # | |
if to_port == -1: | |
to_port = "N/A" | |
#Is source/target an IP v4? | |
if len(rule['IpRanges']) > 0: | |
for ip_range in rule['IpRanges']: | |
cidr_block = ip_range['CidrIp'] | |
print("%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port, cidr_block)) | |
#Is source/target an IP v6? | |
if len(rule['Ipv6Ranges']) > 0: | |
for ip_range in rule['Ipv6Ranges']: | |
cidr_block = ip_range['CidrIpv6'] | |
print("%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port, cidr_block)) | |
#Is source/target a security group? | |
if len(rule['UserIdGroupPairs']) > 0: | |
for source in rule['UserIdGroupPairs']: | |
from_source = source['GroupId'] | |
print("%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port, from_source)) |
We can make this file beautiful and searchable if this error is corrected: It looks like row 2 should actually have 6 columns, instead of 2 in line 1.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Group-Name,Group-ID,In/Out,Protocol,Port,Source/Destination | |
default,sg-0990507b | |
,,Inbound | |
,,,All,All,sg-0990507b | |
,,Outbound | |
,,,All,All,0.0.0.0/0 | |
default,sg-156c2e62 | |
,,Inbound | |
,,,All,All,0.0.0.0/0 | |
,,,All,All,sg-156c2e62 | |
,,,tcp,22,0.0.0.0/0 | |
,,Outbound | |
,,,All,All,0.0.0.0/0 | |
transit-spoke-app-sg,sg-ebb8fa9c | |
,,Inbound | |
,,,tcp,80,175.29.255.240/28 | |
,,,tcp,80,15.0.0.0/8 | |
,,,icmp,N/A,15.0.0.0/8 | |
,,,tcp,22,175.29.255.240/28 | |
,,,tcp,22,15.0.0.0/8 | |
,,,udp,3389,175.29.255.240/28 | |
,,,udp,3389,15.0.0.0/8 | |
,,,tcp,3389,175.29.255.240/28 | |
,,,tcp,3389,15.0.0.0/8 | |
,,Outbound | |
,,,tcp,80,0.0.0.0/0 | |
,,,tcp,80,::/0 | |
,,,All,All,0.0.0.0/0 | |
,,,All,All,::/0 | |
default,sg-b291bfd4 | |
,,Inbound | |
,,,All,All,sg-b291bfd4 | |
,,Outbound | |
,,,All,All,0.0.0.0/0 | |
default,sg-b82d6dc5 | |
,,Inbound | |
,,,All,All,sg-b82d6dc5 | |
,,Outbound | |
,,,All,All,0.0.0.0/0 |
@amgill Thanks for sharing! I suggest to change to_port
in print
function with to_port if (to_port == "All" or from_port == to_port) else ''+str(from_port)+'-'+str(to_port)
as shown in the snippet below to include security groups with different from_port
and to_port
values.
print(%s,%s,%s,%s,%s,%s" % ("", "", "", ip_protpcol, to_port if (to_port == "All" or from_port == to_port) else ''+str(from_port)+'-'+str(to_port), cidr_block))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
slight issue where on the All traffic I was incorrectly getting port info egon the sections where it catches any port (need the same for outbound)
for rule in inbound: if rule['IpProtocol'] == "-1": traffic_type="All Trafic" ip_protpcol="All" to_port="All"
Updated to :
for rule in inbound: if rule['IpProtocol'] == "-1": traffic_type="All Trafic" ip_protpcol="All" to_port="All" from_port="All" port_range="All"
Probably doesnt need both the additions