Informative Alerts with Serverless Slack Unfurling

Written by serhatcan | Published 2018/01/24
Tech Story Tags: aws-lambda | nodejs | slack | opsgenie | chatops

TLDRvia the TL;DR App

Learn how to attach important information into Slack messages using Node.js, Serverless.js, and AWS Lambda

Slack shows lots of great details when you copy and paste a link. Go ahead and paste a link from Medium. You’ll see something like this:

Slack attaches details to your messages. This is called unfurling.

This is called “Link Unfurling” in Slack. For some messages, Slack does this automatically (classic unfurling) and attaches pretty nice details like “Reading Time”. Good news is, you can do this for your links as well! This is especially useful when you need more information or need to retrieve data from a protected source that requires user approval/authentication. When this is the case, you need to get your hands a little dirty and built your own Slack application.

In this blog post, you’ll learn how to build your own Slack unfurling application step by step using a real-life example. We will attach details to your OpsGenie alert when you share an OpsGenie alert’s link.

For those of you who aren’t familiar, OpsGenie is an incident and on-call management solution for DevOps and ITOps teams. We will use OpsGenie in this example because we have experience using its integrations and API. We also believe that it is very useful to see alert details when you copy and paste a link to reduce context switching between apps.

Setting up your environment

Before we dive into the development details, let’s prepare your development environment first. As a starter, you need AWS, Slack, and OpsGenie accounts to run this project.

We chose Serverless (AWS Lambda) computing service for this project because its pricing is pay-per-trigger and we don’t need to care about the maintenance. It makes a lot of sense for this kind of application where you have possible sparse and low volume requests.

We will use Lambda, API Gateway services from AWS, Node.js as the language, and Serverless.js for deploying the project.

I’m going to skip npm and Node.js installations. You can google this — and get confused :D Just remember to install Node.js v6.10 or above because this is the version we are going to use in AWS Lambda as it is the latest supported one. To install Serverless.js, run:

npm install -g serverless

How does the Slack unfurling flow work?

As we are done with the initial setup, it is time to learn about the flow of this project. By following the numbers on this diagram, you can learn how our application’s flow works.

Application flow

One important detail here is Slack’s Events API. We use this API to get notified when an event like a new message or a pin addition to a message happens.

Create your Slack application

Now, it is time to deep dive into the Slack application part. We will built an internal Slack integration. Internal integrations are just like regular Slack apps except they can only be installed in your workspace; hence, you don’t need to implement OAuth authentication flow. This is easier and suits better in our use-case.

First go to https://api.slack.com/apps link and click “Create New App” button. Then, you will give your application a name and select the workspace you want the application to exist. Don’t worry, you can change these details later.

Create your new Slack app!

That is all for now, we will again visit this page once we deploy our function to AWS.

Get an API key from OpsGenie

Get a new account in OpsGenie if you don’t have one. Create a new API integration under integrations ->API Integration.

Create an API integration in OpsGenie

One important tip for this function is that we don’t need this API key to update configurations in OpsGenie or send notifications. So, we configure the integration to have read-only access and suppress notifications.

Create your Lambda function

The easiest way to create your Lambda function is to clone the linked repository below and modify the code as you wish. Then, just install the dependencies.

git clone https://github.com/serhatcan/serverless-opsgenie-slack-alert-unfurling

cd serverless-opsgenie-slack-alert-unfurling

npm install

If you want to start from scratch or build your own code, you have three options:

  • Use this project and replace the logic,
  • Use one of the blueprints that AWS Lambda gives you or use AWS CodeStart to have a more complete setup for bigger projects,
  • Run this serverless command to create a new Lambda function:

serverless create — template aws-nodejs — path my-service

Now, let’s take a look at the main building blocks of our code. Instead of reading from here, you can also take a look at this ~100 lines of code on GitHub.

The flow is like this:

  • Check if we passed the right keys to the Lambda function (Slack verification token, Slack access token-API token, and OpsGenie API key)
  • Verify that request comes from Slack by comparing the verification token we have and the received token from the request
  • Check the event payload and the type of the event we received. If event is;- “url_verification” event: send back the challenge value from the JSON payload because this event means that Slack is checking your endpoint’s health- “event_callback” event: run the logic

Now, as we talked about the main building blocks, let’s also talk a little bit about the logic that runs when an event_callback is received. We use Slack and OpsGenie Node.js SDKs to avoid writing boilerplate code while accessing the APIs. The logic part consists of these steps:

  • A message can contain multiple links from our registered domains (app.opsgenie.com in our case). Slack Event API sends these links in an array. We iterate over those links (event.links in payload) and run messageAttachmentFromLink function for each link
  • First we extract the alertId using a simple regex from a link like this — yours can support additional case if you’d prefer

https://app.opsgenie.com/alert/V2#/show/df2d5224-6df3-4905-a98d-c08c9388f3b5-1516805551907/details

  • Retrieve alert details using the alert ID from OpsGenie
  • Build our Slack message attachment using the details we got
  • Update Slack message with the necessary attachments using Slack API

We learned how our function works. But, I suggest you still go ahead and read the code because it would make more sense for most developers.

Deploy first version of your Lambda function

After creating the Slack app, OpsGenie integration, and writing our function, now it is time to deploy our function. In this step, we will put our function on AWS Lambda but as we still don’t have an API endpoint to tell Slack to make requests, we can’t yet install our app in our workspace. This means that we also don’t have the Slack API key which we’ll get after installing the app.

Once we are done deploying our function, we’ll get an HTTPS endpoint from API Gateway service and use it to complete our configuration in Slack. Then, we’ll update our Slack app’s config by setting up the Slack API key and deploy the app once more.

One step at a time. So in this step, you should get the verification token from Slack app and paste it in the slack_verification_token config in serverless.yml file. We will use this token to verify that requests come from Slack by comparing with the received token.

Slack verification token can be found under Basic information -> App credentials

And we also have our OpsGenie API key so, let’s paste it in our config as well. Our configs will look like this (only missing one is slack_access_token as we didn’t install the app in our workspace yet):

Our config before we deploy first time

Now, we can deploy. Go to your project’s home folder, and run deploy command:

serverless deploy

All will be handled by serverless.js. Serverless uses AWS CloudFormation to spin up your stack. You can also visit CloudFormation to find out more.

CloudFormation Stack Serverless.js created

After you run serverless deploy command

After you run the command and stack creation is done, you will see an HTTP endpoint in terminal. Copy it and continue with the next part!

Configure Slack application

You have the API Gateway endpoint. Slack will use this API endpoint to send event details. To tell Slack about this, go to Event Subscriptions tab.

Enable events and paste the endpoint you got into the “Request URL” input. At this point, Slack will make a request to your endpoint to make sure that it works. No worries, our code knows how to deal with this payload and can return the correct response.

After you get the “Verified” sign, now it is time to subscribe some events. Slack will only send the events you subscribe it to. In our case, to get a call to our endpoint when a link contains app.opsgenie.com domain, we need to subscribe to link_shared event_._

Last step in this page is to tell Slack which domains you want to listen. Add app.opsgenie.com domain under App Unfurl Domains part_._

Now, let’s switch to OAuth & Permissions page from the sidebar. In this page, you need to make sure that you have the links:read and links:write scopes. Read scope is necessary for Slack to send the event to us and write scope is necessary for us to update the message with the attachment. Users need to approve this when they install our app.

Install your Slack app in your workspace

Now, it is time to install the app and get the OAuth Access Token to access Slack API. Go to Install App page and install it :)

Click Install App to Workspace

Authorize the app

After you Authorize the app, you are only one step away from completing the setup!

Update your function and deploy one more time

After the installation in the page that Slack redirects you, you will see OAuth Access Token. Copy and paste it in serverless.yml file’s slack_access_token config.

OAuth Access Token we need to access Slack API

Then deploy the app again, run deploy command second time:

serverless deploy

That is it! ⛱

Let’s try if it works!

We need an OpsGenie alert to test our app. You can create one from Slack by typing /genie alert “test my alert” command or just use the web interface.

Create a new OpsGenie alert

Click the alert details and on the browser, you’ll see an endpoint similar to this:

https://app.opsgenie.com/alert/V2#/show/df2d5224-6df3-4905-a98d-c08c9388f3b5-1516805551907/details

Copy this link and paste it in Slack and enjoy your work!

Enjoy your work!

Code is available in this repository:https://github.com/serhatcan/serverless-opsgenie-slack-alert-unfurling

Further improvements and tips

There are a few things you can do to enhance this integration:

  • Use KMS to securely manage your keys — using environment variables for secret keys isn’t recommended
  • Improve the Slack message with more details, possibly add buttons!
  • If you are thinking about handling more events and want to hide some complexity, you can use Slack Events API module for Node.

Slack has pretty good documentation and a nice sample on Github on unfurling. By following these, you can take your app to the next step!

References and relevant links

Thanks for reading this far!

If you enjoyed the tutorial, don’t forget to 👏 to show your support 😃


Published by HackerNoon on 2018/01/24