Add Support for SNS Topic KmsMasterKeyId Attribute (#3389)

We do not do any validation of the `KmsMasterKeyId` attribute, and simply
store it as-as.  This mimics the behavior in AWS, where the key is not
validated until it is actually used (when publishing[1]).

[1]: https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html

Closes #3216
This commit is contained in:
Brian Pandola 2020-10-16 04:30:07 -07:00 committed by GitHub
parent 6505c893b8
commit 28c1690fc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 21 deletions

View File

@ -45,6 +45,7 @@ class Topic(CloudFormationModel):
self.account_id = DEFAULT_ACCOUNT_ID self.account_id = DEFAULT_ACCOUNT_ID
self.display_name = "" self.display_name = ""
self.delivery_policy = "" self.delivery_policy = ""
self.kms_master_key_id = ""
self.effective_delivery_policy = json.dumps(DEFAULT_EFFECTIVE_DELIVERY_POLICY) self.effective_delivery_policy = json.dumps(DEFAULT_EFFECTIVE_DELIVERY_POLICY)
self.arn = make_arn_for_topic(self.account_id, name, sns_backend.region_name) self.arn = make_arn_for_topic(self.account_id, name, sns_backend.region_name)

View File

@ -158,28 +158,28 @@ class SNSResponse(BaseResponse):
topic = self.backend.get_topic(topic_arn) topic = self.backend.get_topic(topic_arn)
if self.request_json: if self.request_json:
return json.dumps( attributes = {
{ "Owner": topic.account_id,
"GetTopicAttributesResponse": { "Policy": topic.policy,
"GetTopicAttributesResult": { "TopicArn": topic.arn,
"Attributes": { "DisplayName": topic.display_name,
"Owner": topic.account_id, "SubscriptionsPending": topic.subscriptions_pending,
"Policy": topic.policy, "SubscriptionsConfirmed": topic.subscriptions_confimed,
"TopicArn": topic.arn, "SubscriptionsDeleted": topic.subscriptions_deleted,
"DisplayName": topic.display_name, "DeliveryPolicy": topic.delivery_policy,
"SubscriptionsPending": topic.subscriptions_pending, "EffectiveDeliveryPolicy": topic.effective_delivery_policy,
"SubscriptionsConfirmed": topic.subscriptions_confimed, }
"SubscriptionsDeleted": topic.subscriptions_deleted, if topic.kms_master_key_id:
"DeliveryPolicy": topic.delivery_policy, attributes["KmsMasterKeyId"] = topic.kms_master_key_id
"EffectiveDeliveryPolicy": topic.effective_delivery_policy, response = {
} "GetTopicAttributesResponse": {
}, "GetTopicAttributesResult": {"Attributes": attributes},
"ResponseMetadata": { "ResponseMetadata": {
"RequestId": "057f074c-33a7-11df-9540-99d0768312d3" "RequestId": "057f074c-33a7-11df-9540-99d0768312d3"
}, },
}
} }
) }
return json.dumps(response)
template = self.response_template(GET_TOPIC_ATTRIBUTES_TEMPLATE) template = self.response_template(GET_TOPIC_ATTRIBUTES_TEMPLATE)
return template.render(topic=topic) return template.render(topic=topic)
@ -827,6 +827,12 @@ GET_TOPIC_ATTRIBUTES_TEMPLATE = """<GetTopicAttributesResponse xmlns="http://sns
<key>EffectiveDeliveryPolicy</key> <key>EffectiveDeliveryPolicy</key>
<value>{{ topic.effective_delivery_policy }}</value> <value>{{ topic.effective_delivery_policy }}</value>
</entry> </entry>
{% if topic.kms_master_key_id %}
<entry>
<key>KmsMasterKeyId</key>
<value>{{ topic.kms_master_key_id }}</value>
</entry>
{% endif %}
</Attributes> </Attributes>
</GetTopicAttributesResult> </GetTopicAttributesResult>
<ResponseMetadata> <ResponseMetadata>

View File

@ -168,3 +168,25 @@ def test_topic_paging():
topics_list.should.have.length_of(int(DEFAULT_PAGE_SIZE / 2)) topics_list.should.have.length_of(int(DEFAULT_PAGE_SIZE / 2))
next_token.should.equal(None) next_token.should.equal(None)
@mock_sns_deprecated
def test_topic_kms_master_key_id_attribute():
conn = boto.connect_sns()
conn.create_topic("test-sns-no-key-attr")
topics_json = conn.get_all_topics()
topic_arn = topics_json["ListTopicsResponse"]["ListTopicsResult"]["Topics"][0][
"TopicArn"
]
attributes = conn.get_topic_attributes(topic_arn)["GetTopicAttributesResponse"][
"GetTopicAttributesResult"
]["Attributes"]
attributes.should_not.have.key("KmsMasterKeyId")
conn.set_topic_attributes(topic_arn, "KmsMasterKeyId", "test-key")
attributes = conn.get_topic_attributes(topic_arn)["GetTopicAttributesResponse"][
"GetTopicAttributesResult"
]["Attributes"]
attributes.should.have.key("KmsMasterKeyId")
attributes["KmsMasterKeyId"].should.equal("test-key")

View File

@ -520,3 +520,27 @@ def test_untag_resource_error():
conn.untag_resource.when.called_with( conn.untag_resource.when.called_with(
ResourceArn="not-existing-topic", TagKeys=["tag_key_1"] ResourceArn="not-existing-topic", TagKeys=["tag_key_1"]
).should.throw(ClientError, "Resource does not exist") ).should.throw(ClientError, "Resource does not exist")
@mock_sns
def test_topic_kms_master_key_id_attribute():
client = boto3.client("sns", region_name="us-west-2")
resp = client.create_topic(Name="test-sns-no-key-attr",)
topic_arn = resp["TopicArn"]
resp = client.get_topic_attributes(TopicArn=topic_arn)
resp["Attributes"].should_not.have.key("KmsMasterKeyId")
client.set_topic_attributes(
TopicArn=topic_arn, AttributeName="KmsMasterKeyId", AttributeValue="test-key"
)
resp = client.get_topic_attributes(TopicArn=topic_arn)
resp["Attributes"].should.have.key("KmsMasterKeyId")
resp["Attributes"]["KmsMasterKeyId"].should.equal("test-key")
resp = client.create_topic(
Name="test-sns-with-key-attr", Attributes={"KmsMasterKeyId": "key-id",}
)
topic_arn = resp["TopicArn"]
resp = client.get_topic_attributes(TopicArn=topic_arn)
resp["Attributes"].should.have.key("KmsMasterKeyId")
resp["Attributes"]["KmsMasterKeyId"].should.equal("key-id")