I am trying to set up a basic SNS subscription but it looks like AWS never sends the confirmation, either through the console or using the SDK.
Steps I have taken so far:
I have set up a Topic using the AWS console
I have added HTTP subscriptions to both an ngrok tunnel URL and also a public web server URL using both the AWS console and the ruby SDK
I have allowed everyone to subscribe to the Topic by editing the Topic policy in the AWS console
By tailing the logs on both my localhost and public web servers I can see that no request is ever sent to the endpoint.
I'm pretty stumped here because it seems like it should definitely be working, or at least sending something (anything) to my endpoints?
The code I'm using for the ruby sdk is as follows:
sns = AWS::SNS.new(access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'])
# I only have one topic
topic = sns.topics.first
topic.subscribe(URI.parse('http://<NGROK_URL>.ngrok.com/notifications/notify'))
topic.subscriptions.first
# returns: => <AWS::SNS::Subscription arn:PendingConfirmation>
This turned out to be an issue related to the region I was working in. I changed to Oregon and all confirmations are sending immediately.
There must be some permissions setting somewhere that prevents you from sending any messages at all from certain regions, but it was failing silently.
For me, it appears that it may not be the region (though I was trying us-east-1 too), but how ngrok's network is set up. I used a different site-forwarding service (finch) and was completely successful. This AWS forum topic makes be think that the problem may be intermittent, too.
Related
I have a C# AWS Lambda that is calling back to a server with the result of it's work using HttpClient SendAsync.
Sometimes it works fine, other times, having processed exactly the same payload so the call back will be the same it results in a BadGateway. As far as I know I have no further logs available to me as to why.
Anyone got any ideas?
For Bad Gateway (HTTP 502) check the server logs first that you are connecting. It is a server side error so the logs would be a good place to look first. Also with Lambda check that the Lambda scaling is not creating too many connections that makes the web server give issues.
For some security reasons that I can't have a public accessible server to receive data from slack.
So, this is what I'm planning to do:
Inbound message from slack: using RTM API
Outbound message to slack: using RTM API or Web API
Questions:
Any better alternatives?
Any restrictions? (AFAIK, buttons and drop downs can't work)
If Web API reach rate limit, can I use incoming webhook as a backup plan?
RTM only approach
Yes, that would work. With only the RTM API you are limited to:
receiving and responding to messages
Other RTM events.
You can't use any interactive functionality like:
Interactive components (buttons, menus, datepickers)
Dialogs
Rate limit on message posting
Using the webhook as "backup" to circumvent the rate limit is not an option, since the rate limit of posting max 1 message per second applies to all form of message posting.
From the documentation:
In general, apps may post no more than one message per second per
channel, whether a message is posted via chat.postMessage, an incoming
webhook, or one of the many other ways to send messages in to Slack.
Alternatives
You did not give any details about the reasons why your app can't expose an endpoint to the public Internet. But you might want to consider using a VPN tunnel like ngrok.
Yes! Socket Mode
There is a new alternative from slack, Socket Mode, which doesn't require a publicly accessible server.
Note: this is only for private apps.
With Socket Mode you have an API token and your server uses it to communicate with Slack's servers and create a two way socket connection. This means your Slack Bot's code can run on a machine behind a firewall and not require any inbound ports to be opened.
Slack message delivery requires an acknowledgement once you get the message, or else they may retry to deliver it.
Limitations
Socket Mode has two main limitations:
Apps using Socket Mode are not currently allowed in the public Slack App Directory.
Socket Mode is only available for apps using new, granular permissions. If you created your app on or after December of 2019, good news: your app already uses the new permissions. Otherwise, you may have to migrate your classic Slack app to use granular permissions before turning on Socket Mode.
I am trying to use slash commands to my one of the slack channel. I tried to do a POC using git API and it worked fine.
I first created a slash command from this link :
https://api.slack.com/censored/slash-commands
Commnad: /poc
Request URL: http://jsonplaceholder.typicode.com/posts
This worked fine when I type /opc on slack chat box of my channel. It returns some data.
But when I change the Request URL to an internal API, which is accessible only from the office domain, I get error:
Darn – that slash command didn't work (error message: Failure when
receiving data from the peer). Manage the command at .
I believe, slack is not able to access my internal URL in case. Is that possible to see the slack logs?
Can anyone please help me here.
This can not work, since the request URL needs to be accessible from the public Internet in order to work with Slack.
In general most of Slack's interactive features (Slash commands, Interactive messages, Modals, Events API, ...) require your app to provide a public endpoint that can be called by Slack via HTTP.
In order to access internal APIs with Slack you will need some kind of gateway or tunnel through the firewall of your company that exposes the request URL to Slack. There are many ways how to do that and the solution needs to be designed according to the security policy of your company.
Here are a couple of suggestions:
VPN tunnel
One approach would be to run your script for the slash command on an internal webserver (one that has access to the internal API) use a VPN tunnel to expose that web server to the Internet, e.g. with a tool like ngrok.
DMZ
Another approach would be to run your app in the DMZ of your companies network and configure the firewall on both sides to allow access to Slack form the public Internet and your app to you your internal network.
Bridge
Another approach is to host and run that part of your app that interacts with Slack on the public Internet and the part that interacts with your internal network on your internal company network. Then add a secure connection that allows the public part to communicate with the part running on the internal company network.
If opening a connection into the internal network is not an option, there is another way that can allow communication with internal services by inverting the communication direction with a queue.
To do this, you need to deploy a public endpoint that accepts the requests from Slack and puts them onto a queue (e. g. AWS Lambda + SQS, Flask + RabbitMQ) and then poll the queue from the internal network. The polling needs to happen fairly often (at least once a second) to ensure the communication is quick enough for the users not to notice the lag too much. By doing this you can avoid exposing any endpoint of the internal network.
The drawbacks of this approach are more infrastructure complexity and slower response times, but it can be a good alternative in some corporate environments.
Ok, so I have an elastic beanstalk application with a scalable web tier, served behind an ELB. Long story short, I need to be able to subscribe a specific instance within my web tier to an SNS topic. Is it safe for me to use a standard method to get the instance ip address (as detailed in python here How can I get the IP address of eth0 in Python?) and then simply subscribe to an SNS topic using that ip as an http subscriber?
Why? Good question...
My datamodel is made up of lots of objects many of which can have an attached set of users which may want to be able to observe those objects. This web tier in my application is responsible for handling the socket interface (using socket.io) for client applications.
When a user is created in the system, so too is an SNS topic for the user, allowing notifications to be pushed to that user when an object it is interested in changes. The way I am planning to set this up, a client application will connect to EB via socket.io at which point the server instance it connected to will subscribe to that user's SNS topic. Then when an interesting object changes, notifications will be posted to the associated user's topics, thus notifying the server instance that the client application has an open connection to, which can then send a message down the socket.
I believe it is important that the specific instance is subscribed rather than the web tier's external CNAME or ip, as the client application is connected to a specific instance and so only that instance can send messages over it's socket. Subscribing the load balancer would be no good as the notification may be delivered to an instance that the user is not connected to.
I believe the question at the top is all I need, but I'm open to creative solutions if my reasoning seems flawed??
Just incase anyone gets stuck down this same rabbit hole... The solution was to use Redis pub/sub rather than SNS and SQS.
I've try to create a slackbot. Works fine, but my problems are calls from slack to my rest api. My app is an internal service, so it's not available from the internet. I have seen that outgoing webhooks is possible to set, but I have to forward the request back to the internal service which I don't like very much. As far as I know slack is based on websockets, so is it possible to write a bot which run behind my “firewall“ and get it's commands via websocket?
Greetings
Tonka
You can use services like Localtunnel for receiving webhooks behind a firewall.
We use it with a docker container to develop our slack bot in local env.
Webhooks, slash commands, interactive messages, events etc. are based on HTTP.
Only bots use websockets.
But even this bot websocket session still needs to be initiated with an HTTP call.
Not entirely sure how your firewall is set up, but you may want to make your endpoint public to make things easier.