Repository: cloud-custodian/cloud-custodian

Issue:
AWS config source pass supplementaryConfiguration data with resource 
**Is your feature request related to a problem? Please describe.**
Any reason why we do not return `supplementaryConfiguration` along with `configuration` . This would be helpful since this seems to contain tag information on resources which would be useful for further value filters.

https://github.com/cloud-custodian/cloud-custodian/blob/master/c7n/query.py#L350

**Describe the solution you'd like**
We can either add it to the resource data by default , or can create an option on the `config` source that will then add it.

for example:

```
policies: 
  - name: sns-test
    resource: aws.sns
    source: config
    supplimentary-config: true
    query:  
      - clause:  "tags.key = 'tag-check'"
```




Discussion:
we already have tags on resources, you'll have to give a more concrete/specific where this information is providing additional value.

unconstrained use of supplementary info is generally superfluous and also creates an tight coupling of a policy to a particular execution mode which is bad practice.

using a customized source can extract additional useful info to put into standard locations if there is utility in it.
one of the reasons we are looking to use config source is to reduce api calls. for example sns requires separate api calls to list topics, get attributes, and get tags. It looks like if we use config source we can get a lot of that data already in one api call. For some reason though the tags and a few other attributes are returned in supplementaryConfiguration and not the main configuration. we already query both
 ```    s = "select configuration, supplementaryConfiguration where resourceType = '{}'".format(
            self.manager.resource_type.config_type)
```

so looking to just pass that data along so the filters and actions can use them. 

load resource just gets the `configuration` data currently 

```
    def load_resource(self, item):
        if isinstance(item['configuration'], str):
            item_config = json.loads(item['configuration'])
        else:
            item_config = item['configuration']
        return camelResource(item_config)
```
grep through the source for ConfigSource subclasses (there are at least a half-dozen) and do one for sns would be the recommend.

Resolving patch:
diff --git a/c7n/resources/sns.py b/c7n/resources/sns.py
--- a/c7n/resources/sns.py
+++ b/c7n/resources/sns.py
@@ -41,6 +41,15 @@ def _augment(r):
             return list(w.map(_augment, resources))
 
 
+class ConfigSNS(ConfigSource):
+
+    def load_resource(self, item):
+        resource = super().load_resource(item)
+        resource['Tags'] = [{'Key': t['key'], 'Value': t['value']}
+          for t in item['supplementaryConfiguration']['Tags']]
+        return resource
+
+
 @resources.register('sns')
 class SNS(QueryResourceManager):
 
@@ -53,7 +62,7 @@ class resource_type(TypeInfo):
         id = 'TopicArn'
         name = 'DisplayName'
         dimension = 'TopicName'
-        cfn_type = 'AWS::SNS::Topic'
+        cfn_type = config_type = 'AWS::SNS::Topic'
         default_report_fields = (
             'TopicArn',
             'DisplayName',
@@ -65,7 +74,7 @@ class resource_type(TypeInfo):
     permissions = ('sns:ListTagsForResource',)
     source_mapping = {
         'describe': DescribeTopic,
-        'config': ConfigSource
+        'config': ConfigSNS
     }
 
 


Test patch:
diff --git a/tests/data/placebo/test_sns_config/config.SelectResourceConfig_1.json b/tests/data/placebo/test_sns_config/config.SelectResourceConfig_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_sns_config/config.SelectResourceConfig_1.json
@@ -0,0 +1,20 @@
+{
+    "status_code": 200,
+    "data": {
+        "Results": [
+            "{\"configuration\":{\"Policy\":\"{\\\"Version\\\":\\\"2008-10-17\\\",\\\"Id\\\":\\\"__default_policy_ID\\\",\\\"Statement\\\":[{\\\"Sid\\\":\\\"__default_statement_ID\\\",\\\"Effect\\\":\\\"Allow\\\",\\\"Principal\\\":{\\\"AWS\\\":\\\"*\\\"},\\\"Action\\\":[\\\"SNS:GetTopicAttributes\\\",\\\"SNS:SetTopicAttributes\\\",\\\"SNS:AddPermission\\\",\\\"SNS:RemovePermission\\\",\\\"SNS:DeleteTopic\\\",\\\"SNS:Subscribe\\\",\\\"SNS:ListSubscriptionsByTopic\\\",\\\"SNS:Publish\\\",\\\"SNS:Receive\\\"],\\\"Resource\\\":\\\"arn:aws:sns:us-east-1:644160558196:c7n-pratyush\\\",\\\"Condition\\\":{\\\"StringEquals\\\":{\\\"AWS:SourceOwner\\\":\\\"644160558196\\\"}}}]}\",\"Owner\":\"644160558196\",\"KmsMasterKeyId\":\"arn:aws:kms:us-east-1:644160558196:key/ec3b9189-1247-4ecc-8bfd-c492f07621db\",\"TopicArn\":\"arn:aws:sns:us-east-1:644160558196:c7n-pratyush\",\"EffectiveDeliveryPolicy\":\"{\\\"http\\\":{\\\"defaultHealthyRetryPolicy\\\":{\\\"minDelayTarget\\\":20,\\\"maxDelayTarget\\\":20,\\\"numRetries\\\":3,\\\"numMaxDelayRetries\\\":0,\\\"numNoDelayRetries\\\":0,\\\"numMinDelayRetries\\\":0,\\\"backoffFunction\\\":\\\"linear\\\"},\\\"disableSubscriptionOverrides\\\":false}}\",\"DisplayName\":\"\"},\"supplementaryConfiguration\":{\"Tags\":[{\"value\":\"false\",\"key\":\"c7n-encryption-check\"}]}}",
+            "{\"configuration\":{\"Policy\":\"{\\\"Version\\\":\\\"2008-10-17\\\",\\\"Id\\\":\\\"__default_policy_ID\\\",\\\"Statement\\\":[{\\\"Sid\\\":\\\"__default_statement_ID\\\",\\\"Effect\\\":\\\"Allow\\\",\\\"Principal\\\":{\\\"AWS\\\":\\\"*\\\"},\\\"Action\\\":[\\\"SNS:GetTopicAttributes\\\",\\\"SNS:SetTopicAttributes\\\",\\\"SNS:AddPermission\\\",\\\"SNS:RemovePermission\\\",\\\"SNS:DeleteTopic\\\",\\\"SNS:Subscribe\\\",\\\"SNS:ListSubscriptionsByTopic\\\",\\\"SNS:Publish\\\",\\\"SNS:Receive\\\"],\\\"Resource\\\":\\\"arn:aws:sns:us-east-1:644160558196:test\\\",\\\"Condition\\\":{\\\"StringEquals\\\":{\\\"AWS:SourceOwner\\\":\\\"644160558196\\\"}}}]}\",\"Owner\":\"644160558196\",\"TopicArn\":\"arn:aws:sns:us-east-1:644160558196:test\",\"EffectiveDeliveryPolicy\":\"{\\\"http\\\":{\\\"defaultHealthyRetryPolicy\\\":{\\\"minDelayTarget\\\":20,\\\"maxDelayTarget\\\":20,\\\"numRetries\\\":3,\\\"numMaxDelayRetries\\\":0,\\\"numNoDelayRetries\\\":0,\\\"numMinDelayRetries\\\":0,\\\"backoffFunction\\\":\\\"linear\\\"},\\\"disableSubscriptionOverrides\\\":false}}\",\"DisplayName\":\"test\"},\"supplementaryConfiguration\":{\"Tags\":[]}}"
+        ],
+        "QueryInfo": {
+            "SelectFields": [
+                {
+                    "Name": "configuration"
+                },
+                {
+                    "Name": "supplementaryConfiguration"
+                }
+            ]
+        },
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/test_policy.py b/tests/test_policy.py
--- a/tests/test_policy.py
+++ b/tests/test_policy.py
@@ -279,7 +279,6 @@ def test_config_resource_support(self):
             'AWS::ServiceCatalog::CloudFormationProduct',
             'AWS::ServiceCatalog::Portfolio',
             'AWS::SSM::FileData',
-            'AWS::SNS::Topic',
             'AWS::SecretsManager::Secret'}
 
         resource_map = {}
diff --git a/tests/test_sns.py b/tests/test_sns.py
--- a/tests/test_sns.py
+++ b/tests/test_sns.py
@@ -710,6 +710,18 @@ def test_sns_post_finding(self):
             rfinding['Details']['AwsSnsTopic'],
             'AwsSnsTopicDetails', 'securityhub')
 
+    def test_sns_config(self):
+        session_factory = self.replay_flight_data("test_sns_config")
+        p = self.load_policy(
+            {"name": "sns-config",
+             "source": "config",
+             "resource": "sns"},
+            session_factory=session_factory,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 2)
+        self.assertEqual(resources[0]['Tags'][0]['Value'], 'false')
+
 
 class TestSubscription(BaseTest):