Repository: cloud-custodian/cloud-custodian

Issue:
Error using event-rule invalid-targets filter
### Describe the bug

Attempting to clean up event rules with invalid targets, c7n throws an error
"TypeError: argument of type 'NoneType' is not iterable"

### What did you expect to happen?

run the policy without crashing

### Cloud Provider

Amazon Web Services (AWS)

### Cloud Custodian version and dependency information

```shell
Custodian:   0.9.17
Python:      3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08) 
             [Clang 6.0 (clang-600.0.57)]
Platform:    posix.uname_result(sysname='Darwin', nodename='38f9d3ae684c', release='20.6.0', version='Darwin Kernel Version 20.6.0: Tue Apr 19 21:04:45 PDT 2022; root:xnu-7195.141.29~1/RELEASE_X86_64', machine='x86_64')
Using venv:  False
Docker: False
Installed: 

argcomplete==1.12.3
attrs==19.1.0
boto3==1.21.8
botocore==1.24.8
cffi==1.13.2
cryptography==36.0.1
importlib-metadata==4.11.1
jmespath==0.9.4
jsonschema==3.2.0
more-itertools==7.2.0
pycparser==2.19
pyrsistent==0.15.4
python-dateutil==2.8.2
pyyaml==6.0
s3transfer==0.5.2
setuptools==47.1.0
six==1.12.0
tabulate==0.8.7
typing-extensions==4.1.1
urllib3==1.26.8
zipp==0.6.0
```


### Policy

```shell
policies:
  - name: event-rule-invalid-target
    resource: event-rule
    filters:
      - type: value
        key: ManagedBy
        op: not-in
        value: 'amazonaws.com'
        value_type: swap
      - type: invalid-targets
        all: true 
    actions:
      - type: delete
        force: true
```


### Relevant log/traceback output

```shell
% custodian run --cache-period=30 --profile myProfile -v -s ~/c7nout -c test.yml -p event-rule-invalid-target -r us-east-1     
2022-07-06 17:08:34,722: custodian.commands:DEBUG Loaded file test.yml. Contains 16 policies
2022-07-06 17:08:36,491: custodian.output:DEBUG Storing output with <LogFile file:///Users/john_wick/c7nout/event-rule-invalid-target/custodian-run.log>
2022-07-06 17:08:36,503: custodian.policy:DEBUG Running policy:event-rule-invalid-target resource:event-rule region:us-east-1 c7n:0.9.17
2022-07-06 17:08:36,511: custodian.cache:DEBUG Using cache file /Users/john_wick/.cache/cloud-custodian.cache
2022-07-06 17:08:36,511: custodian.resources.eventrule:DEBUG Using cached c7n.resources.cw.EventRule: 1989
2022-07-06 17:16:55,368: custodian.cache:DEBUG Using cache file /Users/john_wick/.cache/cloud-custodian.cache
...
2022-07-06 17:18:37,849: custodian.cache:DEBUG Using cache file /Users/john_wick/.cache/cloud-custodian.cache
len(identities) != 1. Actual value: 2
identities:
['AccountServiceListenerQueue', 'AccountServiceListenerQueue']
2022-07-06 17:18:39,524: custodian.cache:DEBUG Using cache file /Users/john_wick/.cache/cloud-custodian.cache
...
2022-07-06 17:18:44,685: custodian.cache:DEBUG Using cache file /Users/john_wick/.cache/cloud-custodian.cache
2022-07-06 17:18:46,319: custodian.output:DEBUG metric:PolicyException Count:1 policy:event-rule-invalid-target restype:event-rule
2022-07-06 17:18:46,319: custodian.output:DEBUG metric:ApiCalls Count:1858 policy:event-rule-invalid-target restype:event-rule
2022-07-06 17:18:46,319: custodian.output:ERROR Error while executing policy
Traceback (most recent call last):
  File ".../site-packages/c7n/policy.py", line 290, in run
    resources = self.policy.resource_manager.resources()
  File ".../site-packages/c7n/query.py", line 536, in resources
    resources = self.filter_resources(resources)
  File ".../site-packages/c7n/manager.py", line 111, in filter_resources
    resources = f.process(resources, event)
  File ".../site-packages/c7n/resources/cw.py", line 249, in process
    resolved = arn_resolver.resolve(r['c7n:ChildArns'])
  File ".../site-packages/c7n/resources/aws.py", line 180, in resolve
    rmanager = self.manager.get_resource_manager(rtype)
  File ".../site-packages/c7n/manager.py", line 82, in get_resource_manager
    if '.' in resource_type:
TypeError: argument of type 'NoneType' is not iterable
2022-07-06 17:18:46,325: custodian.commands:ERROR Error while executing policy event-rule-invalid-target, continuing
Traceback (most recent call last):
  File ".../site-packages/c7n/commands.py", line 301, in run
    policy()
  File ".../site-packages/c7n/policy.py", line 1242, in __call__
    resources = mode.run()
  File ".../site-packages/c7n/policy.py", line 290, in run
    resources = self.policy.resource_manager.resources()
  File ".../site-packages/c7n/query.py", line 536, in resources
    resources = self.filter_resources(resources)
  File ".../site-packages/c7n/manager.py", line 111, in filter_resources
    resources = f.process(resources, event)
  File ".../site-packages/c7n/resources/cw.py", line 249, in process
    resolved = arn_resolver.resolve(r['c7n:ChildArns'])
  File ".../site-packages/c7n/resources/aws.py", line 180, in resolve
    rmanager = self.manager.get_resource_manager(rtype)
  File ".../site-packages/c7n/manager.py", line 82, in get_resource_manager
    if '.' in resource_type:
TypeError: argument of type 'NoneType' is not iterable
2022-07-06 17:18:46,326: custodian.commands:ERROR The following policies had errors while executing
 - event-rule-invalid-target
```


### Extra information or context

I got the policy working by adding "if rtype is not None:" at line 180 in the resolve method of ArnResolver Class in aws.py, like this:
```
   def resolve(self, arns):
        arns = map(Arn.parse, arns)
        a_service = operator.attrgetter('service')
        a_resource = operator.attrgetter('resource_type')
        kfunc = lambda a: (a_service(a), a_resource(a))  # noqa
        arns = sorted(arns, key=kfunc)
        results = {}
        for (service, arn_type), arn_set in itertools.groupby(arns, key=kfunc):
            arn_set = list(arn_set)
            rtype = ArnResolver.resolve_type(arn_set[0])
            if rtype is not None:
                rmanager = self.manager.get_resource_manager(rtype)
                if rtype == 'sns':
                    resources = rmanager.get_resources(
                        [rarn.arn for rarn in arn_set])
                else:
                    resources = rmanager.get_resources(
                        [rarn.resource for rarn in arn_set])
                for rarn, r in zip(rmanager.get_arns(resources), resources):
                    results[rarn] = r

                for rarn in arn_set:
                    if rarn.arn not in results:
                        results[rarn.arn] = None
        return results

Discussion:

Patch:
diff --git a/c7n/resources/cw.py b/c7n/resources/cw.py
index e932d5adc..1baf1ea89 100644
--- a/c7n/resources/cw.py
+++ b/c7n/resources/cw.py
@@ -194,6 +194,19 @@ class ValidEventRuleTargetFilter(ChildResourceFilter):
     )
 
     permissions = ('events:ListTargetsByRule',)
+    supported_resources = (
+        "aws.sqs",
+        "aws.event-bus",
+        "aws.lambda",
+        "aws.ecs",
+        "aws.ecs-task",
+        "aws.kinesis",
+        "aws.sns",
+        "aws.ssm-parameter",
+        "aws.batch-compute",
+        "aws.codepipeline",
+        "aws.step-machine",
+    )
 
     def validate(self):
         """
@@ -223,21 +236,11 @@ class ValidEventRuleTargetFilter(ChildResourceFilter):
     def process(self, resources, event=None):
         # Due to lazy loading of resources, we need to explicilty load the following
         # potential targets for a event rule target:
-        load_resources(
-            [
-                "aws.sqs",
-                "aws.lambda",
-                "aws.ecs-cluster",
-                "aws.ecs-task",
-                "aws.kinesis",
-                "aws.sns",
-                "aws.ssm-parameter",
-                "aws.batch-compute",
-                "aws.codepipeline",
-            ]
-        )
+
+        load_resources(list(self.supported_resources))
         arn_resolver = ArnResolver(self.manager)
         resources = self.get_rules_with_children(resources)
+        resources = [r for r in resources if self.filter_unsupported_resources(r)]
         results = []
 
         if self.data.get('all'):
@@ -254,6 +257,14 @@ class ValidEventRuleTargetFilter(ChildResourceFilter):
                 results.append(r)
         return results
 
+    def filter_unsupported_resources(self, r):
+        for carn in r.get('c7n:ChildArns'):
+            if 'aws.' + str(ArnResolver.resolve_type(carn)) not in self.supported_resources:
+                self.log.info(
+                    f"Skipping resource {r.get('Arn')}, target type {carn} is not supported")
+                return False
+            return True
+
 
 @EventRule.action_registry.register('delete')
 class EventRuleDelete(BaseAction):


Test patch:
diff --git a/tests/test_cwe.py b/tests/test_cwe.py
index ad7ebf8ca..17721e2b1 100644
--- a/tests/test_cwe.py
+++ b/tests/test_cwe.py
@@ -7,6 +7,7 @@ from unittest import TestCase
 from .common import event_data, BaseTest
 
 from c7n.cwe import CloudWatchEvents
+from c7n.resources import cw
 
 
 @terraform('event_bridge_bus')
@@ -136,6 +137,16 @@ class CloudWatchEventTest(BaseTest):
         resources = policy.run()
         self.assertEqual(len(resources), 0)
 
+    def test_filter_resource_with_unknown_target(self):
+        r = {
+            'Name': 'test-ebs-snapshot',
+            'Arn': 'arn:aws:events:us-east-1:644160558196:rule/test-ebs-snapshot',
+            'c7n:ChildArns': ['arn:aws:events:us-east-1:644160558196:target/create-snapshot',
+                            'arn:aws:lambda:us-east-1:644160558196:function:custodian-code']
+        }
+        self.assertFalse(
+            cw.ValidEventRuleTargetFilter('event-rule').filter_unsupported_resources(r))
+
 
 class CloudWatchEventsFacadeTest(TestCase):