Lesson 18 · 27 min read

Security Hardening and Backups

Locking down what you built: patching, secrets, least privilege, automated backups and tested restores.

What you'll learn in this lesson

  1. Concept: layers, not a single lock
  2. Why this matters
  3. Shared responsibility: what AWS secures, what you secure
  4. The five ways small teams actually get hurt
  5. Layer 1 — identity: keys, MFA, roles
  6. Layer 2 — network: shrink the attack surface
  7. Layer 3 — no SSH: Session Manager
  8. Layer 4 — the server: patching and IMDSv2
  9. Layer 5 — secrets management
  10. Layer 6 — data: encryption and access
  11. Layer 7 — the application and its dependencies
  12. Layer 8 — detection: CloudTrail, GuardDuty, Config
  13. Backups: the part that saves the company
  14. Test the restore — the drill
  15. When a key leaks: the first hour
  16. The hardening checklist
  17. What this costs
  18. Interview corner
  19. Practice task before Lesson 19
  20. Conclusion

Concept

Security is not a product that you switch on. It is the habit of making every part of the system hard to misuse and cheap to recover. This lesson has two halves, and each half is a question:

  • Hardening — “how do I make it hard for the wrong person to do harm?” Hardening means closing weak points so the system is harder to attack.
  • Backups — “when something bad happens anyway, how do I get back?”
The analogy — a castle

A castle is not safe because of one thick wall. It has a moat, walls, a gatehouse, guards who check who comes in, locked inner rooms and a lookout. Sieges sometimes succeed, so it also has a hidden store of food and a practised escape route. This is called defence in depth. Assume that any single layer will fail one day. Make sure the next layer holds.

A useful mindset: assume breach

Do not ask “could someone get in?” Ask “when one credential or one server is compromised, how far can the attacker go, and how fast would we notice?” Everything below answers that question. Keep the blast radius small. The blast radius is how much damage one break-in can cause. Detect problems fast. Make recovery easy.

Words used in this lesson
  • IAM (Identity and Access Management) is the AWS service that decides who may do what in your account. An IAM role is a set of permissions that a machine or person can borrow for a short time, with no password or long-term key.
  • Least privilege is the rule that every user or machine gets only the permissions it needs, and nothing more.
  • A Security Group is a virtual firewall for an AWS resource. It lists which network traffic may come in. A subnet is a smaller part of your private network. A private subnet has no direct route from the internet.
  • ALB (Application Load Balancer) is the service that receives web traffic and spreads it over your servers. EC2 is the AWS service that rents virtual servers.
  • TLS is the protocol that encrypts data as it travels over a network. It is the “S” in HTTPS. Encryption turns data into code that only a key can read.
  • A region is a part of the world where AWS has data centres, for example Mumbai (ap-south-1).
  • CI (continuous integration) is a system that builds and tests your code automatically on every change.

Why this matters

You now hold your customers' data, their logins and their payments. The results of a mistake are real. Laws such as DPDP in India and GDPR in Europe require you to report a data breach. You can lose your customers' trust, and a small company often does not survive. Attackers do not pick you personally. Their programs scan the whole internet automatically. A server with a weak point is found in minutes, not months.

There is good news. Most real incidents come from a short list of ordinary mistakes. If you fix that list, you are safer than most companies.

Shared responsibility: what AWS secures, what you secure

AWS is responsible for (“security of the cloud”)You are responsible for (“security in the cloud”)
PhysicalBuildings, power, hardware, network cabling—
VirtualisationHypervisor, isolation between customers—
EC2 serversNothing inside the operating systemOS patches (security updates), SSH, the firewall, your app and the data
RDS / ElastiCachePatching of the OS and the database engine, and the hardwareWho can connect, users and passwords, the encryption choice, how long backups are kept, and your queries
S3Durability (not losing files) and the service itselfBucket policies, public access, encryption, and what you put in the bucket
IAMThe service works correctlyEvery policy, key, user and role. All of it

Most cloud breaches come from the customer's own settings and stolen credentials, not from failures inside AWS. The right-hand column is your job.

The five ways small teams actually get hurt

ThreatWhat it looks likeThe defence
Leaked credentialsAccess keys in a public repo, a .env file inside a Docker image, or a stolen laptop that is still logged in to the CLIUse roles instead of keys (Lessons 5, 14), use MFA, scan for secrets, and rotate (replace) a key if you have any doubt
Exposed servicesA database, Redis or SSH open to 0.0.0.0/0 (the whole internet), or an S3 bucket set to publicPrivate subnets, Security Group references, S3 Block Public Access, and no port 22
Unpatched softwareA server or an npm package with a known flaw that attackers already useAutomatic OS updates, dependency scanning, and frequent image rebuilds
Weak or shared accessOne admin login shared by five people, former staff who still have access, or no MFAA separate login for each person, least privilege, an access review every quarter, and removal of leavers on the same day
No backups (or untested ones)Ransomware, a bad migration or a mistaken delete happens, and there is nothing to restore fromAutomatic backups, versioning, copies in another account, and a practised restore

Notice how much you have already done. You use roles instead of keys (Lesson 5). Your databases are private (Lessons 6 and 8). Your buckets are private (Lesson 11). Your deploy role has narrow permissions (Lesson 14). This lesson closes the remaining gaps. It also adds detection and recovery.

Layer 1 — identity: keys, MFA, roles

Identity means who or what is allowed to log in. It is the front door, and attackers use it most often. First check it with AWS's own tools. Then apply the rules:

  • In IAM, open the Credential report. It is a CSV file (a simple table) with one row for every user. It shows password age, whether MFA is on, and the age and last use of each access key. MFA (multi-factor authentication) means a second proof of identity, such as a code from a phone app. Look for users with no MFA, keys older than 90 days, and keys that were never used.
  • Check the user list itself. Does each person still work here? Does each identity still need to exist?
  • IAM Access Analyzer (the external access check is free) finds buckets, roles and keys that are shared outside your account. It can also write least-privilege policies (policies that give only the access that is really used) from real usage.
  • Root user: the root user is the all-powerful first account. Turn MFA on (Lesson 0), create no access keys, and never use it for daily work. Check this in the credential report. The <root_account> row must show access_key_1_active = false.
  • MFA for every person, preferably with a hardware key or a passkey. A hardware key is a small USB device that proves you are you. A passkey is a login method that replaces the password. An AWS login with only a password is one stolen password away from total loss.
  • People use IAM Identity Center (single sign-on, SSO). Machines use roles. SSO lets people sign in once with a central account. If any long-lived access key still exists, rotate it, give it the minimum permissions, and name an owner for it.
  • Remove people on the day they leave. This is why groups matter (Lesson 5). One action removes one person, and no access is left over.
  • Review permissions using real data. IAM shows when each service was last used (“last accessed”). If a policy allows 40 services but only 3 are used, make the policy smaller.
Force MFA with a policy, not a request

Asking people to turn on MFA is only a wish. A policy that denies everything except managing their own MFA, until they sign in with MFA, is a real control. AWS publishes a ready-made example called “Allow users to manage their own MFA”. It uses a deny rule with BoolIfExists aws:MultiFactorAuthPresent = false. Attach it to the Developers group.

Stop secrets reaching Git at all

  • Turn on GitHub secret scanning and push protection. Push protection blocks a push that contains an AWS key. It is free for public repositories. For private repositories it is a paid GitHub feature (GitHub Secret Protection).
  • Also add a pre-commit scanner such as gitleaks on your own computer. It checks your code for secrets before each commit.
  • AWS also scans public GitHub. When it finds your key, it restricts the key and emails you. But attack bots are faster than email. If a key ever reaches a public repository, treat it as stolen, however fast you delete the commit. Rotate it.

Layer 2 — network: shrink the attack surface

The safest port is a closed port. (A port is a numbered door on a server that a service listens on.) Check what is open to the world. The list should be very short:

In EC2, go to Security Groups. Look at every inbound rule whose source is 0.0.0.0/0. In our design the only such rule should be alb-sg on ports 80 and 443. If web-sg, db-sg or cache-sg appears, or any group has port 22, 5432 or 6379 open to the world, fix it now.

Should be open to the internetMust never be
The ALB: ports 80 and 443 onlySSH (22), RDP (3389, remote desktop for Windows), databases (5432, 3306), Redis (6379), the app port (3000), Elasticsearch (9200), and admin dashboards
  • Keep databases and caches in private subnets with no public IP. Only web-sg may reach them (Lessons 6, 8, 16).
  • App servers accept traffic only from the ALB (Lesson 12). If they have public IPs, those IPs are for outbound traffic, not inbound.
  • Add AWS WAF (Web Application Firewall) on the ALB or CloudFront. It blocks common web attacks, such as SQL injection (an attack that sneaks database commands into a form field), bad bots and too many requests from one IP. It costs about $5 a month plus $1 per rule and $0.60 per million requests. Start with the AWS-managed core rule set.
  • Turn on VPC Flow Logs. They record the network connections in your VPC, and storing them in S3 is cheap. Later you can answer “who talked to this server?”

Layer 3 — no SSH: Session Manager

In Lesson 7 you opened port 22 to your IP address. That is fine for learning. It is a poor choice for production. Keys are files, and files get copied. Your IP address changes. And every scanner on earth probes an open port 22. AWS Systems Manager Session Manager gives you a shell on a server with no open port, no key pair and no bastion host. (A bastion host is a server that you log in to first, in order to reach other servers.) The SSM agent on the server connects out to AWS, and you connect using your IAM identity.

SSH on port 22Session Manager
Inbound portPort 22 must be openNone
CredentialsA .pem key file that you must store and shareYour IAM/SSO login, with MFA
Who can accessAnyone holding the keyAnyone your IAM policy names
Audit trailOnly what you log yourselfEvery session logged (CloudTrail, optionally full keystrokes to S3/CloudWatch)
Revoking accessChange the key on every serverRemove the IAM permission
  1. Give the instance role permission to talk to SSM

    Attach the AWS-managed policy AmazonSSMManagedInstanceCore to myapp-ec2-role. The migrations in Lesson 14 already need it. The agent is preinstalled on Ubuntu 24.04 images. It needs only this permission and outbound HTTPS. After a few minutes the instance shows as Online in Systems Manager, under Fleet Manager.

  2. Install the Session Manager plugin and connect

    Install the Session Manager plugin for the AWS CLI on your laptop. Then run:

    On your laptop
    • aws ssm start-session --target i-0abc123def456

      Opens a shell on the server with no port 22 and no key pair. The Connect button, then Session Manager, in the console does the same in the browser

    The same tool can also forward a port. This replaces Lesson 8's SSH tunnel to the database, and needs no SSH at all.

  3. Close port 22 and drop the key pair

    Once start-session works, delete the SSH rule from web-sg. The new launch templates already have no key pair (Lesson 12).

Layer 4 — the server: patching and IMDSv2

In our design the server is disposable, and that helps security. Think of servers as cattle, not pets. You do not nurse each one. The best way to patch them is to replace, not repair. On a schedule, rebuild from the latest AMI (the saved server disk image) and the latest app image. Then servers never collect drift (small unplanned changes) or old security holes.

  • Automatic OS security updates as a safety net for servers that live a long time.

Install the unattended-upgrades package in the user-data script (the script that runs when the server first boots) and enable it. Then Ubuntu applies security updates by itself every day.

  • Replace servers regularly. Run an instance refresh (Lesson 12) at least once a month, even when the code has not changed. Then servers get the latest AMI and OS patches. A scheduled GitHub Actions workflow can do this for you.
  • IMDSv2 required (set since Lesson 7). IMDS is the instance metadata service. A server can ask it for its own details, including temporary credentials. Version 2 needs a session token, so a bug in your app cannot easily be turned into credential theft. Check this on every instance.

In the EC2 instance list, add the IMDSv2 column. Every instance should say Required. Any instance that says Optional still accepts the old, weaker version. Fix it in place: choose Actions, then Instance settings, then Modify instance metadata options.

  • Encrypted disks by default. In the EC2 settings, turn on “EBS encryption by default” for the region (EBS is the disk service for EC2). Then no disk is ever created without encryption. The command is aws ec2 enable-ebs-encryption-by-default. It applies to one region at a time.
  • An instance role with least privilege. Review myapp-ec2-role. It should read its own parameters, pull its own image and write its own logs. It should do nothing else.

Layer 5 — secrets management

A secret is anything that gives access. Examples are database passwords, API keys, signing keys and tokens. Here is a ladder of practices, from worst to best:

Where the secret livesVerdict
Hard-coded in source, committed to GitIt leaks the day the repository is shared. Never do this
Baked into a Docker image or a build argumentAnyone who can pull the image can read it
A .env file copied to the server by handIt works, but there is no audit trail and no rotation. It is easy to lose, and it differs from server to server
SSM Parameter Store SecureString (an encrypted parameter), read at boot with the instance roleGood: encrypted, controlled by IAM, audited and free
Secrets Manager with automatic rotationBest for database passwords. It changes them on a schedule
SSM Parameter StoreSecrets Manager
PriceFree (standard parameters)About $0.40 per secret per month, plus API calls
Automatic rotationNo (you must build it yourself)Yes, built in for RDS and other services
Best forApp settings and most secretsDatabase credentials and anything that must be rotated

Our setup already uses Parameter Store (Lesson 12). The upgrade worth making is for the database password. Let RDS manage it in Secrets Manager with rotation. Then it never appears in the Terraform state, in chat messages or on anyone's clipboard.

In RDS, choose Modify and tick Manage master credentials in AWS Secrets Manager. RDS creates the secret and rotates it. The app, or its boot script, reads the secret with permission from its role. The password never has to be copied anywhere.

Rotation is the real prize

A secret that never changes is quietly copied to more places every year. Rotation means replacing a secret with a new one on a schedule. It limits how long a leaked secret stays useful. It also forces you to know where each secret is used. If rotating a credential feels risky, that risk is itself a problem you have found.

Layer 6 — data: encryption and access

StoreAt restIn transitAlso
RDSStorage encryption on (Lesson 8; you cannot add it later to an existing instance)TLS enforced (the default in Postgres 15 and later)Private subnet, deletion protection, and database users with least privilege
S3Default encryption (on by default now)Deny requests that do not use TLS, in the bucket policyBlock Public Access and versioning
EBS disksEncrypted (the default-on setting above)—Encrypted snapshots
ElastiCacheAt-rest encryption on (Lesson 16)TLS + AUTHPrivate subnet
Between the browser and you—HTTPS only, redirect HTTP, and HSTS (a header that tells browsers to always use HTTPS; Lesson 10)Secure and HttpOnly cookies

Encryption at rest means data is encrypted while stored on disk. It protects you from a stolen disk or snapshot. It does not protect you from a compromised application, because the app can read the decrypted data. That layer is access control, which decides who and what may read which rows, files and keys. Here are two points for a multi-tenant product (one app that serves many customers):

  • Tenant isolation is a security control, not an extra feature. Every query filters by tenant. Consider PostgreSQL row-level security as a second layer. It is a database rule that limits which rows a user can see. It still protects you if a developer forgets a WHERE clause. S3 keys and cache keys also include the tenant (Lessons 11, 16).
  • Force TLS on the bucket. Add a deny statement for requests where aws:SecureTransport is false.

Layer 7 — the application and its dependencies

Infrastructure controls cannot fix a vulnerable app. These habits give the most protection for the least effort:

  • Keep dependencies up to date. A dependency is a package that your code uses. Turn on Dependabot (.github/dependabot.yml). It opens update requests for npm packages, GitHub Actions and Docker base images. Most breaches through code use flaws that were fixed months earlier.
  • Scan in the pipeline. Add pnpm audit --prod and an image scan as CI steps. For the image scan use trivy image or ECR scan-on-push from Lesson 9. Make the build fail on serious findings.
  • Follow the basics of the OWASP Top 10. OWASP publishes a list of the ten most common web security risks. Validate input. Use parameterised queries, where the values are sent separately from the SQL text, and never build SQL from strings. Escape output. Check authorisation on every request. Authorisation means checking that the user may access this record, not only that the user is logged in. Set secure cookies. Add security headers (Lesson 10).
  • Do not trust the client. The browser can send anything. Checks on the server are the only real checks. A hidden button is not access control.
  • Pin and review code from other people. Pin means to fix an exact version. This includes GitHub Actions (Lesson 14) and the curl | bash installers that you copy from the internet.

Layer 8 — detection: CloudTrail, GuardDuty, Config

You cannot respond to what you cannot see. Here are three AWS services, in order of importance:

ServiceWhat it doesCost
CloudTrailThe audit log. It records every API call in your account: who, what, when and from which IP. You cannot investigate an incident without itThe last 90 days of management events are free automatically. A trail that saves them to S3 for longer is almost free for one copy
GuardDutyWatches CloudTrail, DNS and network logs and compares them with lists of known threats. Examples: “this key is being used from an IP linked to crypto-mining” and “this server is talking to a known malware host”30-day free trial, then pay for what you use: roughly $5 to $20 a month for a small account
AWS ConfigRecords the settings of your resources over time and flags rule violations. Examples: “this bucket became public” and “this Security Group opened port 22 to the world”You pay for each rule and each recorded change. It can add up, so start with a few rules
  1. CloudTrail: create a trail for all regions. Deliver it to a new S3 bucket with tight access rules. Turn on log file validation, so you can tell if anyone changes the log files.
  2. GuardDuty: choose Get started, then Enable. Then send its findings to the same SNS topic as your alarms (Lesson 17).

Send GuardDuty findings to the alerts topic with an EventBridge rule (EventBridge is the AWS service that reacts to events). Use source: aws.guardduty and a severity of 7 or higher. Then a serious finding reaches a person in the same way as a 5xx alarm. Also set an alarm on root user login. Use a CloudTrail metric filter on userIdentity.type = Root. The root user should almost never sign in.

Backups: the part that saves the company

Hardening lowers the chance of a disaster. Backups lower its cost. Think of ransomware (malware that locks your data and demands money), a bad migration, a deleted table, a hacked admin account or a region outage. The answer is the same for all of them: a recent, separate, tested copy.

The 3-2-1 rule

Keep 3 copies of your data, on 2 different kinds of storage, with 1 copy in another place. In AWS terms, you have the live data, a backup in the same region, and a copy in another region or another account. A hacked production login must not be able to delete that last copy.

WhatHow it is protectedNotes
RDS databaseAutomatic daily backups and point-in-time restore (set to 7 to 35 days, Lesson 8). A manual snapshot before risky changes. A copy of the snapshot in another regionThis is the most valuable data you have. Automatic backups are deleted with the instance unless you choose to keep them. Manual snapshots are not deleted
S3 uploadsVersioning (lets you undo overwrites and deletes). A lifecycle rule that removes old versions. Cross-region replication (automatic copying) to a second bucketConsider Object Lock for data that nobody may change or delete
ServersNothing to back up. You rebuild them from the image, the launch template and TerraformThis is the reward for the stateless design (Lessons 8, 11, 12)
Configuration and infrastructureTerraform code in Git, and a state bucket with versioning (Lesson 15)Also keep a copy of your secrets offline, in a password manager
RedisUsually none, because it is a cache. If sessions matter, use a replica with failoverIf losing it would be a disaster, the data is stored in the wrong place

Put it on autopilot with AWS Backup

AWS Backup is one service where you manage backup schedules, retention times and copies for RDS, EBS, S3, DynamoDB and more. It stores backups in a vault. You can lock a vault so that even an administrator cannot delete the recovery points. This is a real defence against ransomware and against bad insiders. Here is a small but useful plan for this architecture:

  • Daily backups of the RDS instance, kept for 35 days.
  • Weekly backups kept for 12 months. Add a monthly backup kept for 7 years if the law or your rules require it.
  • A copy of each backup in a vault in a second region (for example ap-southeast-1).
  • Backup Vault Lock in compliance mode. Turn it on once you are sure about your retention times.
  • Copy an important RDS snapshot to a second region (choose Actions, then Copy snapshot).
  • Keep versioning on for every bucket that holds user data (Lesson 11).
Backups in the same account can be deleted by the same attacker

If an attacker steals an admin login, they can delete the database and its backups at the same time. The strongest protection is a copy in a separate AWS account that production credentials cannot touch. You can set this up with AWS Organizations, using a “backup” account. A locked vault also helps. A small company should at least keep a copy in another region and protect the accounts that can delete it with MFA.

Test the restore — the drill

A backup that you have never restored is a hope, not a backup. Backups fail quietly, in boring ways. The wrong database was included. The encryption key was deleted. The restore takes nine hours instead of one. The instructions are in the head of someone who has left. The only way to find out is to practise on a calm day.

StepDo
1. Write the targetRPO (recovery point objective) is how much data you can afford to lose, for example 15 minutes. RTO (recovery time objective) is how long you can afford to be down, for example 1 hour.
2. Restore to a NEW instanceNever overwrite production. Restore a snapshot, or a chosen point in time, into a fresh database.
3. Prove the data is rightConnect to it. Count the rows in your key tables. Open a recent record that you know.
4. Time itHow long did the whole job take, from start to finish, including finding the instructions?
5. Fix the runbookWrite down every surprise. The next person (or you, when you are tired) will follow it.
6. Clean upDelete the drill instance so that it stops costing money.
  1. Restore the production database to a new instance called myapp-db-drill, at the latest restorable time (Lesson 8). Production is not touched. Note how long it takes. That is your real recovery time.
  2. Connect to the drill copy from an app server. Check that the data is really there. Count the rows and look at the newest created_at value.
  3. Delete the drill instance so it stops billing.

Do this every quarter and after any major change. The time it took is your real RTO. It is usually longer than the one in your head. For the object store (S3), also practise “restore a deleted file”. Delete a test object, then bring it back from the previous version in the console.

When a key leaks: the first hour

Sooner or later this will happen to someone on your team. If the steps are written down, a stressful moment becomes a checklist. Follow these steps in order:

  1. Contain — deactivate, do not delete yet

    Kill the credential
    • aws iam update-access-key --user-name <USER> --access-key-id <AKIA…> --status Inactive

      Deactivating stops the key at once and keeps the evidence. You can delete it later

    Then attach an explicit Deny everything policy to that identity. An explicit deny always wins (Lesson 5). Also check that the attacker did not create a second key for themselves.

  2. Find out what the key did

    In CloudTrail, open Event history and filter by the access key ID (or the user name). Look for actions that you did not do. Examples are new users or keys, new instances (often used for crypto-mining), changed Security Groups, S3 downloads, snapshot copies to unknown accounts, and changes in other regions. Attackers like regions that you never look at.

  3. Remove what they left behind

    Terminate instances that you do not know. Delete users, roles and keys that you do not know. Review Security Groups and bucket policies. Check for new IAM roles that trust an outside account. If you are in doubt, treat the whole account as unsafe. Rotate everything that the leaked identity could reach, including the database password and the application secrets.

  4. Tell people, then write it up

    If customer data may have been accessed, the law may require you to report it by a deadline. Open a case with AWS Support. They can help, and they sometimes waive the charges from fraudulent use if you act quickly. Then hold a blameless post-mortem, a review that looks for causes and not for someone to blame. Ask how the key leaked, and which control would have stopped it.

The hardening checklist

Copy this into your repository. Every line is something that you have already met in the series:

SECURITY-CHECKLIST.md
## Identity
[ ] Root user: MFA on, no access keys, not used (credential report clean)
[ ] MFA required (by policy) for every human; humans use SSO / IAM Identity Center
[ ] No long-lived access keys on servers or in CI (roles + OIDC)
[ ] Any remaining keys are less than 90 days old, each with a named owner
[ ] Leavers removed the same day; access reviewed every quarter
[ ] GitHub secret scanning and push protection on

## Network
[ ] Only the ALB accepts traffic from 0.0.0.0/0 (ports 80 and 443)
[ ] Port 22 closed; access through SSM Session Manager
[ ] DB and cache in private subnets, no public IP, reachable only from web-sg
[ ] WAF (managed core rule set) on the ALB / CloudFront

## Servers
[ ] IMDSv2 required on every instance
[ ] EBS encryption by default; unattended security upgrades on
[ ] Servers rebuilt from a fresh AMI and image at least every month
[ ] Instance role is least-privilege (reviewed with Access Analyzer)

## Secrets and data
[ ] No secrets in Git, images or build args; all in SSM / Secrets Manager
[ ] DB password managed and rotated by Secrets Manager
[ ] RDS, S3, EBS, Redis encrypted at rest; TLS everywhere in transit
[ ] S3 Block Public Access on at the account level
[ ] Every query, cache key and S3 key is tenant-scoped

## App
[ ] Dependabot, pnpm audit and image scan in CI (fail on high severity)
[ ] Authorisation checked on every request, not only the login

## Detection
[ ] CloudTrail multi-region trail with log validation
[ ] GuardDuty on, findings routed to the alerts topic
[ ] Alarm on root login and on unusual spend

## Backups
[ ] RDS backups kept 7 to 35 days, plus a manual snapshot before risky changes
[ ] Cross-region copy of RDS snapshots; S3 versioning and replication
[ ] Backups protected from deletion (locked vault / separate account)
[ ] Restore drill done this quarter; RTO measured and written down
[ ] Key-leak runbook written and its steps rehearsed

What this costs

ItemApproximate price
IAM, MFA, Access Analyzer, Session Manager, Parameter StoreFree
CloudTrail management events, one trailFree (plus a few cents of S3)
GuardDuty30 days free, then about $5 to $20 a month for a small account
Secrets ManagerAbout $0.40 per secret per month
AWS WAFAbout $5 per web ACL, plus $1 per rule, plus $0.60 per million requests
RDS automated backups (up to DB size)Free
RDS snapshots / cross-region copiesAbout $0.095 per GB per month, plus the cost of transfer between regions
S3 versioning + replicationStorage for each copy, plus the cost of replication transfer
Dependabot, secret scanning (public repos)Free

The most valuable items are free: MFA, no keys, no port 22, private data stores, Access Analyzer and CloudTrail. Everything that costs money here costs less per month than an hour of an engineer's time. That is far cheaper than one incident.

Interview corner

What is the shared responsibility model?

AWS secures the cloud itself. That means the buildings, the hardware, the hypervisor and the software of managed services. The customer secures what they put in the cloud. That means identities and permissions, network rules, OS and application patching on EC2, decisions about data and encryption, and configuration. Managed services move the line up, but they never remove the customer's side.

How do you give engineers shell access to production servers securely?

I use Session Manager instead of SSH. It needs no inbound ports and no shared key pairs. IAM controls access, with MFA. Sessions are logged in CloudTrail and can also be recorded. To remove someone's access, I remove their IAM permission.

Where do you store application secrets on AWS?

In SSM Parameter Store (SecureString) or in Secrets Manager. The app reads them at run time through the IAM role of the instance or task. I never put them in code, images or build arguments. I use Secrets Manager for credentials that need automatic rotation, such as database passwords.

An access key was pushed to a public repo. What do you do?

I deactivate the key at once and add a deny policy. I read CloudTrail for everything the key did, in all regions. I remove any resources or credentials that the attacker created. I rotate everything that the key could reach. I report the incident if the law requires it. Then I add controls such as secret scanning and a move to roles. Deleting the commit does not undo the exposure.

Explain RPO and RTO and how they drive your backup design.

RPO is the most data loss I can accept. It decides how often I back up and whether I need point-in-time restore. RTO is the longest downtime I can accept. It decides the restore method: Multi-AZ failover, snapshot restore or a rebuild in another region. I measure the real RTO by practising restores.

How would you protect backups from ransomware or a compromised admin?

I use backups that cannot be changed (immutable) in locked vaults, with AWS Backup Vault Lock or S3 Object Lock. I keep copies in a separate account and region that production credentials cannot delete. I require MFA for deletes. And I test restores regularly.

Security Groups are open only to the ALB, and the app still leaked data. What might have happened?

Flaws in the application go straight through network controls. Examples are broken authorisation, injection, a vulnerable dependency, or an instance role with too many permissions. Broken authorisation is often called IDOR (insecure direct object reference). It lets a user read another tenant's record by changing an ID in the request. The fixes are an authorisation check on every request, tenant scoping, dependency scanning and roles with least privilege.


Practice task before Lesson 19

  1. Run the credential report. Write down every finding, such as missing MFA, old keys and unused users. Fix each one.
  2. Check your Security Groups as described above. List everything that is open to the internet. Explain why each item is needed, or close it.
  3. Attach the SSM policy to the instance role and connect with start-session. Then remove the port 22 rule and delete the key pair from the launch template.
  4. Turn on CloudTrail, GuardDuty and IAM Access Analyzer. Read the first findings.
  5. Move the database password to RDS-managed Secrets Manager. Update the boot script so that it reads the password from there.
  6. Run the restore drill. Restore to a point in time into a new instance, check the data, record the time it took and delete the copy. Then delete a test S3 object and restore it from its earlier version.
  7. Write the key-leak runbook for your team in ten lines. Then ask a teammate to read it and say what is unclear.
  8. Copy the checklist into your repository. Tick every box that you can honestly tick. The boxes you cannot tick are next quarter's work.
Optional stretch

Hold a game-day, which is a planned practice of an incident. Ask a teammate to “leak” a test key with few permissions into a private repository. See how long secret scanning, GuardDuty or CloudTrail takes to show it. The gap between what you expected and what happened is your plan for improvement.

Conclusion

A secure system is not one that cannot be attacked. It is one where each layer limits the damage that gets past the layer before it. Problems are visible quickly, and recovery is a practised routine.

  • Identity first. Use MFA for people and roles for machines. Have no long-lived keys. Give least privilege. Remove leavers on the same day.
  • Shrink the attack surface. Only the ALB is public. Data stores are private. Close port 22 and use Session Manager.
  • Treat servers as cattle. Rebuild them regularly. Use IMDSv2, encrypted disks and automatic security updates.
  • Keep secrets in a secret store and rotate them. Use encryption at rest and in transit. Scope everything by tenant.
  • Detect problems with CloudTrail, GuardDuty and alerts. Recover with layered, protected and tested backups and a written incident routine.

The system is secure, observable and recoverable. One question remains. What does all of it cost, and how do you keep the bill under control? That is the final lesson.


End of Lesson 18. Next: Lesson 19 — Cost Review and Final Production Architecture.

Published by Jainik · Last updated · How these lessons are made

Keep learning

Part of the study guide

Related series