Reading30 min read·Module 1High exam weight

IAM Best Practices & Least Privilege

Key concepts

  • Principle of least privilege

  • Use roles instead of long-term credentials

  • Enable MFA for privileged users

  • Rotate credentials regularly

  • Use IAM Access Analyzer

The Auditor's Report

Three weeks into her engagement, Priya sends Dana a short audit report from her own AWS account, signed in through the cross-account role Trailbase set up for her. It contains two findings, and neither one has caused an incident. Yet.

Finding one: a policy named TempS3Fix, attached to the Developers group, grants s3:* on every resource in the account. Someone created it during a late-night debugging session back in the shared-root days, promised to tighten it later, and forgot. Finding two: an active access key belonging to the user jordan-contractor, unused for 241 days. Jordan built the trail-map importer last year, finished the project, and left. His key still opens the account from anywhere on the internet.

Dana reads the report twice, then opens a new document titled Trailbase Security Charter. Every rule in it is a scar with a name attached: root lockdown from the Theo incident, policy discipline from Priya's finding one, credential hygiene from finding two. This lesson walks through that charter, because the SAA-C03 exam is essentially asking you to write the same document for a fictional company in every security question.

The organizing idea behind the whole charter is least privilege: every identity should hold exactly the permissions its job requires, and nothing more. You met the principle in lesson 1. This lesson is about practicing it, because least privilege is a continuous process of granting, measuring, and trimming access rather than a checkbox you tick once.

Core Principle

Least Privilege = Minimum Permissions Required. Start with zero permissions and add only what is needed. When in doubt, deny access and wait for a specific request before granting anything.

Exam Tip

SAA-C03 loves the phrases MOST secure and follows best practices. When you see them, the answer almost always combines least privilege, temporary credentials, and the elimination of long-term access keys. Options that grant broad access for convenience are the distractors.

The charter organizes its rules in layers, from the root account at the top down to individual resources. Keep this map in view as we work through each rule:

IAM Security Layers
Figure 1: IAM Best Practices Security Layers - From account root to individual resources

Rule One: Treat Least Privilege as a Process

Why does TempS3Fix matter if nothing bad ever happened through it? Because permissions define your blast radius: the total damage one compromised credential can do. With s3:* on every bucket, a single phished developer password could read every hiker photo, delete every backup, and rewrite every static asset Trailbase serves. Least privilege shrinks that radius until a stolen credential is an annoyance instead of a catastrophe.

There are quieter benefits too. Narrow permissions make audits readable, because Priya can look at a policy and know what a person can actually do. They satisfy compliance frameworks such as SOC 2, HIPAA, and PCI-DSS, which all demand demonstrable access control. And they create accountability, because every grant has an owner and a reason.

Least Privilege

Least privilege means granting only the minimum permissions required to perform a task. This principle:

  • Reduces blast radius - If credentials are compromised, damage is limited
  • Simplifies auditing - Easier to understand who can do what
  • Improves compliance - Meets regulatory requirements (SOC 2, HIPAA, PCI-DSS)
  • Enables accountability - Clear ownership of permissions

Implementation Strategy:

  1. Start with an empty policy (deny all)
  2. Add permissions as needed based on actual requirements
  3. Use IAM Access Analyzer to identify unused permissions
  4. Regularly review and remove unnecessary access

The direction of travel is the part people get wrong. Trailbase used to start from everything and promise to subtract later, which is how TempS3Fix survived for a year. The charter reverses the arrow: start from nothing, and make every addition answer to a real requirement. Remember from lesson 1 that a new IAM user begins with zero permissions anyway; the charter simply insists on keeping that spirit as access grows.

Q

What is the FIRST step in implementing least privilege?

AGrant all permissions and remove as needed
BStart with AWS managed policies with broad access
CStart with zero permissions and add only what is needed
DCopy permissions from a similar existing role

Rule Two: Prefer Credentials That Expire

Jordan's stale access key is the second scar. An access key is a long-term credential: it works forever until a human remembers to rotate or delete it, and humans forget. For 241 days, anyone who found that key in an old laptop backup or a leaked config file could have acted as Jordan. The fix for this class of problem is structural. Use credentials that destroy themselves.

Temporary credentials are short-lived keys issued by AWS STS, the Security Token Service that powers every role assumption you saw in lesson 1. They expire automatically after a configurable window of 15 minutes to 12 hours, AWS rotates them without anyone lifting a finger, and there is nothing durable to embed in code. The Trailbase EC2 fleet already lives this way: the app servers upload hiker photos to trailbase-photos through an instance role, and no server has ever held a permanent key.

Credential Types

AWS supports two types of credentials:

Temporary Credentials (Preferred):

  • Automatically expire after a set time (15 minutes to 12 hours)
  • Automatically rotated by AWS
  • Cannot be embedded in code
  • Provided via IAM roles and STS

Long-Term Credentials (Avoid When Possible):

  • Access keys that never expire unless rotated manually
  • Passwords for console access
  • Must be manually rotated and managed
  • Higher risk if compromised

Credential Comparison

AspectTemporary CredentialsLong-Term Credentials
ExpirationAutomatic (configurable)Never (manual rotation)
RotationAutomatic by AWSManual process required
Storage RiskNever storedCan be leaked in code/logs
Use CaseAWS workloads, federationExternal systems, CLI users
Security LevelHighLower
RecommendedYes - preferred approachOnly when necessary

Dana deletes Jordan's key the same afternoon, and the charter gains a rule: long-term credentials exist only where nothing temporary can work, and each one carries an expiry review date.

Q

Which credential type should be used for an application running on EC2?

AIAM user access keys stored in environment variables
BIAM user access keys stored in the application code
CIAM role attached to the EC2 instance
DRoot account credentials

Rule Three: Let Evidence Write Your Policies

Here is the awkward question Priya's report raises: how does Mara shrink TempS3Fix without breaking the data pipeline that depends on it? Fear of breakage is the reason broad policies survive. Nobody knows exactly which actions are in use, so nobody dares remove any.

IAM Access Analyzer removes the guesswork. It reads the account's CloudTrail history (CloudTrail is the AWS service that records every API call made in the account) and reports which actions an identity actually performed, then generates a policy containing exactly those actions. Mara stops estimating what the pipeline needs and starts measuring it.

IAM Access Analyzer

IAM Access Analyzer is a powerful tool for implementing least privilege. It provides:

Policy Generation:

  • Analyzes CloudTrail logs to see what actions were actually used
  • Generates least-privilege policies based on real access patterns
  • Eliminates guesswork in policy creation

Access Analysis:

  • Identifies resources shared with external entities
  • Detects public access to S3 buckets, KMS keys, etc.
  • Continuous monitoring for permission changes

Policy Validation:

  • Validates policy grammar and syntax
  • Checks against 100+ security best practices
  • Provides actionable recommendations
Least Privilege Implementation Workflow
Figure 2: Step-by-step workflow for implementing least privilege permissions

Step 1: The Broad Starting Point

This is what TempS3Fix looks like today. Broad grants like this are acceptable only as a short-lived scaffold while you gather usage data, and even then only in non-production accounts:

JSONStarting Point - AWS Managed Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": "*"
    }
  ]
}

Step 2: Analyze and Reduce

After two weeks of CloudTrail data, Access Analyzer shows the pipeline uses exactly three S3 actions against one bucket. The refined policy names them, pins the ARNs (remember from lesson 1 that the bucket and the objects inside it are separate resources), and locks the whole thing to one region:

JSONRefined Least-Privilege Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSpecificS3Actions",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-app-bucket",
        "arn:aws:s3:::my-app-bucket/*"
      ],
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    }
  ]
}

Step 3: Add Conditions for Extra Security

A condition narrows the circumstances under which a statement applies at all, and conditions cost nothing to add. The charter treats them as free insurance:

Common IAM Conditions

Condition KeyUse CaseExample
aws:SourceIpRestrict to corporate IP rangeOnly allow from 10.0.0.0/8
aws:RequestedRegionLimit to specific regionsOnly allow us-east-1, us-west-2
aws:PrincipalTagAttribute-based access controlAllow if department=engineering
aws:MultiFactorAuthPresentRequire MFA for sensitive actionsOnly allow if MFA authenticated
aws:SecureTransportRequire HTTPSDeny if request not over TLS
s3:x-amz-aclPrevent public objectsDeny if ACL is public-read

Conditions stack. The statement below applies only when the caller has MFA, uses TLS, and comes from the office network, all at once:

JSONPolicy with Multiple Conditions
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "SecureS3Access",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::sensitive-data/*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true",
          "aws:SecureTransport": "true"
        },
        "IpAddress": {
          "aws:SourceIp": "10.0.0.0/8"
        }
      }
    }
  ]
}
Q

Which AWS service helps generate least-privilege policies based on actual usage?

AAWS Config
BIAM Access Analyzer
CAWS CloudTrail
DAWS Trusted Advisor

The Rest of the Charter

Humans Sign In Through Federation

Trailbase is hiring, and Dana has no appetite for creating and offboarding an IAM user per person forever. Federation means letting a trusted external identity provider vouch for who someone is, so AWS never stores their password at all. IAM Identity Center (formerly AWS SSO) is the AWS service that manages this for a workforce.

Human User Access

Do: Use IAM Identity Center (formerly AWS SSO) for human users

  • Centralized access across multiple AWS accounts
  • Integrates with corporate identity providers (Okta, Azure AD, etc.)
  • Provides temporary credentials automatically

Avoid: Creating individual IAM users for each person

  • Hard to manage at scale
  • Long-term credentials increase risk
  • No centralized visibility

Workloads Wear Roles

The EC2 photo-upload fleet set the pattern, and the charter extends it to every workload. Compute inside AWS gets a role attached directly; workloads outside AWS federate in instead of carrying exported keys.

Workload Access

For AWS Compute (EC2, Lambda, ECS):

  • Attach IAM roles directly to compute resources
  • AWS delivers temporary credentials automatically
  • Credentials rotate automatically every few hours

For External Workloads:

  • Use IAM Roles Anywhere with X.509 certificates
  • Use OIDC federation for Kubernetes workloads
  • Use SAML federation for enterprise applications

MFA Guards the Privileged Paths

The first thing Dana ever did after the Theo incident was lock a hardware MFA device onto root. Multi-factor authentication requires a second proof of identity beyond the password, so a stolen credential alone opens nothing. The charter scales the requirement to the sensitivity of the identity:

MFA Implementation

User TypeMFA RequirementImplementation
Root AccountRequired - Highest PriorityHardware MFA device or passkey
Admin UsersRequired for console and APIVirtual MFA or passkey
Power UsersRequired for sensitive operationsConditional MFA policy
Read-Only UsersRecommendedVirtual MFA app

You can enforce MFA in policy itself. This pattern allows everything only when MFA is present, while leaving a small unauthenticated path so users can see and manage their own MFA devices:

JSONRequire MFA for Sensitive Actions
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAllActionsWithMFA",
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    },
    {
      "Sid": "AllowBasicActionsWithoutMFA",
      "Effect": "Allow",
      "Action": [
        "iam:GetAccountPasswordPolicy",
        "iam:ListMFADevices"
      ],
      "Resource": "*"
    }
  ]
}

Access Is Reviewed on a Calendar

Jordan's key survived 241 days because review was nobody's job. Permissions drift is silent: people change teams, projects end, and grants outlive their reasons. The charter makes review a scheduled event instead of a hope.

Continuous Improvement

Review Frequency:

  • Quarterly: Review all IAM users, roles, and policies
  • After org changes: Review when employees join, leave, or change roles
  • Continuously: Monitor IAM Access Analyzer findings

What to Review:

  • Last accessed information for users and roles
  • Unused permissions that can be removed
  • External access to resources
  • Credential age and rotation status

Boundaries Make Delegation Safe

Theo, older and wiser, now builds Lambda functions and needs to create IAM roles for them. Handing an intern iam:CreateRole sounds like the setup for a sequel, because anyone who can create roles can, in principle, create an admin role and assume it. That move is called privilege escalation: using the permissions you have to grant yourself permissions you were never given.

A permissions boundary closes the loophole. It is a managed policy attached to a user or role that sets the ceiling on what their identity-based policies can ever grant. The effective permissions are the intersection of the identity policy AND the boundary, and the boundary itself grants nothing on its own. Theo can create any role he likes for his functions, but with a boundary applied, none of those roles can touch IAM or Organizations.

Permissions Boundaries

Permissions boundaries set the maximum permissions that identity-based policies can grant. They act as a "ceiling" on permissions.

Use Cases:

  • Allow developers to create IAM roles without granting admin access
  • Delegate IAM administration safely
  • Prevent privilege escalation

Key Point: A permissions boundary only limits permissions; it grants none by itself. The effective permissions are the intersection of the identity policy AND the boundary.

JSONPermissions Boundary Example
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowedServices",
      "Effect": "Allow",
      "Action": [
        "s3:*",
        "dynamodb:*",
        "lambda:*",
        "logs:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyIAMChanges",
      "Effect": "Deny",
      "Action": [
        "iam:*",
        "organizations:*"
      ],
      "Resource": "*"
    }
  ]
}
Q

A company wants to allow developers to create IAM roles but prevent them from creating admin-level roles. What should they use?

AService Control Policies
BIAM Groups
CPermissions Boundaries
DResource-based policies

How the Exam Asks About This

Every one of these charter rules maps onto a recurring SAA-C03 scenario shape. The question describes some company in Trailbase's old situation, and the right answer is the charter rule that fixes it:

Exam Tip

Best-practice questions usually offer one answer with temporary credentials and narrow scope, and three answers that trade security for convenience: embedded keys, wildcard policies, or shared users. Find the option Dana would put in the charter and you have found the answer.

Exam Scenarios and Solutions

ScenarioBest Practice SolutionWhy
Company wants to grant AWS access to employees using corporate credentialsUse IAM Identity Center with SAML federationCentralized management, temporary credentials, no IAM users needed
Application on EC2 needs to access multiple AWS servicesCreate IAM role with specific permissions, attach to EC2Temporary credentials, automatic rotation, no access keys
Developer needs to create IAM roles for Lambda functionsGrant iam:CreateRole with permissions boundaryAllows delegation while preventing privilege escalation
Audit reveals unused permissions in IAM policiesUse IAM Access Analyzer to generate least-privilege policiesReduces attack surface, improves compliance
External vendor needs temporary access to S3 bucketCreate cross-account role with time-limited trust policyTemporary access, auditable, can be revoked instantly
Prevent any IAM user from accessing production without MFAAdd MFA condition to all production resource policiesDefense in depth, protects sensitive resources

Common Pitfalls

Starting with Broad Permissions

Policies with Action star or Resource star written to "get things working" rarely get restricted later; they become technical debt with a blast radius, exactly like TempS3Fix. Start with zero permissions, add specific actions and resources as real requirements appear, and let IAM Access Analyzer show you the exact set in use.

Skipping Conditions

Conditions are free additional security, and leaving them off wastes it. A source IP check, an MFA requirement, or a secure-transport clause can each shut down an entire class of attack. Review the AWS global condition keys whenever you write a policy, and add the ones that apply even when they feel redundant.

Ignoring Resource-Level Permissions

Many actions support specific resource ARNs, and using Resource star anyway grants access to every resource of that type in the account. Check the documentation for resource-level support, pin exact ARNs, and reserve wildcards for the one path segment that genuinely varies, such as arn:aws:s3:::bucket/*.

Setting Permissions Once and Walking Away

Permissions accumulate while jobs change, which is how a departed contractor keeps a working key for 241 days. Schedule quarterly reviews, use last accessed information to find stale grants, and revoke access the day it stops being needed rather than the quarter after.


Quick Reference

Best Practices Quick Reference

PracticePriorityImplementation
Use federation for humansCriticalIAM Identity Center + IdP integration
Use roles for workloadsCriticalAttach roles to EC2, Lambda, ECS
Require MFACriticalEnable for all console users
Apply least privilegeCriticalStart with zero, add as needed
Use conditionsHighIP, MFA, region, secure transport
Regular access reviewsHighQuarterly + after org changes
Remove unused accessHighUse last accessed information
Use permissions boundariesMediumFor delegated IAM administration
TEXTFrequently Used Condition Keys
aws:SourceIp              - Restrict by IP address/range
aws:MultiFactorAuthPresent - Require MFA
aws:SecureTransport       - Require HTTPS
aws:RequestedRegion       - Limit to specific regions
aws:PrincipalTag/*        - Attribute-based access control
aws:CurrentTime           - Time-based restrictions
aws:TokenIssueTime        - Credential age checks


Further Reading

Related services

IAMAccess AnalyzerConfig