Programming Notes
nacho4d avatar

Programming Notes

@nacho4d

Stop Using AWS Root Credentials — Set Up IAM Identity Center Properly

Open a terminal and run this:

cat ~/.aws/credentials

If you see something like this:

[default]
aws_access_key_id = ...
aws_secret_access_key = .../...

You have a problem. Those are long-lived static credentials sitting in plain text on your laptop. This post explains why that is dangerous and walks you through fixing it properly using AWS IAM Identity Center.


1. Why This Matters — The Problem With What You Probably Have

The bad practice

When most people start with AWS they do something like this: create an access key, run aws configure, paste the key in, and get to work. It takes five minutes and it works. The problem is what you end up with:

  • A permanent key that never expires unless you manually rotate it
  • That key in plain text in ~/.aws/credentials
  • Possibly committed to a git repo, copied into CI/CD pipelines, or living in .env files across your projects
  • If those credentials belong to root — unlimited, unrestricted access to everything in your account

One accidental git push, one leaked dotfile, one compromised laptop — and someone can run up thousands of dollars in crypto mining charges before you notice. This happens constantly. Search for it and you will find no shortage of horror stories.

Why root credentials are especially dangerous

The AWS root user is not just a very powerful IAM user. It exists outside the IAM system entirely. No policy can restrict it. No permission boundary applies to it. If someone gets root credentials they can close your account, remove MFA, and delete all your resources — and no IAM policy you write can stop them.

AWS itself says it clearly in their IAM best practices:

Safeguard your root user credentials and don't use them for everyday tasks.

The fix

Replace static credentials with temporary credentials that expire automatically. The modern AWS way to do this is IAM Identity Center — you log in via browser, get credentials that last a few hours, and nothing sensitive ever sits on disk permanently.


2. Concepts and Vocabulary

Before touching the console, make sure these terms are clear. AWS documentation uses them constantly and mixing them up is where most confusion starts.

AWS Account

The top-level container. Everything you create in AWS — EC2 instances, S3 buckets, Lambda functions — lives inside an account. An account is identified by a 12-digit ID like 089123123123. You can have multiple accounts (one for dev, one for prod, etc.).

Root User

The identity created when you first sign up for an AWS account. Identified by the email address you used. It has unlimited power and cannot be restricted. Use it only for the handful of tasks AWS requires root for (like closing the account). Lock it away with MFA and never create access keys for it.

IAM User

A permanent identity inside the IAM service. Has a username, password, and optionally access keys. IAM users made sense in 2010. Today they are discouraged for human access because they have long-lived credentials that are easy to mishandle. AWS's own documentation now recommends against them for most cases. See: IAM Users.

IAM Role

A temporary identity that can be assumed by a principal (a person, a service, an application). When you assume a role, AWS gives you short-lived credentials for that session. Roles are the foundation of secure AWS access — everything modern in AWS uses them.

IAM Policy

A JSON document that says what actions are allowed or denied on which resources. Policies are attached to roles (or users). They are the answer to: what can this identity actually do?

AWS Organizations

A service that groups multiple AWS accounts under one management structure. Even if you only have one account today, enabling Organizations is the right first step — it is free, it unlocks IAM Identity Center, and it prepares you for multi-account setups later. See: AWS Organizations.

IAM Identity Center

The modern central place to manage human access to AWS accounts. Formerly called AWS SSO (Single Sign-On). It manages users, groups, and permission sets. It issues temporary credentials on login. It is free. See: IAM Identity Center docs.

Permission Set

An IAM Identity Center concept. Think of it as a named role template — for example, AdministratorAccess or ReadOnly. You assign a permission set to a user on a specific account. IAM Identity Center creates the actual IAM role behind the scenes.

SSO Session

A named configuration in your local ~/.aws/config that points to your IAM Identity Center portal. When you run aws sso login, it uses this session to know where to authenticate you. You can have multiple sessions for different AWS organisations (personal, client A, client B, etc.).


3. Services Used

All these services are free. Placed in order of setup.

Service Purpose in this setup
AWS Organizations Groups accounts together. Required for IAM Identity Center organization instance.
AWS Identity and Access Management (IAM) Classic identity service. Still used underneath — Identity Center creates IAM roles behind the scenes.
AWS IAM Identity Center Manages SSO users, permission sets, and account assignments. Issues temporary credentials.
AWS Security Token Service (STS) Issues short-lived temporary credentials when you log in. You never interact with it directly.

4. Setting Up IAM Identity Center — Step by Step

You need to be logged into the AWS console as root for the first few steps. After setup, root goes back in the drawer permanently.

Step 1 — Secure root first

Root should have MFA and no access keys. Check now:

  1. In the console, top-right corner → your account name → Security credentials
  2. Under Multi-factor authentication — confirm MFA is enabled. If not, add it now. A hardware security key (FIDO2/U2F) is best. An authenticator app is fine.
  3. Under Access keys — if any key exists, deactivate and delete it. Root should never have an access key.

Step 2 — Enable billing access for IAM identities

By default, even an admin SSO user cannot see your billing console. Fix this now while you are still in root:

  1. Top-right → your account name → Security credentials
  2. Scroll to IAM user and role access to Billing informationEdit
  3. Check Activate IAM AccessUpdate

Step 3 — Enable AWS Organizations

  1. Search for AWS Organizations in the console search bar
  2. Click Create an organization → confirm

Your account becomes the management account. This is free and does not change how your account works. You will also see a banner offering to centralise root access for member accounts — click Enable in IAM. This lets you manage root credentials of any future member accounts centrally, which is a security best practice.

Step 4 — Enable IAM Identity Center

Important: Change your AWS region before clicking Enable. IAM Identity Center is regional and cannot be moved later without deleting it and starting over. Pick the region nearest to you or your team.

  1. Change region in the top-right dropdown — e.g. ap-northeast-1 for Tokyo
  2. Search for IAM Identity Center
  3. Click EnableEnable with AWS Organizations

You will see a success message with a new instance ID. Keep this page open.

Step 5 — Create your SSO admin user

This is the identity you will use for all daily work from now on. Not root. Not an IAM user.

  1. IAM Identity Center left menu → UsersAdd user
  2. Fill in: username (e.g. yourname-admin), email address, first and last name
  3. Click through to Add user
  4. Check your email for an invitation from no-reply@login.awsapps.com
  5. Click the invite link, set a password, and set up MFA on this user too

Step 6 — Create a Permission Set

  1. Left menu → Permission setsCreate permission set
  2. Choose Predefined permission set
  3. Select AdministratorAccess
  4. Keep the default name → Create

For a personal account, AdministratorAccess is fine — you are the only user. For team or client work you would later create scoped-down sets like TerraformDeploy or ReadOnly.

Step 7 — Assign the user to your account

  1. Left menu → AWS accounts
  2. Check the checkbox next to your account
  3. Click Assign users or groups
  4. Select your SSO user → Next
  5. Select AdministratorAccessNextSubmit

AWS provisions a real IAM role behind the scenes with a trust policy allowing your SSO user to assume it. You never manage that role directly.

Step 8 — Note your portal URL

Left menu → Dashboard. You will see your AWS access portal URL:

https://d-xxxxxxxxxx.awsapps.com/start

Save this. It is your login page from now on — not console.aws.amazon.com. You can customise it under Settings → Identity source.

Step 9 — Clean up old credentials

Delete the old access key from AWS first — deleting the local file is not enough, the key still works in AWS until you revoke it there.

  1. Console → top-right → Security credentials (while logged in as whichever IAM user owned the key)
  2. Scroll to Access keys → deactivate → Delete

Then clean up locally:

# Wipe the credentials file
> ~/.aws/credentials

# Also check for other places like:
# ~/.zshrc ~/.bashrc ~/.bash_profile ~/.zprofile
# *.tf, *.env, *.tfvars

Step 10 — Configure the AWS CLI with SSO

aws configure sso

Answer the prompts:

SSO session name (Recommended): personal
SSO start URL [None]: https://d-xxxxxxxxxx.awsapps.com/start
SSO region [None]: ap-northeast-1
SSO registration scopes [sso:account:access]: [press Enter]

# A browser opens — log in as your SSO user and authorise the CLI

Default client Region [None]: ap-northeast-1
CLI default output format [None]: json
CLI profile name [AdministratorAccess]: admin

Your ~/.aws/config now looks like this. No credentials file. No keys anywhere.

[profile admin]
sso_session = personal
sso_account_id = 123456789012
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json

[sso-session personal]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access

5. Verify Everything Works

Log in and confirm your identity:

aws sso login --sso-session personal

aws sts get-caller-identity --profile admin

You should see output like this:

{
    "UserId": "AROAXXXXXXXXXXXXXXXXX:yourname-admin",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_AdministratorAccess_xxx/yourname-admin"
}

Three things to confirm in that output:

  • UserId ends with your SSO username — not root, not an IAM user
  • Arn contains assumed-role — you are using a temporary role, not permanent credentials
  • Account is your correct account ID

When the session expires (typically after 8 hours), just run aws sso login --sso-session personal again. That is your entire credential management workflow now.

5.1. Bonus: Try with Terraform

Use it with Terraform by setting the profile:
export AWS_PROFILE=admin
terraform init
terraform plan

Or in your provider.tf:

provider "aws" {
  region  = "ap-northeast-1"
  profile = "admin"
}

6. Before and After

Before After
Identity Root user or IAM user SSO user (yourname-admin)
Credentials type Static — never expire Temporary — expire in hours
Stored where Plain text in ~/.aws/credentials Nowhere — fetched fresh on each login
Rotation Manual — easy to forget Automatic — always
If credentials leak Permanent access until manually revoked Expires on its own within hours
Multi-account ready No — separate credentials per account Yes — one login, all accounts
Terraform workflow Keys in file, just works (dangerously) aws sso login then terraform

7. What's Next

This setup is the foundation. From here the natural next topics are:

  • Multiple AWS accounts — separate accounts for dev, staging, prod under the same Organization. Same SSO login, different permission sets per account.
  • Scoped permission sets — instead of AdministratorAccess everywhere, create a TerraformDeploy set with only what Terraform actually needs. Use IAM Access Analyzer to discover what was actually used.
  • CI/CD with zero credentials — for GitHub Actions, use OIDC federation. No static keys in your pipeline either.
  • External identity provider — connect IAM Identity Center to Okta, Google Workspace, or Azure AD. Users log in with company credentials, AWS access follows automatically.
  • Service Control Policies — organisation-level guardrails. Even admins cannot exceed them. The right tool for enforcing region restrictions, mandatory tagging, or blocking risky services.
Hope it helped. See you later 🐊

0 comments:

This work is licensed under BSD Zero Clause License | nacho4d ®