Skip to content

Commit

Permalink
add SNS validation of JSON fields type for MessageStructure json (loc…
Browse files Browse the repository at this point in the history
  • Loading branch information
bentsku authored Apr 4, 2023
1 parent b216d67 commit e1b8023
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
4 changes: 4 additions & 0 deletions localstack/services/sns/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,10 @@ def publish(
if message_structure == "json":
try:
message = json.loads(message)
# Keys in the JSON object that correspond to supported transport protocols must have
# simple JSON string values.
# Non-string values will cause the key to be ignored.
message = {key: field for key, field in message.items() if isinstance(field, str)}
# TODO: check no default key for direct TargetArn endpoint publish, need credentials
# see example: https://docs.aws.amazon.com/sns/latest/dg/sns-send-custom-platform-specific-payloads-mobile-devices.html
if "default" not in message and not is_endpoint_publish:
Expand Down
44 changes: 44 additions & 0 deletions tests/integration/test_sns.py
Original file line number Diff line number Diff line change
Expand Up @@ -2876,6 +2876,50 @@ def test_message_structure_json_exc(self, sns_create_topic, snapshot, aws_client
)
snapshot.match("duplicate-json-keys", resp)

with pytest.raises(ClientError) as e:
message = json.dumps({"default": {"object": "test"}})
aws_client.sns.publish(
TopicArn=topic_arn,
Message=message,
MessageStructure="json",
)
snapshot.match("key-is-not-string", e.value.response)

@pytest.mark.aws_validated
def test_message_structure_json_to_sqs(
self, aws_client, sns_create_topic, sqs_create_queue, snapshot, sns_create_sqs_subscription
):
topic_arn = sns_create_topic()["TopicArn"]
queue_name = f"test-queue-{short_uid()}"
queue_url = sqs_create_queue(QueueName=queue_name)

sns_create_sqs_subscription(topic_arn=topic_arn, queue_url=queue_url)

message = json.dumps({"default": "default field", "sqs": json.dumps({"field": "value"})})
aws_client.sns.publish(
TopicArn=topic_arn,
Message=message,
MessageStructure="json",
)
response = aws_client.sqs.receive_message(
QueueUrl=queue_url, WaitTimeSeconds=10, MaxNumberOfMessages=1
)
snapshot.match("get-msg-json-sqs", response)
receipt_handle = response["Messages"][0]["ReceiptHandle"]
aws_client.sqs.delete_message(QueueUrl=queue_url, ReceiptHandle=receipt_handle)

# don't json dumps the SQS field, it will be ignored, and the message received will be the `default`
message = json.dumps({"default": "default field", "sqs": {"field": "value"}})
aws_client.sns.publish(
TopicArn=topic_arn,
Message=message,
MessageStructure="json",
)
response = aws_client.sqs.receive_message(
QueueUrl=queue_url, WaitTimeSeconds=10, MaxNumberOfMessages=1
)
snapshot.match("get-msg-json-default", response)

@pytest.mark.aws_validated
@pytest.mark.skip_snapshot_verify(paths=["$..Attributes.SubscriptionPrincipal"])
def test_set_subscription_filter_policy_scope(
Expand Down
66 changes: 65 additions & 1 deletion tests/integration/test_sns.snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -2361,7 +2361,7 @@
}
},
"tests/integration/test_sns.py::TestSNSProvider::test_message_structure_json_exc": {
"recorded-date": "25-11-2022, 18:42:09",
"recorded-date": "03-04-2023, 21:23:54",
"recorded-content": {
"missing-default-key": {
"Error": {
Expand Down Expand Up @@ -2391,6 +2391,17 @@
"HTTPHeaders": {},
"HTTPStatusCode": 200
}
},
"key-is-not-string": {
"Error": {
"Code": "InvalidParameter",
"Message": "Invalid parameter: Message Structure - No default entry in JSON message body",
"Type": "Sender"
},
"ResponseMetadata": {
"HTTPHeaders": {},
"HTTPStatusCode": 400
}
}
}
},
Expand Down Expand Up @@ -3505,5 +3516,58 @@
}
}
}
},
"tests/integration/test_sns.py::TestSNSProvider::test_message_structure_json_to_sqs": {
"recorded-date": "03-04-2023, 21:52:04",
"recorded-content": {
"get-msg-json-sqs": {
"Messages": [
{
"Body": {
"Type": "Notification",
"MessageId": "<uuid:1>",
"TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>",
"Message": "{\"field\": \"value\"}",
"Timestamp": "date",
"SignatureVersion": "1",
"Signature": "<signature>",
"SigningCertURL": "https://sns.<region>.amazonaws.com/SimpleNotificationService-<signing-cert-file:1>",
"UnsubscribeURL": "<unsubscribe-domain>/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>"
},
"MD5OfBody": "<md5-hash>",
"MessageId": "<uuid:2>",
"ReceiptHandle": "<receipt-handle:1>"
}
],
"ResponseMetadata": {
"HTTPHeaders": {},
"HTTPStatusCode": 200
}
},
"get-msg-json-default": {
"Messages": [
{
"Body": {
"Type": "Notification",
"MessageId": "<uuid:3>",
"TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>",
"Message": "default field",
"Timestamp": "date",
"SignatureVersion": "1",
"Signature": "<signature>",
"SigningCertURL": "https://sns.<region>.amazonaws.com/SimpleNotificationService-<signing-cert-file:1>",
"UnsubscribeURL": "<unsubscribe-domain>/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>"
},
"MD5OfBody": "<md5-hash>",
"MessageId": "<uuid:4>",
"ReceiptHandle": "<receipt-handle:2>"
}
],
"ResponseMetadata": {
"HTTPHeaders": {},
"HTTPStatusCode": 200
}
}
}
}
}

0 comments on commit e1b8023

Please sign in to comment.