Repository: localstack/localstack

Issue:
aws cloudformation sns subscription FilterPolicy not created
When a subscription is created using cloudformation:
```
"ProfileChangedSubscription": {
      "Type": "AWS::SNS::Subscription",
      "Properties": {
        "Endpoint": {
          "Fn::GetAtt": [
            "ProfileChangedQueue",
            "Arn"
          ]
        },
        "Protocol": "sqs",
        "FilterPolicy": {
          "eventType": [
            "created"
          ]
        },
        "TopicArn": {
          "Fn::ImportValue": {
            "Fn::Sub": "${ProfilesProfilePublishStack}-ProfileChangedTopic"
          }
        }
      }
    }
```

The specified subscription filter policy is not created. When I run `get-subscription-attributes`, I get information about non-existing filter policy:

```
{
    "Attributes": {
        "TopicArn": "arn:aws:sns:us-east-1:000000000000:profile-changed-topic",
        "Endpoint": "arn:aws:sqs:us-east-1:000000000000:profile-changed-queue",
        "Protocol": "sqs",
        "SubscriptionArn": "arn:aws:sns:us-east-1:000000000000:profile-changed-topic:936a58be-525b-4228-bfdb-c4b2f6048e8c",
        "FilterPolicy": "None"
    }
}
```


Discussion:

Resolving patch:
diff --git a/localstack/utils/cloudformation/template_deployer.py b/localstack/utils/cloudformation/template_deployer.py
--- a/localstack/utils/cloudformation/template_deployer.py
+++ b/localstack/utils/cloudformation/template_deployer.py
@@ -70,6 +70,15 @@ def get_lambda_code_param(params, **kwargs):
     return code
 
 
+def sns_subscription_params(params, **kwargs):
+    def attr_val(val):
+        return json.dumps(val) if isinstance(val, (dict, list)) else str(val)
+
+    attrs = ['DeliveryPolicy', 'FilterPolicy', 'RawMessageDelivery', 'RedrivePolicy']
+    result = dict([(a, attr_val(params[a])) for a in attrs if a in params])
+    return result
+
+
 # maps resource types to functions and parameters for creation
 RESOURCE_TO_FUNCTION = {
     'S3::Bucket': {
@@ -311,7 +320,8 @@ def get_lambda_code_param(params, **kwargs):
             'parameters': {
                 'TopicArn': 'TopicArn',
                 'Protocol': 'Protocol',
-                'Endpoint': 'Endpoint'
+                'Endpoint': 'Endpoint',
+                'Attributes': sns_subscription_params
             }
         }
     },


Test patch:
diff --git a/tests/integration/templates/template1.yaml b/tests/integration/templates/template1.yaml
--- a/tests/integration/templates/template1.yaml
+++ b/tests/integration/templates/template1.yaml
@@ -30,6 +30,9 @@ Resources:
       Protocol: sqs
       TopicArn: !Ref SNSTopic
       Endpoint: !GetAtt SQSQueue.QueueArn
+      FilterPolicy:
+        eventType:
+          - created
   KinesisStream:
     Type: AWS::Kinesis::Stream
     Properties:
diff --git a/tests/integration/test_cloudformation.py b/tests/integration/test_cloudformation.py
--- a/tests/integration/test_cloudformation.py
+++ b/tests/integration/test_cloudformation.py
@@ -177,6 +177,11 @@ def check_stack():
         subs = [s for s in subs if (':%s:cf-test-queue-1' % TEST_AWS_ACCOUNT_ID) in s['Endpoint']]
         self.assertEqual(len(subs), 1)
         self.assertIn(':%s:%s-test-topic-1-1' % (TEST_AWS_ACCOUNT_ID, stack_name), subs[0]['TopicArn'])
+        # assert that subscription attributes are added properly
+        attrs = sns.get_subscription_attributes(SubscriptionArn=subs[0]['SubscriptionArn'])['Attributes']
+        self.assertEqual(attrs, {'Endpoint': subs[0]['Endpoint'], 'Protocol': 'sqs',
+            'SubscriptionArn': subs[0]['SubscriptionArn'], 'TopicArn': subs[0]['TopicArn'],
+            'FilterPolicy': json.dumps({'eventType': ['created']})})
 
         # assert that Gateway responses have been created
         test_api_name = 'test-api'