DEV Community

Guille Ojeda for AWS Community Builders

Posted on • Updated on • Originally published at

7 Must-Do Security Best Practices for your AWS Account

Security is like a diet: you always say you're gonna start on Monday, and you never do. Today is the day you start.

Note: This content was originally published at the Simple AWS newsletter. Understand the Why behind AWS Solutions. Subscribe for free! 3000 engineers and tech experts already have.

Use case: That AWS account where you run your whole company but you never bothered to improve security


You created your AWS account and started building. You got your MVP running, got some paying customers, and things are going well. You always said you'd eventually come back to improve your security, but figuring out how to do it is harder than you thought, and there's always a new feature to add to your product, so you end up saying you'll get on it next week, and next week, and next week.

Today is the day you finally secure your AWS account.


  • AWS Identity and Access Management (IAM): This is where you create users and assign permissions.

  • Amazon CloudTrail: Logs everything that happens in your account.

  • Amazon GuardDuty: Analyzes the above logs for suspicious activity.

  • AWS Billing: Where you see how much money you're spending.


These practices are for a single AWS account.

Create a password policy

Passwords can be brute forced. No news there. Yet some people still think they're safe with a 10-digit password that's all numbers. Set up a password policy to prevent IAM users from entering insecure passwords, with a minimum of 16 characters. Here's how:

  1. Log in to your AWS account and go to the IAM console.

  2. Choose Account settings on the left.

  3. In the Password policy section, choose Change password policy.

  4. Check your options and click Save.

Create IAM users

The root user can do everything. If you lose access to it, you're done. So don't share it, and don't even use it! Instead, create an IAM User for every person that needs access to AWS, and only use the root in case of emergencies. You'll be tempted to give Administrator permissions to everyone. Instead of that, check out these example policies by AWS and these policies by asecurecloud and take 5 minutes to build something a bit more restrictive.

(tip for Organizations: Don't use IAM, instead use IAM Identity Center to let one user access all your accounts)

Here's how to set up users:

  1. Log in to your AWS account and go to the IAM console.

  2. If you decided to set up your own IAM policies (or use the ones from AWS or Asecurecloud), click Policies on the left and click Create policy.

  3. Click on the JSON tab, paste your JSON. Click Next: Tags.

  4. If you want, enter a tag for your policy. Click Next: Review.

  5. Enter a Name and a Description. Click Create policy. Repeat this for all the policies you want to create.

  6. Next we're going to create groups for our users You'll want to group them by roles or access levels, for example you could have a Developers group and an Infrastructure group. To do that, click User groups on the left and click Create group.

  7. Enter the name, scroll down, and select the policies you want to add (you can use the search box to filter them). Click Create group.

  8. Now we're ready for our users. Click Users on the left and click Add user.

  9. Enter the user name. If they need access to the visual console (the one where you're doing this), check Enable console access. Most people will need it.

  10. If you checked Enable console access, choose either an autogenerated password or enter your own custom password. In either case, check Users must create a new password at next sign-in. Click Next.

  11. Select the group or groups (you can pick more than one) to which you want to add this user. If you pick more than one group, the user's permissions will be a combination of both groups. Click Next and click Create user.

  12. Copy the Console sign-in URL and send it together with your password to the person this user is for. You can also click the button to Email sign-in instructions.

  13. If the user needs programmatic access, on the list of users click on that user, click on the Security credentials tab, scroll down to Access keys and click Create access key.

  14. Select your use case, read the alternatives presented by AWS, check that you understand and click Next.

  15. Enter a Description and click Create access key.

  16. Repeat the user creation process for as many people as you want to give access to your AWS account. Remember, one user per person.

Add MFA to every user

Multi-Factor Authentication means any agent of evil will need to compromise two authentication methods to gain access to your account. For example, your password and your mobile phone (where you install an app that generates a code needed to sign in). Remember to do this for the root user as well!!

(tip for Organizations: do this for all IAM Identity Center users and for the root of each account)

To set it up, see Low Cost Best Practices in AWS.

Enable logging of all account actions

Logs are a record of what happens in a system, right? There's this service called CloudTrail that records every action that is taken at your AWS account. Launched an EC2 instance? It's logged here. Changed a security group? Logged here. Logged in with your user from an unknown IP range? Logged here, and you can get notified (more on that next). Event history is automatically enabled for the past 90 days.

(tip for Organizations: You'll want to collect the logs from all accounts and move them to a single account. I'll update this with a guide for that in the coming weeks)

Let's see how to keep those logs forever in an S3 bucket:

  1. Log in to your AWS account and go to CloudTrail. Click Create trail.

  2. Enter the trail name, such as "all events".

  3. For Storage location, choose Create new S3 bucket to create a bucket.

  4. For Log file SSE-KMS encryption, choose Enabled, and on AWS KMS alias enter a new name for your KMS key.

  5. In Additional settings, for Log file validation, choose Enabled.

  6. Optionally, choose Enabled in CloudWatch Logs to have CloudTrail send the logs to CloudWatch Logs.

  7. On the Choose log events page, you need to decide what events to log. I recommend the following:

    1. Check Management events and Insights events.
    2. In Management events, for API activity, choose both Read and Write. If you're very short on money choose Exclude AWS KMS events.
    3. In Insights events, choose API call rate and API error rate.
  8. Click Next and click Create trail.

Set up a distribution list as your email address

You know that email address you used to create the account? Probably the CEO's or the CTO's. Turns out AWS sends useful info there. What happens if that person is not available? Create a distribution list (which is an address that is automatically forwarded to many addresses) and add addresses there. Here's how:

  1. On Google Worskpaces, go to Directory → Groups.

  2. Click on Create Group and enter name, email and description. Click Next.

  3. For Access type you probably want to set Restricted, but any will do, so long as External can “contact group owners” (i.e. send emails to that address). Click Create Group.

  4. Back on AWS, log in with the root user and go to Account Settings.

  5. Change your contact information to a group you just created, and click Save.

  6. Warning: If you change the root email address to that of a group, anyone with access to the group can recover the password. This is actually a good idea, but be careful with whom you add to that group.

Enable GuardDuty

GuardDuty basically scans your CloudTrail events and warns you when there's unusual activity. Cool, right? It's $4 per million events scanned. And you need to enable it in all regions. Here's how:

  1. Go to the GuardDuty console. Click Get started and click Enable. That's it! Let's explore it a bit.

  2. On the left, go to Settings and click Generate sample findings.

  3. Go back to Findings on the menu on the left, and check out the [SAMPLE] findings generated. That's what you can expect from GuardDuty (though hopefully not that many!)

  4. So, do I need to check GuardDuty every day to see if there's something new? Absolutely not. Let's set it up to notify you on an SNS topic to which you can subscribe a phone number, an email address, etc (I recommend one of the email addresses for a distribution list, created on the recommendation above):

  5. First we'll create the SNS topic. Go to the SNS console, click Topics on the left and Create topic.

  6. For the Type select Standard. Enter a name such as GuardDutyFindings, and click Create topic.

  7. Next we'll subscribe our email or phone to the topic. Click Create subscription, for protocol select either email, enter the email address of one of the distribution lists created above (or create a new one for this) and click Create subscription.

  8. Finally we'll need an EventBridge rule to post GuardDuty findings to the SNS topic. To do that, go to the EventBridge console, click Rules on the left and click Create rule.

  9. Enter a name such as GuardDutyToSNS, leave event bus as “default” and Rule type as Rule with an event pattern. Click Next.

  10. For Event source, choose AWS events. For Creation method, choose Use pattern form. For Event source, choose AWS services. For AWS service, choose GuardDuty. For Event Type, choose GuardDuty Finding. Click Next.

  11. For Target types, choose AWS service. On Select a target, choose SNS topic, and for Topic, choose the name of the SNS topic you created 5 steps ago. Open Additional settings.

  12. In the Additional settings section, for Configure target input, choose Input transformer and click Configure input transformer.

  13. Scroll down to the Target input transformer section, and for Input path, paste the following code:

    { "severity": "$.detail.severity", "Finding_ID": "$", "Finding_Type": "$.detail.type", "region": "$.region", "Finding_description": "$.detail.description" }
  14. Scroll down. For Template, paste the following code (tune it if you want):

    "Heads up! You have a severity GuardDuty finding of type in the region." "Finding Description:" ". " "Check it out on the GuardDuty console:"
  15. Click Confirm. Click Next. Click Next. Click Create rule. To test it, re-generate the sample findings from step 2 and you should get an email for each.

  16. Go grab a glass of water, a cup of tea or a beer. That was a long one!

Create a Budget

There's no way to limit your billing on AWS, but there is a way to get notified if your current spending or forecasted spending for the month exceed a threshold. If you're spending $200/month and suddenly you're on track to spending $500 for that month, you'd like to know ASAP so you can delete those EC2 instances that you forgot you launched!

I'd give you a step by step, but I'll do you one better: Here's an in-console tutorial by AWS. Tip: Set a number above your typical spending (including peaks). You don't want to be deleting 10 emails a month, because you'll get used to ignoring them.


Do I need to do all of that? Yes. It's easy (with this guide), it's either super cheap or free, and it's important. You know it's important, or you wouldn't have read this far.

Do I need to do all of that right now? Now That is a good question. The answer is no, you don't. But you've been postponing this for how long? Tell you what, let's compromise:

  1. Take each best practice

  2. Create a Jira ticket (or Trello, Todoist or whatever you're using to manage tasks)

  3. Paste the step by step there

  4. Schedule it for some time in this sprint or the next.

At least now you know what to do and how to do it.


Wanna get AWS Certified? Adrian Cantrill's courses are the best for that.

Understand the Why behind AWS Solutions.
Join over 3000 devs, tech leads, and experts learning how to architect cloud solutions, not pass exams, with the Simple AWS newsletter.

  • Real-world scenarios
  • The Why behind solutions
  • How to apply best practices

Subscribe for free!

If you'd like to know more about me, you can find me on LinkedIn or at

Top comments (6)

dasheck0 profile image
Stefan Neidig

Came here for the budget tip! This is crucial as AWS pricing policy are sometimes unclear and intransparent. It got better but is far from easy to estimate. So having a budget in place really helps in not burning your credit card :D

guilleojeda profile image
Guille Ojeda

Yeah, estimating is really hard. AWS does tell you everything, but it's A LOT to read!! What budgets saved me from several times is resources I forgot to delete. That damn instance I launched to test something 3 months ago!

dasheck0 profile image
Stefan Neidig

That damn transfer family instance that is way more expensive than the caculator stated (it was $600+ instead of the $10 I calculated with :D)

Thread Thread
guilleojeda profile image
Guille Ojeda

Wow, that's a ton of money. Did you get some credits for it?

Thread Thread
dasheck0 profile image
Stefan Neidig

Honestly I didn't even try. Just lessons learned here. Transfer family is expensive.