AWS is a powerful tool that provides lots of flexibility. The elastic nature of the cloud allows you to dynamically spin up and tear down resources, while only charging for what you use. The downside is, well, anyone with access can spin up and tear down resources in your account with proper access. AWS is a very popular avenue for attackers (both software running on AWS and AWS accounts). It is not uncommon to hear about AWS accounts getting hacked on r/aws. The motivation behind these attacks is either to
- Launch resources and rake up large bills
- Delete running services, causing outages or data loss.
Both these scenarios are not good. In this blog, I'll share some tips on protecting your account. These tips are primarily geared toward an individual or small teams managing AWS Accounts. The enterprise landscape will look very different - they have access to a lot more resources and the use-cases are more complex.
This blog is divided into three parts - Security for console access, Security for programmatic access, and Monitoring. These are the bare minimum controls you should have in your AWS account, and you can add to these based on your risk appetite. I mention some tools I use - I am not affiliated with any of these. Do your own research before adopting any of these.
Protecting console access
Well, there is a lot of content out there on this topic. My best advice here is to do your own research when it comes to security (as I write a blog about security). I try to use trusted organizations or authorities for my own research. And I can point you to this NIST (National Institute of Standards and Technology, U.S. Department of Commerce) publication for a guide to setting up human access to a service. A more digestible version can be found here.
Setting strong password
Duh. I'm sure you already know this. Done set your password as
12345. But you will be surprised how many people do not follow this advice. The best solution I have found is to use a Password Manager. The advantages of password managers are very well documented across the internet. I will highlight the way of using it - DO NOT SHARE PASSWORDS ACROSS SITES. And whatever password manager you choose, make sure to secure it.
All password managers come built-in with generators. USE IT. This is the minimum complexity I use for my passwords.
I highly recommend BitWarden. It is an open-source software, that across multiple devices. It is also free to use and has a good enough library for regular users. If you are one of those people who have no trust in establishments, you can even host your own server. For those preferring a paid solution, you can use LastPass or 1Password. These services also monitor your passwords against leaked databases and offer better support.
This layer gets overlooked very often. I am in fact surprised AWS has not made this a mandatory requirement yet. This does show up as a recommendation in your IAM console if you have not already set it.
For most people, using a Virtual MFA method is enough. Authy and Google Authenticator have worked really well for me in the past. If you are a more advanced user, it makes sense to invest in a hardware MFA. YubiCo is the market leader in this. This is a good investment to protect your online identity across the board, not just on AWS. More and more providers (like Google, Crypto exchanges, Password managers, etc) have started supporting YubiKeys as an MFA method. I use YibuKey 5c NFC for my personal use for sites with hardware MFA integration, and Authy for Virtual MFA.
Disable root credentials
By default, a new AWS account has credentials associated with your root account. These credentials have sudo power for your account, and should NEVER be used. You should disable these credentials as soon as you create your account. You should instead create IAM users with programmatic access for API-based usage. The security checks for programmatic access are discussed in the next section.
Protecting programmatic access
This is slightly less trivial. AWS tends to build API first products, meaning you can do anything and everything using the API (sometimes even before via the console). The API is authenticated using IAM users. Each IAM user has an Access Policy and Security Credentials. Access policy dictates WHAT this user can do. And the Security Credentials dictate the WHO. Anyone with the Security Credentials and do everything specified in the Access Policy of the user.
The right access policy for any role is to implement a Least Privilege policy. It is Security101, and we all know it. But this rarely comes into effect especially when you are a single person or a small team operating complex AWS accounts. So here is my practical way of doing it.
Read-only access by default
The permissions you should use by default should be read-only. This is the user you have exported on your Laptop / Dev environment. It makes it less cumbersome for you to handpick the least privileged policies every time you want to look at a resource / or explore a new service. Having the secret to this leaked would not cause a disaster in your account (like spinning up new resources or destroying production services). There is an AWS managed policy named
ReadOnlyAccess I recommend using.
Roles with Mutation permissions
The credentials for roles with permissions to make changes should be stored more carefully. The recommended way is to have a mechanism to rotate credentials periodically. I fully stand behind this recommendation. This being said, it is not very easy to do, especially for single-person operations or small dev teams. I have seen massive multi-year projects in large enterprises to achieve this goal. My solution is to deactivate the access keys with mutable permissions once I am done with this. This typically lasts hours to days. I just generate a new key the next time I intend to make production changes to an account.
While the previous sections focused on mechanisms to ensure bad things do not happen to your AWS account, this section focuses on knowing about bad things and reducing the blast radius of such things.
You can learn more about CloudTrail on the official documentation page. In a nutshell, this service captures, stores, monitors, and analyzes access to your AWS account. It should be enabled by default. These logs can be useful to analyze why certain resources were launched/terminated. A more active utility of these logs can be to create a monitoring system, to alert you when resources are created. I will write a detailed blog about my monitoring system in the future. For now, you can follow the AWS guide if you are interested in setting this up on your own.
This is a low-hanging fruit you can enable to avoid seeing a surprisingly large AWS bill at the end of the month. This alert combined with AWS Organizations can be an effective monitoring system. You can follow this guide to create billing alerts.
I feel this feature does not get enough credit but is a very powerful tool to manage multiple AWS accounts. If your workflow is like mine and you manage multiple AWS accounts for different projects, AWS Organizations can really simplify your life. Not only does it allow for consolidated billing, but you can also add or close accounts. You do not want to be in a situation where you forgot to close an account before the domain expired for a stale project. There is a list of published best practices for AWS Organizations that you should review.
AWS has an ever-increasing list of security-related services and features. I did not even touch on things like GuardDuty and CloudTrail Insights in this blog. I could write a book on the topic of Best practices for securing your AWS Account. This blog outlines the bare minimum steps you should take to secure your AWS account.