Course outline

2.3

MFA, Password Policy and Protecting Root

MFA devices, password rules, MFA conditions in policies, and what the root user is (and is not) for.

16 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain what the root user is, why no policy can limit it, and list the tasks that only root can do.
  • Lock root away properly: strong password, several MFA devices, no access keys, alerts on every sign-in, and centralized root access when there are many accounts.
  • Explain how MFA works, and choose between passkeys and security keys, virtual authenticator apps and hardware TOTP tokens.
  • Recover from a lost MFA device, for an IAM user and for root.
  • Set an account password policy and know exactly what it does and does not cover.
  • Write policies that require MFA for dangerous actions, avoid the Bool false trap, and use MFA from the CLI.

#Two questions: who are you, and can you prove it?

Lesson 2.1 introduced the identities in an account: the root user, IAM users and groups. Lesson 2.2 showed how AWS decides whether a request is allowed. Both assume one thing: that AWS knows who is making the request. This lesson is about making that true.

Signing in is the moment AWS decides who you are. If an attacker can sign in as you, every permission you have becomes theirs, and the best policies in the world do not help. So the three topics here are all about the sign-in:

  1. The root user, the most powerful identity, and how to keep it out of reach.
  2. MFA, which makes a stolen password useless.
  3. The password policy, which sets the minimum quality of IAM user passwords.

And then one more step: using MFA inside policies, so that the most dangerous actions need a fresh MFA check even after sign-in.

#The root user

When you create an AWS account, you give an email address and a password. That pair becomes the root user: the first identity in the account, with complete access to every service and resource, including billing and the account itself.

Two facts make root different from every other identity:

  • No IAM policy can limit it. You cannot attach a policy to root, and a deny in an IAM policy does not apply to it. (In AWS Organizations, a service control policy can limit the root user of a member account, but never the management account. That is chapter 20.)
  • It can lock you out. Root can change the account’s email and password, and close the account. Whoever controls root controls the account.

#Tasks only root can do

AWS keeps the list short on purpose. In a standalone account (not in an organization), only the root user can:

AreaTask
AccountChange the root email address, root password or root access keys
AccountClose the account, and reopen it during the post-closure period
AccountRestore permissions when the only IAM admin removed their own access
BillingActivate IAM access to the Billing and Cost Management console, and a few other billing tasks
BillingView certain tax invoices
EC2Register as a seller in the Reserved Instance Marketplace
S3Enable MFA Delete on a bucket
S3Edit or delete a bucket policy that denies every principal
SQSEdit or delete a queue policy that denies every principal

Things that are not on the list: creating IAM users, attaching AdministratorAccess, launching anything, reading CloudTrail, changing the account name or contact details, or choosing which Regions are enabled. An admin identity does all of those.

Self-checkQuestion

The only IAM admin in a standalone account edited their own policy by mistake and can no longer manage IAM. Who can fix it?

#Rules for the root user

Every rule comes from the same idea: root is rarely needed, so make it very hard to use.

  • Strong, unique password, from a password manager. AWS requires at least 8 characters with three of four character types, but a long passphrase is much better.
  • MFA, always. AWS now requires MFA on the root user of every account type (standalone, management and member accounts). If it is not set up, you must register it at sign-in, with a short grace period of 14 days at most.
  • More than one MFA device. Root can have up to eight. Keep one in daily reach of the person responsible and one in a safe.
  • No access keys. Access keys are for programs, and a program never needs root. If root has keys, delete them. (If root must ever use the CLI, the aws login command gives short-lived credentials instead of permanent keys.)
  • A group email address owned by the company, such as aws-root@example.com, not one person’s inbox. People go on holiday and leave jobs.
  • Split the secrets. Some companies keep the password with one team and the MFA device with another, so two people must agree to sign in as root.
  • Alert on every root sign-in. CloudTrail records root activity; an EventBridge rule can email the security team whenever root signs in. AWS Config, Security Hub and Trusted Advisor all have checks for “root has no MFA” and “root has access keys”.

The root user: locked away, used only for root-only tasks

One AWS account, one root user, and an everyday admin. See what happens in normal work, in a root-only task, and when an attacker gets the root password.

Scenario

AWS account111122223333
Attackersomewhere on the internet
You (account owner)
Root useremail + password + MFAnot used
Everyday adminIAM identity with MFA
EC2 instances
S3 buckets
Account settingsroot email, close account
CloudTrail + alert rule
Step 1 of 3
1

The root user is the identity that created the account: the sign-up email and password. It can do everything, and no IAM policy can limit it. So on a normal day nobody signs in as root.

#Many accounts: centralized root access

A company with fifty AWS accounts has fifty root users, each with a password, MFA devices and a recovery path to protect. Since November 2024, AWS Organizations can centralize root access:

  • The management account (or a delegated admin for IAM) deletes the root credentials of member accounts: password, access keys, signing certificates and MFA. New accounts created in the organization start with no root credentials.
  • When a root-only task is needed in a member account, the admin starts a privileged root session with sts:AssumeRoot. It lasts at most 15 minutes and is limited to one task, such as deleting a bucket policy that locks everyone out, or allowing password recovery.
  • Without credentials, nobody can sign in as that member root, and “forgot password” does not work, even for someone who takes over the root email inbox.

Centralized root access in AWS Organizations

A company has dozens of member accounts. Instead of guarding a root password and MFA device for each one, the member accounts have no root credentials at all.

Scenario

Management account111122223333
Member account444455556666
Security adminIAM role, MFA
STSroot session, 15 min max
Member rootno password, no keys, no MFApassword + MFA to guard
S3 bucketpolicy denies everyone
Attacker
Step 1 of 3
1

Every AWS account has a root user, including every member account. With 50 accounts that is 50 passwords, 50 MFA devices and 50 recovery paths to protect.

#Multi-factor authentication

A password is something you know. Anything you know can be copied: guessed, phished, reused on a site that gets hacked, or read over your shoulder. MFA adds a second, different kind of proof:

  • something you know: a password or a PIN;
  • something you have: a phone with an authenticator app, a security key;
  • something you are: a fingerprint or a face, usually used to unlock the device that holds the key.

Two passwords are still one factor. The point is that the factors are different kinds, so one theft is not enough. The main benefit, in one line: if your password is stolen, your account is still safe.

Signing in with a password and an MFA code

Rina is an IAM user with a virtual MFA app on her phone. The app and AWS share a secret that was set up once, through a QR code.

Scenario

Rinabrowser
Authenticator appon her phone
AWS sign-in
IAMstores the same secret
account ID, user name, password
Step 1 of 7
1

First factor: something she knows. An IAM user signs in with the account ID or alias, the user name and the password.

#How a 6-digit code works

Virtual authenticator apps and hardware tokens use TOTP, a time-based one-time password:

  1. Setup: share a secret once

    When you assign a virtual MFA device, AWS creates a random secret and shows it as a QR code. The app scans it. Now the app and IAM both hold the same secret, and it never travels again. To finish setup you type two consecutive codes, which proves the app works and its clock is right.

  2. Every 30 seconds: same secret + same time = same code

    The app combines the secret with the current time, cut into 30-second steps, through a hash function (HMAC), and shows the last six digits. IAM does the same calculation. Nothing is sent between them, so the phone can be offline.

  3. Sign-in: compare

    You type the code; IAM computes its own and compares. It accepts a small window around the current time to allow for slightly wrong clocks. A phone whose clock is minutes off produces codes IAM rejects; the fix is automatic network time, or resyncing the device in IAM with two consecutive codes.

#MFA device types

TypeWhat it isStrengthsLimits
Passkeys and security keys (FIDO2)A hardware key such as a YubiKey (USB or NFC), or a synced passkey in a password manager, unlocked with a fingerprint, face or PINPhishing-resistant; no battery; one security key can protect many root and IAM usersEnabled from the console only, not the CLI or API; cannot be passed to STS to get MFA-marked credentials
Virtual authenticator app (TOTP)An app on a phone, such as Google Authenticator, Microsoft Authenticator or a password managerFree, quick to set up, holds tokens for many users on one phoneCodes can be phished; tied to the phone
Hardware TOTP tokenA key fob or display card that shows a 6-digit codeSeparate from the phone, works without a networkMust be bought from AWS’s listed suppliers; battery runs out; one token per user; codes can be phished

SMS is no longer an option. AWS ended support for enabling SMS text-message MFA; text messages can be intercepted, and phone numbers can be hijacked.

#Why passkeys beat codes: phishing

A 6-digit code proves you have the phone, but it does not know which website you type it into. A fake sign-in page can ask for your password and your code, and pass both to the real AWS within seconds. A passkey or security key signs a challenge that is tied to the real website address. On a fake site the browser reports the fake address, the key has nothing to sign, and the attack fails. That is what phishing-resistant means, and why AWS recommends passkeys and security keys first.

A fake sign-in page: a typed code can be stolen, a passkey cannot

Rina clicks a link in an email and lands on a perfect copy of the AWS sign-in page, at a look-alike address. The attacker’s server passes everything she types to the real AWS.

Scenario

Rina
Fake pagesignin-aws-login.example
Real AWS sign-insignin.aws.amazon.com
user name + password
Step 1 of 6
1

The page looks real, so Rina types her password.

Self-checkQuestion

Why does a security key stop a phishing site that relays your sign-in to AWS, while a virtual MFA code does not?

#Several devices, and losing one

  • Each root user and IAM user can register up to eight MFA devices, of any mix of types. Any one of them is enough to sign in.
  • An IAM user must sign in with an existing device to add or remove another.
  • IAM user loses a device: sign in with another registered device and remove the lost one. With only one device, an admin deactivates it and assigns a new one.
  • Root loses a device: use another root MFA device. If all are lost, recovery needs both the account’s email inbox and its contact phone number. Keep both current, and do not let one person control both.
  • Whatever happens, remove a lost or stolen device from the identity at once.

#The account password policy

An AWS account has one password policy, and it applies to the console passwords of IAM users. Without a custom policy, the default applies: 8 to 128 characters, at least three of uppercase, lowercase, numbers and symbols, not the same as the account name or email, and no expiry.

A custom policy can set:

OptionRangeTakes effect
Minimum length6 to 128 charactersNext time a password is set
Require uppercase, lowercase, numbers, symbolsAny combinationNext time a password is set
Password expiration1 to 1095 daysImmediately: older passwords must be changed at next sign-in
Password expiration requires administrator resetOn or offWhen a password expires
Allow users to change their own passwordOn or offImmediately
Prevent password reuseLast 1 to 24 passwordsNext time a password is set

What it does not do, and the exam likes these:

  • It does not apply to the root user or to access keys. An IAM user whose password expired can still use their access keys.
  • There is no lockout option: you cannot lock a user after N failed attempts. The defence against guessing is a long password plus MFA.
  • Raising the minimum length does not force anyone to change a password today; it applies at the next change.

The account password policy at work

Policy: at least 14 characters, three character types, expires after 90 days, the last 5 passwords cannot be reused, users may change their own password.

Scenario

IAM user Karim
Console sign-in
Password policyone per account
new password: dhaka2024
Step 1 of 6
1

Karim changes his password to something easy to remember.

#Requiring MFA inside policies

Signing in with MFA protects the door. But some actions are dangerous enough that you want a fresh MFA check for them specifically: terminating production instances, deleting a bucket, changing IAM. For that, policies have condition keys about MFA (the Condition block of a policy is explained in lesson 2.1).

#aws:MultiFactorAuthPresent

The classic exam question: “How do you make sure users cannot delete an S3 bucket without MFA?” Answer: a policy with a Condition on aws:MultiFactorAuthPresent set to "true".

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DeleteOnlyWithMfa",
      "Effect": "Allow",
      "Action": ["s3:DeleteBucket", "ec2:TerminateInstances"],
      "Resource": "*",
      "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
    }
  ]
}

To use it correctly you need one detail: when is the key in the request at all?

  • Console sign-in: the console works with temporary credentials behind the scenes. The key is present: true if the user signed in with MFA, false if not.
  • Temporary credentials from STS (GetSessionToken or AssumeRole called with an MFA serial and code): present and true.
  • Long-term access keys (the CLI or SDK with a plain access key): the key is missing. Not false: missing.

That one difference decides how each way of writing the condition behaves:

StatementConsole without MFAConsole or STS with MFALong-term access key
Allow + Bool trueNot allowedAllowedNot allowed (key missing)
Allow + BoolIfExists trueNot allowedAllowedAllowed (key missing counts as a match)
Deny + Bool falseDeniedNot deniedNot denied: the trap
Deny + BoolIfExists falseDeniedNot deniedDenied: the recommended guard

The Bool false Deny looks right but lets every long-term access key straight through, because a condition on a missing key does not match. AWS recommends Deny with BoolIfExists false when the rule is “nothing without MFA”. The console’s visual editor “MFA required” option writes the BoolIfExists true Allow, which requires MFA in the console but not for access keys.

Requiring MFA for a dangerous action

Policy on the EC2-Admins group: allow terminating instances only when aws:MultiFactorAuthPresent is true. Watch how the key behaves with each kind of credential.

Scenario

Sofiain EC2-Admins
STS
IAM policy check
EC2i-0abc
signed in with password + MFA
Step 1 of 3
1

Behind the scenes the console uses temporary credentials, and they record that she signed in with MFA.

#Using the CLI under an MFA policy

A user with only an access key cannot satisfy the condition, so they first trade the key plus an MFA code for temporary credentials:

aws sts get-session-token \
  --serial-number arn:aws:iam::111122223333:mfa/sofia-phone \
  --token-code 482913

STS returns an access key, secret key and session token marked as MFA-authenticated. They last 12 hours by default (15 minutes to 36 hours for an IAM user). Put them in a CLI profile or environment variables and the policy is satisfied. Note: this works with virtual and hardware TOTP devices; codes from passkeys and security keys cannot be passed to STS this way, and the newer aws login command handles those.

#aws:MultiFactorAuthAge

“MFA happened” may not be enough; you may want “MFA happened recently”. aws:MultiFactorAuthAge holds the number of seconds since the MFA check:

"Condition": { "NumericLessThan": { "aws:MultiFactorAuthAge": "3600" } }

With this, a session that passed MFA five hours ago cannot terminate instances; the user gets a new session with a fresh code. Like the present key, it is missing for long-term keys.

#MFA on cross-account roles

When users of one account assume a role in another (the full story is lesson 2.4), the trusting account can demand MFA in the role’s trust policy:

{
  "Effect": "Allow",
  "Principal": { "AWS": "arn:aws:iam::444455556666:root" },
  "Action": "sts:AssumeRole",
  "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
}

The user passes their MFA serial and code in the AssumeRole call. MFA is checked once, when the role is assumed; the role’s permissions policy does not need its own MFA condition. (arn:aws:iam::444455556666:root here means “the other account”, not its root user signing in.)

#A preview: S3 MFA Delete

S3 has its own, separate MFA feature. With MFA Delete on a versioned bucket, permanently deleting an object version or changing the versioning state needs an MFA code with the request. Only the root user of the bucket owner’s account can turn it on, and only through the CLI or API. It is covered with versioning in chapter 10.

#How it is used in design

  • Humans use IAM Identity Center with MFA, not IAM users with long-term keys (chapter 20). IAM users, where they remain, all have MFA, and the password policy is set.
  • Root is a break-glass identity. Strong password and two MFA devices in different hands, no access keys, group email, an alert on every sign-in, and a written procedure for when it may be used.
  • Many accounts: centralize root access and remove member root credentials.
  • Destructive actions need MFA: a Deny + BoolIfExists guard on TerminateInstances, DeleteBucket and IAM changes for human roles. Do not put it on the roles your applications use; they have no MFA and would break.
  • Phishing-resistant first: passkeys and security keys for admins and root; virtual apps as a stop-gap.
  • Check it continuously: AWS Config rules and Security Hub controls for root MFA, root access keys and IAM users without MFA, and the credentials report (lesson 2.4) for an account-wide view.

#Try it yourself

Read your account’s password policy (an error means the default policy is in use):

aws iam get-account-password-policy

Set a stronger one:

aws iam update-account-password-policy \
  --minimum-password-length 14 \
  --require-uppercase-characters --require-lowercase-characters \
  --require-numbers --require-symbols \
  --max-password-age 90 --password-reuse-prevention 5 \
  --allow-users-to-change-password

Check that root has MFA (AccountMFAEnabled: 1) and no access keys (AccountAccessKeysPresent: 0):

aws iam get-account-summary \
  --query 'SummaryMap.{RootMfa: AccountMFAEnabled, RootKeys: AccountAccessKeysPresent}'

List your own MFA devices, then get MFA-marked temporary credentials for the CLI:

aws iam list-mfa-devices
aws sts get-session-token --serial-number <your device ARN> --token-code <6 digits>

In the console, open IAM → Users → your user → Security credentials → Assign MFA device, and add a second device so a lost phone never locks you out.

#Summary

Key takeaways

  • The root user (sign-up email + password) has full access and is not limited by IAM policies. Use it only for root-only tasks: changing root email or password, closing the account, restoring a locked-out admin, some billing tasks, RI Marketplace seller, S3 MFA Delete, and unlocking deny-all bucket or queue policies.
  • Root rules: strong password, MFA (now required on every account type), several MFA devices, no access keys, group email, alerts on sign-in. With many accounts, centralize root access and delete member root credentials; sts:AssumeRoot gives a 15-minute task-scoped session.
  • MFA = something you know + something you have (or are). A stolen password alone no longer opens the account.
  • Device types: passkeys and security keys (FIDO2, phishing-resistant, one key for many users), virtual authenticator apps (TOTP), hardware TOTP tokens. SMS is no longer supported. Up to 8 devices per user; any one signs you in.
  • Lost device: IAM user → another device or an admin; root → another device, else email and phone recovery.
  • Password policy: length 6–128, character types, expiry 1–1095 days (immediate), reuse 1–24, admin reset, self-service change. Not for root, not for access keys, no lockout.
  • aws:MultiFactorAuthPresent: present with temporary credentials, missing with long-term keys. Allow + Bool true requires MFA; Deny + BoolIfExists false blocks everything without MFA; Deny + Bool false lets access keys through.
  • CLI with MFA: aws sts get-session-token with the device serial and code. aws:MultiFactorAuthAge requires recent MFA. Cross-account roles require MFA in the trust policy.