The AWS Security Group Auditor requires specific IAM permissions to scan your AWS account. You can configure different permission levels depending on whether you want read-only auditing or the ability to delete unused security groups.
Permission levels
Read-only mode Recommended for most use cases Allows the tool to audit and report on security group usage without making any changes to your account.
Delete mode For automated cleanup Includes read permissions plus the ability to delete unused security groups when you confirm.
Required permissions by service
The tool makes boto3 API calls to 22 AWS services. Below are all the permissions extracted from the actual source code.
Identity and account
Used to retrieve your AWS account ID for log file naming. # Source: check_sg_usage.py:33-34
sts = boto3.client( 'sts' )
account_id = sts.get_caller_identity()[ "Account" ]
EC2 and networking
EC2 permissions (7 actions)
ec2:DescribeSecurityGroups
Lists all security groups in your account - the foundation of the audit. # Source: check_sg_usage.py:49
security_groups = ec2.describe_security_groups()[ 'SecurityGroups' ]
Identifies EC2 instances using each security group and checks Elastic Beanstalk instances. # Source: check_sg_usage.py:70-74, 216
instances = ec2.describe_instances(
Filters = [{ 'Name' : 'instance.group-id' , 'Values' : [sg_id]}]
)
Checks VPC endpoints and Transfer Family server endpoints for security groups. # Source: check_sg_usage.py:243, 313
vpc_endpoints = ec2.describe_vpc_endpoints()[ 'VpcEndpoints' ]
ec2:DescribeVpnConnections
Scans Site-to-Site VPN connections. # Source: check_sg_usage.py:276
vpn_connections = ec2.describe_vpn_connections()
ec2:DescribeCustomerGateways
Checks customer gateways associated with VPN connections. # Source: check_sg_usage.py:282
customer_gateway = ec2.describe_customer_gateways()
Only required for delete mode . Allows deletion of unused security groups.# Source: check_sg_usage.py:356
ec2.delete_security_group( GroupId = sg_id)
Load Balancer permissions (2 actions)
elasticloadbalancing:DescribeLoadBalancers
Lists Classic Load Balancers (ELB) and their security groups. # Source: check_sg_usage.py:81
elbs = elb.describe_load_balancers()[ 'LoadBalancerDescriptions' ]
elasticloadbalancing:DescribeLoadBalancers
Lists Application and Network Load Balancers (ALB/NLB). # Source: check_sg_usage.py:88
elbv2_load_balancers = elbv2.describe_load_balancers()
Database services
Database permissions (4 services)
Checks RDS database instances. # Source: check_sg_usage.py:95
dbs = rds.describe_db_instances()[ 'DBInstances' ]
neptune:DescribeDBInstances
Checks Neptune graph database instances. # Source: check_sg_usage.py:191
neptune_instances = neptune.describe_db_instances()
Checks DocumentDB clusters. # Source: check_sg_usage.py:199
docdb_clusters = docdb.describe_db_clusters()
redshift:DescribeClusters
Checks Redshift data warehouse clusters. # Source: check_sg_usage.py:166
redshift_clusters = redshift.describe_clusters()
Container and compute services
Container orchestration (2 services)
Lists ECS clusters to scan for services. # Source: check_sg_usage.py:107
clusters = ecs.list_clusters()[ 'clusterArns' ]
Lists services within each ECS cluster. # Source: check_sg_usage.py:112-114
service_list_response = ecs.list_services( cluster = cluster_arn)
Gets network configuration details for ECS services (handles 10 services per call). # Source: check_sg_usage.py:124-127
detailed_services_response = ecs.describe_services(
cluster = cluster_arn, services = service_chunk
)
Lists EKS clusters. # Source: check_sg_usage.py:143
eks_clusters = eks.list_clusters()[ 'clusters' ]
Lists node groups within each EKS cluster. # Source: check_sg_usage.py:145
nodegroups = eks.list_nodegroups( clusterName = cluster_name)
Gets security group details for EKS node groups. # Source: check_sg_usage.py:147
nodegroup = eks.describe_nodegroup(
clusterName = cluster_name, nodegroupName = nodegroup_name
)
Platform and developer services (2 services)
Caching and messaging
Caching and streaming (3 services)
elasticache:DescribeCacheClusters
Checks ElastiCache clusters (Redis and Memcached). # Source: check_sg_usage.py:175
cache_clusters = elasticache.describe_cache_clusters(
ShowCacheNodeInfo = True
)
Lists Amazon MSK (Kafka) clusters. # Source: check_sg_usage.py:183
kafka_clusters = kafka.list_clusters()[ 'ClusterInfoList' ]
Lists Amazon MQ message brokers. # Source: check_sg_usage.py:288
mq_brokers = mq.list_brokers()[ 'BrokerSummaries' ]
Gets security group details for MQ brokers. # Source: check_sg_usage.py:290
broker = mq.describe_broker( BrokerId = broker_summary[ 'BrokerId' ])
Analytics and machine learning
Data and ML services (3 services)
Lists SageMaker model endpoints. # Source: check_sg_usage.py:224
sm_endpoints = sagemaker.list_endpoints()[ 'Endpoints' ]
sagemaker:DescribeEndpoint
Gets VPC configuration for SageMaker endpoints. # Source: check_sg_usage.py:226
endpoint_desc = sagemaker.describe_endpoint(
EndpointName = endpoint[ 'EndpointName' ]
)
Lists AWS Glue ETL jobs. # Source: check_sg_usage.py:252
glue_jobs = glue.get_jobs()[ 'Jobs' ]
Gets connection details for Glue jobs. # Source: check_sg_usage.py:257
connection_info = glue.get_connection( Name = connection_name)
Lists Elasticsearch/OpenSearch domains. # Source: check_sg_usage.py:265
es_domains = es.list_domain_names()[ 'DomainNames' ]
es:DescribeElasticsearchDomain
Gets VPC configuration for Elasticsearch domains. # Source: check_sg_usage.py:268
domain_config = es.describe_elasticsearch_domain(
DomainName = domain_name
)
Storage and file transfer
Storage services (3 services)
Lists Amazon FSx file systems. # Source: check_sg_usage.py:298
fsx_file_systems = fsx.describe_file_systems()
Lists AWS Transfer Family servers. # Source: check_sg_usage.py:237
transfer_servers = transfer.list_servers()[ 'Servers' ]
Gets VPC endpoint configuration for Transfer servers. # Source: check_sg_usage.py:240
server_details = transfer.describe_server( ServerId = server_id)
workspaces:DescribeWorkspaceDirectories
Lists Amazon WorkSpaces directories. # Source: check_sg_usage.py:306
workspaces_directories = workspaces.describe_workspace_directories()
IAM policy examples
Read-only policy (recommended)
This policy provides all permissions needed to audit security groups without the ability to make changes.
{
"Version" : "2012-10-17" ,
"Statement" : [
{
"Sid" : "SecurityGroupAuditorReadOnly" ,
"Effect" : "Allow" ,
"Action" : [
"ec2:DescribeSecurityGroups" ,
"ec2:DescribeInstances" ,
"ec2:DescribeVpcEndpoints" ,
"ec2:DescribeVpnConnections" ,
"ec2:DescribeCustomerGateways" ,
"elasticloadbalancing:DescribeLoadBalancers" ,
"rds:DescribeDBInstances" ,
"ecs:ListClusters" ,
"ecs:ListServices" ,
"ecs:DescribeServices" ,
"eks:ListClusters" ,
"eks:ListNodegroups" ,
"eks:DescribeNodegroup" ,
"codebuild:ListProjects" ,
"codebuild:BatchGetProjects" ,
"redshift:DescribeClusters" ,
"elasticache:DescribeCacheClusters" ,
"kafka:ListClusters" ,
"neptune:DescribeDBInstances" ,
"docdb:DescribeDBClusters" ,
"elasticbeanstalk:DescribeEnvironments" ,
"elasticbeanstalk:DescribeEnvironmentResources" ,
"sagemaker:ListEndpoints" ,
"sagemaker:DescribeEndpoint" ,
"transfer:ListServers" ,
"transfer:DescribeServer" ,
"glue:GetJobs" ,
"glue:GetConnection" ,
"es:ListDomainNames" ,
"es:DescribeElasticsearchDomain" ,
"mq:ListBrokers" ,
"mq:DescribeBroker" ,
"fsx:DescribeFileSystems" ,
"workspaces:DescribeWorkspaceDirectories" ,
"sts:GetCallerIdentity"
],
"Resource" : "*"
}
]
}
Full access policy (with deletion)
This policy includes ec2:DeleteSecurityGroup which allows the tool to permanently delete security groups. Use with caution and only in environments where automated cleanup is required.
{
"Version" : "2012-10-17" ,
"Statement" : [
{
"Sid" : "SecurityGroupAuditorReadOnly" ,
"Effect" : "Allow" ,
"Action" : [
"ec2:DescribeSecurityGroups" ,
"ec2:DescribeInstances" ,
"ec2:DescribeVpcEndpoints" ,
"ec2:DescribeVpnConnections" ,
"ec2:DescribeCustomerGateways" ,
"elasticloadbalancing:DescribeLoadBalancers" ,
"rds:DescribeDBInstances" ,
"ecs:ListClusters" ,
"ecs:ListServices" ,
"ecs:DescribeServices" ,
"eks:ListClusters" ,
"eks:ListNodegroups" ,
"eks:DescribeNodegroup" ,
"codebuild:ListProjects" ,
"codebuild:BatchGetProjects" ,
"redshift:DescribeClusters" ,
"elasticache:DescribeCacheClusters" ,
"kafka:ListClusters" ,
"neptune:DescribeDBInstances" ,
"docdb:DescribeDBClusters" ,
"elasticbeanstalk:DescribeEnvironments" ,
"elasticbeanstalk:DescribeEnvironmentResources" ,
"sagemaker:ListEndpoints" ,
"sagemaker:DescribeEndpoint" ,
"transfer:ListServers" ,
"transfer:DescribeServer" ,
"glue:GetJobs" ,
"glue:GetConnection" ,
"es:ListDomainNames" ,
"es:DescribeElasticsearchDomain" ,
"mq:ListBrokers" ,
"mq:DescribeBroker" ,
"fsx:DescribeFileSystems" ,
"workspaces:DescribeWorkspaceDirectories" ,
"sts:GetCallerIdentity"
],
"Resource" : "*"
},
{
"Sid" : "SecurityGroupDeletion" ,
"Effect" : "Allow" ,
"Action" : [
"ec2:DeleteSecurityGroup"
],
"Resource" : "*"
}
]
}
Setting up permissions
Option 1: Create an IAM user
Create a new IAM user in the AWS Console
Attach the read-only policy above
Generate access keys for the user
Configure AWS CLI with the credentials:
aws configure
# Enter Access Key ID, Secret Access Key, and region
Option 2: Use an IAM role (recommended for EC2)
If you’re running the tool from an EC2 instance:
Create an IAM role with the read-only policy
Attach the role to your EC2 instance
The tool will automatically use the instance role credentials
Option 3: Use AWS SSO
aws sso login --profile your-profile
export AWS_PROFILE = your-profile
python check_sg_usage.py
Permission scoping
All permissions require Resource: "*" because the tool needs to scan all resources across your account. AWS does not support resource-level permissions for most describe/list operations.
If you need to restrict the tool to specific regions, use a condition:
{
"Condition" : {
"StringEquals" : {
"aws:RequestedRegion" : [ "us-east-1" , "us-west-2" ]
}
}
}
Troubleshooting permission issues
If you encounter permission errors:
Check CloudTrail logs to see which specific API call failed
Test individual permissions using AWS CLI:
aws ec2 describe-security-groups
aws ecs list-clusters
aws rds describe-db-instances
Verify region access - ensure your credentials work in the region you’re scanning
Check service control policies (SCPs) if using AWS Organizations
Security best practices
Principle of least privilege Start with the read-only policy. Only add deletion permissions if you need automated cleanup.
Use temporary credentials Use AWS SSO or assume-role for time-limited access instead of long-lived access keys.
Enable CloudTrail Monitor all API calls made by the tool to ensure compliance and troubleshooting.
Rotate credentials If using IAM user access keys, rotate them regularly (every 90 days minimum).