0
votes

I am considering NOT using API gateway for performance reasons. Instead, I want to expose a lambda function directly to the web. Unauthenticated IAM credentials are required, and provided by the AWS JavaScript SDK. I realize this could be a concern if a bad actor tries to invoke my function at an astronomical pace and cause major billing issues. I don't think this is likely as someone would specifically have to target my application, request IAM credentials and then invoke the request... a lot of work for little gain, but...

In order to protect my Lambda Function from an attack I was considering the account concurrency feature. By default, the account concurrency feature is limited to 1,000 concurrent requests on the account. I am able to specify reserve concurrency specific to a Lambda function which reduces the remaining overall account concurrency limit (the concurrency limit for the rest of the account).

Would this work: create a dummy lambda function (not publicly accessible), set the dummy Lambda function reserved concurrency really high, e.g. 950... this would leave 50 concurrent lambda requests for my "real" Lambda function... this seems like a simple way to throttle a lambda without using API gateway, etc.

Thoughts?

2
"I am considering NOT using API gateway for performance reasons." The rest of the question is premised on this. What's the performance problem you believe to be present in API Gateway? This seems like a potential case of solving the wrong problem, and doing it the hard way. - Michael - sqlbot
I too would like to understand what performance problems you are facing? - asr9
API gateway is a layer of abstraction on top of Lambda. My initial tests show that using API gateway introduces latency calling the Lambdas... - Cliff Helsel

2 Answers

2
votes

Throttling as you described as a form of protection is completely doable :) and without the need to create a second dummy function as you described.

Lambdas come with a Reserved Concurrency limit that enables you to set a maximum number of concurrent accepted lambdas. If the number of requests exceeds that limit the overflow requests will receive an error 500 response.

To set the concurrent limit you have several options:

The Console

Inside the AWS console navigate to your lambda, in the configurations page scroll down to the Concurrency box, and select Reserved Concurrency (entering your desired number 50)

enter image description here

The Command Line

To modify the Reserved Concurrency via the command line use the following command:

aws lambda put-function-concurrency --function-name YOUR_FUNCTION_NAME_HERE --reserved-concurrent-executions 50 

Serverless Framework File

If your deploying your functions with the serverless framework you can modify the Reserved Concurrency for any lambda inside the function section of you file.

service: stackoverflow # NOTE: update this with your service name

provider:
  name: aws
  runtime: python3.7
  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'us-east-1'}
  profile: ${opt:profile, 'default'}
  environment:
    region: ${self:provider.region}
    stage: ${self:provider.stage}
  stackTags:
    Owner : krapes
    Project : concurrencyLimits
    Service : concurrencyLimits
    Team : brokenLeg
  stackPolicy: # This policy allows updates to all resources
    - Effect: Allow
      Principal: "*"
      Action: "Update:*"
      Resource: "*"

  iamRoleStatements:



functions:
  dummy:
    handler: dummy.main
    timeout: 10
    ## This parameter sets the reserved concurrency for the lambda 'dummy'
    reservedConcurrency: 50
#    events:
#      - http:
#          method: GET
#          path: /dummy
#          resp: json

#plugins:
#  - serverless-python-requirements


custom:
  pythonRequirements:
     dockerizePip: non-linux

Now when testing your lambda, you'll see that with the Reserved Concurrency set the excess requests were returned an error 500 code, and thus protected the system.

Reserved Concurrency
Details (average, fastest, slowest):
  DNS+dialup:   0.0009 secs, 2.0200 secs, 6.0415 secs
  DNS-lookup:   0.0002 secs, 0.0000 secs, 0.0185 secs
  req write:    0.0000 secs, 0.0000 secs, 0.0030 secs
  resp wait:    3.5561 secs, 2.0199 secs, 6.0414 secs
  resp read:    0.0001 secs, 0.0000 secs, 0.0032 secs

Status code distribution:
  [200] 5000 responses
Reserved Concurrency
Details (average, fastest, slowest):
  DNS+dialup:   0.0007 secs, 0.0094 secs, 5.6580 secs
  DNS-lookup:   0.0000 secs, 0.0000 secs, 0.0119 secs
  req write:    0.0000 secs, 0.0000 secs, 0.0033 secs
  resp wait:    1.1845 secs, 0.0093 secs, 5.5826 secs
  resp read:    0.0000 secs, 0.0000 secs, 0.0032 secs

Status code distribution:
  [200] 1638 responses
  [500] 3362 responses

The outputs above were generated using the lambdaLoadTesting tool without reservedConcurrency AND with it set to 25.

0
votes

You can simply set a function-level concurrency limit of 50 on that Lambda function.

Not sure what you mean by "unauthenticated credentials"? If you want your client to invoke your Lambda function directly then your client needs credentials and an associated policy that permits the Lambda invocation.