Objective
- I am using the „new“ API Gateway Websocket service of AWS
- I want to connect using a Websocket client to a Lambda function
- I want to respond to the client using the
ApiGatewayManager
- Lambda function needs to be in a VPC with my RDS for better security (RDS is not public accessible, except for specified IPs in the security group)
- I am using
Node.js 8
in combination withTypescript
Approach
I created a regional AWS API Gateway for Websockets and added a Lambda function for $connect
, $disconnect
and one for the action subscribeChannel
.
I am able to connect and send messages to connected clients.
I also created a VPC with 3 private subnets, all of them are located in eu-central-1
each one in a different Availability Zone (AZ).
Lambda Functions loose their access to the public internet when you add them to a VPC, therefore one approach is adding another public subnet and adding a NAT Gateway to it.
Now I am changing the routing table of the private subnet to delegate 0.0.0.0/0
to the NAT and in the routing table of the public subnet it routes 0.0.0.0/0
to a Internet Gateway.
This seems to work to get access to the public internet, e.g. I am able to request https://google.com
but the ApiGatewayManagement times out as if cannot resolve the AWS service.
Then I looked into VPC Endpoints, as they are designed to make public AWS Services available in private subnets, without routing through the internet. I am able to set it up and receive the private DNS urls. But here I am stuck, I do not know how to use it in my setup/code.
I am managing the whole project using the serverless framework and Cloud Formation resources.
Issue
If the action handler for subscribeChannel
is associated with the VPC then the request to XXXXXXXX.execute-api.eu-central-1.amazonaws.com/develop
times out, as it cannot reach the public internet.
Is a NAT Gateway the correct approach or do I need to use a VPC Endpoint for execute-api? How do I correctly configure the VPC to use this private DNS?
Code
async function channelHandler(event, context) {
return new aws_sdk_1.ApiGatewayManagementApi({
apiVersion: "2018-11-29",
endpoint: event.requestContext.domainName + "/" + event.requestContext.stage,
})
.postToConnection({
ConnectionId: event.requestContext.connectionId,
Data: "Hello, world!",
}).promise()
.then(() => {
return {
statusCode: 200,
body: "Sent message!",
};
})
.catch((error) => {
return {
statusCode: 500,
body: JSON.stringify(error),
};
});
}
Used resources so far:
- https://serverless.com/blog/api-gateway-websockets-example/
- https://github.com/serverless/serverless-websockets-plugin
- https://aws.amazon.com/blogs/compute/announcing-websocket-apis-in-amazon-api-gateway/
- https://github.com/yai333/React-Chat-App-using-AWS-API-Gateway-Websocket-and-Serverless-Framework