Repository: cloud-custodian/cloud-custodian

Issue:
aws - sg ingress/egress filter with cidr/cidrv6 k:v expression errors
given policy

```yaml
policies:
 - name: sg
   resource: aws.security-group
   filters:
   - or:
     - type: ingress
       OnlyPorts: [22, 80, 443]
       CidrV6: "::/0"
     - type: ingress
       OnlyPorts: [22, 80, 443]
       Cidr: "0.0.0.0/0"
```

running leads to a traceback.. the work around is simple with
```
Cidr:
   value: "0.0.0.0/0"
```

but the simple syntax form should work out as well.. traceback follows.

```
2019-06-25 17:50:19,291: custodian.output:ERROR Error while executing policy
Traceback (most recent call last):
  File "/Users/kapilt/projects/custodian/c7n/policy.py", line 232, in run
    resources = self.policy.resource_manager.resources()
  File "/Users/kapilt/projects/custodian/c7n/query.py", line 460, in resources
    resources = self.filter_resources(resources)
  File "/Users/kapilt/projects/custodian/c7n/manager.py", line 109, in filter_resources
    resources = f.process(resources, event)
  File "/Users/kapilt/projects/custodian/c7n/filters/core.py", line 259, in process
    return self.process_set(resources, event)
  File "/Users/kapilt/projects/custodian/c7n/filters/core.py", line 275, in process_set
    r[resource_type.id] for r in f.process(resources, event)])
  File "/Users/kapilt/projects/custodian/c7n/resources/vpc.py", line 991, in process
    return super(SGPermission, self).process(resources, event)
  File "/Users/kapilt/projects/custodian/c7n/filters/core.py", line 197, in process
    return list(filter(self, resources))
  File "/Users/kapilt/projects/custodian/c7n/resources/vpc.py", line 1107, in __call__
    perm_matches['cidrs'] = self.process_cidrs(perm)
  File "/Users/kapilt/projects/custodian/c7n/resources/vpc.py", line 1034, in process_cidrs
    found_v6 = self._process_cidr('CidrV6', 'CidrIpv6', 'Ipv6Ranges', perm)
  File "/Users/kapilt/projects/custodian/c7n/resources/vpc.py", line 1018, in _process_cidr
    match_range['key'] = cidr_type
TypeError: 'str' object does not support item assignment
```



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
@@ -1009,13 +1009,18 @@ def process_ports(self, perm):
         return found
 
     def _process_cidr(self, cidr_key, cidr_type, range_type, perm):
+
         found = None
         ip_perms = perm.get(range_type, [])
         if not ip_perms:
             return False
 
         match_range = self.data[cidr_key]
-        match_range['key'] = cidr_type
+
+        if isinstance(match_range, dict):
+            match_range['key'] = cidr_type
+        else:
+            match_range = {cidr_type: match_range}
 
         vf = ValueFilter(match_range, self.manager)
         vf.annotate = False


Test patch:
diff --git a/tests/data/placebo/test_security_group_perm_cidr_kv/config.SelectResourceConfig_1.json b/tests/data/placebo/test_security_group_perm_cidr_kv/config.SelectResourceConfig_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_security_group_perm_cidr_kv/config.SelectResourceConfig_1.json
@@ -0,0 +1,30 @@
+{
+    "status_code": 200,
+    "data": {
+        "Results": [
+            "{\"configuration\":{\"groupName\":\"default\",\"groupId\":\"sg-6c7fa917\",\"vpcId\":\"vpc-d2d616b5\",\"ipPermissionsEgress\":[{\"ipRanges\":[\"0.0.0.0/0\"],\"prefixListIds\":[],\"userIdGroupPairs\":[],\"ipProtocol\":\"-1\",\"ipv4Ranges\":[{\"cidrIp\":\"0.0.0.0/0\"}],\"ipv6Ranges\":[]}],\"description\":\"default VPC security group\",\"ownerId\":\"644160558196\",\"ipPermissions\":[{\"ipRanges\":[\"108.56.181.242/32\"],\"prefixListIds\":[],\"userIdGroupPairs\":[{\"groupId\":\"sg-6c7fa917\",\"userId\":\"644160558196\"}],\"ipProtocol\":\"-1\",\"ipv4Ranges\":[{\"cidrIp\":\"108.56.181.242/32\"}],\"ipv6Ranges\":[]}],\"tags\":[{\"value\":\"Private\",\"key\":\"NetworkLocation\"}]},\"supplementaryConfiguration\":{}}"
+        ],
+        "QueryInfo": {
+            "SelectFields": [
+                {
+                    "Name": "configuration"
+                },
+                {
+                    "Name": "supplementaryConfiguration"
+                }
+            ]
+        },
+        "ResponseMetadata": {
+            "RequestId": "d8c9d736-cc72-4645-9a4d-6e4117578134",
+            "HTTPStatusCode": 200,
+            "HTTPHeaders": {
+                "x-amzn-requestid": "d8c9d736-cc72-4645-9a4d-6e4117578134",
+                "strict-transport-security": "max-age=86400",
+                "content-type": "application/x-amz-json-1.1",
+                "content-length": "824",
+                "date": "Wed, 26 Jun 2019 03:23:45 GMT"
+            },
+            "RetryAttempts": 0
+        }
+    }
+}
\ 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
@@ -1400,6 +1400,23 @@ def test_ingress_remove(self):
         ]
         self.assertEqual(group_info.get("IpPermissions", []), [])
 
+    def test_permission_cidr_kv(self):
+        factory = self.replay_flight_data('test_security_group_perm_cidr_kv')
+        p = self.load_policy({
+            'name': 'sg-ingress',
+            'resource': 'security-group',
+            'source': 'config',
+            'filters': [{
+                'type': 'egress',
+                'Cidr': '0.0.0.0/0',
+            }],
+            'query': [
+                {'clause': "resourceId ='sg-6c7fa917'"},
+            ]}, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0]['GroupId'], 'sg-6c7fa917')
+
     def test_default_vpc(self):
         # preconditions, more than one vpc, each with at least one
         # security group