How do I set up a cross-account Lambda authorizer for WebSockets? More specifically, so I can use it with Serverless Framework?

0

This guide exists for RestAPIs: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-lambda-authorizer-cross-account-lambda-authorizer.html

This guide exists for WebSocket, but doesn't cover cross-account: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-lambda-auth.html

I am using Serverless Framework v3.36.0, and trying to define an externally managed authorizer lambda that exists in a different account on my org, same region.

My serverless.yml, works fine with this:

  connection_manager:
        handler: functions/connection/handler.connection_manager
        events:
            - websocket:
                route: $connect
            - websocket:
                route: $disconnect

But since I want an external authorizer, I changed it to this:

  connection_manager:
        handler: functions/connection/handler.connection_manager
        events:
            - websocket:
                route: $connect
                authorizer:
                  arn: arn:aws:lambda:us-east-2:IDTHATOWNSAUTHORIZERLAMBDA:function:ITSNAMEHERE
                  identitySource:
                    - 'route.request.header.my-custom-attribute'
            - websocket:
                route: $disconnect

And I end up getting this when I run sls deploy:

Error:
CREATE_FAILED: ITSNAMEHEREauthorizerLambdaPermissionWebsockets (AWS::Lambda::Permission)
Resource handler returned message: "Unable to determine service/operation name to be authorized (Service: Lambda, Status Code: 403, Request ID: )" (RequestToken: , HandlerErrorCode: GeneralServiceException)

I removed RequestToken/ID in case they are sensitive, not sure.

The above is referring to this in the auto-generated CloudFormation script:

"ITSNAMEHEREauthorizerLambdaPermissionWebsockets": {
  "Type": "AWS::Lambda::Permission",
  "DependsOn": [
    "WebsocketsApi"
  ],
  "Properties": {
    "Action": "lambda:InvokeFunction",
    "Principal": "apigateway.amazonaws.com",
    "FunctionName": "arn:aws:lambda:us-east-2:IDTHATOWNSAUTHORIZERLAMBDA:function:ITSNAMEHERE"
  }
},

By deploying a version that doesn't have the additions that causes the error in serverless, I can get the stack to create. Then, if I follow instructions here: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-lambda-authorizer-cross-account-lambda-authorizer.html

I can get the authorizer to be hit cross-account! The problem with this setup though is that everytime I deploy I believe I'll have to repeat these steps in the AWS gui (create authorizer, set authorizer in route request settings, etc)

So how can I do a cross-account lambda authorizer for my websocket api using serverless.yml?

alanmun
asked 3 months ago196 views
2 Answers
1

Please add a resource-based policy to the Lambda function that allows the lambda:InvokeFunction action from the principal apigateway.amazonaws.com. You can do this manually in the AWS Lambda console or through AWS CLI.

Please create an IAM role that API Gateway will assume when calling the cross-account Lambda function. This role should have a trust relationship with apigateway.amazonaws.com and include a policy that allows lambda:InvokeFunction on the external Lambda function.

In myserverless.yml, specify the ARN of the external Lambda function in the authorizer.arn field as you've done. Include the ARN of the IAM role created in the previous step. This might involve using a custom authorizer configuration with the authorizerUri property under the x-amazon-apigateway-authorizer extension.

profile picture
Jagan
answered 3 months ago
  • Hi Jagan, does this policy seem correct?

    aws lambda add-permission
    --function-name "arn:aws:lambda:us-east-2:AccountIdForTheAccountThatHasExternalAuthorizer:function:AuthorizerNameGoesHere"
    --source-arn "arn:aws:execute-api:us-east-2:MyAccountIdHereContainingTheServerlessApp:*"
    --principal apigateway.amazonaws.com
    --statement-id "GrantAPIGatewayCrossAccountInvokePermission"
    --action lambda:InvokeFunction

    Looking into the other things, but if the second thing you mentioned needs to be manually done outside of serverless framework per-deploy, i fear it defeats my purpose

0
Accepted Answer

I figured it out, serverless documentation (v3.38.0) claimed to support my use case but it did not (there was no actual way to specify that I have an externally managed lambda function for websockets). I'm submitting a contribution to enable what I'm trying to do, should be a one liner.

alanmun
answered 3 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions