Skip to content

Instantly share code, notes, and snippets.

@richadams
Last active February 23, 2024 20:46
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 18 You must be signed in to fork a gist
  • Save richadams/384020d6e4e6d4f400d7 to your computer and use it in GitHub Desktop.
Save richadams/384020d6e4e6d4f400d7 to your computer and use it in GitHub Desktop.
A quick and dirty script to list out all security group settings on an AWS account. Barely tested, use at own risk, etc. Requires awscli to be installed.
#!/bin/bash
# Requires: awscli (http://aws.amazon.com/cli/)
# Prints out a list of all security groups and their settings, just for quickly auditing it.
# Your AWS credentials
if [ -z ${AWS_ACCESS_KEY_ID} ]; then
export AWS_ACCESS_KEY_ID='***'
export AWS_SECRET_ACCESS_KEY='***'
fi
# Want to do this for all regions...
REGIONS=(`aws ec2 describe-regions --region us-west-1 --output text | grep "-" | awk -F\t '{print $3}'`)
for REGION in ${REGIONS[*]}; do
echo "=> $REGION"
# Grab all the security group info for this region in one call.
GFILE='/tmp/aws-sec-groups'
aws ec2 describe-security-groups --region $REGION --output text > $GFILE
# Grab list of actively used security groups for EC2.
EC2FILE='/tmp/aws-sec-groups-ec2'
aws ec2 describe-instances --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId' --output text --region $REGION | tr '\t' '\n' | sort | uniq > $EC2FILE
# Grab list of actively used security groups for RDS.
RDSFILE='/tmp/aws-sec-groups-rds'
aws rds describe-db-security-groups --query 'DBSecurityGroups[*].EC2SecurityGroups[*].EC2SecurityGroupId' --output text --region $REGION | tr '\t' '\n' | sort | uniq > $RDSFILE
# Loop over each line of the file and parse it.
old_IFS=$IFS; IFS=$'\n'
cat $GFILE | while read line
do
case $line in
# Header
SECURITYGROUPS*)
PORT_HAS_GLOBAL_RULE=0
SID=(`echo $line | awk -F\t '{print $3}'`)
GNAME=(`echo $line | awk -F\t '{print $4}'`)
# Determine if this group is currently being used by an EC2/RDS instance.
EXTRA=""
grep $SID $EC2FILE &> /dev/null
if [ $? -ne 0 ]; then
grep $SID $RDSFILE &> /dev/null
if [ $? -ne 0 ]; then
EXTRA=" <= ** Not currently used by any EC2 or RDS instance in this region!"
fi
fi
echo " => $SID ($GNAME) $EXTRA"
;;
# Rule Info
IPPERMISSIONS*)
INPORT=(`echo $line | awk -F\t '{print $2}'`)
OUTPORT=(`echo $line | awk -F\t '{print $4}'`)
PROTO=(`echo $line | awk -F\t '{print $3}'`)
;;
IPRANGES*)
EXTRA=""
CIDR=(`echo $line | awk -F\t '{print $2}'`)
# If a global rule was already seen for this port combo, then this rule is redundant!
if [[ "$PORT_HAS_GLOBAL_RULE" = "$PROTO:$INPORT-$OUTPORT" ]] ; then
EXTRA=" <= ** Redundant, /0 was already specified for $PORT_HAS_GLOBAL_RULE."
fi
# Check if we have the global rule enabled.
if [[ "$CIDR" = "0.0.0.0/0" ]]; then
EXTRA=" (!!)" # Mark it as potentially dangerous.
PORT_HAS_GLOBAL_RULE="$PROTO:$INPORT-$OUTPORT" # Also keep track, as it makes other rules redundant.
fi
echo -e " => $PROTO:$INPORT->$OUTPORT\t\t$CIDR $EXTRA"
;;
USERIDGROUPPAIRS*)
EXTRA=""
GROUPID=(`echo $line | awk -F\t '{print $2}'`)
GROUPNAME=(`echo $line | awk -F\t '{print $3}'`)
# If a global rule was already seen for this port combo, then this rule is redundant!
if [[ "$PORT_HAS_GLOBAL_RULE" = "$PROTO:$INPORT-$OUTPORT" ]] ; then
EXTRA=" <= ** Redundant, /0 was already specified for $PORT_HAS_GLOBAL_RULE."
fi
echo -e " => $PROTO:$INPORT->$OUTPORT\t\t$GROUPID ($GROUPNAME) $EXTRA"
;;
esac
done
IFS=$old_IFS
# Clean up
rm $GFILE
rm $EC2FILE
rm $RDSFILE
done
# Remove any credentials from env.
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
echo ""
@ulyssesr
Copy link

Load balancers also use security groups. Something to think about.

@mario-staykov
Copy link

mario-staykov commented Sep 12, 2019

Thanks Rich, that was greatly informative for creating a script that lists EC2 instances associated to given Security Groups, especially for the loop over regions code. It seems it needs a minor change though - AWS seem to have changed the format, so line 12 should end with awk printing argument 4 and not $3.

@mgeeky
Copy link

mgeeky commented Dec 6, 2019

12th line, change to:

aws ec2 describe-regions --query 'Regions[*].RegionName' --output text | tr '\t' '\n'

@devilinux
Copy link

devilinux commented Dec 19, 2019

You can modify 12th line as below as well:

aws ec2 describe-regions --region us-west-1 --output text | grep "-" | awk '{print $3}'

@rflume
Copy link

rflume commented Apr 14, 2020

I get opt-in-not-required for all regions (line 12).

Needed to change it to aws ec2 describe-regions --region us-west-1 --output text | grep "-" | awk -F\t '{print $4}'

Running:

  • aws-cli/1.18.16
  • Python/3.7.3
  • Darwin/19.3.0
  • botocore/1.15.16

@sherri-22
Copy link

This works for me as well

aws ec2 describe-regions --query 'Regions[*].RegionName' --output text | tr '\t' '\n'

@vasu-gaddavalasa
Copy link

[ec2-user@Test ~]$ sh aws_security_group_details.sh >> aws_all_regions_secgroups.txt
[ec2-user@Test ~]$ echo $?
0
[ec2-user@Test ~]$ cat aws_all_regions_secgroups.txt

[ec2-user@Test ~]$

I am not seeing any data though it executed without any errors, any suggestions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment