Skip to content
CAMPUX Cloud Bootcamp
Field notes · Translation guide · Identity & access
Cloud · Identity & access

Entra ID + Azure RBAC vs AWS IAM vs GCP Cloud IAM

By Captain O9 min read

The identity layer is the biggest lie the cheat sheets tell. They put "IAM" in one row across all three clouds. Underneath that word are three genuinely different machines.

New to cloud? CAMPUX is a free, build-first course. Start here →

All three clouds answer the same question — who can do what to which resource — but they wire it differently. Azure splits the job in two: Microsoft Entra ID is the directory that holds identities and does sign-in, and Azure RBAC is a separate system that assigns a role at a scope. AWS IAM fuses both jobs into one service and hands you JSON policy documents. GCP Cloud IAM binds a role to a member directly on a resource. Same idea, three architectures — this is the row you cannot skim.

Every "Azure vs AWS" table on the internet writes IAM once and moves on. It's the single most misleading cell in the whole grid, because the word papers over a real difference in shape. Someone comes from AWS, opens the Azure portal looking for the one place that holds both the users and their permissions, and can't find it — because Azure keeps those in two different places on purpose. Let's take the machine apart.

Two words worth pinning down first

Every one of these systems is doing two separate things, and the whole comparison gets easier once you name them. Authentication is proving who you are — signing in, MFA, the login. Authorization is deciding what you're allowed to do once you're in. Hold that split in your head, because the clouds disagree mainly on whether those two jobs live in one system or two.

Azure: a directory and an authorization system, kept apart

Azure is the one that surprises everyone, so start here. Azure deliberately separates the two jobs into two products.

Microsoft Entra ID is the directory. It stores your users, groups, and service principals; it does authentication — sign-in, MFA, Conditional Access. It lives at the tenant level, above your subscriptions, and it's the same directory your company's Microsoft 365 already uses. Entra knows who you are. It does not, by itself, decide what you can touch in Azure.

Azure RBAC is the authorization system, and it's separate. You take an identity from Entra, pick a role — Owner, Contributor, Reader, or a custom one — and assign it at a scope: a management group, a subscription, a resource group, or a single resource. That assignment inherits downward: a role at the subscription applies to every resource group and resource beneath it. So the mental model is three moving parts — who (Entra identity), what role, and where (scope) — snapped together into a role assignment.

That's why AWS folks get lost: they expect one place. On Azure you look in Entra for the user and in RBAC (on the resource's Access control blade) for the access. Two blades, two systems.

AWS: one service, JSON policies, no separate directory

AWS IAM does both jobs in a single service, scoped to one account. Your principals are IAM users, groups, and roles, and they live inside the account — there's no tenant-wide directory sitting above it the way Entra sits above subscriptions. (Real organizations don't hand out per-account IAM users to humans; they federate people in through IAM Identity Center, the service formerly called AWS SSO. But the primitive is still the in-account principal.)

Authorization on AWS is a JSON policy document. You write, or attach, statements that allow or deny specific actions on specific resources, and you hang that policy on a principal (identity-based) or on the resource itself (resource-based — an S3 bucket policy is the classic example). Evaluation is union-of-allows with explicit-deny-wins: if any attached policy denies an action, it's denied, full stop, regardless of what else allows it. Coming from Azure, the shock is how much you're reading and writing raw JSON instead of picking a named role.

GCP: bind a role to a member, on a resource

GCP Cloud IAM lands between the two. You take a member — a user, a group, or a service account — and you bind a role to it on a resource. Roles come in three flavors: primitive (the old broad Owner/Editor/Viewer), predefined (fine-grained, per-service), and custom. Bindings inherit down the resource tree: a role bound at the organization, a folder, or a project flows to everything beneath it, much like Azure's scope inheritance.

Human identity on GCP comes from Cloud Identity or Google Workspace. And the thing that defines GCP culture: service accounts are everywhere. Almost every workload identity — a VM, a Cloud Run service, a pipeline — is a service account, and a huge share of your IAM bindings are to service accounts rather than people.

The identity layer, three architectures — as of 2026
TraitAzureAWSGCP
Directory (who you are)Microsoft Entra ID (separate product)Inside IAM / IAM Identity CenterCloud Identity / Workspace
Authorization (what you may do)Azure RBAC (separate system)IAM, same serviceCloud IAM, same service
Auth & authz split?Two systems, on purposeOne serviceOne service
How you grant accessAssign a named role at a scopeAttach a JSON policy documentBind a role to a member on a resource
Attach the grant toIdentity, at a scopePrincipal (identity) or resourceMember, on a resource
InheritanceDown the scope tree (mgmt group → resource)None inside an account (SCPs cap across accounts)Down the resource tree (org → resource)
Non-human identityManaged identity / service principalIAM role (assumed)Service account
IAM in three architectures: Azure splits identity (Entra ID) from authorization (Azure RBAC) into two boxes; AWS keeps users and JSON policies in one IAM box; GCP binds a role to a member on the resource itself.AZUREAWSGCPEntra IDdirectory: users,groups, sign-inAzure RBACrole @ scopetwo systems,two places to lookIAMusers / rolesJSON policydocumentsall in one;you write JSONmembersvc acctResource(role bound here)bind rolerole boundON the resource
Figure — Same three letters, three shapes. Azure is two boxes — Entra ID for who you are, Azure RBAC for what you may do — so you look in two places. AWS keeps identities and their JSON policy documents in one IAM box. GCP binds a role to a member (often a service account) directly on the resource.

Azure hands you a named role and a scope. AWS hands you a JSON document. GCP hands you a binding on a resource. Read "IAM" as a synonym and you'll spend a day looking for a place that doesn't exist.

The one row that's genuinely the same: machine identity

For workloads — the app that needs to read a database without a human logging in — the three clouds land in almost the same spot, just with different names. An Azure managed identity or service principal plays the same part as an AWS IAM role that a workload assumes, which plays the same part as a GCP service account. In all three, you're giving a piece of software its own identity and granting that access, so you never bake a password or key into code. If you learn this pattern once, it reads straight across. It's the human side of identity where the clouds diverge.

The leak, stated plainly

"IAM" is three letters over three architectures. Don't carry assumptions across the word. First: Azure's directory-vs-authorization split means you look in two places — Entra for the user, RBAC for the access — while AWS people expect it all under "IAM." Second: AWS makes you read and write JSON policy documents; Azure gives you named role assignments at a scope (less JSON, more scope-thinking); GCP binds roles on resources. Third: inheritance differs — Azure flows down management-group→resource, GCP down org→project, and AWS has no inheritance tree inside an account (a Service Control Policy at the org is the closest, and it caps rather than grants).

The concrete test: "read-only on the prod database"

Abstract mappings blur together, so here's the same real task on all three. You want to give a teammate read-only access to the production database, and nothing else.

Same intent, three motions: assign-a-role-at-a-scope, write-a-policy-document, bind-a-role-on-a-resource. Notice the Azure and GCP versions are a couple of clicks and a role name; the AWS version is the one where you're most likely to over-grant by accident, because you're hand-listing actions.

If you're learning this cold, do it on Azure first. The Entra-versus-RBAC split forces you to see authentication and authorization as two different jobs, laid out as two different screens. Once that's concrete, AWS collapsing them into one service and GCP binding roles on resources both make sense fast — you already know what the two jobs are. That's the order we teach it, starting from what the cloud even is and building up through Entra and subscriptions, then RBAC and Azure Policy, then service principals and managed identity.

Common questions

Is Azure RBAC the same as AWS IAM?

They answer the same question — who can do what to which resource — but they're wired differently. Azure splits the job in two: Microsoft Entra ID is the directory that stores users, groups, and service principals and handles sign-in, while Azure RBAC is a separate system that assigns a role to an identity at a scope. AWS IAM does both jobs in one service, per account, and expects you to write authorization as JSON policy documents attached to principals or resources. So the concept maps but the plumbing does not: on Azure you look in two places, on AWS in one.

Where do users actually live in Azure versus AWS versus GCP?

On Azure, humans live in Microsoft Entra ID, the tenant-wide directory shared across all your subscriptions, and it also does MFA and Conditional Access. On AWS, classic IAM users live inside a single account, but real organizations federate humans through IAM Identity Center (formerly AWS SSO) rather than creating per-account users. On GCP, identities come from Cloud Identity or Google Workspace, and almost every workload runs as a service account. The short version: Azure and GCP put the human directory above the billing boundary; AWS historically put it inside the account.

What replaces JSON policies on Azure?

Named role assignments at a scope. On AWS you write or attach a JSON policy document — allow and deny statements over actions and resources — to a user, group, or role. On Azure you instead pick a role (Owner, Contributor, Reader, or a custom role) and assign it to an identity at a scope: a management group, subscription, resource group, or single resource. You still can author custom roles in JSON, but day to day it's far less document-writing and far more thinking about scope and inheritance. GCP sits in between: you bind a predefined or custom role to a member on a resource.

How does permission inheritance differ across the three?

Azure inherits down its scope tree: a role assigned at a management group or subscription flows to every resource group and resource beneath it. GCP inherits down its resource hierarchy too — a role bound at the organization or a folder or project flows to the resources under it. AWS is the odd one out: inside an account, identity-based policies don't inherit down a tree; each principal's effective permissions are the union of its attached policies, evaluated with explicit-deny-wins. The closest thing to org-level inheritance on AWS is a Service Control Policy, which sets a permission ceiling across accounts rather than granting access.

Read next
Your next class · free
You've read the idea. Class 8 — RBAC & Azure Policy is where you build it, hands-on — no account needed.Start Class 8 →
Captain O
Founder & instructor · CAMPUX Cloud Engineering Bootcamp
Filed under Identity & access. Next note: VNet vs AWS VPC vs GCP VPC →