Repository: cloud-custodian/cloud-custodian

Issue:
Using `config-rule` mode with `aws.kinesis` resource results in `KeyError: 'StreamName'`
### Describe the bug

When upgrading from [`0.9.12`](https://github.com/cloud-custodian/cloud-custodian/releases/tag/0.9.12.0) to [`0.9.16`](https://github.com/cloud-custodian/cloud-custodian/releases/tag/0.9.16.0), it is suggested to use `mode: config-rule` for resources fully supported by Config. After making this change for a policy enforcing tag compliance on Kinesis resources, the corresponding Lambda function errors with `KeyError: 'StreamName'`.

Based on a number of similar issues reported, it seems the problem is related to the difference in the Lambda invocation event shape that Config produces. References to what I believe to be similar issues:

- https://github.com/cloud-custodian/cloud-custodian/issues/6197
- https://github.com/cloud-custodian/cloud-custodian/issues/6268
- https://github.com/cloud-custodian/cloud-custodian/issues/6556
- https://github.com/cloud-custodian/cloud-custodian/issues/7042
- https://github.com/cloud-custodian/cloud-custodian/issues/6940
- https://github.com/cloud-custodian/cloud-custodian/issues/7169

### What did you expect to happen?

I expected my Kinesis tag compliance policy to yield the same results as it did prior to switching over to `config-rule` mode. 

### Cloud Provider

Amazon Web Services (AWS)

### Cloud Custodian version and dependency information

```shell
Custodian:   0.9.16
Python:      3.9.13
Platform:    Ubuntu
Using venv:  True
Docker: False
Installed: 

argcomplete==2.0.0
attrs==21.4.0
boto3==1.21.42
botocore==1.24.42
docutils==0.17.1
importlib-metadata==4.11.3
importlib-resources==5.7.1
jmespath==1.0.0
jsonschema==4.4.0
pyrsistent==0.18.1
python-dateutil==2.8.2
pyyaml==6.0
s3transfer==0.5.2
six==1.16.0
tabulate==0.8.9
typing-extensions==4.2.0
urllib3==1.26.9
zipp==3.8.0
```


### Policy

```yaml
policies:
- name: kinesis-tag-compliance
  resource: aws.kinesis
  mode:
    role: custodian
    type: config-rule
    runtime: python3.9
    tags:
      Name: kinesis-tag-compliance
  filters:
  - or:
    - tag:Name: absent
    - tag:Source: absent
    - type: value
      key: tag:fake-tag-x
      op: not-in
      value:
      - foo
      - bar
    - type: value
      key: tag:fake-tag-y
      op: not-in
      value:
      - "1.2.3"
      - "4.5.6"
    - type: value
      key: "tag:foo/bar"
      op: not-in
      value:
      - foo-value
      - bar-value
    - tag:fake-tag-z: absent
    - type: value
      key: "tag:xxx"
      op: not-in
      value:
      - "1.0"
```


### Relevant log/traceback output

```shell
[ERROR] KeyError: 'StreamName'
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 165, in dispatch_event
    p.push(event, context)
  File "/var/task/c7n/policy.py", line 1201, in push
    return mode.run(event, lambda_ctx)
  File "/var/task/c7n/policy.py", line 898, in run
    resources = super(ConfigRuleMode, self).run(event, lambda_context)
  File "/var/task/c7n/policy.py", line 447, in run
    resources = self.policy.resource_manager.filter_resources(
  File "/var/task/c7n/manager.py", line 111, in filter_resources
    resources = f.process(resources, event)
  File "/var/task/c7n/filters/core.py", line 337, in process
    return self.process_set(resources, event)
  File "/var/task/c7n/filters/core.py", line 349, in process_set
    resource_map = {r[rtype_id]: r for r in resources}
  File "/var/task/c7n/filters/core.py", line 349, in <dictcomp>
    resource_map = {r[rtype_id]: r for r in resources}
```


### Extra information or context

It'd be great if the documentation was accurate. The example on https://cloudcustodian.io/docs/aws/topics/config.html#config-poll-rule doesn't pass a validate with v0.9.16:

```sh
$ custodian validate kinesis-one-stream.yml
2022-06-08 11:46:20,026: custodian.commands:ERROR Configuration invalid: kinesis-one-stream.yml
2022-06-08 11:46:20,026: custodian.commands:ERROR Policy: kinesis-one-stream is invalid: resource:aws.kinesis fully supported by config and should use mode: config-rule
```

Here's a sample Config resource history output:

```sh
$ aws configservice get-resource-config-history --resource-type AWS::Kinesis::Stream --resource-id test
{
    "configurationItems": [
        {
            "version": "1.3",
            "accountId": "xxxx",
            "configurationItemCaptureTime": "xxx",
            "configurationItemStatus": "OK",
            "configurationStateId": "xxxx",
            "configurationItemMD5Hash": "",
            "arn": "arn:aws:kinesis:us-west-1:xxxx:stream/test",
            "resourceType": "AWS::Kinesis::Stream",
            "resourceId": "test",
            "resourceName": "test",
            "awsRegion": "us-west-1",
            "availabilityZone": "Regional",
            "tags": {
                "test": "test"
            },
            "relatedEvents": [],
            "relationships": [],
            "configuration": "{\"Arn\":\"arn:aws:kinesis:us-west-1:xxxx:stream/test\",\"Name\":\"test\",\"RetentionPeriodHours\":24,\"ShardCount\":1,\"Tags\":[{\"Key\":\"test\",\"Value\":\"test\"}]}",
            "supplementaryConfiguration": {}
        },
        {
            "version": "1.3",
            "accountId": "xxxx",
            "configurationItemCaptureTime": "2022-06-08T08:19:31.170000-05:00",
            "configurationItemStatus": "OK",
            "configurationStateId": "xxxx",
            "configurationItemMD5Hash": "",
            "arn": "arn:aws:kinesis:us-west-1:xxxx:stream/test",
            "resourceType": "AWS::Kinesis::Stream",
            "resourceId": "test",
            "resourceName": "test",
            "awsRegion": "us-west-1",
            "availabilityZone": "Regional",
            "tags": {},
            "relatedEvents": [],
            "relationships": [],
            "configuration": "{\"Arn\":\"arn:aws:kinesis:us-west-1:xxxxx:stream/test\",\"Name\":\"test\",\"RetentionPeriodHours\":24,\"ShardCount\":1,\"Tags\":[]}",
            "supplementaryConfiguration": {}
        }
    ]
}
```



Discussion:
For anyone else who comes across this same issue, you can get around the `ERROR Configuration invalid` by setting `ignore-support-check: True` under the `mode` block (this is also undocumented).

Example:

```yaml
policies:
- name: kinesis-tag-compliance
  resource: aws.kinesis
  mode:
    role: custodian
    type: config-poll-rule
    schedule: One_Hour
    ignore-support-check: True
    runtime: python3.9
```
Thanks for raising this @jackson-theisen - sounds like there's some digging to be done regarding `config-rule` mode on this resource and others. Regarding `config-poll-rule` mode, the `ignore-support-check` option was only recently added in #7194 but is mentioned in the [mode docs](https://cloudcustodian.io/docs/aws/resources/aws-modes.html#config-poll-rule).
also fwiw, validating policies in documentation is part of ci. our config support and the ability to one line change between exec modes. is based on some adaptation of the underlying idiosyncratic config format to that returned by the underlying service's describe format. thanks for the details wrt to the recorded config resource content on the stream.

Resolving patch:
diff --git a/c7n/resources/kinesis.py b/c7n/resources/kinesis.py
--- a/c7n/resources/kinesis.py
+++ b/c7n/resources/kinesis.py
@@ -17,6 +17,21 @@ def augment(self, resources):
         return universal_augment(self.manager, super().augment(resources))
 
 
+class ConfigStream(ConfigSource):
+
+    def load_resource(self, item):
+        resource = super().load_resource(item)
+        for ck, dk in {
+                'Arn': 'StreamARN',
+                'Name': 'StreamName'}.items():
+            resource[dk] = resource.pop(ck, None)
+        if 'StreamEncryption' in resource:
+            encrypt = resource.pop('StreamEncryption')
+            resource['EncryptionType'] = encrypt['EncryptionType']
+            resource['KeyId'] = encrypt['KeyId']
+        return resource
+
+
 @resources.register('kinesis')
 class KinesisStream(QueryResourceManager):
     retry = staticmethod(
@@ -36,7 +51,7 @@ class resource_type(TypeInfo):
 
     source_mapping = {
         'describe': DescribeStream,
-        'config': ConfigSource
+        'config': ConfigStream
     }
 
 


Test patch:
diff --git a/tests/data/config/kinesis-stream.json b/tests/data/config/kinesis-stream.json
new file mode 100644
--- /dev/null
+++ b/tests/data/config/kinesis-stream.json
@@ -0,0 +1,21 @@
+{
+    "version": "1.3",
+    "accountId": "644160558196",
+    "configurationItemCaptureTime": "2022-07-21T08:54:37.664000-04:00",
+    "configurationItemStatus": "ResourceDiscovered",
+    "configurationStateId": "1658408077664",
+    "configurationItemMD5Hash": "",
+    "arn": "arn:aws:kinesis:us-east-1:644160558196:stream/stream-encrypted",
+    "resourceType": "AWS::Kinesis::Stream",
+    "resourceId": "stream-encrypted",
+    "resourceName": "stream-encrypted",
+    "awsRegion": "us-east-1",
+    "availabilityZone": "Regional",
+    "tags": {
+        "App": "Magic"
+    },
+    "relatedEvents": [],
+    "relationships": [],
+    "configuration": "{\"Arn\":\"arn:aws:kinesis:us-east-1:644160558196:stream/stream-encrypted\",\"Name\":\"stream-encrypted\",\"RetentionPeriodHours\":24,\"ShardCount\":4,\"Tags\":[{\"Key\":\"App\",\"Value\":\"Magic\"}],\"StreamEncryption\":{\"EncryptionType\":\"KMS\",\"KeyId\":\"alias/aws/kinesis\"}}",
+    "supplementaryConfiguration": {}
+}
diff --git a/tests/test_kinesis.py b/tests/test_kinesis.py
--- a/tests/test_kinesis.py
+++ b/tests/test_kinesis.py
@@ -1,6 +1,18 @@
 # Copyright The Cloud Custodian Authors.
 # SPDX-License-Identifier: Apache-2.0
-from .common import BaseTest
+from .common import BaseTest, event_data
+
+
+def test_stream_config_source(test):
+    p = test.load_policy({
+        'name': 'stream-config',
+        'resource': 'aws.kinesis',
+        'mode': {'type': 'config-rule'}})
+    item = event_data('kinesis-stream.json', 'config')
+    source = p.resource_manager.get_source('config')
+    resource = source.load_resource(item)
+    assert resource['StreamName'] == 'stream-encrypted'
+    assert resource['KeyId'] == 'alias/aws/kinesis'
 
 
 class Kinesis(BaseTest):