We have some security groups that have quite a few rules in them. Rather than having to recreate the same rules for a number of security groups just to accommodate minor differences, is it possible to copy a security group to use as a starting point, or use inheritance, etc?

  • 2
    You can apply multiple security groups to a single resource. Making a copy of a security group seems like a bad idea. Just add the new rules to a new group and apply it to the right instances.
    – Ladadadada
    Commented May 23, 2013 at 6:51
  • I just tried searching for this info but cant find anything that shows how to add additional security groups to a singe EC2 instance. Can you provide a link? Commented May 23, 2013 at 21:07
  • I just wrote a new function in a Python Boto class library I slowly add to. A PITA I shouldn't have had to deal with (as are a lot of things) but at least now I have a simpler and more straight forward interface to do this than anything else I've seen. Commented Aug 22, 2013 at 17:02

10 Answers 10


Doesn't look like you can copy security groups from the web interface. You can however use the AWS CLI to create security groups:

Command :

$ aws ec2 describe-security-groups --group-id MySecurityGroupID

Output :

    "securityGroupInfo": [
            "ipPermissionsEgress": [],
            "groupId": "sg-903004f8",
            "ipPermissions": [],
            "groupName": "MySecurityGroup",
            "ownerId": "803981987763",
            "groupDescription": "AWS-CLI-Example"
    "requestId": "afb680df-d7b1-4f6a-b1a7-344fdb1e3532"

And add rules using command :

aws ec2 authorize-security-group-ingress --group-id MySecurityGroupID --ip-protocol tcp --from-port 22 --to-port 22 --cidr-ip


    "return": "true",
    "requestId": "c24a1c93-150b-4a0a-b56b-b149c0e660d2"

From there you should be able to figure out how to simplify the creation of your security groups.

  • yeah I figured this was the route that would need to be taken... was thinking about doing something similar to this using boto too. Thanks for the example... will give you the thumbs up for it. Thanks. Commented May 23, 2013 at 0:12
  • 1
    You must specify the region btw. e.g. aws ec2 describe-security-groups --group-id MySecurityGroupID --region us-west-2
    – evan.bovie
    Commented Aug 15, 2019 at 22:38

AWS EC2 Console allows you to select the Security Group and perform the operation "Copy to new" in the UI now.

  • 4
    Note that in this way, one can copy SGs only in the same region.
    – 0xc0de
    Commented Dec 22, 2020 at 9:52

Here is the 'copy security groups' python/boto method from a custom library I wrote to make these kinds of things easier / automate them.. Ultimately this was the solution I came up with.

vpcId is the Virtual Private Cloud Id
keys is a dictionary with your AWS keys

The rest should be straight forward to figure out.

def copyEC2SecurityGroup(self, keys, region, securityGroupName, newSecurityGroupName = None, newRegion = None, vpcId = None):

newEc2Connection = None
print("Creating ec2Connection for source region: " + region)
ec2Connection = lib.getEc2Connection(region, keys)

if newRegion is None:
    newRegion = region
    print("New Region Detected, creating for New region: " + newRegion)
    newEc2Connection = lib.getEc2Connection(newRegion, keys)
    newRegionInfo = newEc2Connection.region

print("new region is: %s" % newRegion)

if newSecurityGroupName is None:
    newSecurityGroupName = securityGroupName

print ("new security group is: %s" % newSecurityGroupName)

# if copying in the same region the new security group cannot have the same name.
if newRegion == region:
    if newSecurityGroupName == securityGroupName:
        print ("Old and new security groups cannot have the same name when copying to the same region.")

groups = [group for group in ec2Connection.get_all_security_groups() if group.name == securityGroupName]
print"got groups count " + str(len(groups))
if groups:
    theOldGroup = groups[0]
    print theOldGroup.rules
    print("Can't find security group by the name of: %s" % securityGroupName)
print groups

if newEc2Connection is not None:
    print("Creating new security group in new region")
    sg = newEc2Connection.create_security_group(newSecurityGroupName, newSecurityGroupName, vpcId)
    print("Creating new security group in current region")
    sg = ec2Connection.create_security_group(newSecurityGroupName, newSecurityGroupName, vpcId)

source_groups = []
for rule in theOldGroup.rules:
    for grant in rule.grants:
        strGrant = str(grant)
        if strGrant.startswith("sg"):
            print("Cannot copy 'security group rule' (%s)... only cidr_ip's e.g. xxx.xxx.xxx.xxx/yy." % strGrant)
        grant_nom = grant.name or grant.group_id
        if grant_nom:
            if grant_nom not in source_groups:
                sg.authorize(rule.ip_protocol, rule.from_port, rule.to_port, grant)
            sg.authorize(rule.ip_protocol, rule.from_port, rule.to_port, grant.cidr_ip)
return sg 
  • The code indenting looks out of whack. Can you fix that?
    – Shoan
    Commented Aug 22, 2015 at 1:13
  • @Shoan - Sorry been too long. I'm not actually working with this right now. This is a method I cut from a library I wrote, and I used it regularly when I was using it. So I know it worked at the time I posted it here. If it is an indent thing, then it shouldn't be too hard to figure it out (but I don't have time right now to build out an environment to fiddle with it, but you can ;) ). It could also be an issue with the version of the library maybe? In any case, it still is likely a good starting point for anyone wanting to do this programmatically with Boto. Commented Aug 31, 2015 at 18:23
  • 1
    what is lib? where should I import it from?
    – Suncatcher
    Commented Jul 31, 2017 at 8:51

From AWS Creating a Security Group docs, you can copy a security group using the console.

  1. Select the security group you want to copy
  2. Choose Action
  3. Copy to new

AWS Security Group - Copy to New

  • The most counter-intuitive place to go for making a copy. Thanks. Would be better if you pointed at the EC2 Console. Commented May 8, 2017 at 16:09
  • 6
    As long as you're copying within the same region this works. If you need to duplicate to another region, you still need to use the EC2 CLI. Commented Nov 7, 2018 at 18:15
  • This option doesn't exist in the VPC Dashboard.
    – evan.bovie
    Commented Aug 15, 2019 at 22:36

Consider having a look at this blog. It might be useful for what you are looking at.


  • I wrote some Python Boto stuff to do this. Easier to use than anything I've seen. Commented Aug 22, 2013 at 17:14
  • please summarize the contents of your link Commented Aug 23, 2013 at 3:26
  • 1
    Doesn't work. Use of uninitialized value $type in string eq at create-firewall-script.pl line 43, <> line 1 (#1)
    – Suncatcher
    Commented Aug 13, 2017 at 8:40

Here is the script I made to accomplish this: aws_sg_migrate

Sample usage is

python3 aws_sg_migrate.py --vpc=vpc-05643b6c --shell --src=us-east-1 --dest=us-west-1 sg-111111

It is based on this one and adapted for Python3.

  • The usage seems interesting but there's no script attached?
    – JJarava
    Commented Apr 22, 2018 at 20:41
  • Sorry,= :) Added the link
    – Suncatcher
    Commented Apr 23, 2018 at 9:09

Within the same AWS region, you can copy a security policy using the online GUI. However, sometimes you want to copy things programmatically. For instance, if you have a lot of security policies to copy or if you want to copy across regions.

Here's a simple snippet to do that.

import boto3
from os import environ as env

def copy_security_groups(src_region, tgt_region, grp_names):

    # Initialize client connections for regions
    src_client = boto3.client('ec2', region_name=src_region,
    tgt_client = boto3.client('ec2', region_name=tgt_region,

    # Get info for all security groups and copy them one-by-one
    g_info = src_client.describe_security_groups(
    for g in g_info:
        resp = tgt_client.create_security_group(
            GroupName=g['GroupName'], Description=g['Description'])
        new_grp_id = resp['GroupId']
            GroupId=new_grp_id, IpPermissions=g['IpPermissions'])
            GroupId=new_grp_id, IpPermissions=g['IpPermissionsEgress'])

if __name__ == '__main__':
    copy_security_groups('us-east-1', 'ap-south-1', ['rds-public'])

Due to lack of a proper way of doing this online, I created a super simple script to handle it. Have a look if you're interested.


  • This is not really a good candidate for an "answer" submission. Might be useful as a comment when you have enough rep to post those.
    – Andrew B
    Commented May 22, 2014 at 16:31

From the EC2 console, click on Launch Instance and proceed to enter dummy info until you get to the security group section..

From here click on "Select an Existing Security Group", and below you will see all the security groups you have for that particular VPC. You should see a "Copy to New" link under "Actions", use this to copy all of your ACLs to a new SG.

Or I suppose you could use a script - this is faster IMO..


I had a similar problem but copying SG across different accounts.

Just specify some CONSTANTS at the beginning and the function copy_sg will copy them.

No error check is in place therefore it the target SG already exists it will fail.

Follow a general solution that can be used also intra-account:

#!/usr/bin/env python3
# coding: utf-8

import boto3
from typing import Any,  List

# This profile needs to be able to assume the specified role in SRC/TGT account
appops_session = boto3.Session(profile_name='YOUR_PRECONFIGURE_PROFILE')

ROLE = "THE ROLE TO BE ASSUMED"  # I presume it is the same in SRC/TGT Account

TGT_REGION = "eu-central-1"

region = "ap-southeast-2"
dst_vpc_id = "vpc-XXXXXXXXXXXXXXX"
sg_list = ["sg-XXXXXXXX", "sg-YYYYYYYYY"]

def aws_sts_cred(account, role):
    """Get the STS credential.

    return  credential_object
    sts_creds = {}
    sts_conn = appops_session.client('sts')

    role_arn = "arn:aws:iam::" + account + ":role/" + role
    assumed_role = sts_conn.assume_role(RoleArn=role_arn,
    sts_creds["aws_access_key_id"] = assumed_role['Credentials']['AccessKeyId']
    sts_creds["aws_secret_access_key"] = assumed_role['Credentials']['SecretAccessKey']
    sts_creds["aws_session_token"] = assumed_role['Credentials']['SessionToken']
    return sts_creds

def aws_conn(service: str, region: str, **kwargs) -> Any:
    """Create a client object."""
    return boto3.client(service, region_name=region, **kwargs)

def dump_sg(client, vpcid: str = "", sgids: List = []) -> List:
    """Dump the specified SG."""
    sg_info = client.describe_security_groups(
            Filters = [{'Name': 'group-id', 'Values': sgids}])['SecurityGroups']
    return sg_info

def copy_sg(tgt_client, sgs, vpcid=""):
    for sg in sgs:
        # With no Vpc ID the SG is created in the default VPC.
        resp = tgt_client.create_security_group(
            GroupName=sg['GroupName'], Description=sg['Description'], VpcId=vpcid)
        new_grp_id = resp['GroupId']
            GroupId=new_grp_id, IpPermissions=sg.get('IpPermissions', list()))
        if sg.get('IpPermissionsEgress') != []:
            # It doesn't work with an empty list
                GroupId=new_grp_id, IpPermissions=sg.get('IpPermissionsEgress'))
        print("Create SG {} - \"{}\" - \"{}\" in VPCID: {}".format(new_grp_id, sg['GroupName'], sg['Description'], vpcid))

STS_CRED = aws_sts_cred(SRC_ACCOUNT, ROLE)

src_client = aws_conn("ec2", region, **STS_CRED)

sg_list = dump_sg(src_client, sgids=sg_list)

tgt_client = aws_conn("ec2", TGT_REGION, **STS_CRED_TGT)

copy_sg(tgt_client, sg_list)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .