12th July, 2020

Using AWS budgets to monitor region usage

When I was an AWS consultant in the UK, I worked primarily with public sector customers. They were mostly in the very early stages of cloud adoption, and my primary tasks became helping these customers setup their AWS environment, such that they trusted it enough to put workloads into AWS.

One of the concerns the customers often had was they only wanted workloads running in a specific AWS region. There could be many reasons for this, but if pressed we could probably get to an agreement that this was more because it felt nice than for any compliance reasons. At least as long as the data stayed in EU.
There are however good reasons to stick to as few regions as possible. Primarily that it is just easier to manage your environment if you do not need to check each region to see if you have any stray EC2 instances running.

The primary tool to prevent usage of unwanted AWS regions is to setup a Service Control Policy (SCP) blocking any regions not on an approved list. The AWS documentation even provides you with an example for how to set this up.
There are however a few caveats; it does not play well with AWS Control Tower, you still need to allow a bunch of global services, and finally SCPs does not apply to you AWS organization's root account. Nonetheless, SCPs are what we have and they are a decent solution for setting up a region block.

A region block is only one step in setting up an AWS environment. More often than not, you want to ensure your environment is compliant with your policies by setting up Config Rules, EC2 default encryption, blocking public S3 buckets and maybe GuardDuty or other security tools.
At this point in the planning phase, someone will ask: "What regions should we enable our compliance checks in?"

Should we deploy GuardDuty and Config Rules to regions where we do not expect any workloads to be deployed? We did block access to those regions so there should be nothing to monitor. But what if someone disables the block, or deploys resources in the organization's root account where the block does not apply? One of the problems are also that we have blocked access to those regions, so you cannot deploy your security tools.
So will the extra cost of running tools in "empty" regions be worth it? I am not only talking about the cost of the tools, but also the extra operational cost of having to manage the SCPs in a way that gives access to the tools but nothing else.

Manually monitoring using Cost Explorer

I cannot tell you if the effort in setting up monitoring in all AWS regions are worth it, but I can propose a different solution.

If one of your services is following your general guidance and not leaking any data it is not supposed to, you are probably not worried about someone using the wrong region, as long as they can correct it within a few days. And hopefully your development process uses some sort of development cycle where you would catch development workloads in the wrong region before the production workload is deployed there.

You can use AWS Config with an aggregator to check for resources in all accounts and regions, but with default deployed resources, this becomes a bit noisy. You also have to deploy the Config Recorder in all accounts and regions, and that is surprisingly a non-trivial task, especially if you have to retrofit this on an existing organization.

If however you are satisfied with being notified within 1-2 days of someone deploying resources to a non-approved region, you can use your AWS bill!

AWS billing information is updated between 8 and 48 hours after a resource have started to cost you money, so there will be some slack. But you do not need to wait until the end of the month to find out what you will be charged for on yesterdays resources. Instead you can use the AWS Cost Explorer to get a day by day breakdown of your costs.
Even better, the cost explorer allows you to filter on various dimensions, such as region!

My primary usage is in eu-west-1 (Ireland) and this is what Cost Explorer shows for the last 6 months if I filter out my primary region.

Cost explorer with region filtering and service grouping

As you can see, I have excluded three regions here: EU (Ireland) which is where my primary workloads are running, global which are global costs such as Route53 or if you have registered a domain through AWS and finally "No Region" which is the "region" where taxes are paid.
I have also set "Group By" to service so the output will show me which services are being used outside my primary region.

This might not look that impressive as my personal accounts have very little usage. We see that CloudFront has a charge and it turns out that CloudFront is charged in the regions where the data is leaving the AWS network. My CloudFront distribution is the cheapest price class, which supports U.S., Canada and Europe, so if I were to filter for the CloudFront service, I see that CloudFront is charging me in EU (Ireland), US East (N. Virginia) and Canada (Central).

Ignoring CloudFront, I see that Cost Explorer have also found entries for API Gateway, S3, Lambda, DynamoDB and others. You can see in the table below the graph that the cost for API Gateway is $0, but it is still listed there because I do have an API gateway deployed that does have a slight usage. Just not enough for me to be charged.

This actually surprised me, because I thought that all my stuff was running out of EU (Ireland), but it turned out that this blog and a few other experiments were in reality deployed to EU (London).

So using Cost Explorer, you are able to manually check you are not using resources outside your designated regions. In my example I grouped the costs by months because that looked better in the screenshot, but the costs are updated in Cost Explorer on a daily basis, so you do not need to wait for next months bill to see where your resources are running.

Automatically monitoring using Budgets.

If you do not want to look at Cost Explorer on a daily basis, for the sole reason of checking if your developers have managed to get around your region block, you can use AWS Budgets to alert you on usage in unexpected regions.

To setup a budget, go to the AWS Billing console. Choose Budgets in the menu to the left and click the Create budget button in the upper right corner.

Budget console

You want to create a Cost Budget. Unlike Cost Explorer, you are unfortunately not able to do "exclude" filtering, so you will need to select all the regions that are prohibited from use. This also means when new AWS regions are launched, you will need to update this budget.

I found when I tried to setup a budget, not all the regions were listed in the filter. I am not sure how the selection in the filter is created, but to be sure I got all the regions, I put together a CloudFormation template which creates a budget for all regions except Global, no-region and EU (Ireland). You can find the template on Github and alter to your own needs.

The budget I have created from that template looks like this.

Final budget overview

This is still not a perfect monitoring solution, especially any CloudFront charges might prove problematic, but I hope that it can help someone rest a bit easier, knowing that there is some control over what AWS regions are being used in their organization.