
Adding rules to all security groups at once
Hello, I'm Lee Sujae from Classmethod.
Sometimes there are cases when you need to add certain rules to all security groups, such as when implementing Client VPN.
If you only have a few security groups, this isn't a problem, but if you have dozens or hundreds of security groups, adding rules to each one manually becomes inefficient in many ways.
For these cases, I've created a Python code.
AI: I've translated the text while maintaining the original Markdown formatting. The translation preserves the exact structure and paragraph breaks of the original Korean text.## Code first
Code
#!/usr/bin/env python3
import csv
import boto3
import botocore
import sys
def add_security_group_rules(sg_file, rules_file):
"""
Add security group
Args:
sg_file: Security group list csv file
rules_file: Rules to add csv file
"""
# Initialize AWS EC2 client
try:
ec2 = boto3.client("ec2")
except Exception as e:
print(f"AWS error : {e}")
return False
# Read security group list
sg_dict = {}
try:
with open(sg_file, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
sg_dict[row["GroupName"]] = row["GroupId"]
print(f"Confirmed {len(sg_dict)} security groups")
except Exception as e:
print(f"Failed to read security groups : {e}")
return False
# Read and add rules
success_count = 0
error_count = 0
try:
with open(rules_file, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
sg_name = row["sg_name"]
direction = row["direction"]
protocol = row["protocol"]
from_port = int(row["from_port"]) if row["from_port"] else None
to_port = int(row["to_port"]) if row["to_port"] else None
cidr = row["cidr"]
description = row.get("description", "")
# Check security group ID
if sg_name not in sg_dict:
print(f"Failed to find security group with name : {sg_name}")
error_count += 1
continue
sg_id = sg_dict[sg_name]
# Add rule
if add_rule(
ec2,
sg_id,
direction,
protocol,
from_port,
to_port,
cidr,
description,
):
print(
f"Rule added successfully : {sg_name} ({direction}) {protocol}:{from_port}-{to_port} {cidr}"
)
success_count += 1
else:
error_count += 1
except Exception as e:
print(f"Failed to read rules file : {e}")
return False
print(f"\nResults: {success_count} successful, {error_count} errors")
return error_count == 0
def add_rule(ec2, sg_id, direction, protocol, from_port, to_port, cidr, description):
"""
Add individual rule
"""
try:
# IP
ip_permission = {
"IpProtocol": protocol,
"IpRanges": [{"CidrIp": cidr, "Description": description}],
}
# If port specification exists
if from_port is not None:
ip_permission["FromPort"] = from_port
if to_port is not None:
ip_permission["ToPort"] = to_port
# Add inbound or outbound rule
if direction.lower() == "inbound":
ec2.authorize_security_group_ingress(
GroupId=sg_id, IpPermissions=[ip_permission]
)
elif direction.lower() == "outbound":
ec2.authorize_security_group_egress(
GroupId=sg_id, IpPermissions=[ip_permission]
)
else:
print(f"Invalid setting : {direction}")
return False
return True
except botocore.exceptions.ClientError as e:
error_code = e.response["Error"]["Code"]
if error_code == "InvalidPermission.Duplicate":
print(f"The same rule already exists in this group : {sg_id}")
return True # Consider it successful if identical rule already exists
else:
print(f"Error adding rule ({sg_id}): {e}")
return False
except Exception as e:
print(f"Other error ({sg_id}): {e}")
return False
def main():
sg_file = sys.argv[1]
rules_file = sys.argv[2]
print("Starting addition of rules to AWS security groups")
success = add_security_group_rules(sg_file, rules_file)
if success:
print("All rules added successfully")
else:
print("Some rules were not added")
sys.exit(1)
if __name__ == "__main__":
main()
```## How to Use
To run this, you need a security group CSV file that lists the target security groups and a CSV file containing the rules to be added.
### Security Group CSV
The sample is as follows:
```csv
GroupId,GroupName
sg-0d499fcd31e37bb14,clientvpntestsg
sg-0094e1017a3411dd6,testsg
Creating a CSV of security groups is simple.
First, access the security group page in the AWS console.
Then, check the necessary security groups as shown and click "Export security groups to CSV" to output them all at once.
You can use the group name and ID columns from the exported CSV by copying them directly into a separate CSV file.
Rules CSV
The sample is as follows:
sg_name,direction,protocol,from_port,to_port,cidr,description
clientvpntestsg,inbound,tcp,80,80,219.255.147.112/32,HTTP access
testsg,inbound,tcp,443,443,219.255.147.112/32,HTTPS access
You need to create this CSV file yourself.
You can target multiple groups in a single CSV file, and add both inbound and outbound rules.
Execution
Once the CSV files are ready, run the code with the following command:
# python {code file name}.py {security group csv} {rules csv}
$ python test.py sg.csv rules.csv
If it runs without issues, you'll see output like this:
python3 test.py sg.csv sgrules.csv
AWS security group rule addition started
2 security groups confirmed
Rule addition successful: clientvpntestsg (inbound) tcp:80-80 219.255.147.112/32
Rule addition successful: testsg (inbound) tcp:443-443 219.255.147.112/32
Results: 2 successful, 0 errors
All rules added successfully
Conclusion
I created this because I needed it for actual use, and I hope it helps those reading this article.
Thank you for reading this long post.
Please send any typos or content feedback to must01940 gmail.
For inquiries, contact Classmethod Korea!
Classmethod Korea conducts various seminars and events.
Please refer to the page below for ongoing events.
For AWS consultations and inquiries about Classmethod Members, please contact us at:
Info@classmethod.kr