AWS for Azure people
You already run things in Azure: subscriptions, resource groups, Entra ID, role assignments, storage accounts, Key Vault. AWS solves the same problems with different boundaries, and the boundaries are what bite you on call. This lesson maps one cloud onto the other, then shows the three ideas everything else in AWS rests on: the account, the Region, and the API call.
Need to know: an AWS account (a 12-digit number) is the unit of isolation, billing and quotas, and it has its own identity store (IAM). Most resources live in one Region; IAM is global. Everything is named by an ARN. Every action - console click, CLI command, Terraform apply - is a signed HTTPS call to a service API, and IAM policies talk about those calls by name (s3:GetObject).
The account is the boundary
An AWS account is a container for resources with a 12-digit account ID. It is the line AWS draws for:
- isolation: nothing in one account can touch another account unless someone explicitly allows it on both sides;
- billing: the bill is per account (Organizations adds it up);
- quotas: limits such as "5,000 IAM users" or "10,000 buckets" are per account (and often per Region);
- identity: every account has its own IAM - its own users, roles and policies.
That last point is the biggest change from Azure. In Azure, identities live in the Entra ID tenant and a role assignment gives them rights on a subscription. In AWS, an IAM user exists in exactly one account. To work in a second account you either have a user there too, or - the normal way - you assume a role in it.
Every account also has a root user: the email address and password used to create it. Root can do everything, including closing the account and changing the payment method, and no policy can limit it inside the account. The rules for root are short: a strong password, MFA, no access keys, locked away, used only for the handful of tasks only root can do.
Companies run many accounts - one per environment, per team, per workload - grouped with AWS Organizations:
- the management account owns the organization and pays the bill;
- member accounts sit in organizational units (OUs), a tree like Azure management groups;
- service control policies (SCPs) are guardrails attached to the root, an OU or an account: they cap what anyone in those accounts can do (deny everything outside two Regions, never disable CloudTrail), and they apply even to the account's admins;
- IAM Identity Center is where people sign in once and pick an account and a role ("permission set"). It is the AWS answer to "log in with Entra ID", and it can use Entra ID as its identity source.
In an interview: "An account is the hard boundary for security, billing and quotas. Regions are where resources physically live; Availability Zones are isolated data centres inside a Region. IAM is global to the account, most other services are regional."
Regions, Availability Zones and global services
A Region is a geographic area with its own copy of most services: eu-central-1 (Frankfurt), eu-west-1 (Ireland), us-east-1 (N. Virginia). Inside each Region are three or more Availability Zones (AZs) - one or more data centres each, with independent power and networking, close enough for synchronous replication. Their names are eu-central-1a, -1b, -1c; the letters are shuffled per account, so the stable names are the AZ IDs (euc1-az1).
Most resources belong to one Region: a KMS key in eu-central-1 cannot decrypt data in eu-west-1, and aws kms list-keys only lists the keys of the Region you ask. A few services are global: IAM (users, roles and policies are the same everywhere), Organizations, Route 53, CloudFront. S3 is in between: bucket names are global (unique across all of AWS), but each bucket lives in one Region.
$ aws sts get-caller-identity
{
"UserId": "AIDAEVXTZTVCSMBGJ2WDW",
"Account": "111122223333",
"Arn": "arn:aws:iam::111122223333:user/learner"
}
$ aws s3api list-buckets --query 'Buckets[].[Name,BucketRegion]' --output text
oncall-lab-docs-111122223333 eu-central-1
oncall-lab-dr-111122223333 eu-west-1
oncall-lab-logs-111122223333 eu-central-1
The DR bucket is in Ireland, the others in Frankfurt - one account, one list, two Regions. KMS keys are strictly per Region:
$ KEY=$(aws kms create-key --description 'try: Frankfurt only' --query KeyMetadata.KeyId --output text)
$ aws kms describe-key --key-id $KEY --query KeyMetadata.Arn --output text
arn:aws:kms:eu-central-1:111122223333:key/46a9b14b-238e-4e21-8153-217a14708778
$ aws kms describe-key --key-id $KEY --region eu-west-1
aws: [ERROR]: An error occurred (NotFoundException) when calling the DescribeKey operation: Key 'arn:aws:kms:eu-west-1:111122223333:key/46a9b14b-238e-4e21-8153-217a14708778' does not exist
The key exists - in eu-central-1 (the profile's Region, so the first describe-key needed no --region). Asked in eu-west-1, KMS has never heard of it: there is no global list of keys to fall back on. IAM does not care about Regions at all:
$ aws iam get-user --region eu-west-1 --query User.Arn --output text
arn:aws:iam::111122223333:user/learner
$ aws iam get-user --region us-east-1 --query User.Arn --output text
arn:aws:iam::111122223333:user/learner
Azure to AWS: the mapping
| Azure | AWS | Watch out for |
|---|---|---|
| Entra ID tenant | IAM Identity Center (people), IAM in each account | IAM users and roles exist in one account only |
| Management group | Organizations OU | SCPs are deny-style guardrails, not grants |
| Subscription | Account | The account is also the identity boundary |
| Resource group | No direct equivalent: tags, CloudFormation stacks, Resource Groups | You delete "everything for this app" by tag or stack, not by group |
| Role assignment (RBAC) | An IAM policy attached to a user, group or role | One policy language covers management AND data (s3:GetObject) |
| Azure Policy (deny) | SCPs, plus AWS Config rules for auditing | |
| Managed identity | IAM role (an instance profile on EC2, IRSA / Pod Identity on EKS) | Roles have a trust policy saying who may use them |
| Service principal + client secret | IAM user + access key (avoid), or a role with OIDC | Long-lived keys are the classic AWS leak |
| Key Vault keys | KMS | Every key has a key policy that must allow you |
| Key Vault secrets | Secrets Manager / SSM Parameter Store | |
| Storage account + blob container | S3 bucket | The bucket name is global; no account-level key |
| VNet / subnet | VPC / subnet | AWS subnets live in one AZ |
| NSG | Security group (stateful) + network ACL (stateless) | |
| Load Balancer / Application Gateway | NLB / ALB | |
| AKS | EKS | |
| Azure Monitor, Log Analytics (KQL) | CloudWatch metrics, Logs, Logs Insights | |
| Activity Log | CloudTrail | |
| Cost Management | Cost Explorer, Budgets | |
| ARM / Bicep | CloudFormation / CDK (and Terraform for both) | |
az CLI | aws CLI | --query is JMESPath in both |
The row that changes how you debug: Azure splits the control plane (manage the storage account) from the data plane (read a blob), and an Owner cannot read Key Vault secrets without a data role. AWS has one IAM policy language for both: s3:CreateBucket and s3:GetObject are just two actions, and an admin policy ("Action": "*") covers both - unless a resource's own policy (a bucket policy, a KMS key policy) says otherwise. You will meet that "unless" in every lab of this chapter.
ARNs: the name of everything
An Amazon Resource Name identifies a resource across all of AWS:
arn:partition:service:region:account-id:resource
arn:aws:iam::111122223333:user/learner IAM: global, no Region
arn:aws:iam::111122223333:role/ci-deploy
arn:aws:sts::111122223333:assumed-role/ci-deploy/build-4711 a session of that role
arn:aws:s3:::oncall-lab-docs-111122223333 S3: no Region, no account
arn:aws:s3:::oncall-lab-docs-111122223333/runbooks/s3-public.md an object
arn:aws:kms:eu-central-1:111122223333:key/1234abcd-... KMS: Region and account
The partition is aws almost everywhere (aws-cn in China, aws-us-gov in GovCloud). Empty fields are part of the format: a bucket ARN has no Region and no account because bucket names are already globally unique. Policies match resources by ARN, with * and ? as wildcards - arn:aws:s3:::oncall-lab-docs-111122223333/runbooks/* is "every object under runbooks/".
$ aws iam get-user --query User.Arn --output text
arn:aws:iam::111122223333:user/learner
$ aws iam list-groups-for-user --user-name learner --query 'Groups[].Arn' --output text
arn:aws:iam::111122223333:group/platform-admins
Every action is an API call
The console, the CLI, the SDKs, Terraform: all of them send signed HTTPS requests to service endpoints such as iam.amazonaws.com, sts.eu-central-1.amazonaws.com or s3.eu-central-1.amazonaws.com. The signature (SigV4) is computed from your secret key, so the key itself never travels. Each request names one action in the form service:Operation:
| You type | The API action |
|---|---|
aws iam create-user --user-name ana | iam:CreateUser |
aws s3 ls s3://bucket | s3:ListBucket (the ListObjectsV2 operation) |
aws s3 cp s3://bucket/key . | s3:GetObject (after a HeadObject) |
aws kms decrypt ... | kms:Decrypt |
Policies grant and deny those action names, AccessDenied errors quote them, and CloudTrail records them. When a command fails, the question is always: which API call, made by which principal, against which resource ARN?
$ aws cloudtrail lookup-events --region us-east-1 --max-items 2 --query 'Events[].[EventTime,EventName,Username]' --output text
2026-09-22T20:00:04+00:00 ListGroupsForUser learner
2026-09-22T20:00:04+00:00 GetUser learner
IAM calls are recorded in us-east-1 even though you sent them from Frankfurt: IAM is a global service and CloudTrail keeps global events there. Remember that the day you hunt for "who deleted this role".
The lab account
(simulator) Everything in this chapter runs against a simulated AWS account, 111122223333 (the account ID AWS uses in its own documentation), alias oncall-lab, home Region eu-central-1, DR Region eu-west-1. You are the IAM user learner, an administrator through the group platform-admins. The account is a member of an organization whose SCPs you will meet later. No request leaves the box and nothing costs money - but every output, error message and policy decision follows the real services. The lab installed the CLI for this lesson; in the first lab you install it yourself.
You can now: say what an account, a Region and an AZ are and which services are global; map an Azure concept to its AWS counterpart and name the difference that matters; read an ARN; and name the API action behind a CLI command.