· engineering · 4 min read
Cost-Control "Kill Switch" for AWS CloudFront?
Trying to use AWS Cloudwatch to implement a "kill switch" that automatically disables CloudFront distribution if the bandwidth cost exceeds a specified threshold.
Table of Contents
A client has an AWS setup that serves a static site from S3 via CloudFront, including some large files.
This configuration presents a risk: a bug, or a malicious actor could exploit this by frequently requesting these files, rapidly inflating our AWS bill.
Given that AWS’s EstimatedCharges
metric updates every six hours and resets monthly, monitoring this is not suitable for immediate responses required by our scenario.
AWS CloudFront does contain some mitigation against DDOS attacks, but not at the application layer.
The client would rather interrupt the service for everyone, than face extremely high bills.
Cost Calculation
We have configured our CloudFront with PriceClass_100 to ensure content delivery from American and European edge locations, minimizing costs from more expensive regions.
Serving under 10TB, our costs are approximately $0.085 per GB, as bandwidth is the primary cost factor. Our objective is to monitor this and trigger protective measures if costs risk exceeding our budget.
Ideally we would be able to trigger an alarm based on a rolling total. But AWS explicitly advises against using either SUM or ROLLING_SUM metric math in alarms.
So realistically, we need to evaluate what the most we are willing to spend in any given hour is, and disable the distribution if that threshold is reached.
Solution Overview
Our solution involves creating a CloudWatch alarm that monitors the BytesDownloaded metric from the CloudFront distribution, coupled with a Lambda function that disables the distribution when the bandwidth cost crosses our set limit. This mechanism acts swiftly, independently of standard billing alerts, providing an additional layer of financial safety.
It should be noted that billing alerts were also enabled for this client account, and the notification of the team via eventBridge when the Alarm state changes was handled separately.
CloudFormation Implementation
Below is the CloudFormation template to set up the necessary components:
Explanation:
Lambda Function: Disables the CloudFront distribution when triggered.
IAM Role: Grants the necessary permissions to the Lambda function to modify CloudFront configurations.
CloudWatch Alarm: Monitors data transfer and triggers the Lambda function if the transferred data cost exceeds our preset threshold. Since December 2023 it has been possible to trigger a lambda function directly from the alarm, without SNS or something as an intermediary.
Conclusion
Implementing a CloudFront kill switch via AWS CloudFormation can add a simple layer of reactive cost control to help ensure your AWS spending remains within budget without manual intervention, particularly for applications serving large files, where traffic spikes can quickly lead to unexpectedly high charges.
If we were able to take advanatage of metric math in a Cloudwatch Alarm, this solution would be much better than it currently is, as we could set a monthly budget and react immediately when it is reached. As it is this approach only allows us to react to the last hours worth of data, and thus we need to toe the line between reacting to legitimate interest and a DDOS attack.
Nonetheless it might still be useful, given that it could take up to 6 hours to receive a billing alert (and maybe longer to act on it).
About James Babington
A cloud architect and engineer with a wealth of experience across AWS, web development, and security, James enjoys writing about the technical challenges and solutions he's encountered, but most of all he loves it when a plan comes together and it all just works.
No comments yet. Be the first to comment!