Menu
Engineering
14/02/2022
AWS Security Baseline
AWS Security Baseline provides a checklist of security practices and steps that should be part of every AWS application - no excuses.
#AWS #security
decoration

AWS Security Baseline provides a checklist of security practices and steps that should be part of every AWS application - no excuses.

This document is meant to be updated and improved over time.

Principles

  1. SANE DEFAULTS - there are just things that no one should do when setting up any software - in cloud or otherwise. If these are taken care of, you're covered from 99% of the attacks. It's similar to having a doors, locks and basic alarm in your house - unless you're really juicy target, it's good enough to deter most of the attacks.
  2. EXTENSIBILITY - when you start growing, the defaults should be easily extensible, so that we can build in more security mechanisms on top of what already exists, without the need to do complex migrations. For example, the situation we want to avoid is having all the production resources in AWS management account, because in order to introduce separate accounts for different environments it is neccessary to do some migrations.

In engineering, everything is about the trade-offs. That's why at the beginning of an MVP development everyone has access to production environment and database. Then, as the product grows, gets users, we can tighten the security aspects more, restrict access to resources, introduce additional roles and so on.

It's needless to say that it does not make sense to have a fortress-like security setup for the product that does not have any users. That's what sane defaults are all about.

Let's see what we consider Security Baseline for AWS - this is what we implement from day one.

AWS ACCOUNT MANAGEMENT

  1. MFA is set up on root accounts
  2. Consolidated billing and billing alarms are set up and tested
  3. Multi account setup - Security, Production, and Logs accounts exist

AWS account setup utilises AWS Organization and follows multi-account setup described in the best practices documentation.

Of course, that does not mean that we should have 5 different environments from day one. But having a separate management and billing account, security (where all the IAM users are defined) and production accounts is a good start. 

Multi-factor Authentication is also necessary for root accounts.

DATABASE SECURITY

  1. Database is not open to the world - credentials are set up
  2. Database is in private subnet and reachable only from services inside of a VPC (if VPC is used)

A database is a heart of every software. No one wants their heart exposed to the world. It's dangerous world out there. Even though not leaving the database open to the world seems like a common wisdom, there are thousands databases the are exposed. How that happens? I don't think that the case is that the engineers do not know that a database needs to be protected. More likely is that a proof of concept phase moved to production too quickly and no one remembered to set up the database authentication and configure the firewall. That's what we want to achieve by having a checklist.

APPLICATION SERVICES AND SECURITY GROUPS

  1. Backend Services are reachable only from a load balancer

Backend services are behind a load balancer and have firewall configuration (security groups) so that they listen only on designated ports and can only be accessed from the load balancer. Why? We don't want to allow SSH-ing into our backend services from anywhere, there's rarely a reason to ping or invoke a production backend service from anywhere except for load balancer. The goal is to keep attack vector as small as possible.

USER AUTHENTICATION

  1. User credentials (passwords) are not stored in plain text in the database
  2. Use a library or a service for managing user credentials

If possible, offload user authentication and authorisation to AWS Cognito. Also, do not try to implement your own encryption library.

CREDENTIALS AND SECRETS MANAGEMENT

  1. Do not keep plain text credentials and tokens in the codebase;
  2. Use AWS Secrets Manager, Ansible Vault or similar service to handle secrets.
  3. Do not log any sensitive information (password hashes, connection strings, tokens etc.)

One of the infamous security breaches at Facebook a while ago happened because before the passwords being hashed and stored in the database (hashed, as it should be), the plain text passwords were logged (most likely for testing/debugging purposes) and stored on log servers.

ENCRYPTION AT REST AND IN TRANSIT

  1. HTTPS must be used (most likely to be terminated on Load Balancer)
  2. HTTP must be redirected to HTTPS
  3. Encryption at rest should almost always be used

Both encryption in transit (HTTPS) and encryption at rest are so easy to set up, come with very little performance and maintenance overhead, and are almost free that there is absolutely no reason not to do it correctly.

OTHER?

Is there something we missed or got wrong? Let us know!