Repository: cloud-custodian/cloud-custodian

Issue:
Security group from config needs normalization on ingress/egress permissions
This keeps on getting invoked when running a config rule with the following policy:

```
    resource: security-group
    filters:
      - type: ingress
        Cidr:
          value: 0.0.0.0/0
          op: eq
          value_type: cidr
      - type: ingress
        Ports: [23]
    mode:
      type: config-rule
    actions:
      - type: remove-permissions
        egress: matched
```

```
argument of type 'NoneType' is not iterable: TypeError
Traceback (most recent call last):
File "/var/task/custodian_policy.py", line 4, in run
return handler.dispatch_event(event, context)
File "/var/task/c7n/handler.py", line 86, in dispatch_event
p.push(event, context)
File "/var/task/c7n/policy.py", line 579, in push
return mode.run(event, lambda_ctx)
File "/var/task/c7n/policy.py", line 489, in run
resources = super(ConfigRuleMode, self).run(event, lambda_context)
File "/var/task/c7n/policy.py", line 387, in run
resources, event)
File "/var/task/c7n/manager.py", line 86, in filter_resources
resources = f.process(resources, event)
File "/var/task/c7n/resources/vpc.py", line 692, in process
return super(SGPermission, self).process(resources, event)
File "/var/task/c7n/filters/core.py", line 161, in process
return filter(self, resources)
File "/var/task/c7n/resources/vpc.py", line 775, in __call__
cidr_found = self.process_cidrs(perm)
File "/var/task/c7n/resources/vpc.py", line 718, in process_cidrs
found = vf(ip_range)
File "/var/task/c7n/filters/core.py", line 330, in __call__
matched = self.match(i)
File "/var/task/c7n/filters/core.py", line 386, in match
v, r = self.process_value_type(self.v, r)
File "/var/task/c7n/filters/core.py", line 445, in process_value_type
v = parse_cidr(value)
File "/var/task/c7n/utils.py", line 325, in parse_cidr
if '/' not in value:
TypeError: argument of type 'NoneType' is not iterable
```


Discussion:
could you include or gist a sanitized (no account id) version of the config event as well, should be available in the cloud watch log for the lambda.
Here is the event. 
```
{
    "configRuleId": "config-rule-ze67a5",
    "version": "1.0",
    "configRuleName": "custodian-SecurityGroupIdentifierConfig",
    "configRuleArn": "arn:aws:config:us-east-1:**********:config-rule/config-rule-ze67a5",
    "invokingEvent": "{\"configurationItemDiff\":null,\"configurationItem\":{\"relatedEvents\":[\"e76ce5dd-fc23-41d5-9a56-9b9b7288095c\"],\"relationships\":[{\"resourceId\":\"eni-**********\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::NetworkInterface\",\"name\":\"Is associated with NetworkInterface\"},{\"resourceId\":\"i-**********\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::Instance\",\"name\":\"Is associated with Instance\"},{\"resourceId\":\"vpc-4c39712a\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::VPC\",\"name\":\"Is contained in Vpc\"}],\"configuration\":{\"ownerId\":\"**********\",\"groupName\":\"Eclipse Che powered by Bitnami-5.9.1-0 on Ubuntu 14.04.3-AutogenByAWSMP-\",\"groupId\":\"sg-b4d493ca\",\"description\":\"This security group was generated by AWS Marketplace and is based on recommended settings for Eclipse Che powered by Bitnami version 5.9.1-0 on Ubuntu 14.04.3 provided by Bitnami\",\"ipPermissions\":[{\"ipProtocol\":\"tcp\",\"fromPort\":23,\"toPort\":23,\"userIdGroupPairs\":[],\"ipv6Ranges\":[],\"prefixListIds\":[],\"ipv4Ranges\":[{\"cidrIp\":\"0.0.0.0/0\"}],\"ipRanges\":[\"0.0.0.0/0\"]}],\"ipPermissionsEgress\":[{\"ipProtocol\":\"-1\",\"userIdGroupPairs\":[],\"ipv6Ranges\":[],\"prefixListIds\":[],\"ipv4Ranges\":[{\"cidrIp\":\"0.0.0.0/0\"}],\"ipRanges\":[\"0.0.0.0/0\"]}],\"vpcId\":\"vpc-**********\",\"tags\":[{\"key\":\"ComplianceStatus\",\"value\":\"No\"},{\"key\":\"Name\",\"value\":\"\"}]},\"supplementaryConfiguration\":{},\"tags\":{\"ComplianceStatus\":\"No\",\"Name\":\"\"},\"configurationItemVersion\":\"1.2\",\"configurationItemCaptureTime\":\"2017-05-25T14:46:10.911Z\",\"configurationStateId\":1495723570911,\"awsAccountId\":\"**********\",\"configurationItemStatus\":\"OK\",\"resourceType\":\"AWS::EC2::SecurityGroup\",\"resourceId\":\"sg-**********\",\"resourceName\":null,\"ARN\":\"arn:aws:ec2:us-east-1:**********:security-group/sg-**********\",\"awsRegion\":\"us-east-1\",\"availabilityZone\":\"Not Applicable\",\"configurationStateMd5Hash\":\"**********\",\"resourceCreationTime\":null},\"notificationCreationTime\":\"2017-05-26T11:00:18.875Z\",\"messageType\":\"ConfigurationItemChangeNotification\",\"recordVersion\":\"1.2\"}",
    "eventLeftScope": false,
    "debug": true,
    "executionRoleArn": "arn:aws:iam::**********:role/service-role/config-role-us-east-1",
    "accountId": "**********"
}
```
Hope this helps the debugging process but the config rule does not identify all my SGs in the region which i find odd. When i do dryruns it will say something similar to 4 filtered down to 1 or 2. But when i check the config rule it says 2 of my SGs are compliant ignoring the others. 
thanks, it looks like config is doing some odd mangling here, it adds a new key Ipv4Ranges with the the dict list of CidrIp, but on the default attribute of IpRanges it mangles out the CidrIp which is causing the error. its probably worthwhile to roll this into #907 pull request which is handling some of the other config oddities.
So the lambda function did some ETL to the original event? 
just T from EL. config has a different internal representation then say the ec2 api.

Resolving patch:
diff --git a/c7n/resources/vpc.py b/c7n/resources/vpc.py
--- a/c7n/resources/vpc.py
+++ b/c7n/resources/vpc.py
@@ -26,7 +26,7 @@
 import c7n.filters.vpc as net_filters
 from c7n.filters.related import RelatedResourceFilter
 from c7n.filters.revisions import Diff
-from c7n.query import QueryResourceManager
+from c7n.query import QueryResourceManager, ConfigSource, DescribeSource
 from c7n.manager import resources
 from c7n.tags import universal_augment
 from c7n.utils import (
@@ -231,7 +231,29 @@ class resource_type(object):
         config_type = "AWS::EC2::SecurityGroup"
         id_prefix = "sg-"
 
-    augment = universal_augment
+    def get_source(self, source_type):
+        if source_type == 'config':
+            return ConfigSG(self)
+        elif source_type == 'describe':
+            return DescribeSG(self)
+        return super(SecurityGroup, self).get_source(source_type)
+
+
+class DescribeSG(DescribeSource):
+
+    def augment(self, resources):
+        return universal_augment(self.manager, resources)
+
+
+class ConfigSG(ConfigSource):
+
+    def augment(self, resources):
+        for r in resources:
+            for p in r.get('IpPermissions', ()):
+                p['IpRanges'] = p.pop('Ipv4Ranges')
+            for p in r.get('IpPermissionsEgress', ()):
+                p['IpRanges'] = p.pop('Ipv4Ranges')
+        return resources
 
 
 @SecurityGroup.filter_registry.register('diff')
diff --git a/c7n/utils.py b/c7n/utils.py
--- a/c7n/utils.py
+++ b/c7n/utils.py
@@ -200,7 +200,7 @@ def camelResource(obj):
         if isinstance(v, dict):
             camelResource(v)
         elif isinstance(v, list):
-            map(camelResource, v)
+            list(map(camelResource, v))
     return obj
 
 


Test patch:
diff --git a/tests/data/placebo/test_security_group_config_source/config.GetResourceConfigHistory_1.json b/tests/data/placebo/test_security_group_config_source/config.GetResourceConfigHistory_1.json
--- a/tests/data/placebo/test_security_group_config_source/config.GetResourceConfigHistory_1.json
+++ b/tests/data/placebo/test_security_group_config_source/config.GetResourceConfigHistory_1.json
@@ -4,31 +4,16 @@
         "configurationItems": [
             {
                 "configurationItemCaptureTime": {
-                    "hour": 0, 
+                    "hour": 6, 
                     "__class__": "datetime", 
-                    "month": 1, 
-                    "second": 23, 
-                    "microsecond": 464000, 
+                    "month": 8, 
+                    "second": 58, 
+                    "microsecond": 830000, 
                     "year": 2017, 
-                    "day": 26, 
-                    "minute": 28
+                    "day": 10, 
+                    "minute": 50
                 }, 
                 "relationships": [
-                    {
-                        "resourceType": "AWS::EC2::NetworkInterface", 
-                        "resourceId": "eni-0fac0bfc", 
-                        "relationshipName": "Is associated with NetworkInterface"
-                    }, 
-                    {
-                        "resourceType": "AWS::EC2::NetworkInterface", 
-                        "resourceId": "eni-23fd50d0", 
-                        "relationshipName": "Is associated with NetworkInterface"
-                    }, 
-                    {
-                        "resourceType": "AWS::EC2::NetworkInterface", 
-                        "resourceId": "eni-dd0bcf23", 
-                        "relationshipName": "Is associated with NetworkInterface"
-                    }, 
                     {
                         "resourceType": "AWS::EC2::VPC", 
                         "resourceId": "vpc-d2d616b5", 
@@ -37,29 +22,35 @@
                 ], 
                 "availabilityZone": "Not Applicable", 
                 "awsRegion": "us-east-1", 
-                "tags": {}, 
+                "tags": {
+                    "Name": "", 
+                    "c7n-test-tag": "c7n-test-val"
+                }, 
                 "resourceType": "AWS::EC2::SecurityGroup", 
                 "resourceId": "sg-6c7fa917", 
-                "configurationStateId": "1485408503464", 
-                "relatedEvents": [], 
+                "configurationStateId": "1502362258830", 
+                "relatedEvents": [
+                    "dc38f4d3-e652-4d54-9438-52821e74cf7c"
+                ], 
                 "arn": "arn:aws:ec2:us-east-1:644160558196:security-group/sg-6c7fa917", 
                 "version": "1.2", 
-                "configurationItemMD5Hash": "53f2d3b57aa239238047b5bf2cd75bfb", 
+                "configurationItemMD5Hash": "4e51d919fa402efb191edd0f11c29980", 
                 "supplementaryConfiguration": {}, 
-                "configuration": "{\"ownerId\":\"644160558196\",\"groupName\":\"default\",\"groupId\":\"sg-6c7fa917\",\"description\":\"default VPC security group\",\"ipPermissions\":[{\"ipProtocol\":\"-1\",\"fromPort\":null,\"toPort\":null,\"userIdGroupPairs\":[{\"userId\":\"644160558196\",\"groupName\":null,\"groupId\":\"sg-6c7fa917\",\"vpcId\":null,\"vpcPeeringConnectionId\":null,\"peeringStatus\":null}],\"ipRanges\":[\"108.56.181.242/32\"],\"prefixListIds\":[]}],\"ipPermissionsEgress\":[{\"ipProtocol\":\"-1\",\"fromPort\":null,\"toPort\":null,\"userIdGroupPairs\":[],\"ipRanges\":[\"0.0.0.0/0\"],\"prefixListIds\":[]}],\"vpcId\":\"vpc-d2d616b5\",\"tags\":[]}", 
+                "resourceName": "default", 
+                "configuration": "{\"description\":\"default VPC security group\",\"groupName\":\"default\",\"ipPermissions\":[{\"ipProtocol\":\"-1\",\"ipv6Ranges\":[],\"prefixListIds\":[],\"userIdGroupPairs\":[{\"groupId\":\"sg-6c7fa917\",\"userId\":\"644160558196\"}],\"ipv4Ranges\":[{\"cidrIp\":\"108.56.181.242/32\"}],\"ipRanges\":[\"108.56.181.242/32\"]}],\"ownerId\":\"644160558196\",\"groupId\":\"sg-6c7fa917\",\"ipPermissionsEgress\":[{\"ipProtocol\":\"-1\",\"ipv6Ranges\":[],\"prefixListIds\":[],\"userIdGroupPairs\":[],\"ipv4Ranges\":[{\"cidrIp\":\"0.0.0.0/0\"}],\"ipRanges\":[\"0.0.0.0/0\"]}],\"tags\":[{\"key\":\"Name\",\"value\":\"\"},{\"key\":\"c7n-test-tag\",\"value\":\"c7n-test-val\"}],\"vpcId\":\"vpc-d2d616b5\"}", 
                 "configurationItemStatus": "OK", 
                 "accountId": "644160558196"
             }
         ], 
-        "nextToken": "eyJlbmNyeXB0ZWREYXRhIjpbMTI1LDEwMCwtNzAsLTksLTY3LC0xLC02OSwtNSw1NSwtMTEyLDYsNTIsMTgsLTEyNywtMzIsLTU2LDUsODQsLTExNSwtMjcsLTc5LC0yOSwtNjAsLTEyMywtNjQsMzIsMzcsNDksODksNTksLTg0LC03NSwtODksLTgxLC0xMTYsMTAxLC00NSwtMzksMTIsLTEwNiwtODgsLTEyOCw1NCw2OCw1MCwtOTEsLTcxLDEzLC05NywtMzQsLTc1LC00Nyw0NiwtNDIsNDgsNDYsNzksOTksLTMsLTEwMCwtNzEsLTI1LC0xLC0xMTEsLTkwLDc1LC04NywtMTEwLDkwLC03NiwtODEsNDcsLTE3LC0xMDUsLTc3LC03MiwtMTExLDI4LDUyLC03MCw0MiwtMSwxMTYsLTEwNywxMTIsOCw2Myw2MSwtMjUsLTQsNTgsLTQ5LDM5LDU4LDEwOCwxMTQsMTEwLC02Niw0NSwtMTE3LDEwMywtODUsLTQxLC0zNiwxNywtNTQsOTgsLTYxLDE4LC05NiwxMDMsLTYxLC01NiwtNDAsLTIsOSwxNywtMTEsLTMzLDEyMSwtMTI4LC0xMywtODUsNjcsNjMsNDEsLTExOCwxMTgsLTEwNywtNTMsNjEsMTE1LC0xMjcsLTExMiwtMzcsMzksODEsMzMsMTUsNzEsNjAsNywtODYsNDgsLTEwNCwtMTI3LC0xMTYsLTEwMSwtMTEzLC01LC00NCw2OSw2NCwtMTIwLC02NCwxMjMsNjcsLTUsMTI3LDEwMSw4NSwxMDMsLTg0LDcyLDYzLC0xMDddLCJtYXRlcmlhbFNldFNlcmlhbE51bWJlciI6MSwiaXZQYXJhbWV0ZXJTcGVjIjp7Iml2IjpbMTI1LDk1LC0zOCw0LC0yNiwtNDYsLTkzLDg1LDcsMSw3MCwxMjUsLTg4LDEsNjMsMzRdfX0=", 
+        "nextToken": "eyJlbmNyeXB0ZWREYXRhIjpbLTM2LDMzLDExNSw3LDczLC05OSwtNjMsLTI2LDg0LC0xNiw3MCw0Niw4OCwtOCwtMTksMTAzLC0xMDgsNjIsMjEsLTExNCwtMTA0LC0yMCw4MiwtODYsLTE1LDgxLDY5LDEwMSw3MSw4OSwtNTIsNDgsLTg2LDU4LDUzLDEwNyw2LDExNCwtOCw3OSw5NSwtMTE0LDY2LDQ2LDYxLC01OCw2MiwzMiwtNDMsNzUsLTU0LC01OCwtMTEwLDEsLTI1LC04Miw1NCw3MywzNywtMTI2LC01OCwtNzUsMzYsLTk5LDQzLDEwNCwxMTcsNzgsNjksLTE2LC0yMiwtNzYsMjAsLTExMywtOTEsOTYsLTM1LDI3LDExNywtMTAwLC01MSwxMTUsNDUsLTYyLC04Miw2OSwxMTAsOTgsLTEyMCwtODIsNzIsMTEwLC0xMDksLTk0LDczLC0xMjAsNzksMTEzLDI3LDU4LC01NSw5OCwtMTA5LC0xMDQsLTQzLDczLC0xMjgsMzYsODQsNTcsLTcsLTYxLDQwLC00NywtMTcsNjMsLTY2LDI4LDk4LC04NCwtOTcsLTYzLDk3LC0xMTQsOTMsMyw5MSw4MCwxMCwtMTAwLDc1LC0xMTksNzYsLTc2LC0yMywzMywtNTEsLTE0LC03MCwtMzksNzYsLTEwNCwtNTAsLTcsLTEyNiwxMDQsLTk0LDc1LDY0LC02NiwxMjcsMTE5LDExNiwxMDksMjAsLTEyNSwxOSw0MywxMDUsLTQyLDE2LC02MSwxMjEsODUsNzIsLTEwM10sIm1hdGVyaWFsU2V0U2VyaWFsTnVtYmVyIjoxLCJpdlBhcmFtZXRlclNwZWMiOnsiaXYiOlstMzksLTM4LC05LDEyNywxMTMsNTYsMTYsMTMsLTMwLC0xOSwtNTMsNjUsMzgsLTM5LC02OSwxMTZdfX0=", 
         "ResponseMetadata": {
             "RetryAttempts": 0, 
             "HTTPStatusCode": 200, 
-            "RequestId": "0dcd7d7c-e9b2-11e6-89d1-b91eccf729ed", 
+            "RequestId": "2fb087b9-8350-11e7-bb70-11370d223f3a", 
             "HTTPHeaders": {
-                "x-amzn-requestid": "0dcd7d7c-e9b2-11e6-89d1-b91eccf729ed", 
-                "date": "Fri, 03 Feb 2017 01:42:42 GMT", 
-                "content-length": "2681", 
+                "x-amzn-requestid": "2fb087b9-8350-11e7-bb70-11370d223f3a", 
+                "date": "Thu, 17 Aug 2017 13:30:06 GMT", 
+                "content-length": "2443", 
                 "content-type": "application/x-amz-json-1.1"
             }
         }
diff --git a/tests/data/placebo/test_security_group_config_source/config.ListDiscoveredResources_1.json b/tests/data/placebo/test_security_group_config_source/config.ListDiscoveredResources_1.json
--- a/tests/data/placebo/test_security_group_config_source/config.ListDiscoveredResources_1.json
+++ b/tests/data/placebo/test_security_group_config_source/config.ListDiscoveredResources_1.json
@@ -4,18 +4,19 @@
         "ResponseMetadata": {
             "RetryAttempts": 0, 
             "HTTPStatusCode": 200, 
-            "RequestId": "0c87b6c8-e9b2-11e6-88cd-3bd72eb352d1", 
+            "RequestId": "2f737e91-8350-11e7-aaa4-3379113bde23", 
             "HTTPHeaders": {
-                "x-amzn-requestid": "0c87b6c8-e9b2-11e6-88cd-3bd72eb352d1", 
-                "date": "Fri, 03 Feb 2017 01:42:40 GMT", 
-                "content-length": "1495", 
+                "x-amzn-requestid": "2f737e91-8350-11e7-aaa4-3379113bde23", 
+                "date": "Thu, 17 Aug 2017 13:30:06 GMT", 
+                "content-length": "524", 
                 "content-type": "application/x-amz-json-1.1"
             }
         }, 
         "resourceIdentifiers": [
             {
                 "resourceType": "AWS::EC2::SecurityGroup", 
-                "resourceId": "sg-6c7fa917"
+                "resourceId": "sg-6c7fa917", 
+                "resourceName": "default"
             }
         ]
     }
diff --git a/tests/data/placebo/test_security_group_config_source/ec2.DescribeSecurityGroups_1.json b/tests/data/placebo/test_security_group_config_source/ec2.DescribeSecurityGroups_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_config_source/ec2.DescribeSecurityGroups_1.json
@@ -0,0 +1,67 @@
+{
+    "status_code": 200, 
+    "data": {
+        "SecurityGroups": [
+            {
+                "IpPermissionsEgress": [
+                    {
+                        "IpProtocol": "-1", 
+                        "PrefixListIds": [], 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "0.0.0.0/0"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [], 
+                        "Ipv6Ranges": []
+                    }
+                ], 
+                "Description": "default VPC security group", 
+                "Tags": [
+                    {
+                        "Value": "", 
+                        "Key": "Name"
+                    }, 
+                    {
+                        "Value": "c7n-test-val", 
+                        "Key": "c7n-test-tag"
+                    }
+                ], 
+                "IpPermissions": [
+                    {
+                        "IpProtocol": "-1", 
+                        "PrefixListIds": [], 
+                        "IpRanges": [
+                            {
+                                "CidrIp": "108.56.181.242/32"
+                            }
+                        ], 
+                        "UserIdGroupPairs": [
+                            {
+                                "UserId": "644160558196", 
+                                "GroupId": "sg-6c7fa917"
+                            }
+                        ], 
+                        "Ipv6Ranges": []
+                    }
+                ], 
+                "GroupName": "default", 
+                "VpcId": "vpc-d2d616b5", 
+                "OwnerId": "644160558196", 
+                "GroupId": "sg-6c7fa917"
+            }
+        ], 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "55726307-1840-4bae-bea0-8c3cfec65e62", 
+            "HTTPHeaders": {
+                "transfer-encoding": "chunked", 
+                "vary": "Accept-Encoding", 
+                "server": "AmazonEC2", 
+                "content-type": "text/xml;charset=UTF-8", 
+                "date": "Thu, 17 Aug 2017 13:30:06 GMT"
+            }
+        }
+    }
+}
diff --git a/tests/data/placebo/test_security_group_config_source/ec2.DescribeVpcs_1.json b/tests/data/placebo/test_security_group_config_source/ec2.DescribeVpcs_1.json
--- a/tests/data/placebo/test_security_group_config_source/ec2.DescribeVpcs_1.json
+++ b/tests/data/placebo/test_security_group_config_source/ec2.DescribeVpcs_1.json
@@ -3,40 +3,56 @@
     "data": {
         "Vpcs": [
             {
-                "VpcId": "vpc-29e0314f", 
+                "VpcId": "vpc-f1516b97", 
                 "InstanceTenancy": "default", 
+                "Tags": [
+                    {
+                        "Value": "FancyTestVPC", 
+                        "Key": "Name"
+                    }, 
+                    {
+                        "Value": "tagfanncyvalue", 
+                        "Key": "tagfancykey"
+                    }
+                ], 
                 "State": "available", 
                 "DhcpOptionsId": "dopt-24ff1940", 
-                "CidrBlock": "10.42.0.0/16", 
+                "CidrBlock": "10.0.42.0/24", 
                 "IsDefault": false
             }, 
             {
-                "VpcId": "vpc-72885e14", 
+                "VpcId": "vpc-d2d616b5", 
                 "InstanceTenancy": "default", 
                 "State": "available", 
                 "DhcpOptionsId": "dopt-24ff1940", 
-                "CidrBlock": "10.42.0.0/16", 
-                "IsDefault": false
+                "CidrBlock": "172.31.0.0/16", 
+                "IsDefault": true
             }, 
             {
-                "VpcId": "vpc-d2d616b5", 
+                "VpcId": "vpc-9ca119e5", 
                 "InstanceTenancy": "default", 
+                "Tags": [
+                    {
+                        "Value": "no-flow-logs", 
+                        "Key": "Name"
+                    }
+                ], 
                 "State": "available", 
                 "DhcpOptionsId": "dopt-24ff1940", 
-                "CidrBlock": "172.31.0.0/16", 
-                "IsDefault": true
+                "CidrBlock": "10.0.10.0/24", 
+                "IsDefault": false
             }
         ], 
         "ResponseMetadata": {
             "RetryAttempts": 0, 
             "HTTPStatusCode": 200, 
-            "RequestId": "26ce68bb-5e02-4746-a974-08a17de8575c", 
+            "RequestId": "b659ee1b-0007-4fa9-aca7-ec36a6f6e8a1", 
             "HTTPHeaders": {
                 "transfer-encoding": "chunked", 
                 "vary": "Accept-Encoding", 
                 "server": "AmazonEC2", 
                 "content-type": "text/xml;charset=UTF-8", 
-                "date": "Fri, 03 Feb 2017 01:42:45 GMT"
+                "date": "Thu, 17 Aug 2017 13:30:07 GMT"
             }
         }
     }
diff --git a/tests/data/placebo/test_security_group_config_source/tagging.GetResources_1.json b/tests/data/placebo/test_security_group_config_source/tagging.GetResources_1.json
--- a/tests/data/placebo/test_security_group_config_source/tagging.GetResources_1.json
+++ b/tests/data/placebo/test_security_group_config_source/tagging.GetResources_1.json
@@ -2,15 +2,29 @@
     "status_code": 200, 
     "data": {
         "PaginationToken": "", 
-        "ResourceTagMappingList": [], 
+        "ResourceTagMappingList": [
+            {
+                "ResourceARN": "arn:aws:ec2:us-east-1:644160558196:security-group/sg-6c7fa917", 
+                "Tags": [
+                    {
+                        "Value": "", 
+                        "Key": "Name"
+                    }, 
+                    {
+                        "Value": "c7n-test-val", 
+                        "Key": "c7n-test-tag"
+                    }
+                ]
+            }
+        ], 
         "ResponseMetadata": {
             "RetryAttempts": 0, 
             "HTTPStatusCode": 200, 
-            "RequestId": "02273fa4-5b4f-11e7-b54b-cf03244b62a5", 
+            "RequestId": "2f45def0-8350-11e7-9be3-817126018688", 
             "HTTPHeaders": {
-                "x-amzn-requestid": "02273fa4-5b4f-11e7-b54b-cf03244b62a5", 
-                "date": "Tue, 27 Jun 2017 15:40:55 GMT", 
-                "content-length": "1444", 
+                "x-amzn-requestid": "2f45def0-8350-11e7-9be3-817126018688", 
+                "date": "Thu, 17 Aug 2017 13:30:06 GMT", 
+                "content-length": "210", 
                 "content-type": "application/x-amz-json-1.1"
             }
         }
diff --git a/tests/test_utils.py b/tests/test_utils.py
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -180,6 +180,37 @@ def test_generate_arn(self):
                 separator=':'),
             'arn:aws:rds:us-east-1:123456789012:og:mysql-option-group1')
 
+    def test_camel_nested(self):
+        nest ={'description': 'default VPC security group',
+               'groupId': 'sg-6c7fa917',
+               'groupName': 'default',
+               'ipPermissions': [{'ipProtocol': '-1',
+                                  'ipRanges': ['108.56.181.242/32'],
+                                  'ipv4Ranges': [{'cidrIp': '108.56.181.242/32'}],
+                                  'ipv6Ranges': [],
+                                  'prefixListIds': [],
+                                  'userIdGroupPairs': [{'groupId': 'sg-6c7fa917',
+                                                        'userId': '644160558196'}]}],
+               'ipPermissionsEgress': [{'ipProtocol': '-1',
+                                        'ipRanges': ['0.0.0.0/0'],
+                                        'ipv4Ranges': [{'cidrIp': '0.0.0.0/0'}],
+                                        'ipv6Ranges': [],
+                                        'prefixListIds': [],
+                                        'userIdGroupPairs': []}],
+               'ownerId': '644160558196',
+               'tags': [{'key': 'Name', 'value': ''},
+                        {'key': 'c7n-test-tag', 'value': 'c7n-test-val'}],
+               'vpcId': 'vpc-d2d616b5'}
+        self.assertEqual(
+            utils.camelResource(nest)['IpPermissions'],
+            [{u'IpProtocol': u'-1',
+              u'IpRanges': [u'108.56.181.242/32'],
+              u'Ipv4Ranges': [{u'CidrIp': u'108.56.181.242/32'}],
+              u'Ipv6Ranges': [],
+              u'PrefixListIds': [],
+              u'UserIdGroupPairs': [{u'GroupId': u'sg-6c7fa917',
+                                     u'UserId': u'644160558196'}]}])
+                         
     def test_camel_case(self):
         d = {'zebraMoon': [{'instanceId': 123}, 'moon'],
              'color': {'yellow': 1, 'green': 2}}
diff --git a/tests/test_vpc.py b/tests/test_vpc.py
--- a/tests/test_vpc.py
+++ b/tests/test_vpc.py
@@ -328,7 +328,6 @@ def test_network_location_triple_intersect(self):
         self.assertEqual(len(resources), 0)
 
 
-
 class NetworkAclTest(BaseTest):
 
     @functional
@@ -796,17 +795,28 @@ def test_default_vpc(self):
     def test_config_source(self):
         factory = self.replay_flight_data(
             'test_security_group_config_source')
+        p = self.load_policy({
+            'name': 'sg-test',
+            'resource': 'security-group',
+            'filters': [{'GroupId': 'sg-6c7fa917'}]},
+            session_factory=factory)
+        d_resources = p.run()
+        self.assertEqual(len(d_resources), 1)
+
         p = self.load_policy({
             'name': 'sg-test',
             'source': 'config',
             'resource': 'security-group',
             'filters': [
                 {'type': 'default-vpc'},
-                {'GroupName': 'default'}]},
+                {'GroupId': 'sg-6c7fa917'}]},
             session_factory=factory)
-        resources = p.run()
-        self.assertEqual(len(resources), 1)
-        self.assertEqual(resources[0]['GroupId'], 'sg-6c7fa917')
+        c_resources = p.run()
+
+        self.assertEqual(len(c_resources), 1)
+        self.assertEqual(c_resources[0]['GroupId'], 'sg-6c7fa917')
+        self.maxDiff = None
+        self.assertEqual(c_resources, d_resources)
 
     def test_only_ports_ingress(self):
         p = self.load_policy({