I am trying to set-up a websocket gateway to a Lambda function in AWS. When I do this manually I can successfully deploy the websocket and try it out using wscat. However I would like to build the architecture up using CloudFormation.
The structure of my CloudFormation yaml file looks like this:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
lambdaRole:
Type: String
Default: ...
backendRole:
Type: String
Default: ...
lambdaImage:
Type: String
Default: ...
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ImageUri: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${backendRole}:${lambdaImage}
Description: lambda connect function
FunctionName: myLambdaFunction
MemorySize: 128
Role: !Sub arn:aws:iam::${AWS::AccountId}:role/${lambdaRole}
Timeout: 3
PackageType: Image
MyWebSocket:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: MyWebSocket
ProtocolType: WEBSOCKET
RouteSelectionExpression: $request.body.action
MyIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref MyWebSocket
Description: Lambda Integration
IntegrationType: AWS_PROXY
IntegrationUri: !Join
- ''
- - 'arn:'
- !Ref 'AWS::Partition'
- ':apigateway:'
- !Ref 'AWS::Region'
- ':lambda:path/2015-03-31/functions/'
- !GetAtt MyLambdaFunction.Arn
- /invocations
IntegrationMethod: POST
MyConnectRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref MyWebSocket
RouteKey: $connect
Target: !Join
- /
- - integrations
- !Ref MyIntegration
MyDefaultRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref MyWebSocket
RouteKey: $default
Target: !Join
- /
- - integrations
- !Ref MyIntegration
MyResponseRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref MyWebSocket
RouteKey: add
RouteResponseSelectionExpression: $default
Target: !Join
- /
- - integrations
- !Ref MyIntegration
MyRouteResponse:
Type: AWS::ApiGatewayV2::RouteResponse
Properties:
RouteId: !Ref MyResponseRoute
ApiId: !Ref MyWebSocket
RouteResponseKey: $default
MyIntegrationResponse:
Type: AWS::ApiGatewayV2::IntegrationResponse
Properties:
IntegrationId: !Ref MyIntegration
IntegrationResponseKey: /201/
ApiId: !Ref MyWebSocket
testStage:
Type: AWS::ApiGatewayV2::Stage
DependsOn:
- MyConnectRoute
- MyDefaultRoute
- MyResponseRoute
Properties:
ApiId: !Ref MyWebSocket
StageName: testStage
MyDeployment:
Type: AWS::ApiGatewayV2::Deployment
Properties:
ApiId: !Ref MyWebSocket
Description: My Deployment
StageName: !Ref testStage
The stack is build without any errors and (almost) everything looks like I intended. However other than in the manually build version the integration of the Lambda function into the websocket does not seem to add the required trigger for the Lambda function. When I manually add a Lambda function to an API Gateway, this automatically adds the trigger.
What do I need to change in my CloudFormation Yaml file to also add the trigger to the Lambda function?
Trigger automatically added to Lambda function when Lambda function is manually added to API Gateway:

No trigger added when Lambda function is added to API Gateway using CloudFormation:

It looks like you may just need to include the Lambda permission for api gateway.
LambdaFunctionPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
Principal: apigateway.amazonaws.com
FunctionName: !Ref MyLambdaFunction
DependsOn: MyWebSocket
If you are having issues with Cloudformation creation it would probably be helpful to also create an account config for logging and chain the dependsOn order of the gateway resources like this.
ApiGwAccountConfig:
Type: "AWS::ApiGateway::Account"
Properties:
CloudWatchRoleArn: !GetAtt "rRoleForCloudtrail.Arn"
rRoleForCloudtrail:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- apigateway.amazonaws.com
Action:
- sts:AssumeRole
Policies:
-
PolicyName: "apigateway-cloudwatch"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:DescribeLogGroups
- logs:DescribeLogStreams
- logs:PutLogEvents
- logs:GetLogEvents
- logs:FilterLogEvents
Resource: "*"
testStage:
Type: AWS::ApiGatewayV2::Stage
Properties:
ApiId: !Ref MyWebSocket
StageName: testStage
DefaultRouteSettings:
DetailedMetricsEnabled: true
LoggingLevel: INFO
DataTraceEnabled: true
DependsOn: ApiGwAccountConfig
MyDeployment:
Type: AWS::ApiGatewayV2::Deployment
DependsOn:
- MyConnectRoute
- MyDefaultRoute
- MyResponseRoute
Properties:
ApiId: !Ref MyWebSocket
Description: My Deployment
StageName: !Ref testStage
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With