AWS Unpacked #1: IAM

Categories: AWS

Keys to the Cloud Kingdom: Navigating IAM

Blog header image
TL;DR
IAM is your permissions HQ in AWS. It's how you control who can do what and where. From IAM users and groups to roles and temporary credentials via STS, IAM is the backbone of security and access in the cloud. Whether you're logging in via the Console, scripting with the CLI, or federating through IAM Identity Center, IAM ensures only the right people (or services) get the right access, and nothing more. Treat IAM like the adult in the room: cautious, deliberate, and full of rules for good reason.

In my last post, I said using the AWS Console felt like being a kid in a candy store - you’re surrounded by endless options, and it’s tempting to grab everything. But like any smart parent knows, just because the candy’s there doesn’t mean you should have free rein. That’s where IAM (Identity and Access Management) comes in. Think of it as the system of permission slips, locks, and supervision that keeps AWS accounts secure, organized, and in control.

Let’s break it down.

What Is IAM?

IAM is a global service that lets you manage who can do what in your AWS account. When you first open an AWS account, you get a root user - basically the parent with total, unrestricted access.

But just like a parent shouldn’t hand over the credit card and keys to the candy store, you should never use or share the root account for day-to-day work. Instead, you create IAM users, group them if needed, and assign permissions through policies.

Users, Groups, and Policies

  • Users: Individual identities in your AWS account.
  • Groups: Collections of users. Users can be in multiple groups - or none at all.
  • Policies: Documents that define what actions are allowed or denied on which resources.

The core rule here is the principle of least privilege: give just enough access to get the job done, nothing more.

Important: Groups can only contain users, not other groups. This isn’t like nesting folders.

IAM Policies

IAM policies are where you spell out exactly who can do what, where, and when in your AWS account. Think of them like a contract between AWS and the user, service, or role.

Here’s what a basic policy is made of:

  • Effect: Allow or Deny
  • Action: What the entity is allowed (or denied) to do, like s3:GetObject or ec2:StartInstances
  • Resource: Which AWS resources the action applies to, for example, the specific EC2 instance, referred to by its ARN.
  • Principal: Who the policy applies to (only required in resource-based policies) - this is either a user, role, or account ID - often used for cross-account access.

A policy can either be identity-based (attached to a user) or resource-based (attached to a resource, eg. an S3 bucket). IAM itself only supports identity-based policies. If you want to define permissions on a resource, like an S3 bucket, that’s done with a resource-based policy - typically defined in that service, not in IAM. Identity-based policies (attached to users/roles) don’t need a Principal—they already know who they’re attached to. Resource-based policies (like S3 bucket policies) must include a Principal.

Want to be extra careful? Use the Condition block to narrow access.

Example: A Real Policy With Conditions

Here’s a policy that lets a user start EC2 instances, but only in us-west-2 and only from a specific IP range:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:StartInstances",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-west-2"
        },
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}

This is where IAM gets powerful: you’re not just handing out keys—you’re setting boundaries on how, when, and where they can be used.

Securing Access: Passwords, MFA, and More

AWS gives you tools to lock things down properly:

  • Enforce password rules: length, complexity, expiration.
  • Enable MFA (multi-factor authentication):
    • Virtual (e.g., Google Authenticator)
    • U2F (YubiKey)
    • Hardware fob

Even better, you can track usage:

  • Credential Report: Overview of all users and their credential health.
  • Access Advisor: Shows what services a user actually accessed, and when.

Beyond the Console: CLI, SDK, and CloudShell

You don’t have to (and often shouldn’t) click around in the Console forever. You can:

  • Use the CLI with access keys.
  • Automate with SDKs (e.g., Python Boto3).
  • Jump into CloudShell, AWS’s browser-based terminal. It’s like opening a command line from within the Console itself.

Just note: long-term access keys should be avoided where possible. It’s better to assume roles using temporary credentials via STS, especially in production.

IAM Roles: Giving AWS Services Permissions

Need an EC2 instance to access an S3 bucket? Use an IAM role.

Roles let you assign temporary permissions to trusted entities (such as AWS services, users from other accounts or federated identities), no need to embed long-term credentials. Think of it like saying: “Hey EC2, you can act as this trusted user for a while.”

Scaling Access: AWS Organizations

Managing multiple AWS accounts? Use AWS Organizations:

  • Define a management account and link member accounts.
  • Get consolidated billing and shared savings plans.
  • Apply Service Control Policies (SCPs) to control what users and roles in accounts can or can’t do. It’s crucial to remember that SCPs only set maximum permissions. They do not grant any permissions themselves. If an SCP allows an action, but an identity-based policy denies it, the deny still wins. If an SCP denies an action, no identity-based policy can override it. SCPs apply to all users and roles in member accounts, including the root user of those accounts.
  • Send all CloudTrail logs to a centralized account for audit and security tracking.

AWS STS: Temporary Passes to the Candy Store

Sometimes, you don’t want to hand someone permanent access. You just want to say: “Here’s a permission slip, it works for 1 hour. Go do your thing, then it self-destructs.”

That’s what AWS Security Token Service (STS) does. STS issues temporary security credentials for:

  • Assuming IAM roles (e.g., when an EC2 instance takes on a role to access S3)

  • Federated access (e.g., your employee logs in via Google Workspace or Microsoft Entra ID and gets temporary AWS credentials)

  • Cross-account access (e.g., Account A lets a role from Account B access its S3 bucket)

These temporary credentials are:

  • Time-limited (from a few minutes to hours)
  • Scoped (only the permissions you need)
  • Safer (no long-lived access keys lying around)

In practice, AWS STS isn’t something you interact with directly in the Console like EC2 or S3. Instead, it quietly works behind the scenes whenever temporary credentials are needed. When a user logs in via IAM Identity Center, when an EC2 instance uses a role, or when you switch roles in the Console, STS is issuing short-term credentials under the hood. The only time you really see STS is when you call it directly via the CLI or SDK, like with sts:AssumeRole. That’s when you’re explicitly asking for temporary credentials to do something in AWS. So while you don’t “use” STS day-to-day, it’s working quietly in the background and every time IAM grants temporary access, STS is what actually issues the credentials.

Policy Evaluation Logic

Remember, by default, all requests are implicitly denied unless explicitly allowed. Here’s the comprehensive order and logic:

  1. Explicit Deny in any policy (SCP, identity-based, resource-based, permissions boundary, session policy): If any applicable policy contains an explicit deny, the request is denied immediately, regardless of any allow statements.
  2. AWS Organizations Service Control Policies (SCPs): If no explicit deny is present, AWS evaluates SCPs. SCPs define the maximum permissions that member accounts within an Organization can have. If an SCP doesn’t explicitly allow an action, it’s implicitly denied at the Organization level, overriding any potential allows in policies below.
  3. Resource-Based Policies and Identity-Based Policies: If not denied by an explicit deny or an SCP, AWS then evaluates a combination of resource-based policies (attached to the resource being accessed, e.g., S3 bucket policy) and identity-based policies (attached to the IAM user, group, or role initiating the request).
    • For the request to be allowed, both the identity-based policy AND the resource-based policy (if applicable to the resource) must contain an Allow statement.
    • If one is an Allow and the other is an implicit Deny (i.e., silent or no relevant statement), the request is denied.
  4. Permissions Boundaries: If a permissions boundary is attached to an IAM user or role, it sets the maximum permissions that identity can ever have. Even if an identity-based policy grants an action, if the permissions boundary doesn’t also allow it, the action is denied.
  5. Session Policies: These are temporary policies passed when assuming a role via sts:AssumeRole or similar actions. They further narrow down the permissions of the assumed role, acting as an additional filter on top of the role’s identity-based policies and any applicable permissions boundary.

Remember, by default, all requests are implicitly denied unless explicitly allowed. An explicit deny always overrides an allow.

IAM Identity Center: Centralized Access Management

Formerly known as AWS Single Sign-On (SSO), IAM Identity Center allows you to manage user access across multiple AWS accounts and applications from a single location. Key features include:

  • Use either the built-in identity store in IAM Identity Centre, or Integration with third-party Identity Providers: Connects with external identity providers like Microsoft Entra ID (formerly Azure AD), Okta, and Google Workspace.
  • Centralized Permission Management: Assign permissions based on job functions or custom needs across AWS accounts.
  • Single Sign-On (SSO): Provides users with one-click access to all their assigned accounts and applications.
  • Audit and Compliance: Simplifies auditing by providing a centralized view of user access.

A permission set is a reusable set of permissions (policies) that IAM Identity Center uses to grant users or groups access to one or more accounts. When a user picks an account and permission set from the Identity Center portal, they assume a temporary role with exactly those permissions. Behind the scenes, when a user picks a permission set for an account, IAM Identity Center creates a role in that account with the exact permissions of that permission set.

AWS Directory Services: Managed Active Directory in the Cloud

AWS Directory Service offers multiple ways to use Microsoft Active Directory (AD) with other AWS services:

  • AWS Managed Microsoft AD: A fully managed, cloud-native directory service that supports Active Directory-aware workloads. You can establish a “trusted” connection between your on-premise AD and the AWS Managed AD so that users can authenticate using either the on-premise or the AWS Managed ID. This is ideal if you already have your own on-premise Microsoft AD and want to enhance your service. It supports MFA.
  • AD Connector: A proxy that connects AWS services to your existing on-premises Microsoft AD without requiring directory synchronization. This is different from the Managed Microsoft AD in that it only acts as a proxy and all requests are redirected to the on-premise AD. It supports MFA.
  • Simple AD: A standalone, low-scale directory compatible with Microsoft AD. It cannot be joined with a on-premise AD.

Both AWS Managed Microsoft AD and AD Connector integrate seamlessly with IAM Identity Center, allowing you to use your existing AD users and groups to manage access to AWS accounts and applications.

AWS Control Tower: Simplifying Multi-Account Management

AWS Control Tower is a service that helps you set up and govern a secure, multi-account AWS environment based on AWS best practices - especially useful if you’re managing multiple AWS accounts in a business or enterprise.

Think of it as a pre-packaged solution that gives you a “landing zone”: a ready-made, multi-account structure with guardrails, logging, security baselines, and automation all baked in.

When you use Control Tower, it automatically creates:

  • An AWS Organization (if you don’t already have one)
  • An audit account for centralized logging and security
  • A log archive account for storing CloudTrail and config logs
  • A management account to oversee everything
  • And a VPC setup in each account (optional)

It gives you an Account Factory, which is a self-service tool for creating new AWS accounts pre-configured with your guardrails and policies.

You can also enforce guardrails, which are a mix of:

  • Preventive controls (SCPs that block certain actions)
  • Detective controls (like AWS Config rules that alert you to drift)

Control Tower is ideal for organizations that need to scale quickly but stay compliant, because it saves you from manually wiring up Organizations, SCPs, logging, security, and account provisioning. In summary, Control Tower is the “easy button” for setting up a secure, scalable AWS environment with multiple accounts — without having to glue it all together yourself. Control Tower leverages and integrates other AWS services like AWS Organizations, IAM Identity Center, AWS Config, AWS CloudTrail, and Amazon S3 for logging and governance. It provides a unified dashboard for monitoring compliance and account activity.

IAM Best Practices

  • Avoid using the root account. Enable MFA and lock it down.
  • Use roles instead of long-term credentials wherever possible.
  • Apply the principle of least privilege to every user, group, and service.
  • Rotate access keys regularly, and monitor usage.
  • Use IAM Identity Center for SSO across accounts.
  • Tag IAM resources for audit and access control.
  • Use Conditions in policies to restrict by IP, region, etc.

About the Author

Dawie Loots is a data scientist with a keen interest in using technology to solve real-world problems. He combines data science expertise with his background as a Chartered Accountant and executive leader to help organizations build scalable, value-driven solutions.

Back to Blog