Logo
CloudWithSingh
Back to all posts
AWS
Security
Azure

AWS IAM for Azure Admins: What Confused Me and What Finally Clicked

A practical breakdown of AWS IAM from someone who thinks in Azure RBAC — policies, roles, principals, and the mental model shifts that actually matter.

Parveen Singh
October 10, 2025
9 min read
TLDR

AWS IAM is fundamentally different from Azure RBAC — it's policy-based rather than role-based. AWS "roles" are identities (like Azure managed identities), not permission sets. Learn the JSON policy format, use IAM Identity Center for humans, use roles for services, and stop creating IAM users with access keys.

If you come from Azure, you think about identity in a very specific way. There's Entra ID at the top. Users and groups live there. You assign RBAC roles at various scopes — management group, subscription, resource group, resource. It's hierarchical, it's clean, and after a while it becomes second nature.

Then you open AWS IAM and everything you thought you knew about cloud identity gets challenged.

When I went deep on AWS IAM — beyond the surface-level understanding from my Cloud Practitioner days — I was genuinely thrown off. Not because it's harder than Azure RBAC — it's different. And "different" when you have years of muscle memory in another platform is more disorienting than "hard."

Here's what tripped me up, what eventually clicked, and the mental model I wish someone had laid out clearly from the start.

The Fundamental Difference Nobody Explains Well

In Azure, the model is: "Give this identity this role at this scope."

In AWS, the model is: "Attach this policy document that specifies what actions are allowed on what resources."

Azure is declarative and role-based. AWS is explicit and action-based.

Let me show you what I mean:

Azure RBAC:

Assign "Storage Blob Data Reader" role to user@company.com at resource group scope

AWS IAM:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

Both achieve the same thing, but the AWS version forces you to think about exactly which actions you're granting. There's no pre-built "reader" role that bundles 20 permissions together. You specify each action explicitly.

Initially, I wasn't a fan. It felt verbose and error-prone. But the more I worked with it, the more I started to appreciate it. You know exactly what a policy grants. No surprises hiding behind a friendly role name.

Users, Groups, Roles — Same Words, Different Meanings

This is where my Azure brain really struggled:

ConceptAzureAWSThe Confusion
UserLives in Entra ID tenantLives in AWS accountSimilar enough
GroupEntra ID group, assign RBAC rolesIAM group, attach policiesSimilar enough
RolePre-defined set of permissions (RBAC role)An identity that can be assumedCompletely different

That last row is the one that broke my brain.

In Azure, a "role" is a collection of permissions (like "Contributor" or "Reader"). In AWS, a "role" is an identity — something that EC2 instances, Lambda functions, or even other AWS accounts can "become" temporarily.

AWS roles are closer to Azure's managed identities than to Azure's RBAC roles. An EC2 instance assumes a role to get permissions, just like an Azure VM uses a managed identity to access Key Vault.

Once that clicked, everything else started making sense.

Gotcha

AWS IAM "roles" are identities that can be assumed — not permission sets like Azure RBAC roles. An EC2 instance assumes a role, just like an Azure VM uses a managed identity. Don't confuse AWS roles with Azure roles — they're completely different concepts sharing the same name.

The Policy Evaluation Logic That Tripped Me Up

AWS IAM has an evaluation logic that feels simple in theory but creates real confusion in practice:

  1. By default, everything is denied (implicit deny)
  2. Explicit allows in attached policies grant access
  3. Explicit denies always win, no matter what

Sounds straightforward, right? Until you hit these scenarios:

Scenario 1: Identity-based vs Resource-based policies

In Azure, you mainly deal with RBAC assignments on the identity side. AWS has two places permissions can live:

  • Identity-based policies: Attached to the user/group/role ("What can this identity do?")
  • Resource-based policies: Attached to the resource itself ("Who can access this resource?")

S3 bucket policies are resource-based. So an S3 bucket can say "Allow account 123456789 to read from me" — and it works even if the user's identity-based policy doesn't mention S3 at all.

This two-side permission model doesn't really exist in Azure the same way. It's powerful but it means you need to check both sides when troubleshooting access issues.

Scenario 2: Service Control Policies (SCPs)

If you're using AWS Organizations (multi-account setup), SCPs layer on top of everything. They're like guardrails — they don't grant access, they restrict what's possible in child accounts.

The Azure equivalent would be Azure Policy deny effects combined with management group-scoped restrictions. Similar intent, different execution.

The Mistakes I Made (So You Don't Have To)

Mistake 1: Using the root user for everything

In Azure, the first Global Admin account is essentially the root. In AWS, the root user is the equivalent — but AWS is much more aggressive about telling you to stop using it.

Set up IAM Identity Center (formerly AWS SSO) immediately. Create admin users through there. Enable MFA on root. Then lock root away and forget about it.

Mistake 2: Creating IAM users for applications

In Azure, managed identities handle service-to-service authentication. In AWS, the equivalent is IAM roles with trust policies.

My instinct was to create an IAM user, generate access keys, and pass them to my application. Don't do this. Create an IAM role, define what it can do, and let your EC2/Lambda/ECS assume that role. No credentials to manage, no keys to rotate.

Mistake 3: Overly broad policies to "make it work"

We've all done "Action": "*", "Resource": "*" to unblock ourselves during testing. In AWS, this is particularly dangerous because there's no easy equivalent to Azure's "just make them a Contributor on this resource group" that limits the blast radius.

Warning

Never use "Action": "*", "Resource": "*" to unblock yourself, even in dev. In AWS there's no resource group boundary limiting the blast radius like in Azure. An overly broad policy gives access to your entire account — billing, IAM, everything.

My workflow now: Start with exactly the permissions you need. Use the IAM Policy Simulator to test. Use CloudTrail to see what API calls your application actually makes. Then write a policy that matches reality rather than guessing.

The Translation Guide I Built for Myself

After spending real time working with IAM, I made this reference card:

What You Want to DoAzure ApproachAWS Approach
Give a user read access to storageAssign "Storage Blob Data Reader" roleAttach policy with s3:GetObject action
Let a VM access a databaseManaged Identity + RBACInstance Profile + IAM Role
Restrict what a team can doAzure Policy + RBACSCPs + IAM Policies
Give temporary access to a partnerEntra ID Guest + RBACCross-account role assumption
Centralise identity managementEntra ID tenantIAM Identity Center
Require MFA for admin actionsConditional AccessIAM policy condition aws:MultiFactorAuthPresent
Audit who did whatActivity Log + Entra ID Sign-in LogsCloudTrail

What AWS IAM Gets Right

Credit where it's due:

  • Policy Simulator — You can test IAM policies before deploying them. Azure doesn't have an equivalent that's as easy to use.
  • Access Analyzer — Finds resources shared with external accounts. Brilliant tool.
Pro Tip

Enable IAM Access Analyzer immediately in every AWS account. It continuously monitors for resources shared with external accounts — catching misconfigurations that could expose your S3 buckets or IAM roles to the internet.

  • Last Accessed information — Shows which permissions in a policy were actually used. Makes it easy to tighten policies over time.
  • Policy versioning — Customer managed policies support versioning. You can roll back a bad policy change.

What Azure Does Better

  • Pre-built roles — Having curated roles like "Storage Blob Data Reader" is legitimately more productive than writing JSON policies for common patterns.
  • Entra ID as a full IdP — Conditional Access, PIM (Privileged Identity Management), Identity Protection — Azure treats identity as a whole platform, not just a permissions system.
  • Scope hierarchy — Management group → subscription → resource group → resource. The cascade is elegant and intuitive.

My Recommendation for Azure Admins Learning AWS IAM

  1. Don't try to map everything 1:1. Some things translate cleanly. Others don't. Accept that.
  2. Start with IAM Identity Center, not IAM users. This is the modern way to manage human identities in AWS.
  3. Learn the policy JSON format. You don't need to memorize every action, but you need to be comfortable reading and editing policy documents.
  4. Use roles for everything. If something needs permissions to access an AWS resource, it should assume a role. Creating IAM users with access keys is legacy behaviour.
  5. Practice in a safe environment. Misconfigurations in IAM can expose your entire AWS account. Use CloudLearn's IAM labs to experiment with policies, roles, and cross-account access without risk.

The best thing I did was stop trying to force Azure patterns onto AWS. AWS IAM is different from Azure RBAC, but once you stop expecting it to behave like Azure, it starts making a lot of sense.

Resource

Next: The $73 Free Tier Bill

What happens when an Azure engineer hits unexpected AWS charges — and how to prevent it.

Read Next

Part 2 of my "Azure to AWS" series. Previously: Getting Started with AWS. Next up: what happened when the free tier surprised me with a bill I didn't expect.

Read Next