Giter Site home page Giter Site logo

terraform-aws-slackbot's Introduction

Serverless Slackbot

arch

terraform build

A simple, serverless, asynchronous HTTP back end for your Slack app.

The application intentionally does very little: it will receive an event from Slack in the form of an HTTP request, verify its origin, publish the payload to EventBridge where it can be processed downstream using event patterns, and finally respond to Slack with an empty 200 OK response.

Adding asynchronous features to your slackbot is as simple as adding the appropriate EventBridge rule/target, and some kind of handler function. See the section on responding to events asynchronously for details.

In some cases, you may want your Slack app to send a custom, synchronous, response to Slack instead of an empty 200 OK. External select menus and some callbacks, for example, need to respond to Slack with custom data and cannot be processed asyncronously. See the section on responding to events synchronously for details.

NOTE — Previous versions of this module attempted to be as unopinionated as possible when creating Slackbots.

v24 takes a more "batteries included" appoach, creating:

  • Regional HTTP API
  • EventBridge event bus
  • SecretsManager secret container
  • Route53 record with regional latency routing configuration

Example Usage

See the example project for detailed usage.

data "aws_acm_certificate" "cert" {
  domain = "example.com"
  types  = ["AMAZON_ISSUED"]
}

data "aws_route53_zone" "zone" {
  name = "example.com."
}

module "slackbot" {
  source  = "amancevice/slackbot/aws"
  version = "~> 24.0"

  # API GATEWAY
  api_name = "slackbot"

  # DNS
  domain_name            = "slack.example.com"
  domain_certificate_arn = data.aws_acm_certificate.cert.arn
  domain_zone_id         = data.aws_route53_zone.zone.id

  # EVENT BUS
  event_bus_name = "slackbot"

  # LAMBDA
  receiver_function_name  = "slackbot-receiver"
  responder_function_name = "slackbot-responder"
  slack_api_function_name = "slackbot-slack-api"

  # SECRET
  secret_name = "slackbot"

  # CUSTOM RESPONDERS
  custom_responders = {
    "POST /-/callbacks"  = "arn:aws:lambda:us-east-1:123456789012:function:my-callbacks"
    "POST /-/menus"      = "arn:aws:lambda:us-east-1:123456789012:function:my-menus"
    "POST /-/slash/fizz" = "arn:aws:lambda:us-east-1:123456789012:function:my-slash-fizz"
  }

  # TAGS
  tags = {
    #
  }
}

NOTE — after applying this module you must update the SecretsManager secret with the slackbot configuration JSON (all values are optional except where indicated)

Example JSON:

{
  "SLACK_API_TOKEN": "xoxb-xxxx",
  "SLACK_OAUTH_CLIENT_ID": "xxxx",
  "SLACK_OAUTH_CLIENT_SECRET": "xxxx",
  "SLACK_OAUTH_SCOPE": "app_mentions:read chat:write",
  "SLACK_OAUTH_USER_SCOPE": "",
  "SLACK_OAUTH_ERROR_URI": "<oauth-error-URI>",
  "SLACK_OAUTH_REDIRECT_URI": "<oauth-redirect-URI>",
  "SLACK_OAUTH_SUCCESS_URI": "<oauth-success-URI>",
  "SLACK_SIGNING_SECRET": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // required
  "SLACK_SIGNING_VERSION": "v0"
}

HTTP Routes

Endpoints are provided for the following routes:

Route Event Published? Synchronous Support? Purpose
GET /health No No Healthcheck to ensure your API is functional
GET /install No No Helper to begin Slack's OAuth flow
GET /oauth Yes No Complete Slack's OAuth2 workflow (v2)
POST /callbacks Yes Yes Handle Slack's interactive messages
POST /events Yes No Handle events from Slack's Events API
POST /menus Yes Yes Handle external select menus
POST /slash/{cmd} Yes Yes Handle Slack's slash commands

Responding to Events Synchronously

If you need to respond to Slack with a JSON payload (external select menus, for example), you will need to write an additional lambda function and attach it to the module via the custom_responses variable.

The custom_responses variable should be a map of API Route Keys => Lambda ARNs. Route Keys must start with POST /-/ and should match their async counterparts.

Example:

module "slackbot" {
  #

  custom_responses = {
    "POST /-/callbacks"  = "arn:aws:lambda:us-east-1:123456789012:function:my-sync-callbacks"
    "POST /-/menus"      = "arn:aws:lambda:us-east-1:123456789012:function:my-sync-menus"
    "POST /-/slash/fizz" = "arn:aws:lambda:us-east-1:123456789012:function:my-sync-slash-fizz"
  }
}

Requests to synchronous endpoints are signed using AWS Signature v4 and forwarded to the /-/* equivalent. By Default these requests are captured by the POST /-/{proxy+} route and respond with a 200 OK response. Adding your own custom responses override this behavior.

See the example project for usage.

Responding to Events Asynchronously

EventBridge events are discoverable using event patterns. Filter events using a bus name, source value, detail-type, or even parts of the event payload.

The following table shows the mapping of route-to-detail-type:

Route Event Bus Source Detail Type
GET /oauth <your-bus-name> oauth install
POST /callbacks <your-bus-name> <callback_type> <callback_id>
POST /events <your-bus-name> event_callback <event_type>
POST /menus <your-bus-name> block_suggestion <callback_id>
POST /slash/{cmd} <your-bus-name> slash_command /<command>

Example Event Patterns

In order to process a given event you will need to create an EventBridge rule with a pattern that targets a specific event.

The following examples show how a subscription might me made in Terraform:

Callbacks

resource "aws_cloudwatch_event_rule" "block_actions" {
  #
  event_pattern = jsonencode({
    source      = ["block_actions"]
    detail-type = ["my_action_id"]
  })
}
resource "aws_cloudwatch_event_rule" "view_submission" {
  #
  event_pattern = jsonencode({
    source      = ["view_submission"]
    detail-type = ["my_callback_id"]
  })
}

Event

resource "aws_cloudwatch_event_rule" "app_home_opened" {
  #
  event_pattern = jsonencode({
    source      = ["event_callback"]
    detail-type = ["app_home_opened"]
  })
}

OAuth

resource "aws_cloudwatch_event_rule" "oauth" {
  #
  event_pattern = jsonencode({
    source      = ["oauth"]
    detail-type = ["install"]
  })
}

Slash Command

resource "aws_cloudwatch_event_rule" "slash" {
  #
  event_pattern = jsonencode({
    source      = ["slash_comand"]
    detail-type = ["/my-command"]
  })
}

terraform-aws-slackbot's People

Contributors

amancevice avatar tomtomau avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.