Public urls for Lambda functions are relatively new feature in that AWS service. It might
super useful when you create function and want to provide it fast. You can create URL with
one click fin AWS Management Console and call it with curl. Without fighting with API
Gateway configuration.
This approach has one drawback. If some bad actor will find url of your function it might cost you a lot. Everythink depends how your function is configured, but with default settings allow unlimited executions.The good news is that with Cloudwatch support you can setup throttling function, that will temporary disable Lambda function, if it receives too many requests.
Let's create Lambda function hello-url-fn
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
}),
}
and configure function url NONE auth type. Lambda service will automatically generate
unique function url. Let's assume it is https://hello.lambda-url.eu-central-1.on.aws.You
can open it in web browser and check if function sends response.
In next step we will create Cloudwatch alarm url-request-alarm, that will be triggered
when function hello-url-fn will receive too many request. Requests count can be measured
with metric Lambda/UrlRequestCount. Our alarm will be triggered if function will be
receiving more than 9 requests / minute in last 5 minutes. If function receive less requests
in one minute, then alarm will come back to normal state.
On every change of alarm's state, it will send notification to SNS topic
url-request-alarm-topic.
The last puzzle piece is another Lambda function throttle-fn, that is triggered by
notification from SNS topic url-request-alarm-topic.
import json
import boto3
def lambda_handler(event, context):
client = boto3.client('lambda')
subject = event['Records'][0]['Sns']['Subject']
executions = 1
if subject.startswith('ALARM'):
executions = 0
print('Disble')
else:
print('Enable')
client.put_function_concurrency(
FunctionName='hello-url-fn',
ReservedConcurrentExecutions=executions
)
return {
'statusCode': 200,
'body': ''
}
Every Cloudwatch notification has specific structure. We will use Subject property to
identify new state of alarm url-request-alarm. If subject starts with phrase ALARM we
assume, that state has changed from OK to ALARM. It means, that in last 5 minutes
function was receiving more than 9 requests per minute and must be disabled. If subject
doesn't start with word ALARM then we assume, that state has changed from ALARM to OK
and hello-url-fn can be activated again.
We disable or enable Lambda function by changing reserved concurrency level. That property specifies, how many instances of function can be run at the same time. If reserved concurrency is equal to 0, then all incoming requests are throttled and function is never invoked.
Fuction URL for AWS Lambda is useful feature, but misused might expose you to high costs. For that reason lambda with public url must be carefuly monitored. If we configure alarm with reasonable threshold we will be notified soon enough to make proper action.