1

I write a tornado service as the Amazon SNS endpoint.

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        logging.info('get')
        self.sns()
        self.write(self.request.body.decode('utf-8'))

    def post(self):
        logging.info('post')
        self.sns()
        self.write(self.request.body.decode('utf-8'))

    def sns(self):
        headers = self.request.headers
        logging.info('HEADER: {}'.format(headers))
        arn = headers.get('x-amz-sns-subscription-arn')
        obj = json.loads(self.request.body)

        if headers.get('x-amz-sns-message-type') == 'SubscriptionConfirmation':
            logging.info('REQUEST: {}'.format(self.request))
            subscribe_url = obj[u'SubscribeURL']
            logging.info('URL:{}'.format(subscribe_url))
            return '<Arn %r>' % arn

        elif headers.get('x-amz-sns-message-type') == 'UnsubscribeConfirmation':
            logging.info('Unsubscription')

        elif headers.get('x-amz-sns-message-type') == 'Notification':
            logging.info('Unsubscription')

        return '', 200

But when I subscribe the endpoint to SNS, I didn't get any HTTP POST request. No logs was printed. So I tried to do curl instead, and the logs shows it fine. I'm more convinced that SNS didn't send the request rather than my endpoint didn't receive it. I have no idea how to proceed. Please help. Thanks.

Lishu
  • 1,438
  • 1
  • 13
  • 14
  • Can you make a successful connection to your endpoint *from the Internet?* That is where SNS notifications come from, so your endpoint must be externally-accessible in order for this to work... SNS doesn't have a back door into EC2. – Michael - sqlbot Mar 05 '15 at 13:45
  • where is your HTTP endpoint running? (ie what did you enter in the subscribe box in sns?) – Mircea Mar 05 '15 at 15:10
  • @Mircea My end point is running here: http://ec2-54-70-92-91.us-west-2.compute.amazonaws.com/test – Lishu Mar 05 '15 at 16:16
  • @Michael-sqlbot It is externally-accessible. I curl some message to the same endpoint from my lcoal box, and it receive it fine. – Lishu Mar 05 '15 at 16:30
  • 1
    what is the format of the endpoint? It's highly unlikely SNS is not doing the right thing. – Mircea Mar 05 '15 at 17:00
  • @Mircea You mean protocol? It's HTTP. – Lishu Mar 05 '15 at 17:33
  • yeah... can you show me the endpoint here? (replace anything that might be confidential) – Mircea Mar 05 '15 at 17:39
  • @Mircea I did, http://ec2-54-70-92-91.us-west-2.compute.amazonaws.com/test is my endpoint – Lishu Mar 05 '15 at 17:56
  • does not look like there is something running there, or security groups on that instance may prevent traffic from the internet. If you hit the endpoint from your machine (not an EC2 machine) does it work? – Mircea Mar 05 '15 at 18:25
  • @Mircea Right, the outside traffic might get blocked, but I can hit the endpoint (not EC2) from my local machine. I curl message, the endpoint receive it fine, but not from SNS. – Lishu Mar 05 '15 at 19:26
  • tried your endpoint from outside and it's not working. so I would say there is a problem on the path. – Mircea Mar 05 '15 at 21:38

1 Answers1

2

Right, the outside traffic might get blocked, but I can hit the endpoint (not EC2) from my local machine. 

This misses the point. You have to allow inbound connectivity from the Internet before SNS can access your http(s) endpoint. SNS does not have a back door to your instances.

The source IP address ranges for SNS notifications are published, so you can allow them in your security group...

https://forums.aws.amazon.com/ann.jspa?annID=1649

However, you need to be aware that the list is subject to change, so the best practice may be to make your endpoint globally-accessible.

It is also important to validate the messages using the signature provided, as well as to validate the public key of the certificate in the message by verifying that the URL for the certificate is legitimately associated with SNS, and by fetching the cert with HTTPS and validating the certificate provided during that TLS request as legitimately belonging to Amazon.

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

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • 1
    You are right. It's due to security group inbound connectivity. I get the message once I make my endpoint globally-accessible. Thanks. – Lishu Mar 09 '15 at 17:22