Repository: cloud-custodian/cloud-custodian

Issue:
sg ingress/egress filter option for self-reference 
ie. SelfReference: true matches if the group allows traffic to itself.


Discussion:

Resolving patch:
diff --git a/c7n/resources/vpc.py b/c7n/resources/vpc.py
--- a/c7n/resources/vpc.py
+++ b/c7n/resources/vpc.py
@@ -461,8 +461,17 @@ class SGPermission(Filter):
         IpProtocol: -1
         FromPort: 445
 
+    We also have specialized handling for matching self-references in
+    ingress/egress permissions. The following example matches on ingress
+    rules which allow traffic its own same security group.
+
+    .. code-block: yaml
+
+      - type: ingress
+        SelfReference: True
+
     As well for assertions that a ingress/egress permission only matches
-    a given set of ports, *note* onlyports is an inverse match.
+    a given set of ports, *note* OnlyPorts is an inverse match.
 
     .. code-block: yaml
 
@@ -480,7 +489,7 @@ class SGPermission(Filter):
     perm_attrs = set((
         'IpProtocol', 'FromPort', 'ToPort', 'UserIdGroupPairs',
         'IpRanges', 'PrefixListIds'))
-    filter_attrs = set(('Cidr', 'Ports', 'OnlyPorts'))
+    filter_attrs = set(('Cidr', 'Ports', 'OnlyPorts', 'SelfReference'))
     attrs = perm_attrs.union(filter_attrs)
 
     def validate(self):
@@ -538,8 +547,17 @@ def process_cidrs(self, perm):
                     found = False
         return found
 
+    def process_self_reference(self, perm, sg_id):
+        found = None
+        if 'UserIdGroupPairs' in perm and 'SelfReference' in self.data:
+            self_reference = sg_id in [p['GroupId']
+                                       for p in perm['UserIdGroupPairs']]
+            found = self_reference & self.data['SelfReference']
+        return found
+
     def __call__(self, resource):
         matched = []
+        sg_id = resource['GroupId']
         for perm in resource[self.ip_permissions_key]:
             found = None
             for f in self.vfilters:
@@ -558,6 +576,12 @@ def __call__(self, resource):
                 if cidr_found is not None:
                     found = (
                         found is not None and cidr_found & found or cidr_found)
+            if found is None or found:
+                self_reference_found = self.process_self_reference(perm, sg_id)
+                if self_reference_found is not None:
+                    found = (
+                        found is not None and
+                        self_reference_found & found or self_reference_found)
             if not found:
                 continue
             matched.append(perm)
@@ -576,7 +600,8 @@ class IPPermission(SGPermission):
         #'additionalProperties': True,
         'properties': {
             'type': {'enum': ['ingress']},
-            'Ports': {'type': 'array', 'items': {'type': 'integer'}}
+            'Ports': {'type': 'array', 'items': {'type': 'integer'}},
+            'SelfReference': {'type': 'boolean'}
             },
         'required': ['type']}
 
@@ -589,7 +614,8 @@ class IPPermissionEgress(SGPermission):
         'type': 'object',
         #'additionalProperties': True,
         'properties': {
-            'type': {'enum': ['egress']}
+            'type': {'enum': ['egress']},
+            'SelfReference': {'type': 'boolean'}
             },
         'required': ['type']}
 


Test patch:
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupEgress_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupEgress_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupEgress_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "c3e10188-6f30-45e7-bcb7-7d780c6c573a", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:11:46 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "1c967cf2-b8f7-42f4-a4db-eee689e0a3c9", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:09:33 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_2.json b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_2.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "cf50ab67-da69-4038-9254-74ad48f42bd1", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:09:41 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_3.json b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.AuthorizeSecurityGroupIngress_3.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "88418409-bec7-4154-a9a5-9f7ec385e6fd", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:11:23 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.CreateSecurityGroup_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.CreateSecurityGroup_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.CreateSecurityGroup_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "GroupId": "sg-46a8b13f", 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "68691456-5298-4528-bab8-86c1cf5a1cf7", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:09:20 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.CreateSecurityGroup_2.json b/tests/data/placebo/test_security_group_self_reference/ec2.CreateSecurityGroup_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.CreateSecurityGroup_2.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200, 
+    "data": {
+        "GroupId": "sg-f6abb28f", 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "084dd53d-2a53-4779-8a4f-95a67dff3ad5", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:11:34 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.CreateVpc_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.CreateVpc_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.CreateVpc_1.json
@@ -0,0 +1,26 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "75677232-8eb5-48e9-9e59-de9b54ec99d7", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:08:57 GMT"
+            }
+        }, 
+        "Vpc": {
+            "VpcId": "vpc-07d70c60", 
+            "InstanceTenancy": "default", 
+            "Tags": [], 
+            "State": "pending", 
+            "DhcpOptionsId": "dopt-78ab4f1c", 
+            "CidrBlock": "10.4.0.0/16", 
+            "IsDefault": false
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DeleteSecurityGroup_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.DeleteSecurityGroup_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DeleteSecurityGroup_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "cdcc234e-f055-4ec0-8c69-905b28ee1df1", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:13:01 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DeleteSecurityGroup_2.json b/tests/data/placebo/test_security_group_self_reference/ec2.DeleteSecurityGroup_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DeleteSecurityGroup_2.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "28cee169-65a3-454a-8653-51acec63ceb8", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:13:03 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DeleteVpc_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.DeleteVpc_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DeleteVpc_1.json
@@ -0,0 +1,17 @@
+{
+    "status_code": 200, 
+    "data": {
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "286c843d-a452-4aba-b86e-794e0855c102", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:13:17 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_1.json b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_1.json
@@ -0,0 +1,51 @@
+{
+    "status_code": 200, 
+    "data": {
+        "SecurityGroups": [
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "default VPC security group", 
+                "IpPermissions": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [], 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "GroupName": "default", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-7ea8b107"
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "28c1940a-d3a8-46e5-8747-14ca125fb905", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:09:08 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_2.json b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_2.json
@@ -0,0 +1,146 @@
+{
+    "status_code": 200, 
+    "data": {
+        "SecurityGroups": [
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "SG 1", 
+                "IpPermissions": [
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 80, 
+                        "IpRanges": [], 
+                        "ToPort": 80, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-46a8b13f"
+                            }, 
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ]
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 61000, 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "10.2.0.0/16"
+                            }
+                        ], 
+                        "ToPort": 61000, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": []
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 60000, 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "10.2.0.0/16"
+                            }
+                        ], 
+                        "ToPort": 62000, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": []
+                    }
+                ], 
+                "GroupName": "sg1", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-46a8b13f"
+            }, 
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "default VPC security group", 
+                "IpPermissions": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [], 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "GroupName": "default", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-7ea8b107"
+            }, 
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 443, 
+                        "IpRanges": [], 
+                        "ToPort": 443, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-46a8b13f"
+                            }
+                        ]
+                    }
+                ], 
+                "Description": "SG 2", 
+                "IpPermissions": [], 
+                "GroupName": "sg2", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-f6abb28f"
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "31e1bc3f-0259-4cbb-a4e6-f97645e27a7f", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:12:25 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_3.json b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_3.json
@@ -0,0 +1,146 @@
+{
+    "status_code": 200, 
+    "data": {
+        "SecurityGroups": [
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "SG 1", 
+                "IpPermissions": [
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 80, 
+                        "IpRanges": [], 
+                        "ToPort": 80, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-46a8b13f"
+                            }, 
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ]
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 61000, 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "10.2.0.0/16"
+                            }
+                        ], 
+                        "ToPort": 61000, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": []
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 60000, 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "10.2.0.0/16"
+                            }
+                        ], 
+                        "ToPort": 62000, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": []
+                    }
+                ], 
+                "GroupName": "sg1", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-46a8b13f"
+            }, 
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "default VPC security group", 
+                "IpPermissions": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [], 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "GroupName": "default", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-7ea8b107"
+            }, 
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 443, 
+                        "IpRanges": [], 
+                        "ToPort": 443, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-46a8b13f"
+                            }
+                        ]
+                    }
+                ], 
+                "Description": "SG 2", 
+                "IpPermissions": [], 
+                "GroupName": "sg2", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-f6abb28f"
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "31e1bc3f-0259-4cbb-a4e6-f97645e27a7f", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:12:25 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_4.json b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_4.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_self_reference/ec2.DescribeSecurityGroups_4.json
@@ -0,0 +1,146 @@
+{
+    "status_code": 200, 
+    "data": {
+        "SecurityGroups": [
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "SG 1", 
+                "IpPermissions": [
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 80, 
+                        "IpRanges": [], 
+                        "ToPort": 80, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-46a8b13f"
+                            }, 
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ]
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 61000, 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "10.2.0.0/16"
+                            }
+                        ], 
+                        "ToPort": 61000, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": []
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 60000, 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "10.2.0.0/16"
+                            }
+                        ], 
+                        "ToPort": 62000, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": []
+                    }
+                ], 
+                "GroupName": "sg1", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-46a8b13f"
+            }, 
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "Description": "default VPC security group", 
+                "IpPermissions": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [], 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-7ea8b107"
+                            }
+                        ], 
+                        "PrefixListIds": []
+                    }
+                ], 
+                "GroupName": "default", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-7ea8b107"
+            }, 
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "PrefixListIds": []
+                    }, 
+                    {
+                        "PrefixListIds": [], 
+                        "FromPort": 443, 
+                        "IpRanges": [], 
+                        "ToPort": 443, 
+                        "IpProtocol": "tcp", 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-46a8b13f"
+                            }
+                        ]
+                    }
+                ], 
+                "Description": "SG 2", 
+                "IpPermissions": [], 
+                "GroupName": "sg2", 
+                "VpcId": "vpc-07d70c60", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-f6abb28f"
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "31e1bc3f-0259-4cbb-a4e6-f97645e27a7f", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Fri, 16 Dec 2016 15:12:25 GMT"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/test_vpc.py b/tests/test_vpc.py
--- a/tests/test_vpc.py
+++ b/tests/test_vpc.py
@@ -205,6 +205,100 @@ def test_only_ports(self):
               u'ToPort': 62000,
               u'UserIdGroupPairs': []}])
 
+    def test_self_reference(self):
+        factory = self.replay_flight_data(
+            'test_security_group_self_reference')
+        client = factory().client('ec2')
+
+        vpc_id = client.create_vpc(CidrBlock='10.4.0.0/16')['Vpc']['VpcId']
+        self.addCleanup(client.delete_vpc, VpcId=vpc_id)
+        # Find the ID of the default security group.
+        default_sg_id = client.describe_security_groups(Filters=[
+            {'Name': 'vpc-id', 'Values': [vpc_id]},
+            {'Name': 'group-name', 'Values': ['default']}])['SecurityGroups'][0]['GroupId']
+
+        sg1_id = client.create_security_group(
+            GroupName='sg1',
+            VpcId=vpc_id,
+            Description='SG 1')['GroupId']
+        self.addCleanup(client.delete_security_group, GroupId=sg1_id)
+        client.authorize_security_group_ingress(
+            GroupId=sg1_id,
+            IpPermissions=[{
+                'IpProtocol': 'tcp',
+                'FromPort': 80,
+                'ToPort': 80,
+                'UserIdGroupPairs': [
+                    {
+                        'GroupId': default_sg_id
+                    },
+                    {
+                        'GroupId': sg1_id
+                    }]
+            }])
+        client.authorize_security_group_ingress(
+            GroupId=sg1_id,
+            IpProtocol='tcp',
+            FromPort=60000,
+            ToPort=62000,
+            CidrIp='10.2.0.0/16')
+        client.authorize_security_group_ingress(
+            GroupId=sg1_id,
+            IpProtocol='tcp',
+            FromPort=61000,
+            ToPort=61000,
+            CidrIp='10.2.0.0/16')
+
+        sg2_id = client.create_security_group(
+            GroupName='sg2',
+            VpcId=vpc_id,
+            Description='SG 2')['GroupId']
+        self.addCleanup(client.delete_security_group, GroupId=sg2_id)
+        client.authorize_security_group_egress(
+            GroupId=sg2_id,
+            IpPermissions=[{
+                'IpProtocol': 'tcp',
+                'FromPort': 443,
+                'ToPort': 443,
+                'UserIdGroupPairs': [
+                    {
+                        'GroupId': sg1_id
+                    }]
+            }])
+
+        p = self.load_policy({
+            'name': 'sg-find0',
+            'resource': 'security-group',
+            'filters': [
+                {'type': 'ingress',
+                 'SelfReference': False},
+                {'GroupName': 'sg1'}]
+            }, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 0)
+
+        p = self.load_policy({
+            'name': 'sg-find1',
+            'resource': 'security-group',
+            'filters': [
+                {'type': 'ingress',
+                 'SelfReference': True},
+                {'GroupName': 'sg1'}]
+            }, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+
+        p = self.load_policy({
+            'name': 'sg-find2',
+            'resource': 'security-group',
+            'filters': [
+                {'type': 'egress',
+                 'SelfReference': True},
+                {'GroupName': 'sg2'}]
+            }, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 0)
+
     def test_security_group_delete(self):
         factory = self.replay_flight_data(
             'test_security_group_delete')