Some time ago I was looking for a solution to find unused/unattached security groups within an AWS environment. Unfortunately I haven’t found an easy way to do it, except selecting all of them and trying to press delete to see notification on the ones which can’t be removed. I tried to find any dependencies to determine groups in-use and finally I found it. If security group isn’t attached to any network interface it is probably unused. Why probably? Because if you’ve a launch configuration (assigned to an auto scaling group) with defined security group, a group won’t be attached to a network interface until there aren’t available EC2 instances. If desired capacity of auto scaling group is equal to 0, you’ll be able to remove a group which is theoretically in-use.
I created a script, which allows you to scan all region whenever you want.

  • sg-scanner is available on GitHub
  • if you find any issues please report them on GitHub issues section
  • if you’ve any features requests please ask for them also on GitHub

Script requirments

This tool is written in Python and it should work with versions 2.x and 3.x.

I tested it under Windows 10 and Ubuntu 16.04, but it should also work on other distros. Make sure you’ve Python and all required libs installed and you’re ready to go!

How it looks like & Use cases

You can use it on your EC2 instance (using an IAM role) or from your local PC (using AWS Access Key and Secret Key). I strongly recommend not to use it from an EC2 instance with AWS credentials because it isn’t really a good practice. You can find a policy with defined minimum required permission in repository – sgscanner-policy.json.

There are two scanning scenarios:

  • unattached – which finds security groups that aren’t binded to any AWS service
  • unsecure – which finds security groups with ports open from CIDR

If a group isn’t attached to any network interface, it’ll be marked as unused. Generally, all security groups binded to an AWS Services such as: EC2, RDS, Lambda, Load Balancers, WorkSpaces, AppStream and more, must be attached to network interface.

General parameters overview:

$ python REGION MODE --accesskey="youAccessKey" --secretkey="yourSecretKey" --ignoreports=80,443
  • region – AWS region e.g “eu-west-1
  • mode – scanning scenario e.g “unattached“, “unsecure
  • –accesskey (optional) – access key of your AWS user
  • –secretkey (optional) – secret key of your AWS user
  • –ignoreports (optional) – list of ports that should be ignored while scanning for unsecure groups

Example of scanning eu-west-1 region for unattached groups:

$ python eu-west-1 unattached --accesskey="ABC" --secretkey="123"

and the result is:

Example of scanning eu-west-1 region for unsecure groups:

$ python eu-west-1 unsecure --accesskey="ABC" --secretkey="123"

and the result is:
You can exclude ports that are frequently open from, such as 80 or 443. Let’s take a look at another scanning example in eu-west-1 region and unsecured groups:

$ python eu-west-1 unsecure --accesskey="ABC" --secretkey="123" --ignoreports=80,443

and the result is:

As you can see ports 80 and 443 aren’t part of the output. There is one exception: if ports passed into –ignoreports argument are a part of port range, then those ports won’t be skipped. For example, if you add port 500 to ignore list and security group has a rule, which allows for port range 450-550, it’ll show as a part of the output:

and that’s all!


As you can see, it’s pretty simple tool, but it can be really useful. You can filter output using grep or select-string -pattern. I’m going to add filtering by any IP address (not only, and maybe I’ll add export to CSV function as well 🙂 .

Write A Comment