Mandeep Singh
Mandeep Singh

Reputation: 8224

Node.js How to create an API endpoint only accessible to SNS topic?

I want to send an HTTP request from SNS to a public API endpoint hosted on a Node.js server. However, I want to configure that API to only accept POST requests from that SNS topic and nothing else. I could insert a token inside the SNS message but I don't control the SNS message. It is coming from SES in case of bounced emails. Is it possible to see the domain of the request and only allow if it is coming from a trusted domain (AWS in this case) ?

Upvotes: 2

Views: 957

Answers (1)

Michael - sqlbot
Michael - sqlbot

Reputation: 179084

You cannot restrict the accessibility of your endpoint to "only SNS" -- even if you knew the IP address ranges of SNS, that would be of limited value, because anybody could be using SNS. It would be a false sense of security.

However, SNS messages are designed in such a way that there should be no need to restrict accessibility of the endpoint by IP addresses. You should be doing this, anyway.

You should verify the authenticity of a notification, subscription confirmation, or unsubscribe confirmation message sent by Amazon SNS. Using information contained in the Amazon SNS message, your endpoint can recreate the string to sign and the signature so that you can verify the contents of the message by matching the signature you recreated from the message contents with the signature that Amazon SNS sent with the message.

http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.verify.signature.html

First, the HTTP request header x-amz-sns-topic-arn identifies the topic. If it's not a topic you expect, don't process the message. If this value doesn't agree with the TopicArn in the message itself, don't process the message.

Next, the message body contains a SigningCertURL. This is the URL where your code fetches the certificate that SNS used to sign the message. If this URL's scheme is not https and the hostname is not sns.[region].amazonaws.com, don't download the certificate, and don't process the message.

Otherwise, fetch the cert from the URL provided, and cache it locally in memory or on disk so that you don't have to fetch it with every message you handle (you'll typically see the same cert used repeatedly). Ensure that your user agent isn't configured not to validate the destination server's certificate against the trust store and against the request hostname. In this configuration, you have assurance that the certificate itself is really coming from SNS, because your user agent will not negotiate SSL with a system with an untrusted certificate, and you've verified that the hostname is one controlled by AWS.

Next, generate the canonical hash of the message and validate it against the Signature provided with the message, as documented at the link above.

If the message is genuinely from SNS, the signature will validate correctly, and the message should be processed. Otherwise, it should not be processed.

Upvotes: 1

Related Questions