Notes · Learn AWS · CHAPTER 1

Hello, AWS

Where do you even click first? This chapter takes you from "I have an Azure subscription, where's the AWS equivalent?" to a working CLI that talks to your AWS account. Account hierarchy, regions, AZs, auth, profiles, and the one command that proves it's all wired up.

Coming from Azure, the first hurdle in AWS isn't technical - it's mental. The shape of "where stuff lives" is different. Subscriptions become accounts. Resource groups disappear. Regions feel familiar but their internal structure is two layers, not one. This chapter establishes the mental map you'll hang every later concept off.

In this chapter
  1. The cheat table
  2. Accounts vs Subscriptions
  3. Regions and Availability Zones
  4. CLI auth: az login vs aws configure
  5. SSO and Identity Center
  6. Profiles and multi-account life
  7. Try it: prove you're connected
  8. Quick check (quiz)
  9. Gotchas for Azure devs
  10. Project Compass: build along
  11. Recap & next

The cheat table: Azure → AWS

If you remember nothing else from this chapter, internalize this table. Every concept the rest of the chapter introduces hangs off one of these rows.

Concept Azure AWS
Identity boundary Microsoft Entra tenant AWS Organization root
Org hierarchy node Management Group Organizational Unit (OU)
Billing & isolation boundary Subscription AWS Account
Logical resource grouping Resource Group (RG) no clean equivalent - use tags + naming conventions
Region eastus, westeurope (~60) us-east-1, eu-west-1 (~33)
Availability Zone 3 AZs per region (most) 2-6 AZs per region (varies)
Default region picker Set per resource or via --location Set per CLI profile via region = ...
CLI az (Azure CLI) aws (AWS CLI v2)
Web console URL portal.azure.com console.aws.amazon.com
Browser auth az login (opens browser) aws sso login (opens browser, only if SSO configured)
Service principal App Registration / SP IAM User (long-lived) or IAM Role (assumed)
Resource ID format /subscriptions/<id>/resourceGroups/<rg>/.../<name> arn:aws:<svc>:<region>:<account>:<type>/<name>
The one row that bites: Resource Groups. In Azure you rely on RGs as a billing rollup, a lifecycle scope (delete the RG, delete everything inside), and an RBAC scope. AWS has none of that. Tags do the rollup work, but lifecycle and deletion are per-resource. Many Azure-to-AWS migrations stub their toe here in the first week.
What's in a name? - AWS naming origins
S3
Simple Storage Service. Three S's. Launched in 2006, named for its goal: storage so simple a developer could use it without thinking. Mostly succeeded.
EC2
Elastic Compute Cloud. Two C's. The "elastic" was 2006-era marketing for "you can scale up and down without buying servers".
IAM
Identity and Access Management. Boring acronym, important service. Pronounced "I am" by everyone but the docs.
STS
Security Token Service. Hands out short-lived credentials when you assume a role. You rarely call it directly; the CLI/SDK does it for you under the hood.
ARN
Amazon Resource Name. Pronounced "arn" (rhymes with "barn"), not "A-R-N". Saves you syllables in every status meeting.
AZ
Availability Zone. Physically separate data center. The fun part: AWS won't tell you exactly how separate (different building? different campus? different power grid?), just that they're "designed to be isolated from failures in other AZs".
VPC
Virtual Private Cloud. Your isolated network inside an AWS region. The name predates the broader meaning of "VPC" in industry - AWS coined it in 2009.

Accounts vs Subscriptions

ELI5: what is an AWS account?
An AWS account is like a Lego box. Everything you build (servers, buckets, queues) lives inside one box. The box has its own bill, its own front door (sign-in URL), and its own set of locks (IAM). If you want to lock things down between teams, you give each team their own Lego box. In Azure you'd probably use one tenant with multiple subscriptions. In AWS you use one Organization with multiple accounts. Same idea, different word.

An AWS account is the fundamental unit of billing, security, and resource isolation. It's most similar to an Azure Subscription, but with one important twist: in AWS, the account is also the strongest practical security boundary. AWS culture leans on "use lots of accounts" - one per environment, one per team, sometimes one per workload. In Azure, you tend to use fewer subscriptions and lean on RGs and AAD groups for isolation.

Side-by-side: the hierarchy

Azure
Microsoft Entra tenant
  └─ Management Group (root)
      └─ Management Group (corp)
          └─ Subscription (prod)
              └─ Resource Group (rg-web-prod)
                  └─ App Service (myapi)
                  └─ Storage Account (mystg)
                  └─ Key Vault (kv-prod)
AWS
AWS Organization (root)
  └─ OU (corp)
      └─ AWS Account (prod, 123456789012)
          └─ # no RG layer
          └─ Lambda (myapi)        # tagged env=prod
          └─ S3 Bucket (mystg)     # tagged env=prod
          └─ Secrets Manager (kv)  # tagged env=prod

Notice the missing layer on the AWS side. The Resource Group concept just isn't there. In AWS, the way you express "these things belong together" is:

What's in an Account ID?

Anatomy of an ARN (Amazon Resource Name) arn:aws:s3:us-east-1:123456789012:bucket/my-bucket-name prefix partition service region account ID (12 digits) resource Some services omit region (IAM is global) or account (public AWS resources). Globally-unique resources like S3 buckets omit region in the ARN too.
ARNs are AWS's universal "fully qualified name" - the equivalent of an Azure Resource ID. You will paste them into IAM policies dozens of times.
One account or many? AWS's recommended pattern is multi-account from day one: a dedicated billing/management account, then separate accounts for prod, non-prod, sandbox, security, audit. This sounds like overkill if you're coming from a "one big subscription" Azure setup, but it's how AWS expects you to scope blast radius. Chapter 12 covers AWS Organizations and how to wire this up cleanly.

Regions and Availability Zones

ELI5: regions and AZs
A region is a city. An availability zone is a separate building in that city, far enough away that one flood / fire / power outage won't take down the others. AWS lets you spread your app across multiple buildings in the same city for safety - and tells you the building numbers. Azure has the same idea but is less explicit about exposing the building numbers to you.

Both clouds have regions (geographic locations) and within each region, multiple availability zones (physically separate data centers). The naming and the way you reference them is where Azure habits break.

Region naming

Azure regions
# Human-readable, location-based
eastus
westeurope
northeurope
australiaeast
japaneast

# Also has paired regions for DR
# eastus  ↔ westus
# pairs are fixed and prescriptive
AWS regions
# Code-style with sequence numbers
us-east-1      # N. Virginia (default)
us-west-2      # Oregon
eu-west-1      # Ireland
ap-southeast-2 # Sydney
ap-northeast-1 # Tokyo

# No "paired regions" concept
# DR pairing is up to you

The us-east-1 thing

us-east-1 matters more than any other region. It's AWS's oldest region, hosts the most services, and is the default for many global services (IAM, Route 53, CloudFront). Many AWS bugs and outages historically center there. If you're picking a region for a "global" service, default to us-east-1. For everything else, pick by proximity to users.

Fun fact AWS launched in 2006 with S3 in one region: us-east-1. The naming convention assumed many east-coast regions would follow. They didn't. us-east-2 (Ohio) wasn't added until 2016 - a full decade later. That ten-year monopoly is why so many "global" services still resolve through us-east-1 even today. If you're wondering why us-east-1 outages cause Slack to break - now you know.
Real-world incident The S3 outage that broke the internet (Feb 28, 2017) ~$150M in losses

An AWS engineer was debugging a billing-system slowdown in us-east-1 and ran a aws s3 command intended to remove a small set of capacity servers. The command had a typo and removed a much larger set. The S3 index subsystem went down for ~4 hours.

Casualties: Slack, Trello, Quora, Imgur, Medium, Coursera, GitHub status, IFTTT, and - in a moment of perfect dark comedy - the AWS Service Health Dashboard itself, which depended on S3 to render its "everything is fine" icons.

Lesson for Azure devs: us-east-1 is more like a tier-zero dependency than a region. If your service "must stay up", design for us-east-1 to disappear. Multi-region failover is a chapter-12 topic, but the awareness starts here.

AZs aren't fixed names

Surprise: when you read us-east-1a, the a doesn't mean the same physical zone across accounts. AWS randomizes the letter assignment per account to prevent everyone from piling into "zone a". If you want to coordinate AZ placement across accounts, use the AZ ID (e.g., use1-az1) returned by aws ec2 describe-availability-zones. Azure has no equivalent randomization.

Picking your default region

Azure CLI default location
# Set per command
az group create -n rg-test \
  --location eastus

# Or set a CLI default
az configure --defaults \
  location=eastus
AWS CLI default region
# Set per command
aws s3 ls --region us-east-1

# Or set per profile (typical)
aws configure set region us-east-1

# Or via env var (CI/CD)
export AWS_REGION=us-east-1
Region != global: Some AWS services are regional (S3 buckets, EC2 instances, VPCs) and some are global (IAM, Route 53, CloudFront, WAF, billing). Console shows the regional ones in the region picker top-right; global ones appear regardless. Azure also has this split (Front Door is global, App Service is regional) but the AWS console is more explicit about it.
Cost trap: the $5,000 cross-AZ surprise ~$5,000 / month

You deploy a chatty microservice across 3 AZs in us-east-1 for high availability. Each of the 6 services sends roughly 10 GB/day to each peer (typical for sidecar-heavy designs). Your dev environment bill is $40/month. Prod is $5,200/month. Where did the extra ~$5,160 come from?

Click to reveal the trap
Cross-AZ data transfer. Within a single AWS region, traffic between AZs costs $0.01/GB each way ($0.02/GB round-trip). Your "highly available" 3-AZ spread means most service-to-service calls cross an AZ boundary.

Math: 6 services × 5 peers each × 10 GB/day × 30 days × $0.02/GB ≈ $1,800/month per service tier. Multiply across all tiers in a realistic prod deployment and $5K is conservative; large meshes routinely hit $20K-$50K/month here.

Fix: use a single AZ for chatty service meshes (with replica failover, not active-active across AZs), or use VPC endpoints / PrivateLink for AWS-service calls, or refactor to reduce chattiness. Tools like VPC Flow Logs + Cost Explorer's data-transfer breakdown are how you discover this.

Azure trap reminder: Azure currently charges nothing for cross-AZ traffic within a region for most services. "Spread everything across AZs by default" is a habit that's safe in Azure and expensive in AWS.

CLI auth: az login vs aws configure

ELI5: how does the CLI know who I am?
When you run az, the Azure CLI quietly checks a cookie-like file on your laptop with a token. az login refreshed that token by opening a browser. AWS does almost the same thing, but uses a different file (~/.aws/credentials) and historically used long-lived access keys (like passwords you paste in once) instead of browser logins. Modern AWS shops use SSO, which is browser-based like Azure.

Installing the AWS CLI

terminal · macOS
# Homebrew is the easy path
brew install awscli

# Verify
aws --version
# aws-cli/2.15.0 Python/3.11.6 Darwin/23.0.0
terminal · Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscli.zip"
unzip awscli.zip
sudo ./aws/install
aws --version

The two auth styles

AWS has two ways to authenticate the CLI, and you need to know which one your org expects:

Style When to use What gets stored
Long-lived access key Personal AWS accounts, CI/CD machines, legacy setups. AWS now discourages this for human users. ~/.aws/credentials with aws_access_key_id + aws_secret_access_key. Effectively forever.
SSO (IAM Identity Center) Any company AWS environment in 2025+. Equivalent to az login - browser-based, short-lived tokens. ~/.aws/sso/cache/*.json with a token. Expires (typically 8-12 hours). Refresh via aws sso login.

Style 1: long-lived access key (old-school)

Azure
# Service principal style
az login --service-principal \
  --username <app-id> \
  --password <client-secret> \
  --tenant <tenant-id>

# Token cached in ~/.azure/
AWS
# Interactive, prompts for 4 values
aws configure

# AWS Access Key ID: AKIA...
# AWS Secret Access Key: ********
# Default region: us-east-1
# Default output format: json

# Or set directly:
aws configure set aws_access_key_id AKIA...
aws configure set aws_secret_access_key ********

After aws configure, you have a file:

~/.aws/credentials
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
~/.aws/config
[default]
region = us-east-1
output = json
Treat access keys like database root passwords. They're long-lived and have whatever permissions your IAM user has. If you commit them to git or paste them in a Slack channel, rotate them immediately. AWS has a public "leaked-keys" scanner that monitors GitHub and will email you, but assume the worst.
Bug hunt: why does aws s3 ls fail with "Unable to locate credentials"?

A colleague pings you. They swear they ran aws configure and pasted in their access key. But every command fails. Their ~/.aws/credentials file looks like this:

~/.aws/credentials
[default]
access_key_id = AKIAIOSFODNN7EXAMPLE
secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

What's wrong? (One small thing. Look closely at the key names.)

Click to reveal the bug
The keys are missing the aws_ prefix. AWS CLI looks for aws_access_key_id and aws_secret_access_key - not the unprefixed names. The file is parseable, the section is valid, but the CLI silently treats those values as unknown options and falls back to "no credentials found".

Fix: prefix both keys with aws_. Or better, just run aws configure and let the CLI write the file for you.

Style 2: SSO / Identity Center (modern)

This is the az login equivalent. Browser-based, short-lived tokens, no secrets on your laptop.

~/.aws/config
# Created once via `aws configure sso`
[profile dev]
sso_session = my-org
sso_account_id = 123456789012
sso_role_name = DeveloperAccess
region = us-east-1

[profile prod]
sso_session = my-org
sso_account_id = 987654321098
sso_role_name = ReadOnlyAccess
region = us-east-1

[sso-session my-org]
sso_start_url = https://my-org.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
terminal
# Once per session (~8-12 hour token)
aws sso login --profile dev

# Then every command picks up the token
aws sts get-caller-identity --profile dev
aws s3 ls --profile dev
If you're learning on a personal account: start with aws configure and an IAM user with an access key. It's simpler. Move to Identity Center / SSO later when you're working in a multi-account org.

SSO and Identity Center

In Azure, AAD handles human identity for the whole tenant. In AWS, IAM was originally per-account, which made multi-account life painful (one IAM user per account!). AWS Identity Center (née AWS SSO) fixed that by acting as a federation layer above all your accounts.

How SSO login resolves to permissions You sunilt@nvidia.com Identity Provider Microsoft Entra, Okta, or AWS-native AWS Identity Center maps users → roles in each account prod account ReadOnlyAccess role dev account DeveloperAccess role sandbox account AdminAccess role 1. SAML/OIDC 2. map 3. assume role
Identity Center is the "Azure-AAD-like" layer for multi-account AWS. Your laptop talks to Identity Center once, and Identity Center hands you a short-lived role token in whichever account you need.

Three things to know about Identity Center:

  1. It can use AAD as the upstream IDP. Many enterprises run Microsoft Entra for human identity even when their compute is on AWS. Identity Center federates with AAD via SAML or SCIM.
  2. It runs in one account (the "management account" of the AWS Organization) but provisions access to all accounts in the org. Users don't need an IAM identity in each account.
  3. Tokens are short-lived (default 1-12 hours). When the CLI says ExpiredToken, run aws sso login --profile <name> to refresh.

Profiles and multi-account life

ELI5: what's a profile?
A profile is a named set of credentials. You can have a profile called "work-prod" and another called "personal" and another called "client-x". When you run aws s3 ls --profile work-prod, the CLI uses that specific set. Azure has the same idea but calls them "subscriptions in your context" and you switch with az account set - not quite the same shape but the goal is identical.

Because AWS pushes you toward multi-account, profiles become essential. Almost every AWS user has at least 2-3 profiles in their ~/.aws/config.

Side-by-side: switching context

Azure
# List subscriptions
az account list -o table

# Switch active subscription
az account set --subscription "prod-sub"

# Then all subsequent commands
# use that subscription
az group list
AWS
# List configured profiles
aws configure list-profiles

# Pass --profile per command
aws s3 ls --profile prod

# Or set for the shell session
export AWS_PROFILE=prod
aws s3 ls   # now uses prod
Quality-of-life tip: install aws-vault (long-lived keys) or just rely on AWS_PROFILE + shell prompt. Many engineers add their active profile to their shell prompt - it's the single best way to avoid running prod commands in a dev shell or vice versa.

A realistic ~/.aws/config

~/.aws/config
[sso-session my-org]
sso_start_url = https://my-org.awsapps.com/start
sso_region = us-east-1

[profile sandbox]
sso_session = my-org
sso_account_id = 111111111111
sso_role_name = AdministratorAccess
region = us-east-1
output = json

[profile dev]
sso_session = my-org
sso_account_id = 222222222222
sso_role_name = DeveloperAccess
region = us-east-1
output = json

[profile prod-readonly]
sso_session = my-org
sso_account_id = 333333333333
sso_role_name = ReadOnlyAccess
region = us-east-1
output = json

# Role chaining: assume a role in prod from your dev creds
[profile prod-deploy]
source_profile = dev
role_arn = arn:aws:iam::333333333333:role/DeployerRole
region = us-east-1

That last profile is worth a closer look. source_profile + role_arn is the AWS equivalent of "run this command as a different identity that I'm allowed to switch into". You stay authenticated as your normal dev user, but for this profile the CLI silently calls sts:AssumeRole and uses the returned credentials. We'll dig into this in Chapter 2.

Try it: prove you're connected

Hello-world for AWS CLI $0

One command. Confirms your CLI is installed, your credentials are valid, and AWS can see you. The AWS equivalent of az account show.

terminal
# If you set up SSO:
aws sso login --profile dev

# If you used aws configure (access keys), skip the login.

aws sts get-caller-identity

Expected output:

terminal · output
{
  "UserId": "AROA...EXAMPLE:sunilt",
  "Account": "123456789012",
  "Arn": "arn:aws:sts::123456789012:assumed-role/DeveloperAccess/sunilt"
}

Read the ARN closely. It tells you four things at once: that you authenticated via STS (the temporary-credential service), the account ID, the role name you assumed, and your session name. This is the single most useful debugging command in AWS - whenever something says "access denied", start by running this to confirm who you actually are.

Bonus: poke around

Read-only exploration $0
terminal
# What region am I defaulting to?
aws configure get region

# What regions exist?
aws ec2 describe-regions \
  --query 'Regions[].RegionName' --output table

# Any S3 buckets in this account?
aws s3 ls

# Account-level summary (free)
aws iam get-account-summary

All of these are describe / list / get calls - read-only and free. Get comfortable with this rhythm: every AWS service has describe-* and list-* commands that cost nothing to call.

Quick check

Test yourself - 4 questions

Don't peek. Think first, then click to reveal the answer.

1. You created an S3 bucket five minutes ago. You log into the AWS console, navigate to S3, but the bucket isn't there. What's the most likely cause?

  • The bucket failed to provision silently.
  • You're looking at the wrong region in the top-right region picker.
  • S3 has eventual consistency for new buckets.
  • You need to refresh the IAM permissions cache.
Show answer
Answer: b. S3's console view is region-scoped even though bucket names are globally unique. The bucket exists; you're filtering it out. Click the region picker top-right (or "All Regions" in the new S3 console). This trap hits every Azure dev in their first week.

2. Which of these is a global AWS service (not scoped to one region)?

  • EC2
  • RDS
  • IAM
  • S3 (the bucket itself)
Show answer
Answer: c. IAM is global - users, roles, and policies you create exist account-wide, no region needed. S3 bucket names are global (unique across AWS) but each bucket physically lives in one region. CloudFront, Route 53, WAF are other global services. The trick is that IAM's "home region" for API calls is us-east-1, which is why us-east-1 outages can break IAM.

3. aws sts get-caller-identity tells you...

  • Your account billing balance.
  • Your CLI version.
  • The ARN, account ID, and user/role currently authenticated.
  • Whether MFA is enabled for your user.
Show answer
Answer: c. This is the AWS "whoami" - it returns the principal you're authenticated as. If the returned ARN looks wrong (wrong account ID, wrong role), you've got a profile or env-var problem. It's the first command to run for almost any "access denied" debugging session.

4. Your teammate launches an EC2 instance in us-east-1a. You launch one in us-east-1a too. Are you in the same physical data center?

  • Yes - AZ letters are stable globally.
  • Not necessarily - AZ letter assignments are randomized per account.
  • Only if you're in the same Organization.
  • Only if both accounts are billed to the same payer.
Show answer
Answer: b. AWS randomizes the letter assignment per account to prevent everyone defaulting to "AZ a". To compare zones across accounts, use the AZ ID (e.g., use1-az1) from aws ec2 describe-availability-zones --query 'AvailabilityZones[].[ZoneName,ZoneId]'. This becomes important when peering VPCs across accounts in chapter 3.

Gotchas for Azure devs

1. There is no "global view". The AWS console only shows resources in the currently-selected region. If you created a bucket in us-west-2 and you're looking at us-east-1, it'll be invisible. Azure's portal stitches across all regions by default; AWS doesn't.
2. No Resource Group means no easy "delete everything". When you're done experimenting in Azure you delete the RG and the bill stops. In AWS you must delete each resource individually, or destroy via the IaC tool you used to create them. Forgotten EC2 instances and NAT Gateways are the #1 source of surprise bills.
3. Access keys are dangerous and rotate is on you. Azure SPs expire and force rotation. AWS access keys live forever unless you actively rotate or revoke. Use SSO, set key-age limits, or skip IAM users for humans entirely.
4. us-east-1 is special, and that's also a risk. Many global services route through it. A us-east-1 outage has cascading effects on services you thought were in other regions (IAM, billing, CloudFront edges). If you're building anything where global availability matters, read the AWS multi-region guidance.
5. The "root user" is not your daily login. When you create an AWS account, the email + password you used becomes the root user. AWS strongly advises locking it away (hardware MFA, strong password, never use it day-to-day) and doing actual work as an IAM user / SSO identity. Azure has no equivalent "scary root" - the global admin role is powerful but treated more normally.

Project Compass: a service you'll build across the doc

From here on, every chapter has a Project Compass section that advances one fictional NVIDIA-flavored service: gfn-reports. It reads GeForce NOW session telemetry from a queue, aggregates it, exposes a query API, and emits alerts. By chapter 12 you'll have wired up almost the whole AWS stack to support it.

Compass exists so you're not learning services in isolation. Each chapter's slice connects to the previous one - the IAM role you create in chapter 2 will get S3 permissions in chapter 5, Lambda permissions in chapter 11, and Terraform-managed in chapter 12.

Project Compass · Step 1 of 12 Bootstrap your CLI profile

Goal: a clean, named profile we can refer to as compass in every following chapter. Pick a non-prod AWS account you can experiment in freely.

This chapter's slice
terminal · SSO path
aws configure sso --profile compass
# Walks through SSO start URL, account, role, region
aws sso login --profile compass
aws sts get-caller-identity --profile compass
terminal · access-key path (personal account)
aws configure --profile compass
# Paste your access key, region (us-east-1), output (json)
aws sts get-caller-identity --profile compass

Once get-caller-identity returns a healthy ARN, you're done with chapter 1's Compass slice. Every subsequent chapter will add --profile compass to its commands and assume this profile is configured.

Where Compass goes from here
ch1 · profile ch2 · IAM role ch3 · VPC ch4 · Lambda ch5 · S3 ch6 · DynamoDB ch7 · SQS ch8 · KMS ch9 · alarms ch10 · EKS ch11 · API GW ch12 · Terraform

Recap & next

What stuck?

Common pitfalls so far

TrapFix
"Bucket disappeared!"Wrong region in console picker. Check top-right.
"Access denied" but I'm an adminRun aws sts get-caller-identity - you're probably on the wrong profile.
"My access key works for everything I tested"That's the problem. Rotate it, use SSO.
"My teammate sees different AZs"Letter assignment is per-account. Use AZ IDs (use1-az1) for coordination.
NEXT CHAPTER
2. IAM & Identity
Users, roles, policies, STS. The chapter every later chapter assumes.