Skip to content

Latest commit

 

History

History
208 lines (156 loc) · 6.41 KB

webhook.md

File metadata and controls

208 lines (156 loc) · 6.41 KB

Webhook

Every application needs to interact with an ecosystem of 3rd party SaaS providers. Implementing a webhook HTTP endpoint in your application allows this ecosystem of external applications to notify you. Your application can then react to those notifications and perform tasks accordingly.

Quick start

serverless plugin install -n serverless-lift
service: my-app
provider:
    name: aws

constructs:
    stripe:
        type: webhook
        authorizer:
            handler: myAuthorizer.main
        path: /my-webhook-endpoint
        method: POST

plugins:
    - serverless-lift

How it works

Each webhook construct deploys the following resources:

  • an API Gateway V2 HTTP API and its $default stage
  • an EventBridge EventBus
  • an IAM Role allowing API Gateway to use PutEvents API of Eventbridge
  • an API Gateway V2 route
  • an API Gateway V2 integration defining mappings of parameters between the HTTP request body and the Eventbridge Event's body
  • a custom Lambda authorizer to handle signature verification at API Gateway level

Variables

Each webhook construct exposes the following variable:

  • busName: the name of the deployed EventBridge bus

This can be used to reference the bus on which notification are published, for example:

constructs:
    stripe:
        # ...

functions:
    myConsumer:
        handler: src/stripeConsumer.handler
        events:
            -   eventBridge:
                    eventBus: ${construct:stripe.busName}
                    pattern:
                        source:
                            # filter all events received on stripe webhook
                            - stripe
                        detail-type:
                            - invoice.paid

How it works: the ${construct:stripe.busName} variable will automatically be replaced with a CloudFormation reference to the EventBridge bus.

Configuration reference

Path

Required

constructs:
    stripe:
        type: webhook
        path: /my-path

The endpoint your webhook should be exposed on. Always starts with a /. The final URL for the webhook endpoint will be displayed in the information section when running a serverless deploy command and will be https://{id}.execute-api.{region}.amazonaws.com{path}

Authorizer

Conditional - depends on insecure value

constructs:
    stripe:
        # ...
        authorizer:
            handler: stripe/authorizer.main

The authorizer is a Lambda function that checks that webhooks are valid.

Note: the "authorizer" Lambda function is configured inside the webhook construct, instead of being defined in the functions section.

The only required value is the handler: this should point to the code that authenticate 3rd party notification. The handler will receive an event from API Gateway using payload format v2. The handler should be written to return the expected simple payload format.

// authorizer.js
export const main = (event, context, callback) => {
  callback(null, {
    "isAuthorized": true,
  });
}

All settings allowed for functions can be used under the authorizer key. For example:

constructs:
    stripe:
        # ...
        authorizer:
            handler: stripe/authorizer.main
            environment:
                STRIPE_SECRET: my-secret

Lift will automatically configure the function to be triggered by API Gateway. It is not necessary to define events on the function.

Disabling authorizer

Optional Defaults to false.

It is possible to skip writing an authorizer function by setting insecure: true.

HTTP requests on the wehbook endpoint will not be validated. This setting is not recommended and SHOULD NOT BE USED IN PRODUCTION to prevent webhook injection as well as Denial of Wallet attacks.

constructs:
    stripe:
        # ...
        insecure: true

Event type

Optional Defaults to Webhook.

Can either be a dynamic path selector:

constructs:
    stripe:
        # ...
        eventType: $request.body.type

Or a static string:

constructs:
    stripe:
        # ...
        eventType: stripe

Always favor dynamic path selector to ensure the minimum amount of compute is executed downstream. The list of available dynamic selector is available in API Gateway documentation.

Method

Optional Defaults to POST

This is the HTTP method the webhook will accept. It can be any of the following:

  • POST
  • PUT
  • PATCH
constructs:
    stripe:
        # ...
        method: POST

Extensions

You can specify an extensions property on the webhook construct to extend the underlying CloudFormation resources. In the exemple below, the EventBridge Bus CloudFormation resource generated by the stripe webhook construct will be extended with the new Name: StripeBus CloudFormation property.

constructs:
    stripe:
        type: webhook
        insecure: true
        path: /stripe
        extensions:
            bus:
                Properties:
                    Name: StripeBus

Available extensions

Extension key CloudFormation resource CloudFormation documentation
api AWS::ApiGatewayV2::Api Link
bus AWS::Events::EventBus Link

More options

Feel like a common extension pattern should be implemented as part of the construct configuration? Open a GitHub issue.