Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added websockets authorizer support #5867

Merged
merged 4 commits into from
Feb 28, 2019
Merged

Added websockets authorizer support #5867

merged 4 commits into from
Feb 28, 2019

Conversation

eahefnawy
Copy link
Contributor

@eahefnawy eahefnawy commented Feb 26, 2019

What did you implement:

Closes #5857
Closes #5874

How did you implement it:

Using the Authorizer CF template, and mapping it to the Route template, and setting the required permissions.

How can we verify it:

Using the following service:

service: websocket-authorizers

provider:
  name: aws
  stage: dev
  runtime: nodejs8.10

functions:
  connect:
    handler: handler.connect
    events:
      - websocket:
          route: $connect
          authorizer:
            name: auth
            identitySource:
              - 'route.request.header.Auth'
              - 'route.request.querystring.Auth'
  default:
    handler: handler.default
    events:
      - websocket:
          route: $default

  auth:
    handler: handler.auth
// handler.js
'use strict';

const AWS = require('aws-sdk')

// the following section injects the new ApiGatewayManagementApi service
// into the Lambda AWS SDK, otherwise you'll have to deploy the entire new version of the SDK

/* START ApiGatewayManagementApi injection */
const { Service, apiLoader } = AWS

apiLoader.services['apigatewaymanagementapi'] = {}

const model = {
  metadata: {
    apiVersion: '2018-11-29',
    endpointPrefix: 'execute-api',
    signingName: 'execute-api',
    serviceFullName: 'AmazonApiGatewayManagementApi',
    serviceId: 'ApiGatewayManagementApi',
    protocol: 'rest-json',
    jsonVersion: '1.1',
    uid: 'apigatewaymanagementapi-2018-11-29',
    signatureVersion: 'v4'
  },
  operations: {
    PostToConnection: {
      http: {
        requestUri: '/@connections/{connectionId}',
        responseCode: 200
      },
      input: {
        type: 'structure',
        members: {
          Data: {
            type: 'blob'
          },
          ConnectionId: {
            location: 'uri',
            locationName: 'connectionId'
          }
        },
        required: ['ConnectionId', 'Data'],
        payload: 'Data'
      }
    }
  },
  paginators: {},
  shapes: {}
}

AWS.ApiGatewayManagementApi = Service.defineService('apigatewaymanagementapi', ['2018-11-29'])
Object.defineProperty(apiLoader.services['apigatewaymanagementapi'], '2018-11-29', {
  // eslint-disable-next-line
  get: function get() {
    return model
  },
  enumerable: true,
  configurable: true
})
/* END ApiGatewayManagementApi injection */

module.exports.connect = (event, context, cb) => {
  cb(null, {
    statusCode: 200,
    body: 'Connected.'
  });
};

module.exports.default = async (event, context, cb) => {

  const client = new AWS.ApiGatewayManagementApi({
    apiVersion: '2018-11-29',
    endpoint: `https://${event.requestContext.domainName}/${event.requestContext.stage}`
  });

  await client
    .postToConnection({
      ConnectionId: event.requestContext.connectionId,
      Data: `default route received: ${event.body}`
    })
    .promise();

  cb(null, {
    statusCode: 200,
    body: 'Sent.'
  });
};

module.exports.auth = async (event, context) => {
  return {
    "principalId": "user",
    "policyDocument": {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Action": "execute-api:Invoke",
          "Effect": "Allow",
          "Resource": event.methodArn
        }
      ]
    }
  };
};

deploy, then connect to the ws url:

wscat -c wss://<ID>.execute-api.us-east-1.amazonaws.com/dev?Auth=foo -H Auth:bar
# connection should SUCCEED because you provided both identity sources: querystring & header

wscat -c wss://<ID>.execute-api.us-east-1.amazonaws.com/dev -H Auth:bar
# connection should FAIL because you ONLY provided the header
# and your serverless.yml clearly states that you need the querystring identity source
# If you remove the `identitySource` from `serverless.yml`, it should SUCCEED
# because using ONLY the header is the default behavior

Todos:

  • Write tests
  • Write documentation
  • Fix linting errors
  • Make sure code coverage hasn't dropped
  • Provide verification config / commands / resources
  • Enable "Allow edits from maintainers" for this PR
  • Update the messages below

Is this ready for review?: YES
Is it a breaking change?: NO

@eahefnawy eahefnawy self-assigned this Feb 26, 2019
@eahefnawy eahefnawy added this to the 1.39.0 milestone Feb 26, 2019
@eahefnawy eahefnawy marked this pull request as ready for review February 27, 2019 13:03
@eahefnawy eahefnawy requested a review from pmuens February 27, 2019 13:03
@eahefnawy eahefnawy changed the title Added authorizer support Added websockets authorizer support Feb 27, 2019
Copy link
Contributor

@dschep dschep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested it, but the code looks good to me!

@eahefnawy eahefnawy requested a review from dschep February 28, 2019 11:54
@eahefnawy eahefnawy merged commit 0293040 into master Feb 28, 2019
@eahefnawy eahefnawy deleted the wb-authorizers branch February 28, 2019 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add option to set Websocket API name Add support for Websockets Authorizers
2 participants