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
已提問 4 個月前檢視次數 215 次
2 個答案
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
已回答 4 個月前
  • 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
已接受的答案

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
已回答 4 個月前

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南