Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


title: “AWS Certification” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification

AWS Certification

Personal AWS certification preparation hub — training materials and learned concepts organized in a zettelkasten-style structure.

Structure

aws-certification/
├── training/       # Raw training materials, course notes, dumps
└── learnings/      # Zettelkasten — atomic notes per learned concept

Target Certification

Currently preparing: AWS Certified Cloud Practitioner (CLF-C02) via Stephane Maarek’s Udemy course.

  • [[udemy-clf-c02-progress]] — Course progress tracker (section ↔ notes dashboard)

Sections

  • [[training/README]] — Training materials index
  • [[learnings/README]] — Learned topics index (zettelkasten)
  • [[aws-certification-training-workflow]] — Methodology: how training content becomes zettelkasten notes

See Also

  • [[aws/README]] — General AWS knowledge base

title: “AWS Certification Training Workflow” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • workflow
  • zettelkasten
  • methodology

AWS Certification Training Workflow

What It Is

A repeatable process for turning AWS training lab content (HTML from the training platform) into structured, interlinked knowledge notes organized in a zettelkasten-style system. The workflow leverages Kiro as an AI assistant to accelerate extraction and structuring.

Why It Matters

Raw training materials are hard to review and retain. By extracting atomic concepts and filing them by domain, you build a personal knowledge graph that supports spaced retrieval, cross-linking, and exam-ready review.

Key Concepts

The Three-Phase Approach

PhaseInputOutputWhere
1. CaptureHTML from training platformClean Markdown fileaws-certification/training/
2. Extract & DispatchMarkdown training fileAtomic zettelkasten notesaws-certification/learnings/<domain>/
3. MOC (Map of Content)Atomic notes from phase 2Topic index pageaws-certification/learnings/<topic>-moc.md

Zettelkasten Domains

Notes are dispatched into domain folders based on their primary topic:

  • compute/ — EC2, Lambda, ECS, EKS, Fargate
  • storage/ — S3, EBS, EFS, FSx
  • networking/ — VPC, Route53, CloudFront, ELB
  • databases/ — RDS, DynamoDB, Aurora, ElastiCache
  • security/ — IAM, KMS, WAF, Shield, ACLs, policies
  • monitoring/ — CloudWatch, CloudTrail, X-Ray
  • architecture/ — Well-Architected, patterns, DR
  • serverless/ — Lambda patterns, API Gateway, Step Functions
  • devops/ — CI/CD, CLI, SSM, IaC

Note Principles (Zettelkasten)

  1. One idea per note — each file captures a single concept or service
  2. Interlink heavily — use [[wiki-links]] to connect related ideas
  3. Use the knowledge template — consistent frontmatter with type: knowledge
  4. Source attribution — note which training the knowledge came from
  5. Grow organically — add notes as you learn, refine over time

How It Works

Phase 1: Structure Setup (one-time)

Create the folder hierarchy under aws-certification/:

  • training/ — raw training materials (HTML + converted MD)
  • learnings/ — zettelkasten with domain sub-folders, each with a README index

Phase 2: Training Capture

  1. Copy HTML from the AWS training platform
  2. Paste into training/<Training-Name>.html
  3. Ask Kiro to convert to Markdown (same name, .md suffix)
  4. The MD file preserves all content: objectives, steps, code blocks, policies

Phase 3: Analysis & Dispatch

  1. Kiro reads the MD training file
  2. Identifies distinct learnable topics (concepts, services, patterns)
  3. Groups them by domain (storage, security, devops, etc.)
  4. Creates one atomic note per topic using the knowledge template
  5. Interlinks notes with [[wiki-links]]
  6. Updates domain README indexes with new entries

Phase 4: MOC (Map of Content)

After dispatching notes, create or update a topic-level index page:

  1. Check if learnings/<topic>-moc.md already exists (e.g. s3-moc.md)
  2. If not, create it with type: moc in frontmatter
  3. Link to the training source (the lab in training/)
  4. Group all related atomic notes by domain (storage, security, devops…)
  5. Add review questions to support self-testing
  6. If the MOC already exists, enrich it with the new notes from this training

Why MOCs matter:

  • They provide a single entry point per topic across all domains
  • They work everywhere: Obsidian (graph hub), mdbook, publish, GitHub
  • Unlike tags, they are navigable pages — not just search filters
  • They enable topic-based revision independent of training sequence

Naming convention: <service-or-topic>-moc.md — e.g. s3-moc.md, ec2-moc.md, iam-moc.md

Examples

From the “Introduction to Amazon S3” training, 11 atomic notes were extracted:

  • Storage (4): s3-fundamentals, s3-bucket-configuration, s3-object-operations, s3-versioning
  • Security (5): s3-block-public-access, s3-access-control-lists, s3-bucket-policies, aws-arns, iam-instance-profiles
  • DevOps (2): aws-cli-s3-commands, ssm-session-manager

Then a MOC was created: [[learnings/s3-moc|S3 — Map of Content]] linking all 11 notes + training source + review questions.

Gotchas

  • Some topics cross multiple domains — place in the primary domain and link from others
  • Training labs are procedural; extract the concepts behind the procedures, not the step numbers
  • Don’t duplicate knowledge already captured — check existing notes first and enrich them instead
  • HTML formatting varies — Kiro handles the cleanup, but verify code blocks and JSON are intact

See Also

  • [[training/README]] — Training materials index
  • [[learnings/README]] — Zettelkasten index
  • [[learnings/s3-moc]] — S3 Map of Content (example MOC)

title: “Udemy CLF-C02 — Course Progress Tracker” created: 2026-10-18 updated: 2026-10-18 type: moc tags:

  • aws
  • certification
  • clf-c02
  • cloud-practitioner
  • udemy
  • progress

Udemy CLF-C02 — Course Progress Tracker

Dashboard mapping Stephane Maarek’s AWS Certified Cloud Practitioner (CLF-C02) Udemy course to the BHU zettelkasten notes. One row per course section: track where you are and which notes exist.

Target Certification

  • Exam: AWS Certified Cloud Practitioner (CLF-C02)
  • Level: Foundational
  • Course: Ultimate AWS Certified Cloud Practitioner (CLF-C02) — Stephane Maarek
  • Course length: ~15 hours
  • Goal: pass the exam + build a solid AWS foundation

How to Use This Tracker

  1. Watch a section in the course.
  2. Tell Kiro: “Section N —
    ”
    (optionally drop the section slides PDF in chat).
  3. Kiro creates/enriches atomic notes in learnings/<domain>/ and links them here.
  4. Mark the section status below.

Status legend: [ ] not started · [~] in progress · [x] notes done

Section Map

#SectionPrimary domain(s)StatusNotes
1Introduction & Course Material—[ ]—
2Cloud Computing & AWS Fundamentalsarchitecture[ ]—
3IAM — Identity & Access Managementsecurity[~]existing: [[learnings/security/iam-users]], [[learnings/security/iam-groups]], [[learnings/security/iam-policy-structure]], [[learnings/security/iam-managed-vs-inline-policies]], [[learnings/security/iam-sign-in-url]]
4EC2 — Elastic Compute Cloudcompute[ ]—
5EC2 Instance Storage (EBS, EFS, AMI)storage[ ]—
6ELB & ASG — Load Balancing & Auto Scalingcompute[ ]—
7Amazon S3storage, security[~]existing: [[learnings/s3-moc]] and S3 notes in storage/ + security/
8Databases & Analytics (RDS, Aurora, DynamoDB, Redshift…)databases[ ]—
9Other Compute (Lambda, ECS, Fargate, Batch, Lightsail)compute, serverless[ ]—
10Deploying & Managing Infra (CloudFormation, Beanstalk, CodeX, SSM)devops[~]existing: [[learnings/devops/ssm-session-manager]]
11Global Infrastructure (Route 53, CloudFront, Global Accelerator)networking[ ]—
12Cloud Integration (SQS, SNS, EventBridge, Step Functions)serverless[ ]—
13Cloud Monitoring (CloudWatch, CloudTrail, X-Ray, Health)monitoring[~]existing: [[learnings/monitoring/aws-budgets-cost-controls]]
14VPC & Networkingnetworking[~]existing: VPC notes in networking/ (see [[learnings/networking/README]])
15Security & Compliance (Shield, WAF, GuardDuty, KMS, Inspector…)security[ ]—
16Machine Learning (Rekognition, Comprehend, SageMaker…)architecture[ ]—
17Account Management, Billing & Support (Organizations, Budgets, pricing)monitoring[~]existing: [[learnings/monitoring/aws-budgets-cost-controls]]
18Advanced Identity (Cognito, Directory Services, IAM Identity Center)security[ ]—
19Other Services (grab-bag)architecture[ ]—
20AWS Architecting & Ecosystem (Well-Architected, Trusted Advisor)architecture[ ]—
21Exam Preparation & Practice—[ ]—

Section numbering follows the typical CLF-C02 course order; adjust rows if your course version differs slightly.

Already-Covered Head Start

From earlier work, these domains already have solid notes you can reuse for revision:

  • S3 — fully mapped in [[learnings/s3-moc]]
  • IAM — users, groups, policies, sign-in URL (security/)
  • VPC — fundamentals, subnets, route tables, security groups, NACLs, IGW, NAT, CIDR (networking/)
  • Monitoring — AWS Budgets & cost controls

Revision Workflow

  • Each note carries Exam Tips and Review Questions sections for CLF-C02.
  • Ask Kiro: “Quiz me on ” to be tested from the Review Questions.
  • Use domain MOCs (like [[learnings/s3-moc]]) to revise a whole area at once.

See Also

  • [[README]] — AWS Certification hub
  • [[learnings/README]] — Zettelkasten index
  • [[aws-certification-training-workflow]] — Training HTML → zettelkasten methodology

title: “AWS Certification — Learnings (Zettelkasten)” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • zettelkasten

Learnings

Zettelkasten-style repository of atomic notes — one concept per note, heavily interlinked.

How to Use

  1. One idea per note — each file captures a single concept, service, or pattern
  2. Link liberally — use [[note-name]] to connect related ideas
  3. Use tags — add relevant tags in frontmatter for cross-cutting retrieval
  4. Grow organically — add notes as you learn, don’t pre-plan exhaustively

Domains

  • [[compute/README]] — EC2, Lambda, ECS, EKS, Fargate, Batch
  • [[storage/README]] — S3, EBS, EFS, FSx, Storage Gateway
  • [[networking/README]] — VPC, Route53, CloudFront, Direct Connect, ELB
  • [[databases/README]] — RDS, DynamoDB, Aurora, ElastiCache, Redshift
  • [[security/README]] — IAM, KMS, Secrets Manager, WAF, Shield, GuardDuty
  • [[monitoring/README]] — CloudWatch, CloudTrail, X-Ray, Config
  • [[architecture/README]] — Well-Architected, patterns, high availability, disaster recovery
  • [[serverless/README]] — Lambda patterns, API Gateway, Step Functions, EventBridge
  • [[devops/README]] — CI/CD, CodePipeline, CodeBuild, CodeDeploy, IaC

See Also

  • [[../training/README]] — Raw training materials
  • [[../../aws/README]] — General AWS knowledge base

title: “S3 — Map of Content” created: 2026-07-20 updated: 2026-07-20 type: moc tags:

  • aws
  • s3
  • moc

S3 — Map of Content

Everything related to Amazon S3, gathered from all domains in one place.

Training Source

  • [[../training/Introduction-to-Amazon-Simple-Storage-Service-S3|Introduction to Amazon S3 (lab)]]

Storage — Core Concepts

  • [[storage/s3-fundamentals|S3 Fundamentals]] — Object storage model, durability, key concepts
  • [[storage/s3-bucket-configuration|S3 Bucket Configuration]] — Naming rules, region selection, object ownership
  • [[storage/s3-object-operations|S3 Object Operations]] — Upload, download, metadata, Object URL
  • [[storage/s3-versioning|S3 Versioning]] — Enable versioning, delete markers, recovering objects

Security — Access Control

  • [[security/s3-block-public-access|S3 Block Public Access]] — BPA settings, hierarchy, interaction with ACLs/policies
  • [[security/s3-access-control-lists|S3 Access Control Lists]] — Legacy ACLs, object ownership, making objects public
  • [[security/s3-bucket-policies|S3 Bucket Policies]] — JSON policy structure, Policy Generator, common actions
  • [[security/aws-arns|AWS ARNs]] — ARN format, S3-specific ARNs, common patterns
  • [[security/iam-instance-profiles|IAM Instance Profiles]] — EC2 roles for S3 access, credential delivery via IMDS
  • [[security/s3-access-without-public|S3 Access Without Public Exposure]] — Granting access via bucket policy while keeping BPA ON and ACLs disabled

DevOps — CLI & Tools

  • [[devops/aws-cli-s3-commands|AWS CLI S3 Commands]] — s3 cp, s3 ls, s3 mb, high-level vs low-level commands

Review Questions

  • What are the 3 mechanisms to control access to S3? (BPA, ACLs, Bucket Policies)
  • How does an EC2 instance access S3 without hardcoded credentials?
  • What happens when you delete a versioned object?
  • What’s the difference between s3:// commands and s3api commands?

title: “Learnings — Architecture” created: 2026-07-20 updated: 2026-10-28 type: knowledge tags:

  • aws
  • certification
  • architecture

Architecture

Atomic notes on AWS architecture patterns — Well-Architected Framework, high availability, disaster recovery, design patterns.

Notes

  • [[cloudfront-custom-domain-vs-default-url]] — Default CloudFront URL vs custom domain: setup, cost, DNS/ACM, migration path (migration now done — see runbook)
  • [[adr-001-s3-cloudfront-personal-site-hosting]] — ADR: start the personal S3 + CloudFront site on the default CloudFront URL (custom domain added 2026-10-28)

title: “ADR-001 — Start S3 + CloudFront Personal Site on the Default CloudFront URL” created: 2026-10-23 updated: 2026-10-28 type: adr status: accepted tags:

  • aws
  • certification
  • architecture
  • adr
  • cloudfront
  • s3

ADR-001 — Start S3 + CloudFront Personal Site on the Default CloudFront URL

Status

accepted — and the deferred migration path was later executed.

Update (2026-10-28): the custom domain was added as planned (the “purely additive” migration below). Domain mimifasol.com registered in Route 53 (not an external registrar — the original note preferred external to avoid the hosted-zone fee, but Route 53 was chosen deliberately as part of the AWS certification learning), apex mimifasol.com + docs.mimifasol.com wired to the existing distribution via ACM + Alias records. The original decision (start on the default URL) stands as recorded; see [[deploy-custom-domain-route53-acm-cloudfront]] for what was actually done.

Context

The mdBook static site generated in bhu-docs/public/book/ (AWS certification notes) needs hosting on AWS as S3 + CloudFront for personal use. Traffic is very low (a few visitors per day) and the primary objective is minimal cost. A decision is needed on whether to use a custom domain (e.g. docs.example.com) or the default CloudFront URL (e.g. d1234xyz.cloudfront.net) for the first deployment. No domain is owned yet.

See [[cloudfront-custom-domain-vs-default-url]] for the full concept explanation.

Decision

Use the default CloudFront URL for the first deployment. Defer the custom domain until a concrete need for a memorable URL arises. If/when a domain is added, prefer a subdomain (docs.) on an external registrar to avoid Route 53’s hosted-zone fee.

Options Considered

Option A — Default CloudFront URL

  • Pros: $0 cost; zero DNS/TLS setup; HTTPS works immediately via AWS-managed cert; lets us focus on the real work (private bucket + OAC, cache invalidation, build pipeline).
  • Cons: URL is ugly and not memorable; not “ours”; changes if the distribution is recreated.

Option B — Custom Domain Now

  • Pros: clean, memorable, stable URL from day one.
  • Cons: requires buying a domain (~$10–15/year) if none exists; ACM cert in us-east-1; DNS wiring (alias/CNAME); $0.50/month if DNS is on Route 53. Extra effort for no functional gain at this stage.

Consequences

  • Positive: near-zero recurring cost; fastest path to a working, HTTPS-served site; no vendor lock-in — the migration to a custom domain is purely additive.
  • Negative: the URL must be bookmarked rather than typed from memory; sharing the link is less elegant.
  • Migration path: adding a custom domain later requires no rebuild — request an ACM cert in us-east-1, add the domain under Alternate domain names + attach the cert, and create the DNS record. S3 bucket, distribution, content, and pipeline stay identical, and the *.cloudfront.net URL keeps working in parallel.

See Also

  • [[cloudfront-custom-domain-vs-default-url]]
  • [[deploy-custom-domain-route53-acm-cloudfront]]
  • [[aws-budgets-cost-controls]]
  • [[s3-fundamentals]]

title: “CloudFront Custom Domain vs Default URL” created: 2026-10-23 updated: 2026-10-28 type: knowledge tags:

  • aws
  • certification
  • architecture
  • cloudfront
  • s3
  • dns
  • acm

CloudFront Custom Domain vs Default URL

Realized (2026-10-28): the bhu-docs public site made exactly this migration — from the default *.cloudfront.net URL to the custom domain mimifasol.com / docs.mimifasol.com (Route 53 + ACM, apex Alias). The step-by-step procedure is the runbook [[deploy-custom-domain-route53-acm-cloudfront]]; this note is the concept behind it.

What It Is

When you serve a static site from S3 + CloudFront, you can reach it either through the default CloudFront URL that AWS generates (e.g. d1234xyz.cloudfront.net) or through a custom domain you own (e.g. docs.example.com). Both serve the exact same content from the same distribution. The difference is the address and the plumbing (DNS + TLS certificate) required behind it.

Why It Matters

Choosing between them is a classic first decision when hosting a static site cheaply on AWS. It affects setup effort, recurring cost, and whether the URL is memorable and “yours”. It is also a common certification topic (CloudFront, ACM, Route 53 alias records). Importantly, the choice is not irreversible — you can start with the default URL and add a custom domain later with no rebuild.

Key Concepts

Default CloudFront URL

  • Provided automatically the moment the distribution is created — no configuration.
  • HTTPS works immediately: AWS manages the TLS certificate for *.cloudfront.net at no cost.
  • The URL is not memorable, not “yours”, and changes if the distribution is recreated.

Custom Domain

Requires three pieces of plumbing wired to the existing distribution:

PieceDetail
ACM certificatePublic TLS cert for your domain. Must be requested in us-east-1 (CloudFront only reads ACM certs from N. Virginia). Free. Validated via a DNS CNAME record; auto-renews for life.
CloudFront configAdd the domain under Alternate domain names (CNAMEs) and attach the ACM certificate.
DNS recordPoint the domain at the distribution (alias or CNAME — see below).

DNS Options for a Custom Domain

  • Route 53: use an Alias A (and AAAA for IPv6) record to the distribution. AWS-specific, free, and able to point an apex (root) domain at CloudFront.
  • External DNS (OVH, Gandi, Cloudflare): use a CNAME from docs.example.com to d1234xyz.cloudfront.net. Works well for a subdomain.
  • Apex / root domain: a plain CNAME at the root is forbidden by the DNS standard. Use Route 53 alias, a registrar that offers CNAME flattening / ALIAS, or simply prefer a subdomain (docs.) to avoid the problem entirely.

How It Works

Both options terminate at the same CloudFront distribution, which pulls objects from a private S3 bucket (ideally locked down with Origin Access Control). The only thing that changes is how the request’s hostname is resolved and which TLS certificate CloudFront presents:

  • Default URL → DNS for *.cloudfront.net is AWS-managed, cert is AWS-managed. Zero setup.
  • Custom domain → your DNS resolves your hostname to the distribution, and CloudFront presents the ACM cert you attached for that hostname.

Examples

Cost comparison (low personal traffic: a few visitors/day, a few MB)

ItemDefault URLCustom Domain
CloudFront egress~$0 (free tier)~$0 (free tier)
S3 storage (few MB)a few centsa few cents
ACM certificate—Free
Route 53 hosted zone—$0.50/month per zone (only if DNS is on Route 53)
Domain name—~$10–15/year, varies by TLD

Net: default URL ≈ $0. Custom domain ≈ price of the domain + $0 to $0.50/month depending on where DNS is hosted. The certificate is never a cost.

Migrating from default URL to custom domain later

No rebuild needed — it is an additive config change on the existing distribution:

  1. Request an ACM certificate in us-east-1 for the domain.
  2. Add the domain under Alternate domain names and attach the cert.
  3. Create the DNS record (alias or CNAME) pointing at the distribution.

The S3 bucket, distribution, content, and build pipeline stay identical. The *.cloudfront.net URL keeps working in parallel.

Gotchas

  • ACM region trap: the certificate for CloudFront must live in us-east-1, even if the bucket/content is elsewhere. A cert in another region will not appear in the CloudFront dropdown.
  • Apex CNAME is illegal: cannot put a plain CNAME on the root domain. Use Route 53 alias, CNAME flattening, or a subdomain.
  • Adding a domain to CloudFront without also configuring the matching ACM cert will fail TLS.
  • Route 53 charges $0.50/month per hosted zone regardless of traffic — keep DNS on an external registrar to avoid it if cost is the priority.
  • The default URL is tied to the distribution; recreate the distribution and the URL changes. A custom domain is stable across rebuilds.

See Also

  • [[deploy-custom-domain-route53-acm-cloudfront]]
  • [[route53-alias-vs-cname]]
  • [[adr-001-s3-cloudfront-personal-site-hosting]]
  • [[aws-budgets-cost-controls]]
  • [[s3-fundamentals]]

title: “Learnings — Compute” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • compute

Compute

Atomic notes on AWS compute services — EC2, Lambda, ECS, EKS, Fargate, Batch.

Notes


title: “Learnings — Databases” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • databases

Databases

Atomic notes on AWS database services — RDS, DynamoDB, Aurora, ElastiCache, Redshift.

Notes


title: “Learnings — DevOps” created: 2026-07-20 updated: 2026-10-28 type: knowledge tags:

  • aws
  • certification
  • devops

DevOps

Atomic notes on AWS DevOps — CI/CD, CodePipeline, CodeBuild, CodeDeploy, Infrastructure as Code.

Notes

  • [[aws-cli-s3-commands]] — High-level S3 CLI commands (cp, ls, sync), permissions mapping
  • [[ssm-session-manager]] — Secure shell access to EC2 without SSH, audit logging
  • [[cloudfront-s3-cli-cheat-sheet]] — Acronyms (OAC, OAI, ACM…) + CLI commands for the S3/CloudFront deploy (Phase 1)
  • [[route53-acm-cloudfront-custom-domain-cheat-sheet]] — Acronyms (CNAME, apex, AAAA, Alias…), Route 53 record properties, and commands for the custom-domain flow (Phase 2)

Runbooks

  • [[deploy-static-site-s3-cloudfront-oac]] — Build + deploy the mdBook site to S3 + CloudFront + OAC (Phase 1, CLI)
  • [[deploy-custom-domain-route53-acm-cloudfront]] — Register the domain in Route 53, ACM cert (us-east-1), attach to CloudFront, apex Alias (Phase 2, console)

Decisions (ADR)

  • [[adr-001-infra-tooling-static-site]] — Infra tooling for the mdBook static site: CLI learning pass, then CDK

title: “ADR-001 — Infrastructure tooling for the mdBook static site deployment” created: 2026-10-23 updated: 2026-10-23 type: adr status: accepted tags:

  • aws
  • certification
  • devops
  • iac
  • decision

ADR-001 — Infrastructure tooling for the mdBook static site deployment

Status

accepted

Context

The bhu-docs mdBook static site (public/book/) must be deployed on AWS using an S3 + CloudFront + OAC + ACM architecture. This is a personal, low-traffic setup.

The decision at hand is which tool to use to provision the infrastructure — not the architecture itself (the three target resources are the same regardless of tool: one S3 bucket, one CloudFront distribution with Origin Access Control, one ACM certificate in us-east-1).

Key constraints and priorities:

  • Learning context: preparing for the AWS Certified Cloud Practitioner (CLF-C02). Pedagogical value matters.
  • Idempotence: the setup should be re-runnable without side effects.
  • Reproducibility: it must be easy to tear down and recreate the whole stack.
  • Maintainability for a solo, occasional operator.

Decision

Adopt a two-phase approach:

  1. Phase 1 — AWS CLI (learning pass). Provision the three resources with linear, readable aws CLI commands, run step by step, to understand the actual API calls and their dependency order. Defensive code is explicitly out of scope in this phase (no “already exists?” checks, no retries, no error handling) — it would add noise and hide the very sequence we want to learn.
  2. Phase 2 — AWS CDK (production pass). Once the mechanics are understood, rebuild the infrastructure cleanly with the AWS CDK. This phase owns idempotence, clean teardown (cdk destroy), and maintainability.

CDK was chosen over Terraform as the final tool primarily because its engine, CloudFormation, is part of the CLF-C02 exam scope, so the deployment doubles as exam revision. CloudFormation also manages state server-side (in the stack), so there is no local state file to safeguard.

Options Considered

Option A — AWS CLI (bash scripts)

  • Pros:
    • Maximum transparency: each command maps directly to an AWS API call.
    • Nothing extra to install (SSO-configured AWS CLI already available).
    • Best option to understand what actually happens behind each resource.
  • Cons:
    • Not idempotent by nature; re-running errors out or duplicates.
    • No state, no clean teardown — requires a separate, hand-maintained teardown script (empty bucket before delete, disable CloudFront distribution before removal, ~15 min propagation wait).
    • CloudFront + OAC + ACM is verbose (large JSON config, manual DNS validation).

Option B — Terraform

  • Pros:
    • Idempotent by design (plan / apply).
    • terraform destroy tears everything down in the correct order — strong fit for destroy/recreate.
    • Large community, many copyable “S3 + CloudFront + OAC” examples.
    • High transferable professional value (multi-cloud, widely used).
  • Cons:
    • State management is the operator’s responsibility (terraform.tfstate must not be lost; remote S3 backend introduces a chicken-and-egg bootstrap).
    • HCL is an additional language to learn.
    • Out of scope for CLF-C02.

Option C — AWS CDK

  • Pros:
    • 100% AWS-native; CloudFormation/CDK are in the CLF-C02 exam scope (revision + build).
    • State managed by AWS inside the CloudFormation stack — no local state file.
    • High-level constructs (L2/L3) pre-wire OAC, bucket policy, and the ACM↔CloudFront link, so far less code than CLI or Terraform.
    • Can be written in a familiar language (TypeScript, Python, or Java).
  • Cons:
    • Heaviest toolchain to install/understand (Node.js + CDK CLI + cdk bootstrap).
    • Abstraction hides detail — worse for learning the raw mechanics than the CLI.
    • CloudFormation rollback states can be confusing for beginners.

Consequences

Positive:

  • The CLI-first pass builds genuine understanding of the API-level steps and their dependencies, which transfers directly to CLF-C02 concepts.
  • The CDK endgame gives idempotence, one-command teardown/recreate, no local state to guard, and exam-relevant CloudFormation experience.

Negative / trade-offs:

  • Doing two passes costs more time than going straight to CDK.
  • The CLI pass is intentionally throwaway and not maintainable — that is accepted and by design.

Notes:

  • The ACM certificate for CloudFront must be created in us-east-1 (AWS constraint). The account already defaults to us-east-1, so this is transparent, but it is a classic detail a CLI pass must handle manually.

See Also

  • [[aws-cli-s3-commands]] — High-level vs low-level S3 CLI commands
  • [[README]] — DevOps learnings index

title: “AWS CLI S3 Commands” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • cli
  • devops
  • certification

AWS CLI S3 Commands

What It Is

The AWS CLI provides two command groups for interacting with S3:

  • aws s3 — high-level commands (cp, mv, ls, sync, rm) that feel like Unix file operations
  • aws s3api — low-level 1:1 mapping to S3 API operations (for fine-grained control)

Why It Matters

The CLI is the primary way to interact with S3 from EC2 instances, scripts, and CI/CD pipelines. Exam questions often test whether you understand the correct command and required permissions.

Key Concepts

High-Level Commands (aws s3)

CommandDescriptionExample
lsList buckets or objectsaws s3 ls s3://mybucket/
cpCopy file to/from S3aws s3 cp file.txt s3://mybucket/
mvMove (copy + delete source)aws s3 mv s3://mybucket/old.txt s3://mybucket/new.txt
rmDelete an objectaws s3 rm s3://mybucket/file.txt
syncSync directory with bucketaws s3 sync ./local/ s3://mybucket/prefix/
mbMake bucketaws s3 mb s3://new-bucket-name
rbRemove bucketaws s3 rb s3://bucket --force

Required Permissions per Command

CLI CommandS3 Permission Needed
aws s3 lss3:ListBucket
aws s3 ls s3://bucket/s3:ListBucket
aws s3 cp local s3://s3:PutObject
aws s3 cp s3:// locals3:GetObject
aws s3 rms3:DeleteObject

Authentication

  • On EC2 with an Instance Profile: credentials are automatic (no config needed)
  • Locally: uses ~/.aws/credentials or environment variables
  • The CLI checks credentials in this order: env vars → config file → instance profile

Useful Flags

  • --recursive — apply to all objects under a prefix
  • --exclude / --include — filter files in sync/cp operations
  • --dryrun — preview what would happen without executing

Examples

# List all buckets
aws s3 ls

# List objects in a bucket
aws s3 ls s3://reportbucket-123456/

# Upload a file
aws s3 cp report.txt s3://reportbucket-123456/

# Download a file
aws s3 cp s3://reportbucket-123456/report.txt ./report.txt

# Sync a local directory to S3
aws s3 sync ./reports/ s3://reportbucket-123456/reports/ --delete

Gotchas

  • aws s3 ls (no argument) lists buckets — requires s3:ListAllMyBuckets
  • aws s3 ls s3://bucket lists objects — requires s3:ListBucket on the bucket
  • Upload failure usually means missing s3:PutObject permission, not a CLI issue
  • sync --delete removes destination files not present in source — use carefully

See Also

  • [[s3-object-operations]]
  • [[iam-instance-profiles]]
  • [[s3-bucket-policies]]

title: “CloudFront + S3 Deployment” created: 2026-10-26 updated: 2026-10-28 type: cheat-sheet tags:

  • aws
  • certification
  • cheat-sheet
  • cloudfront
  • s3
  • oac
  • cli
  • clf-c02

CloudFront + S3 Deployment — Cheat Sheet

Quick reference for the S3 + CloudFront + OAC static-site pattern and the AWS CLI commands used to deploy it. Built from the real Phase 1 deployment (see runbook [[deploy-static-site-s3-cloudfront-oac]]).

Acronyms

AcronymFull nameWhat it is / why it matters (CLF-C02)
OACOrigin Access ControlCurrent, recommended way to let only CloudFront read a private S3 bucket. Signs origin requests with SigV4. Supports SSE-KMS, all regions, more HTTP methods.
OAIOrigin Access IdentityLegacy predecessor of OAC. Still works but AWS recommends OAC for new setups. If the exam shows OAI, know it’s the old way.
CDNContent Delivery NetworkCloudFront itself — caches content at edge locations near users to cut latency and origin load.
ACMAWS Certificate ManagerIssues/manages free public TLS certs. For CloudFront, the cert must be in us-east-1. Not needed for the default *.cloudfront.net URL; required once a custom domain is added (Phase 2, now done — see [[deploy-custom-domain-route53-acm-cloudfront]]).
SigV4Signature Version 4AWS request-signing algorithm. OAC uses it to prove an origin request really came from your distribution.
TTLTime To LiveHow long CloudFront caches an object before re-checking the origin. Invalidation forces an early refresh.
PoPPoint of PresenceAn edge location (e.g. FRA56 = Frankfurt). Shown in the x-amz-cf-pop response header.
SSEServer-Side EncryptionEncryption at rest for S3 objects (e.g. SSE-S3/AES256). OAC works with encrypted objects; OAI struggles with SSE-KMS.
BPABlock Public AccessS3 safety switch (4 settings) that keeps a bucket private even if a policy/ACL would expose it. Kept ON here.
ARNAmazon Resource NameUnique ID for an AWS resource. The bucket policy scopes read access to the distribution’s ARN.
CDKCloud Development KitInfrastructure-as-code in a real language. Candidate for a later IaC rewrite (Phase 1 deploy is CLI; Phase 2 custom domain was done via the console).

Why a private bucket (not S3 static website hosting)?

Private bucket + CloudFront + OACPublic S3 website endpoint
Public exposureNone — bucket stays privateBucket readable by anyone
HTTPSYes (CloudFront)No (S3 website endpoint is HTTP only)
Caching / CDNYesNo
Cost on readsCheaper (cached egress)Direct S3 GET per request
Extras (WAF, geo)AvailableNot available

Quick Reference — CLI commands used

CommandDescription
aws sts get-caller-identityWho am I / which account (verify auth)
aws configure get regionShow configured default region
aws s3api create-bucketCreate the bucket (low-level API)
aws s3api put-public-access-blockEnforce Block Public Access (keep private)
aws s3api put-bucket-policyAttach policy allowing only the distribution
aws cloudfront create-origin-access-controlCreate the OAC
aws cloudfront create-distribution-with-tagsCreate the distribution (+ tags)
aws cloudfront get-distributionRead status / domain name
aws cloudfront wait distribution-deployedBlock until Deployed (built-in waiter)
aws s3 sync ... --deleteUpload content, mirror deletions
aws cloudfront create-invalidation --paths "/*"Clear the edge cache
aws cloudfront get-invalidationCheck invalidation InProgress/Completed

Common Patterns

Check deployment status / progress

DIST_ID=<your-dist-id>

# Status: InProgress -> Deployed
aws cloudfront get-distribution --id "$DIST_ID" \
  --query 'Distribution.{Status:Status,Domain:DomainName}' --output table

# Block until live
aws cloudfront wait distribution-deployed --id "$DIST_ID"

Test the live site

DOMAIN=<id>.cloudfront.net
curl -sI "http://$DOMAIN"  | head -n1   # expect 301 -> HTTPS
curl -sI "https://$DOMAIN" | head -n1   # expect 200

Useful response headers to read:

  • x-cache: Hit from cloudfront → served from edge cache (not origin)
  • x-amz-cf-pop: FRA56-P5 → edge location (Frankfurt)
  • x-amz-server-side-encryption: AES256 → objects encrypted at rest

Upload only changed files + refresh cache

aws s3 sync ./public/book/ s3://my-bucket/ --delete
aws cloudfront create-invalidation --distribution-id "$DIST_ID" --paths "/*"

Minimal private-bucket policy (OAC)

{
  "Effect": "Allow",
  "Principal": { "Service": "cloudfront.amazonaws.com" },
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::<acct>:distribution/<DIST_ID>" } }
}

Tips & Tricks

  • us-east-1 for CloudFront: distributions are global, but ACM certs for CloudFront must live in us-east-1. Keep everything there to avoid surprises.
  • New distribution ≈ 5–10 min to deploy; the domain may not resolve until then — expected, not a failure.
  • Invalidations: first 1,000 paths/month are free; /* counts as one path.
  • create-bucket + us-east-1: do NOT pass LocationConstraint for us-east-1 (it errors); it IS required for every other region.
  • Delete order: a distribution must be disabled AND Deployed before it can be deleted — the destroy script waits for you.
  • s3 sync --delete mirrors deletions to the bucket — safe here (bucket is dedicated to the site), dangerous on shared buckets.

Exam Gotchas (CLF-C02)

  • OAC = modern, OAI = legacy → prefer OAC.
  • CloudFront cert → us-east-1 only.
  • Default *.cloudfront.net URL already has free managed HTTPS — no ACM needed. A custom domain needs an ACM cert in us-east-1 + an alternate domain name + a DNS record (done for mimifasol.com — see [[deploy-custom-domain-route53-acm-cloudfront]]).
  • Private bucket + CloudFront is the recommended secure static-site pattern, not the public S3 website endpoint.
  • Block Public Access is defense in depth — keep it on even with a scoped policy.

See Also

  • [[deploy-static-site-s3-cloudfront-oac]]
  • [[deploy-custom-domain-route53-acm-cloudfront]]
  • [[route53-acm-cloudfront-custom-domain-cheat-sheet]]
  • [[cloudfront-custom-domain-vs-default-url]]
  • [[adr-001-s3-cloudfront-personal-site-hosting]]
  • [[aws-cli-s3-commands]]
  • [[s3-access-without-public]]
  • [[s3-block-public-access]]

title: “Deploy a Custom Domain to CloudFront with Route 53 + ACM” created: 2026-10-28 updated: 2026-10-28 type: runbook tags:

  • aws
  • certification
  • devops
  • route53
  • acm
  • cloudfront
  • dns
  • tls
  • deployment

Deploy a Custom Domain to CloudFront with Route 53 + ACM

Purpose

Register the domain mimifasol.com in AWS Route 53, issue a public TLS certificate for it in ACM (us-east-1), attach the domain to the existing CloudFront distribution as an alternate domain name, and point the apex at the distribution with Alias A + AAAA records. End state: the Phase 1 private S3 + CloudFront + OAC site is reachable at https://mimifasol.com.

This is Phase 2 (custom domain) of the bhu-docs public site. Phase 1 (private bucket, CloudFront, OAC, default *.cloudfront.net URL) is described in [[deploy-static-site-s3-cloudfront-oac]]. The DNS theory behind the apex Alias requirement is in [[route53-alias-vs-cname]] and [[route53-dns-records]].

This runbook is console-first (each screen is described, for certification study), with equivalent/verification CLI commands next to each step.

Prerequisites

  • Active SSO session (aws login) — credentials last 12h, us-east-1
  • Phase 1 deployed: CloudFront distribution serving the site on its *.cloudfront.net URL (see public/.deploy-state for the live IDs)
  • Correct account + region us-east-1 (account/resource IDs live in private config — bhu-skills steering and the gitignored public/.deploy-state — never in this published note)
  • AWS CLI v2 + jq (for the verification commands)
  • Budget awareness: .com registration is $16/year (STANDARD price, billed immediately, non-refundable); a Route 53 hosted zone is $0.50/month; ACM public certs are free

Key Facts (read before starting)

  • route53domains (registration) is us-east-1 only — the registrar API and console live there regardless of your default region.
  • ACM cert for CloudFront must be in us-east-1 — CloudFront only reads certs from N. Virginia. If you issue it anywhere else, it will not appear in the distribution’s certificate picker.
  • Apex needs an Alias, not a CNAME — mimifasol.com already has NS + SOA, so a CNAME there is illegal (RFC 1034). Route 53 Alias A/AAAA is the fix. See [[route53-alias-vs-cname]].
  • Registering a domain auto-creates a hosted zone with the same name and its NS/SOA records. Use that zone for everything else.

Procedure

Step 1 — Register mimifasol.com in Route 53

Console: Route 53 → Domains → Registered domains → Register domains.

  1. Search box: type mimifasol.com, click Check. Confirm it shows Available. Add to cart, Continue.
  2. Contact details: fill registrant / admin / tech contact (one block, reusable for all three). Real data is required by ICANN.
  3. Privacy protection: leave Enabled (default) — hides personal contact data in public WHOIS, free with Route 53.
  4. Auto-renew: leave Enabled so the domain does not silently expire.
  5. Review, accept the ICANN agreement, Complete order.

Registration is asynchronous. Status goes from the order being submitted to the domain appearing under Registered domains. .com is usually a few minutes but can take up to ~1 hour (occasionally longer for other TLDs).

Billing / payment — there is no separate card entry in the register flow. Clicking Complete order charges the payment method already on file for the AWS account (the same one used for S3/CloudFront). The $16 appears as a Route 53 domain-registration line item on the regular AWS bill, charged ~on order (not deferred to month-end). To pre-check: Billing and Cost Management → Payment methods → confirm a valid, non-expired card is present (changing the payment method itself is typically a root-user action; using the existing one is not). With auto-renew ON, next year’s fee is charged automatically to the same method ~1 month before expiry — disable auto-renew to let the domain lapse (see Rollback). See [[aws-budgets-config]].

CLI check / verify:

# Availability (registrar API is us-east-1 only)
aws route53domains check-domain-availability \
  --domain-name mimifasol.com --region us-east-1
# -> "Availability": "AVAILABLE"

# After ordering, track operation + registration
aws route53domains list-operations --region us-east-1
aws route53domains list-domains --region us-east-1

Registration automatically creates a public hosted zone for mimifasol.com. Grab its ID (used in later steps):

aws route53 list-hosted-zones-by-name \
  --dns-name mimifasol.com \
  --query 'HostedZones[0].Id' --output text
# -> /hostedzone/ZXXXXXXXXXXXXX

This deployment (2026-10-28): registration operation REGISTER_DOMAIN returned SUCCESSFUL after ~11 min. A public hosted zone was auto-created (2 records = NS + SOA), expiry 2027-10-28, auto-renew ON. The site’s existing CloudFront distribution was reused; its assigned *.cloudfront.net domain is the Alias target in Step 5 (note it is not derived from the distribution ID — read it with get-distribution). Concrete IDs are kept in private config (bhu-skills steering + gitignored public/.deploy-state), not here.

Step 2 — Request the ACM certificate (us-east-1)

Console: Certificate Manager → Request certificate (confirm the region selector top-right reads N. Virginia / us-east-1 first).

  1. Choose Request a public certificate, Next.
  2. Fully qualified domain name: mimifasol.com.
  3. Add another name: *.mimifasol.com (wildcard — covers benoit., docs., ohmb., … in one cert).
  4. Validation method: DNS validation (recommended — renews automatically as long as the DNS record stays in place).
  5. Key algorithm: leave RSA 2048 (default).
  6. Request. The cert appears with status Pending validation.

CLI equivalent:

aws acm request-certificate \
  --domain-name mimifasol.com \
  --subject-alternative-names '*.mimifasol.com' \
  --validation-method DNS \
  --region us-east-1
# -> "CertificateArn": "arn:aws:acm:us-east-1:<ACCOUNT_ID>:certificate/<CERT_ID>"

Step 3 — Validate the certificate via Route 53 DNS

Console: open the certificate → Domains section → button Create records in Route 53.

  1. ACM shows one CNAME validation record per distinct name. Because both names share the same base domain, ACM typically shows one _<hash>.mimifasol.com CNAME covering the pair.
  2. Click Create records in Route 53 → ACM writes the CNAME(s) straight into the mimifasol.com hosted zone. Create records.
  3. Wait. Status flips Pending validation → Issued, usually a few minutes (can be up to ~30 min).

These _<hash> CNAMEs are validation-only records; leave them in the zone forever so ACM can auto-renew the cert.

This deployment (2026-10-28): the cert was issued in us-east-1. As expected, both names (mimifasol.com + *.mimifasol.com) shared a single validation CNAME (_<hash>.mimifasol.com → _<hash>.acm-validations.aws). The concrete cert ARN and validation hashes are kept in private config, not in this published note.

CLI equivalent (only if not using the console button):

# Inspect the validation records ACM wants
aws acm describe-certificate --certificate-arn "$CERT_ARN" \
  --region us-east-1 \
  --query 'Certificate.DomainValidationOptions[].ResourceRecord'

# Block until issued
aws acm wait certificate-validated \
  --certificate-arn "$CERT_ARN" --region us-east-1

Step 4 — Attach the domain to the CloudFront distribution

Console: CloudFront → Distributions → (the bhu-docs distribution) → General → Settings → Edit.

  1. Alternate domain names (CNAMEs): Add item → mimifasol.com, then Add item again → docs.mimifasol.com. Both are served by this distribution: the apex as a temporary landing (umbrella not built yet) and docs. as the real home of the bhu-docs site. Both are already covered by the cert (mimifasol.com + the *.mimifasol.com wildcard).
  2. Custom SSL certificate: switch from Default CloudFront certificate to Custom, then pick the mimifasol.com ACM cert from the dropdown.
    • If it is not in the list, the cert is not Issued or not in us-east-1 — recheck Step 2/3.
  3. Leave Security policy at the recommended default (TLSv1.2_2021).
  4. Save changes. The distribution status goes Deploying; wait for it to finish (~5–10 min) before testing.

CLI verify:

DIST_ID=$(grep DIST_ID ~/work/skills/bhu-docs/public/.deploy-state | cut -d= -f2)
aws cloudfront get-distribution --id "$DIST_ID" \
  --query 'Distribution.{Status:Status,Aliases:DistributionConfig.Aliases.Items,Cert:DistributionConfig.ViewerCertificate.ACMCertificateArn}'
aws cloudfront wait distribution-deployed --id "$DIST_ID"

Step 5 — Create the Alias records (apex + docs., A + AAAA)

Console: Route 53 → Hosted zones → mimifasol.com → Create record.

Create four records total: A + AAAA for the apex, A + AAAA for docs..

Apex (mimifasol.com):

  1. Record name: leave empty (= apex mimifasol.com).
  2. Record type: A – IPv4 address.
  3. Alias: toggle ON.
  4. Route traffic to: Alias to CloudFront distribution → region shows automatically → pick the distribution *.cloudfront.net domain.
  5. Create record.
  6. Repeat 1–5 with Record type = AAAA (IPv6) pointing at the same distribution. Both A and AAAA are needed so the site resolves on IPv4 and IPv6.

Sub-domain (docs.mimifasol.com):

  1. Create record again, Record name: docs.
  2. Record type A, Alias ON, Alias to CloudFront distribution, same distribution. Create record.
  3. Repeat with Record type AAAA for docs.

Apex = Alias, mandatory. A CNAME at the apex is rejected because of the existing NS/SOA records. A sub-domain like docs. could use a CNAME, but we use Alias there too for consistency and free resolution. See [[route53-alias-vs-cname]].

CLI equivalent (change batch):

ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name mimifasol.com \
  --query 'HostedZones[0].Id' --output text)
CF_DOMAIN=$(aws cloudfront get-distribution --id "$DIST_ID" \
  --query 'Distribution.DomainName' --output text)
# CloudFront's fixed Alias hosted-zone ID is always Z2FDTNDATAQYW2
cat > /tmp/apex-alias.json <<JSON
{"Changes":[
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"mimifasol.com","Type":"A",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}},
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"mimifasol.com","Type":"AAAA",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}},
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"docs.mimifasol.com","Type":"A",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}},
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"docs.mimifasol.com","Type":"AAAA",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}}
]}
JSON
aws route53 change-resource-record-sets \
  --hosted-zone-id "$ZONE_ID" --change-batch file:///tmp/apex-alias.json

Verification

# DNS resolves both names to CloudFront edge IPs (A + AAAA).
# NOTE: `dig` is NOT installed by default on Ubuntu 24.04 (it ships in the
# `bind9-dnsutils` package: `sudo apt install bind9-dnsutils`). If `dig` is
# missing, use `getent` (always present) or `nslookup`, or just rely on the
# curl check below — a 200 proves DNS resolved.
dig +short A    mimifasol.com            # or: getent ahosts mimifasol.com
dig +short AAAA mimifasol.com
dig +short A    docs.mimifasol.com       # or: getent ahosts docs.mimifasol.com
dig +short AAAA docs.mimifasol.com

# TLS + HTTP: HTTP should 301 -> HTTPS; HTTPS should 200 (both names)
curl -sI http://mimifasol.com       | head -n1     # 301
curl -sI https://mimifasol.com      | head -n1     # HTTP/2 200
curl -sI https://docs.mimifasol.com | head -n1     # HTTP/2 200

# Certificate CN/SAN served matches the domain
echo | openssl s_client -connect mimifasol.com:443 -servername mimifasol.com 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName

Open https://mimifasol.com and https://docs.mimifasol.com in a browser: valid padlock, no name-mismatch warning, and the mdBook site loads.

This deployment (2026-10-28) — all checks passed:

  • DNS: both names resolve to the same CloudFront edges — IPv4 18.66.112.{2,6,14,37}, IPv6 2600:9000:223f:... (A + AAAA).
  • http://mimifasol.com → 301; https://mimifasol.com and https://docs.mimifasol.com → HTTP/2 200.
  • Cert served: subject=CN=mimifasol.com, SAN DNS:mimifasol.com, DNS:*.mimifasol.com.
  • Tooling note: dig/nslookup were absent; used getent ahosts and nc -vz <host> 443 instead — both work out of the box on this Ubuntu.

Rollback

  • Detach domain from CloudFront: edit the distribution, remove the alternate domain names (mimifasol.com, docs.mimifasol.com), switch the certificate back to Default CloudFront certificate, save. The site returns to the *.cloudfront.net URL.
  • Remove DNS records: delete the apex and docs. A + AAAA alias records in the hosted zone. (Keep the ACM _<hash> validation CNAMEs if you may reattach later.)
  • Certificate: an unused ACM cert costs nothing; delete it only if you are sure. A cert in use by CloudFront cannot be deleted until detached.
  • Domain registration is NOT easily reversible — .com is billed on registration and is non-refundable. Do not register unless committed. You can disable auto-renew to let it lapse at year end.

Notes

  • Timing: domain registration (minutes to ~1h), ACM validation (minutes to ~30 min), CloudFront redeploy (~5–10 min). The apex Alias itself resolves almost immediately once the distribution is deployed.
  • Cost: .com ~$13/yr (non-refundable), hosted zone $0.50/mo, ACM public cert free, Alias queries to AWS targets free. See [[aws-budgets-config]].
  • Wildcard cert covers one level (*.mimifasol.com), not nested (*.*.mimifasol.com). One cert now serves every planned sub-domain (benoit., docs., ohmb., …).
  • Why not CNAME at apex: NS + SOA already live there; RFC 1034 forbids a CNAME coexisting with other records. Route 53 Alias sidesteps this by looking like an A record. See [[route53-dns-records]].
  • Sub-domains later: each new sub-domain = one Alias (or CNAME) record in the zone + adding it as a CloudFront alternate domain name (already covered by the wildcard cert).

See Also

  • [[route53-acm-cloudfront-custom-domain-cheat-sheet]]
  • [[deploy-static-site-s3-cloudfront-oac]]
  • [[cloudfront-s3-cli-cheat-sheet]]
  • [[cloudfront-custom-domain-vs-default-url]]
  • [[route53-alias-vs-cname]]
  • [[route53-dns-records]]
  • [[umbrella-domain-musical-name]]
  • [[adr-001-s3-cloudfront-personal-site-hosting]]

title: “Deploy the mdBook Static Site to S3 + CloudFront + OAC” created: 2026-10-26 updated: 2026-10-28 type: runbook tags:

  • aws
  • certification
  • devops
  • s3
  • cloudfront
  • oac
  • deployment

Deploy the mdBook Static Site to S3 + CloudFront + OAC

Purpose

Build the public mdBook site (bhu-docs/public/book/) and deploy it to AWS as a private S3 bucket fronted by CloudFront, where CloudFront is the only reader (authorized via Origin Access Control). HTTPS is served on the default *.cloudfront.net URL. This is Phase 1 (AWS CLI, no custom domain, no ACM).

Phase 2 (custom domain) is done — mimifasol.com / docs.mimifasol.com now front this same distribution via Route 53 + ACM. See [[deploy-custom-domain-route53-acm-cloudfront]].

See the design rationale in [[adr-001-s3-cloudfront-personal-site-hosting]] and the domain/URL discussion in [[cloudfront-custom-domain-vs-default-url]].

Prerequisites

  • AWS CLI v2 installed (aws --version)
  • Active SSO session (aws login) — credentials last 12h
  • jq installed (jq --version) — the scripts parse JSON with it
  • Region us-east-1, correct account (the IDs live in private config, not here)
  • Site built: bhu-docs/public/book/index.html exists

Architecture

Visitor ──HTTPS──> CloudFront (edge, e.g. FRA56 Frankfurt)
                        │  cache miss
                        │  SigV4-signed origin request (OAC)
                        ▼
                   S3 bucket (PRIVATE, Block Public Access ON)
                   bucket policy: allow ONLY this distribution ARN
ResourcePurpose
S3 bucket (private)Origin — stores the HTML/CSS/JS. Never public.
OACLets only this CloudFront distribution read the bucket (SigV4).
CloudFront distributionCDN + HTTPS + cache; the single reader of the bucket.
Bucket policyGrants s3:GetObject to the CloudFront service principal, scoped to the distribution ARN.

Procedure

The whole flow is two scripts in bhu-docs/scripts/. Both are idempotent (deploy) / safe (destroy with typed confirmation).

Step 1 — Build the static site

bash ~/work/skills/bhu-docs/scripts/build-public.sh

Expected output:

✓ Build public terminé -> .../public/book/

Step 2 — Deploy to AWS

bash ~/work/skills/bhu-docs/scripts/deploy-public.sh

What it does (6 steps): create/ensure private bucket → ensure OAC → ensure distribution → apply bucket policy → s3 sync → invalidate cache. It prints the site URL and writes resource IDs to public/.deploy-state (gitignored).

Expected tail:

Site URL : https://<id>.cloudfront.net
Dist ID  : <DIST_ID>

Step 3 — Update content later (re-deploy)

Just re-run build + deploy. The script reuses the existing bucket, OAC, and distribution (found by stable name/comment) and only syncs changed files + invalidates the cache. No duplicate resources.

bash ~/work/skills/bhu-docs/scripts/build-public.sh
bash ~/work/skills/bhu-docs/scripts/deploy-public.sh

Verification

DIST_ID=$(grep DIST_ID ~/work/skills/bhu-docs/public/.deploy-state | cut -d= -f2)

# Distribution status: InProgress -> Deployed (~5-10 min on first create)
aws cloudfront get-distribution --id "$DIST_ID" \
  --query 'Distribution.Status' --output text

# Block until fully deployed (built-in waiter)
aws cloudfront wait distribution-deployed --id "$DIST_ID"

# HTTP should 301 -> HTTPS; HTTPS should 200
DOMAIN=$(grep DIST_DOMAIN ~/work/skills/bhu-docs/public/.deploy-state | cut -d= -f2)
curl -sI "http://$DOMAIN"  | head -n1    # HTTP/1.1 301 Moved Permanently
curl -sI "https://$DOMAIN" | head -n1    # HTTP/2 200

A 200 with headers x-cache: Hit from cloudfront and x-amz-cf-pop: FRA56-* confirms the edge (Frankfurt) is serving cached content from the us-east-1 origin — the CDN working as intended.

Rollback / Cleanup

Tear down every resource to avoid residual cost. Destructive and irreversible; the site goes offline.

bash ~/work/skills/bhu-docs/scripts/destroy-public.sh   # type: destroy

Order matters (and the script handles it): disable distribution → wait for Deployed → delete distribution → delete OAC → empty + delete bucket. A CloudFront distribution must be disabled and fully deployed before it can be deleted (the wait can take several minutes).

Notes

  • First-create timing: a new distribution takes ~5–10 min to reach Deployed. Until then, the *.cloudfront.net host may not resolve (curl: (6) Could not resolve host) — this is expected, not an error.
  • Cost: effectively ~$0 at this scale (CloudFront free tier 1 TB/10M req per month; S3 a few cents; invalidations 1,000 paths/month free). See [[aws-budgets-cost-controls]].
  • OAC vs OAI: OAC is the current recommended mechanism; OAI is legacy. See the cheat-sheet [[cloudfront-s3-cli-cheat-sheet]] and [[s3-access-without-public]].
  • Idempotency: the deploy script discovers resources by deterministic name (bucket), OAC name, and distribution comment — re-running updates instead of duplicating.
  • Known content wart: udemy-clf-c02-progress.md has unclosed <section> / <domain> HTML tags that mdBook warns about. Site still builds; worth escaping later.

See Also

  • [[cloudfront-s3-cli-cheat-sheet]]
  • [[adr-001-s3-cloudfront-personal-site-hosting]]
  • [[cloudfront-custom-domain-vs-default-url]]
  • [[s3-access-without-public]]
  • [[s3-block-public-access]]
  • [[aws-cli-s3-commands]]

title: “Route 53 + ACM + CloudFront Custom Domain — Cheat Sheet” created: 2026-10-28 updated: 2026-10-28 type: cheat-sheet tags:

  • aws
  • certification
  • cheat-sheet
  • route53
  • acm
  • cloudfront
  • dns
  • tls
  • clf-c02

Route 53 + ACM + CloudFront Custom Domain — Cheat Sheet

Quick reference for putting a custom domain in front of a CloudFront distribution: register a domain in Route 53, issue an ACM cert, wire DNS. Built from the real mimifasol.com deployment — full procedure in the runbook [[deploy-custom-domain-route53-acm-cloudfront]], theory in [[route53-alias-vs-cname]] and [[route53-dns-records]].

Acronyms & Terms

Acronym / termStands forWhat it is / its roleWhere you meet it
DNSDomain Name SystemThe phone book: turns a name (mimifasol.com) into an address (an IP).Everywhere; the whole point of Route 53.
Route 53(AWS’s 53 = DNS port)AWS’s managed DNS + domain registrar. Holds your records, can buy domains.Console → Route 53.
Hosted zone—The container of all DNS records for one domain. Auto-created when you register in Route 53.Route 53 → Hosted zones → mimifasol.com.
Apexzone apex / root / naked domainThe domain with nothing in front: mimifasol.com (vs docs.mimifasol.com). Always carries NS + SOA.The record with an empty Name in the zone.
Sub-domain—A label in front of the apex: docs., benoit., www..A record whose Name is docs, etc.
AAddress (IPv4)Maps a name → an IPv4 address (18.66.112.6).Record Type = A.
AAAA“quad-A” (IPv6)Maps a name → an IPv6 address (2600:9000:...). Add it so IPv6 clients resolve too.Record Type = AAAA.
CNAMECanonical Name“This name is an alias for another name.” Illegal at the apex (coexists with nothing).Record Type = CNAME (sub-domains only).
Alias—Route 53-only record that looks like an A/AAAA but points at an AWS resource (CloudFront, ELB, S3…). Legal at the apex; free to resolve.Record with Alias = ON.
NSName ServerThe 4 authoritative servers for the zone. Mandatory at the apex.Auto-created in the zone.
SOAStart Of AuthorityZone metadata (primary NS, refresh timers). Mandatory, one per zone.Auto-created in the zone.
TTLTime To LiveHow long resolvers cache a record (seconds). Alias records inherit the target’s TTL (no manual field).On non-alias records.
ACMAWS Certificate ManagerIssues/renews free public TLS certs. For CloudFront the cert must be in us-east-1.Console → Certificate Manager (region N. Virginia).
SANSubject Alternative NameExtra names a cert covers beyond the primary. We used *.mimifasol.com.The cert’s domain list.
Wildcard*.domainA SAN covering one level of sub-domains (docs., benoit.) — not the apex, not nested.The *.mimifasol.com SAN.
TLS / SSLTransport Layer SecurityEncrypts HTTPS; the cert proves the server’s identity.The padlock; CloudFront “Custom SSL certificate”.
CloudFront—AWS CDN; terminates HTTPS and serves cached content from edges.The distribution (ID in private config).
Alternate domain name (CNAME)—The custom hostnames a distribution accepts (confusingly labelled “CNAMEs” in the console — unrelated to CNAME records).Distribution → Settings → Alternate domain names.
Distribution domain—The *.cloudfront.net name CloudFront assigns (e.g. dXXXXXXXXXXXXX.cloudfront.net). Not derived from the distribution ID.get-distribution … DomainName; the Alias target.
OACOrigin Access ControlLets only CloudFront read the private S3 origin. (Phase 1 concept.)See [[cloudfront-s3-cli-cheat-sheet]].

Route 53 Record Properties (the fields you set)

When you create a record in a hosted zone, these are the attributes to understand. Shown for the apex-Alias-to-CloudFront case we built.

PropertyWhat it meansValues / notesOur value
Record nameThe hostname, relative to the zoneEmpty = apex; docs = docs.mimifasol.comempty + docs
Record typeWhat kind of answerA, AAAA, CNAME, MX, TXT, NS, SOA…A and AAAA
AliasToggle: is this a Route 53 Alias?ON → points at an AWS resource; OFF → you type a value/IPON
Route traffic to (Alias ON)Which AWS resource the alias targetsCloudFront, ELB, S3 website, API GW, or another R53 recordAlias to CloudFront distribution
Value/Route traffic to (Alias OFF)The raw record dataAn IP (A/AAAA), a hostname (CNAME), text (TXT)…n/a (we used Alias)
TTLCache lifetime in secondsEditable for non-alias; hidden/managed for Aliasn/a (Alias)
Routing policyHow R53 chooses among multiple recordsSimple, Weighted, Latency, Failover, Geolocation, Multi-valueSimple
Evaluate target healthAlias-only: skip this target if unhealthyYes/No; off for a single static CloudFront targetNo

Apex rule in one line: apex (mimifasol.com) → Alias A/AAAA (CNAME is illegal there); sub-domain (docs.) → Alias or CNAME (we used Alias).

The one magic constant

When creating an Alias-to-CloudFront via CLI/JSON, the AliasTarget needs CloudFront’s fixed global hosted-zone ID:

Z2FDTNDATAQYW2

Same value for every CloudFront distribution worldwide — it tells Route 53 “the target is CloudFront”. (In the console you don’t type it; the dropdown handles it.)

Quick Reference — Commands

CommandDescription
aws route53domains check-domain-availability --domain-name X --region us-east-1Is the domain free? (route53domains is us-east-1 only)
aws route53domains list-domains --region us-east-1List registered domains
aws route53 list-hosted-zones-by-name --dns-name XFind a zone’s ID
aws acm request-certificate --domain-name X --subject-alternative-names '*.X' --validation-method DNS --region us-east-1Request a public cert (us-east-1 for CloudFront)
aws acm describe-certificate --certificate-arn ARN --region us-east-1 --query 'Certificate.Status'Cert status: PENDING_VALIDATION → ISSUED
aws acm wait certificate-validated --certificate-arn ARN --region us-east-1Block until issued
aws cloudfront get-distribution --id ID --query 'Distribution.DomainName'The assigned *.cloudfront.net domain (the Alias target)
aws cloudfront wait distribution-deployed --id IDBlock until the distribution finishes deploying
aws route53 change-resource-record-sets --hosted-zone-id Z… --change-batch file://batch.jsonCreate/update records (Alias A/AAAA)
aws route53 list-resource-record-sets --hosted-zone-id Z…List the zone’s records

Common Patterns

1. Request + validate a cert (us-east-1)

CERT_ARN=$(aws acm request-certificate \
  --domain-name mimifasol.com \
  --subject-alternative-names '*.mimifasol.com' \
  --validation-method DNS --region us-east-1 \
  --query 'CertificateArn' --output text)

# In the ACM console: "Create records in Route 53" (writes the validation CNAME).
aws acm wait certificate-validated --certificate-arn "$CERT_ARN" --region us-east-1

2. Apex + sub-domain Alias → CloudFront (A + AAAA)

DIST_ID=$(grep DIST_ID ~/work/skills/bhu-docs/public/.deploy-state | cut -d= -f2)
ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name mimifasol.com \
  --query 'HostedZones[0].Id' --output text)
CF_DOMAIN=$(aws cloudfront get-distribution --id "$DIST_ID" \
  --query 'Distribution.DomainName' --output text)   # e.g. dXXXXXXXXXXXXX.cloudfront.net

cat > /tmp/alias.json <<JSON
{"Changes":[
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"mimifasol.com","Type":"A",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}},
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"mimifasol.com","Type":"AAAA",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}},
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"docs.mimifasol.com","Type":"A",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}},
 {"Action":"UPSERT","ResourceRecordSet":{"Name":"docs.mimifasol.com","Type":"AAAA",
   "AliasTarget":{"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"$CF_DOMAIN","EvaluateTargetHealth":false}}}
]}
JSON
aws route53 change-resource-record-sets --hosted-zone-id "$ZONE_ID" \
  --change-batch file:///tmp/alias.json

3. Verify end-to-end (no dig needed)

getent ahosts mimifasol.com            # resolves to CloudFront IPs (A + AAAA)
curl -sI http://mimifasol.com  | head -n1     # 301 -> HTTPS
curl -sI https://mimifasol.com | head -n1     # HTTP/2 200
echo | openssl s_client -connect mimifasol.com:443 -servername mimifasol.com 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName   # CN + SAN match

Tips & Tricks

  • ACM region trap: a CloudFront cert MUST be in us-east-1, or it won’t appear in the distribution’s cert dropdown — no matter where the bucket is.
  • Apex CNAME is illegal (RFC 1034): the apex already has NS + SOA. Use an Alias at the apex; it looks like an A record but points at the AWS target.
  • Add both A and AAAA: miss AAAA and IPv6-only clients can’t reach you. Alias resolution to an AWS target is free.
  • DNS validation auto-renews: leave the _<hash> validation CNAME in the zone forever — ACM re-checks it to renew the cert silently.
  • CloudFront domain ≠ distribution ID: it’s assigned (dXXXXXXXXXXXXX.cloudfront.net). Always read it with get-distribution.
  • Two legs per custom name: (1) add it as an alternate domain name on the distribution and (2) create the DNS record. One without the other fails.
  • route53domains is us-east-1 only — the registrar API lives nowhere else.

Publicly Observable vs Private

A public hosted zone answers DNS queries from anyone — that is its job. But DNS resolution (public) and the Route 53 management API (private) are two different planes. Know which is which.

Anyone on the internet CANOnly an authenticated principal CAN
Resolve a known name (A, AAAA, CNAME, MX, TXT, NS, SOA, CAA)list-resource-record-sets — dump all records in a zone
See where the apex / docs. point (CloudFront IPs)See the hosted-zone ID, distribution ID, OAC ID, ARNs
Read NS + SOA for the domainCreate / change / delete records
Confirm a guessed sub-domain exists (www., api.)Query the route53 / route53domains APIs

Key limits that protect you:

  • No “list all” over DNS. DNS is lookup-by-name; you cannot ask a public resolver to enumerate a zone. Attackers must guess names (dictionary / brute-force), they cannot dump them.
  • Zone transfer (AXFR) is blocked. AXFR is the only protocol that dumps a whole zone — and Route 53 refuses public AXFR (only its own name servers do it internally). So dig AXFR … fails by design.
  • The management API needs SigV4-signed credentials. Plain curl / dig can never reach list-resource-record-sets or see IDs/ARNs. That is why redacting account/resource IDs from published docs matters — those IDs are not otherwise discoverable from the outside.

See what the public can observe (DNS-over-HTTPS, no AWS creds)

# Google DoH (JSON). type: 1=A, 28=AAAA, 2=NS, 6=SOA, 5=CNAME, 257=CAA
curl -s 'https://dns.google/resolve?name=mimifasol.com&type=A'      | jq
curl -s 'https://dns.google/resolve?name=docs.mimifasol.com&type=A' | jq
curl -s 'https://dns.google/resolve?name=mimifasol.com&type=NS'     | jq

# Cloudflare DoH (needs the accept header)
curl -s -H 'accept: application/dns-json' \
  'https://cloudflare-dns.com/dns-query?name=mimifasol.com&type=AAAA' | jq

# AXFR (full-zone dump) — fails against Route 53 by design:
dig AXFR mimifasol.com @<one-of-the-zone-NS>   # -> Transfer failed

Takeaway: your apex/docs. records being resolvable is normal and not a leak — that is public DNS working. The private plane (IDs, ARNs, the ability to list/modify) stays behind authenticated AWS APIs.

Exam Gotchas (CLF-C02)

  • Apex → Alias, never CNAME. Classic trap.
  • CloudFront cert → us-east-1 only.
  • Alias to an AWS resource is free; CNAME lookups are billed queries.
  • A record = IPv4, AAAA = IPv6, CNAME = name→name, Alias = name→AWS resource.
  • Hosted zone = $0.50/month; public ACM cert = free; .com ≈ $14–16/year.
  • Public DNS resolution ≠ the Route 53 API: resolvers answer known names; only signed API calls can list/modify records. AXFR is blocked on Route 53.

See Also

  • [[deploy-custom-domain-route53-acm-cloudfront]]
  • [[route53-alias-vs-cname]]
  • [[route53-dns-records]]
  • [[cloudfront-s3-cli-cheat-sheet]]
  • [[cloudfront-custom-domain-vs-default-url]]
  • [[deploy-static-site-s3-cloudfront-oac]]

title: “AWS Systems Manager Session Manager” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • ssm
  • ec2
  • devops
  • security
  • certification

AWS Systems Manager Session Manager

What It Is

Session Manager is a capability of AWS Systems Manager that lets you open a secure shell session to an EC2 instance without opening inbound ports (SSH/22), managing bastion hosts, or distributing SSH keys.

Why It Matters

Session Manager is the AWS-recommended way to access EC2 instances interactively. It eliminates common attack vectors (exposed SSH ports) and provides full audit logging. Frequently tested as the secure alternative to SSH.

Key Concepts

How It Works

User (Console/CLI) → HTTPS (443) → SSM Agent on EC2 → Shell session
  1. The EC2 instance runs the SSM Agent (pre-installed on Amazon Linux 2, Ubuntu, Windows AMIs)
  2. The agent communicates outbound to the SSM service over HTTPS (port 443)
  3. No inbound security group rules needed — no port 22 exposure
  4. User initiates session from Console or CLI: aws ssm start-session --target i-xxxxx

Prerequisites

RequirementDetail
SSM AgentMust be installed and running on the instance
IAM RoleInstance needs a role with AmazonSSMManagedInstanceCore policy
NetworkOutbound HTTPS (443) to SSM endpoints (or VPC endpoint)
No SSH key neededAuthentication is handled via IAM

Security Benefits

  • No open inbound ports — security groups can deny all inbound traffic
  • No SSH keys to manage — access controlled via IAM policies
  • Full audit trail — sessions logged to CloudTrail, optionally to S3/CloudWatch
  • Session recording — can capture all commands and output
  • IAM-based access control — fine-grained who-can-connect-to-what

Connecting via Console

  1. EC2 → Instances → select instance → Connect
  2. Choose Session Manager tab
  3. Click Connect → browser-based shell opens

Gotchas

  • Instance must have outbound internet or a VPC endpoint for ssm, ssmmessages, and ec2messages
  • If the SSM Agent is stopped or the IAM role is missing, the instance won’t appear as “managed”
  • Session Manager works with private instances (no public IP needed)
  • Default shell is sh; configure in SSM preferences for bash

See Also

  • [[iam-instance-profiles]]
  • [[aws-cli-s3-commands]]

title: “Learnings — Monitoring” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • monitoring

Monitoring

Atomic notes on AWS monitoring and observability — CloudWatch, CloudTrail, X-Ray, Config.

Notes


title: “AWS Budgets — Cost Controls & Budget Actions” created: 2026-08-09 updated: 2026-08-09 type: knowledge tags:

  • aws
  • budgets
  • cost-management
  • iam
  • monitoring
  • certification

AWS Budgets — Cost Controls & Budget Actions

What It Is

AWS Budgets is the native service for monitoring and reacting to spending on an AWS account. It allows you to define monthly cost thresholds and trigger alerts or automatic actions (Budget Actions) when those thresholds are reached.

Why It Matters

AWS does not offer a hard cap that automatically shuts down all services when a spending amount is reached. This is by design (availability > cost protection). You must configure your own guardrails.

Key Concepts

What AWS Budgets Can Do

FeatureDescription
Email alertsNotification when X% of the budget is consumed
Budget Actions — IAM PolicyAttach a deny policy that blocks creation of new resources
Budget Actions — SCPApply a Service Control Policy (requires AWS Organizations)
Budget Actions — Stop instancesTarget specific EC2/RDS instances

What AWS Budgets Cannot Do Natively

  • Automatically stop all running resources
  • Guarantee an absolute monthly cost maximum (already-consumed data is still billed)
  • Block storage charges (EBS, S3) and network charges (NAT Gateway, data transfer)

Budget Controls for AWS (Open-Source Solution)

An AWS Labs solution that goes beyond native Budgets:

  • Tag BudgetControlAction: Stop → stops resources at 90% of budget
  • Tag BudgetControlAction: Terminate → deletes resources (irreversible)
  • Supports EC2, RDS Aurora, SageMaker, OpenSearch
  • GitHub: https://github.com/awslabs/budget-controls-for-aws

How Budget Actions Work — Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                           AWS Account                                    │
│                                                                         │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │                         AWS BUDGETS                               │  │
│  │                                                                   │  │
│  │  ┌─────────────────────────────────┐                              │  │
│  │  │  Budget (monthly, $X)           │                              │  │
│  │  └────────────┬────────────────────┘                              │  │
│  │               │                                                   │  │
│  │               │ triggers at configured thresholds                 │  │
│  │               ▼                                                   │  │
│  │  ┌─────────────────────────────────┐                              │  │
│  │  │  📧 Email Alerts                │                              │  │
│  │  └─────────────────────────────────┘                              │  │
│  │                                                                   │  │
│  │               │ triggers at 100%                                  │  │
│  │               ▼                                                   │  │
│  │  ┌─────────────────────────────────────────────────────────────┐  │  │
│  │  │  Budget Action (AUTOMATIC)                                  │  │  │
│  │  │  Type: APPLY_IAM_POLICY                                     │  │  │
│  │  └────────────┬────────────────────────────────────────────────┘  │  │
│  │               │                                                   │  │
│  └───────────────┼───────────────────────────────────────────────────┘  │
│                  │ assumes                                               │
│                  ▼                                                       │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  IAM Role: Execution Role                                         │  │
│  │  Trust: budgets.amazonaws.com                                     │  │
│  │  Permissions: iam:AttachRolePolicy, iam:DetachRolePolicy          │  │
│  └────────────┬──────────────────────────────────────────────────────┘  │
│               │ attaches/detaches                                       │
│               ▼                                                         │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  IAM Policy: Deny Policy                                          │  │
│  │  Effect: DENY                                                     │  │
│  │  Actions: ec2:RunInstances, rds:CreateDBInstance, etc.            │  │
│  └────────────┬──────────────────────────────────────────────────────┘  │
│               │ attached to (when budget exceeded)                      │
│               ▼                                                         │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  IAM Role: Your SSO Role                                          │  │
│  │  (assumed by your Identity Center user)                           │  │
│  │                                                                   │  │
│  │  Normally: AdministratorAccess (Allow *)                          │  │
│  │  When budget exceeded: + Deny Policy (Deny > Allow → blocked)     │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│                  ▲                                                       │
│                  │ assumes via SSO                                       │
│                  │                                                       │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  IAM Identity Center User                                         │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Step-by-Step Explanation

Setting up a Budget Action requires 4 steps in sequence. Each builds on the previous one.

Step 1           Step 2               Step 3               Step 4
─────────        ─────────            ─────────            ─────────
 BUDGET     →    DENY POLICY    →    EXECUTION ROLE   →   BUDGET ACTION
 (the watcher)   (the weapon)        (the arm)            (the link)

 "monitors       "here's what        "here's who is       "when X happens,
  spending"       we forbid"          allowed to act"      use the arm to
                                                           apply the weapon"

Step 1 — Create the Budget

Creates a counter that monitors monthly spending and sends email alerts.

IAM concept: None. This is passive monitoring only.


Step 2 — Create the Deny Policy

Creates a JSON “rules document” stored in IAM. The document says: “whoever has this policy attached cannot do ec2:RunInstances, rds:CreateDBInstance, etc.”

IAM concept: A Policy is just a JSON document. It does nothing until it’s attached to someone (user, group, or role). It’s like a “forbidden” sign sitting in a drawer — it forbids nothing until you hang it somewhere.


Step 3 — Create the Execution Role

Two sub-steps:

  • 3a: Create a role that only the budgets.amazonaws.com service can assume. This is the “trust policy” — it answers “WHO can become this role?”
  • 3b: Give this role permission to attach and detach policies on other roles. This is the “permissions policy” — it answers “WHAT can this role do once assumed?”

IAM concept: A Role has two faces:

┌─────────────────────────────────────────────────────┐
│  IAM Role                                           │
│                                                     │
│  ┌─────────────────────────┐                        │
│  │  Trust Policy           │  ← WHO can assume it   │
│  │  (assume-role-policy)   │     (here: Budgets)    │
│  └─────────────────────────┘                        │
│                                                     │
│  ┌─────────────────────────┐                        │
│  │  Permissions Policy     │  ← WHAT it can do      │
│  │  (inline or managed)    │     (here: attach/     │
│  │                         │      detach policies)  │
│  └─────────────────────────┘                        │
│                                                     │
└─────────────────────────────────────────────────────┘

Analogy: It’s like a car key. The trust policy says “only the restaurant valet can use this key”. The permissions policy says “this key only allows starting the engine and moving 10m” (not taking the highway).


Step 4 — Create the Budget Action

Links everything together. This is the “recipe” that tells AWS Budgets:

  • When: budget reaches 100%
  • How: assume the Execution Role
  • What: attach the Deny Policy
  • On whom: your SSO Role
  • Approval: automatic (no human approval needed)

Why Deny Wins Over Allow

AWS evaluates permissions in this order:

  1. Is there an explicit DENY?  ──→ YES → DENIED (stop)
                                      │
                                     NO
                                      │
  2. Is there an explicit ALLOW? ──→ YES → ALLOWED
                                      │
                                     NO
                                      │
  3. Denied by default (implicit deny)

Even if AdministratorAccess grants Allow * (everything is allowed), a single explicit Deny on ec2:RunInstances is enough to block it. Deny always wins.

How to Lift the Block

When the budget is exceeded and the action fires, you have 3 options:

  1. CLI — detach the deny policy from the SSO role (aws iam detach-role-policy)
  2. Console — IAM → Roles → find SSO role → Permissions → remove the deny policy
  3. Budgets reverse — aws budgets execute-budget-action ... --execution-type REVERSE_ACTION

After lifting the block, if spending is still > 100%, the action will re-trigger after a few hours. Fix the cost source first, or temporarily increase the budget.

Gotchas

  • Budget Actions do not stop already-running resources — they only block future creations
  • NAT Gateways cost ~$0.045/h even with no traffic — destroy them after each lab
  • Alerts have a delay (a few hours) because AWS Budgets relies on billing data which is not real-time
  • Free Tier is not covered by budgets — a free resource that exits Free Tier will start billing without prior alert
  • Budget Actions require an execution role (IAM Role) with permission to attach policies

See Also

  • [[../../aws/aws-budgets-config]] — actual configuration and source commands for our account
  • [[../security/README]]

title: “Learnings — Networking” created: 2026-07-20 updated: 2026-10-28 type: knowledge tags:

  • aws
  • certification
  • networking

Networking

Atomic notes on AWS networking — VPC, Route53, CloudFront, Direct Connect, ELB.

Notes

VPC

  • [[vpc-fundamentals]] — What a VPC is, isolation, core components, CIDR constraints
  • [[vpc-subnets]] — Public vs private subnets, AZ constraint, reserved IPs
  • [[vpc-route-tables]] — Route evaluation logic, local route, public vs private routing
  • [[vpc-internet-gateway]] — IGW characteristics, requirements for Internet access
  • [[vpc-nat-gateway]] — Outbound-only connectivity for private subnets, deployment options
  • [[vpc-network-acls]] — Stateless firewall at subnet level, rule evaluation order
  • [[vpc-security-groups]] — Stateful firewall at instance level, default SG behavior

IP Addressing

  • [[cidr-notation]] — CIDR notation explained (IP ranges, prefix length, subnets)

DNS / Route 53

  • [[route53-alias-vs-cname]] — Alias vs CNAME and the apex rule (exam trap)

Applied

  • [[deploy-custom-domain-route53-acm-cloudfront]] — runbook: register a domain in Route 53, ACM cert, attach to CloudFront, apex Alias (the alias-vs-CNAME theory put into practice for mimifasol.com)

title: “CIDR Notation” created: 2026-07-23 updated: 2026-07-23 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

CIDR Notation

What It Is

CIDR (Classless Inter-Domain Routing) is a compact notation to express a range of IP addresses. The format is:

network_address / prefix_length

The prefix length indicates how many of the 32 bits (IPv4) are fixed and identify the network. The remaining bits are available for hosts.

Why It Matters

  • Every VPC, subnet, security group rule, and route table entry in AWS uses CIDR notation
  • Understanding CIDR is required to design non-overlapping network segments
  • Misconfigured CIDR blocks lead to routing conflicts or wasted IP space

Key Concepts

Formula: 2^(32 - prefix) = number of addresses

NotationNetwork bitsHost bitsAddresses
/16161665,536
/24248256
/2828416
/323201

Rules of thumb:

  • /16 → large network (~65k IPs) → typical for a VPC
  • /24 → small network (256 IPs) → typical for a subnet
  • The larger the prefix number, the smaller the network

How It Works

A CIDR block like 10.0.0.0/16 means:

  • The first 16 bits (10.0) are locked — they identify the network
  • The last 16 bits (x.x) are free — they identify hosts
  • Range: 10.0.0.0 to 10.0.255.255

Subnets are carved out of a VPC’s CIDR block by using a longer prefix:

VPC 10.0.0.0/16          → full block 10.0.x.x
  ├── 10.0.25.0/24       → sub-block 10.0.25.x  (public subnet)
  ├── 10.0.50.0/24       → sub-block 10.0.50.x  (private subnet)
  └── ... remaining space available for other subnets

Examples

AWS Default VPC: 172.31.0.0/16

  • Automatically created in every region
  • Range: 172.31.0.0 to 172.31.255.255
  • Pre-configured with /20 subnets (4,096 IPs each), one per AZ

Lab VPC: 10.0.0.0/16

  • Public subnet: 10.0.25.0/24 → 256 addresses (10.0.25.0 – 10.0.25.255)
  • Private subnet: 10.0.50.0/24 → 256 addresses (10.0.50.0 – 10.0.50.255)

AWS reserved addresses per subnet (5 total):

  • .0 — network address
  • .1 — VPC router
  • .2 — DNS server
  • .3 — reserved for future use
  • .255 — broadcast (not supported in VPC but reserved)

So a /24 subnet has 251 usable IPs, not 256.

Gotchas

  • A VPC CIDR block cannot be changed after creation (but secondary blocks can be added)
  • Subnets cannot overlap within a VPC
  • AWS enforces a minimum of /28 (16 IPs) and maximum of /16 (65,536 IPs) for VPC CIDR blocks
  • The 5 reserved addresses per subnet matter more in small subnets (a /28 only has 11 usable IPs)
  • CIDR blocks from peered VPCs must not overlap

See Also

  • [[s3-fundamentals]]
  • [[aws-arns]]

title: “Route 53 — Alias vs CNAME (and the Apex Rule)” created: 2026-10-28 updated: 2026-10-28 type: knowledge tags:

  • aws
  • certification
  • networking
  • route53
  • dns

Route 53 — Alias vs CNAME (and the Apex Rule)

What It Is

Two ways to point a DNS name at another target, plus the rule that decides which one you must use at the apex (root) of a domain.

  • Apex / zone apex / naked domain: the domain with nothing in front (example.com), as opposed to www.example.com. It always carries mandatory NS and SOA records.
  • CNAME: standard DNS record aliasing one name to another name.
  • Alias: Route 53 proprietary record that behaves like an A record but points to an AWS resource.

Why It Matters

Pointing a custom domain at CloudFront / ALB / S3 is a recurring exam scenario. The trap: candidates put a CNAME at the apex, which is invalid.

Key Concepts

The apex rule: a CNAME cannot coexist with any other record on the same name (RFC 1034). The apex already has NS + SOA, so a CNAME at the apex is illegal. This is a DNS rule, not an AWS limitation.

The Route 53 fix: the Alias record looks like an A record (legal at the apex) but resolves an AWS target server-side. It gives CNAME-like behaviour at the apex.

How It Works

CNAMEAlias
TypeStandard DNSRoute 53 proprietary
At apex (example.com)❌ Invalid✅ Valid
At sub-domain (www.)✅ Valid✅ Valid
TargetAny DNS nameAWS resources + Route 53 records
Query costBilledFree (AWS targets)

Decision shortcut:

Need to point the APEX at an AWS resource?      → Alias (CNAME not allowed)
Need to point a SUB-DOMAIN at an AWS resource?  → Alias (preferred) or CNAME
Need to point at an EXTERNAL (non-AWS) name?    → CNAME (sub-domain only)

Examples

example.com        A (Alias)    → CloudFront        # apex, CNAME impossible
example.com        AAAA (Alias) → CloudFront        # IPv6
www.example.com    CNAME        → d123.cloudfront.net

Gotchas

  • CNAME at the apex is a guaranteed wrong answer on the exam.
  • Alias only targets specific AWS resources (CloudFront, ALB/ELB, S3 website, API Gateway, another Route 53 record) — not arbitrary external hosts.
  • Alias to an AWS resource is free; CNAME resolution is a billable query.
  • For CloudFront, remember the paired requirement: the ACM certificate must be in us-east-1.

See Also

  • [[cidr-notation]]
  • [[route53-dns-records]]
  • [[deploy-custom-domain-route53-acm-cloudfront]] — this rule applied in practice (apex Alias for mimifasol.com → CloudFront)
  • [[route53-acm-cloudfront-custom-domain-cheat-sheet]] — quick reference (record properties, acronyms, commands)

title: “VPC Fundamentals” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

VPC Fundamentals

What It Is

An Amazon Virtual Private Cloud (VPC) is a logically isolated virtual network within the AWS cloud. It gives you complete control over your networking environment: IP address ranges, subnets, route tables, and network gateways.

Why It Matters

Every AWS resource that needs network connectivity (EC2, RDS, Lambda in VPC mode, ECS, etc.) lives inside a VPC. Understanding VPC architecture is foundational to AWS certification and to designing secure, scalable infrastructure.

Key Concepts

VPC Characteristics

  • Spans a single Region but can cover multiple Availability Zones
  • Defined by a CIDR block (e.g., 10.0.0.0/16) — the overall IP address range
  • Provides logical isolation from other VPCs and the public Internet
  • Supports both IPv4 and IPv6

Core Components

ComponentRole
SubnetsSubdivisions of the VPC IP range, each in one AZ
Route TablesDetermine where network traffic is directed
Internet GatewayConnects the VPC to the Internet
NAT GatewayAllows private subnets outbound Internet access
Network ACLsStateless firewall at the subnet level
Security GroupsStateful firewall at the instance level

VPC Wizard

The VPC and more wizard automates creation of:

  • The VPC itself
  • Public and private subnets
  • Route tables with appropriate routes
  • An Internet Gateway (attached)
  • A NAT Gateway (in the public subnet)

Default VPC

  • AWS automatically creates a default VPC in each Region
  • CIDR: 172.31.0.0/16
  • Comes with a public subnet in each AZ, an Internet Gateway, and a default route table
  • Instances launched in the default VPC get a public IP by default

Allowed CIDR Ranges

  • Minimum: /28 (16 IP addresses)
  • Maximum: /16 (65,536 IP addresses)
  • Secondary CIDR blocks can be added after creation
  • Primary CIDR block cannot be changed after creation

Gotchas

  • A VPC is Region-scoped, not AZ-scoped
  • You can have multiple VPCs per Region (default limit: 5, soft limit)
  • VPC peering allows cross-VPC communication but CIDR blocks must not overlap
  • Resources in a VPC have no Internet access unless explicitly configured (IGW + route + public IP or NAT)

See Also

  • [[vpc-subnets]]
  • [[vpc-route-tables]]
  • [[vpc-internet-gateway]]
  • [[vpc-nat-gateway]]
  • [[vpc-network-acls]]
  • [[vpc-security-groups]]
  • [[cidr-notation]]

title: “VPC Internet Gateway” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

VPC Internet Gateway

What It Is

An Internet Gateway (IGW) is a VPC component that enables communication between resources in the VPC and the Internet. It serves as the gateway for all inbound and outbound Internet traffic.

Why It Matters

Without an IGW, a VPC has absolutely no Internet connectivity. Understanding how the IGW interacts with route tables, public IPs, and subnets is essential for VPC design and troubleshooting connectivity issues.

Key Concepts

Characteristics

  • Horizontally scaled — handles any amount of traffic
  • Redundant and highly available — no single point of failure
  • Imposes no bandwidth constraints or availability risks
  • Supports both IPv4 and IPv6
  • One IGW per VPC (you cannot attach multiple)

Requirements for Internet Access

A resource in a VPC needs all three of these to reach the Internet:

  1. An Internet Gateway attached to the VPC
  2. A route in the subnet’s route table pointing 0.0.0.0/0 → IGW
  3. A public IP address (or Elastic IP) assigned to the resource

If any of these is missing, outbound Internet access will fail.

What Makes a Subnet Public

A subnet is public if and only if its route table has a route to an Internet Gateway:

0.0.0.0/0 → igw-xxxxxxxx

How It Works

EC2 instance (public IP) → Route table → IGW → Internet
Internet → IGW → Route table → EC2 instance (public IP)

The IGW performs Network Address Translation (1:1 NAT) between the instance’s private IP and its public IP.

Gotchas

  • An IGW does not perform NAT for private IPs without a public/Elastic IP — those instances cannot reach the Internet through the IGW
  • Detaching an IGW immediately breaks all Internet connectivity for the VPC
  • You can have only one IGW per VPC
  • An IGW alone is not enough — the route table and public IP are also required

See Also

  • [[vpc-fundamentals]]
  • [[vpc-subnets]]
  • [[vpc-route-tables]]
  • [[vpc-nat-gateway]]

title: “VPC NAT Gateway” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

VPC NAT Gateway

What It Is

A NAT Gateway is an AWS-managed Network Address Translation service that enables resources in a private subnet to initiate outbound connections to the Internet while preventing the Internet from initiating inbound connections to those resources.

Why It Matters

Private subnets need Internet access for tasks like downloading patches, calling external APIs, or reaching AWS service endpoints. The NAT Gateway provides this without exposing the resources publicly. This is a core pattern for secure VPC architectures.

Key Concepts

How It Works

Private Instance → Private Subnet Route Table → NAT Gateway (in public subnet) → IGW → Internet
  1. Instance in private subnet sends traffic to the Internet
  2. Route table sends 0.0.0.0/0 traffic to the NAT Gateway
  3. NAT Gateway translates the private IP to its own Elastic IP
  4. Traffic exits through the Internet Gateway
  5. Response follows the reverse path

Characteristics

  • AWS-managed — no patching, no maintenance
  • Outbound-only — Internet cannot initiate connections to private resources
  • Lives in a public subnet (needs IGW access itself)
  • Has an Elastic IP (static public IP for outbound traffic)
  • Scales automatically up to 100 Gbps
  • Supports TCP, UDP, and ICMP

Deployment Options

OptionDescriptionUse Case
Zonal (1 AZ)One NAT GW in one public subnetCost-effective for single-AZ apps
Multi-AZOne NAT GW per AZHigh availability for production

NAT Gateway vs NAT Instance

AspectNAT GatewayNAT Instance
ManagementAWS-managedSelf-managed EC2
AvailabilityBuilt-in HA within AZMust configure yourself
BandwidthUp to 100 GbpsDepends on instance type
CostPer-hour + per-GBInstance cost only
Security groupsNot supportedSupported

Cost Considerations

NAT Gateways are billed for:

  • Hourly charge (per NAT Gateway)
  • Data processing (per GB of traffic)

This can become expensive with high data transfer volumes.

Gotchas

  • A NAT Gateway is AZ-specific — if the AZ goes down, so does the NAT Gateway
  • For HA, deploy one NAT Gateway per AZ with each private subnet routing to its own
  • NAT Gateways cannot be used by resources in the same subnet they live in
  • You cannot associate a security group with a NAT Gateway (use NACLs instead)
  • NAT Gateway needs an Elastic IP — there’s a limit of 5 EIPs per Region (soft limit)

See Also

  • [[vpc-fundamentals]]
  • [[vpc-subnets]]
  • [[vpc-route-tables]]
  • [[vpc-internet-gateway]]
  • [[vpc-security-groups]]

title: “VPC Network ACLs” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

VPC Network ACLs

What It Is

A Network Access Control List (NACL) is an optional stateless firewall that controls inbound and outbound traffic at the subnet level. Every subnet in a VPC is associated with a NACL.

Why It Matters

NACLs provide an additional layer of defense beyond security groups. Understanding the difference between NACLs (stateless, subnet-level) and security groups (stateful, instance-level) is critical for both exam preparation and real-world VPC design.

Key Concepts

Stateless vs Stateful

FeatureNetwork ACLSecurity Group
LevelSubnetInstance
StatefulNo — must allow return traffic explicitlyYes — return traffic auto-allowed
Rule typeAllow AND DenyAllow only (implicit deny)
EvaluationRules processed in number orderAll rules evaluated together

Rule Structure

FieldDescription
Rule numberPriority (lower = evaluated first)
TypeTraffic type (e.g., All Traffic, HTTP, SSH)
ProtocolTCP, UDP, ICMP, etc.
Port rangeDestination port(s)
Source/DestinationCIDR block
Allow/DenyAction to take

Default NACL

The default NACL (created with the VPC) allows all inbound and outbound traffic:

Rule #DirectionActionTrafficCIDR
100InboundAllowAll0.0.0.0/0
100OutboundAllowAll0.0.0.0/0
*BothDenyAll0.0.0.0/0

The * rule is the catch-all: if no numbered rule matches, traffic is denied.

Custom NACL

A newly created custom NACL denies all traffic by default (only has the * deny rule). You must explicitly add allow rules.

Rule Evaluation Order

  1. Rules are evaluated in ascending order by rule number
  2. First matching rule wins (stops evaluation)
  3. If no rule matches, the * catch-all denies the traffic

Ephemeral Ports

Because NACLs are stateless, you must allow ephemeral ports (1024–65535) for return traffic on outbound rules when a client connects to a service.

Gotchas

  • NACLs are stateless — allowing inbound HTTP (port 80) does NOT automatically allow the response on ephemeral ports
  • The default NACL allows everything; a custom NACL denies everything — easy to confuse
  • Rule numbers should use increments (e.g., 100, 200, 300) to leave room for insertion
  • A subnet can only be associated with one NACL at a time
  • NACLs apply to all instances in the subnet — cannot target specific instances

See Also

  • [[vpc-security-groups]]
  • [[vpc-subnets]]
  • [[vpc-fundamentals]]
  • [[vpc-route-tables]]

title: “VPC Route Tables” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

VPC Route Tables

What It Is

A Route Table is a set of rules (routes) that determine where network traffic from a subnet is directed. Every subnet must be associated with exactly one route table.

Why It Matters

Route tables are the mechanism that defines whether a subnet is public or private. They control all traffic flow within and out of the VPC. Misconfigured routes are a common cause of connectivity failures.

Key Concepts

Route Structure

Each route has two parts:

FieldDescriptionExample
DestinationThe CIDR block the traffic is heading to10.0.0.0/16, 0.0.0.0/0
TargetWhere to send matching trafficlocal, igw-xxx, nat-xxx

Route Evaluation

Routes are evaluated from most specific (longest prefix / biggest number after /) to least specific:

  1. 10.0.0.0/16 → local (more specific, matches VPC traffic first)
  2. 0.0.0.0/0 → igw or nat (catch-all for everything else)

The most specific matching route wins.

Public Subnet Route Table

DestinationTargetPurpose
10.0.0.0/16localVPC-internal communication
0.0.0.0/0igw-xxxInternet-bound traffic → Internet Gateway

Private Subnet Route Table

DestinationTargetPurpose
10.0.0.0/16localVPC-internal communication
0.0.0.0/0nat-xxxInternet-bound traffic → NAT Gateway

Main Route Table

  • Every VPC has a main route table automatically
  • Subnets without an explicit association use the main route table
  • Best practice: leave the main route table restrictive (no IGW route) and explicitly associate public subnets with a custom route table

The local Route

  • Automatically present in every route table
  • Cannot be removed or modified
  • Ensures all subnets within the VPC can communicate with each other

Gotchas

  • A subnet can only be associated with one route table at a time
  • Multiple subnets can share the same route table
  • The local route is immutable — you cannot block intra-VPC traffic via route tables (use NACLs or security groups instead)
  • Adding a route to 0.0.0.0/0 → igw effectively makes the associated subnet public

See Also

  • [[vpc-subnets]]
  • [[vpc-internet-gateway]]
  • [[vpc-nat-gateway]]
  • [[vpc-fundamentals]]
  • [[cidr-notation]]

title: “VPC Security Groups” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc
  • security

VPC Security Groups

What It Is

A Security Group is a stateful virtual firewall that controls inbound and outbound traffic at the instance level (ENI level). It is the primary mechanism for controlling network access to AWS resources within a VPC.

Why It Matters

Security groups are the first line of defense for individual resources. They are used everywhere — EC2, RDS, Lambda (VPC mode), ELB, etc. Understanding their behavior is fundamental to AWS networking and security.

Key Concepts

Characteristics

  • Operates at the instance level (technically at the ENI — Elastic Network Interface)
  • Stateful — if you allow inbound traffic, the response is automatically allowed outbound (and vice versa)
  • Allow rules only — you cannot create deny rules; anything not explicitly allowed is implicitly denied
  • All rules are evaluated together (no priority/ordering)
  • Up to 5 security groups per instance (default)

Default Security Group

Every VPC comes with a default security group with these rules:

DirectionRuleEffect
InboundSource = self (same SG)Allow all traffic from instances in the same SG
InboundAll other sourcesDeny (implicit)
OutboundAll destinationsAllow all traffic

The self-referencing inbound rule means: instances sharing this security group can communicate freely with each other, but nothing else can reach them.

Custom Security Groups

When you create a new security group:

  • No inbound rules (all inbound denied by default)
  • All outbound allowed by default
  • You add rules to permit specific traffic

Rule Components

FieldDescriptionExample
TypeProtocol/port presetHTTP, SSH, Custom TCP
ProtocolTCP, UDP, ICMPTCP
Port rangePort(s) to allow80, 443, 22
Source/DestinationCIDR, IP, or another SG0.0.0.0/0, sg-abc123

Referencing Other Security Groups

Instead of using CIDR blocks, you can reference another security group as a source:

Inbound rule: Allow TCP 3306 from sg-webapp

This means “allow MySQL connections from any instance in the sg-webapp security group” — even as instances scale up/down, the rule stays valid.

Gotchas

  • Security groups are stateful — no need to configure return traffic rules (unlike NACLs)
  • You cannot deny specific traffic — only allow; for deny rules, use NACLs
  • Changes to security group rules take effect immediately
  • An instance can belong to multiple security groups — all rules are aggregated (union of all allows)
  • Security groups are VPC-scoped — they cannot be shared across VPCs (unless using VPC peering with security group references in the same Region)
  • If you remove all outbound rules, instances cannot initiate any outbound connections

See Also

  • [[vpc-network-acls]]
  • [[vpc-subnets]]
  • [[vpc-fundamentals]]
  • [[iam-policy-structure]]

title: “VPC Subnets” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • networking
  • vpc

VPC Subnets

What It Is

A Subnet is a range of IP addresses within a VPC. It represents a segment of the VPC’s CIDR block and exists in exactly one Availability Zone.

Why It Matters

Subnets are where your resources actually live. The distinction between public and private subnets is fundamental to AWS network security architecture and heavily tested on certification exams.

Key Concepts

Subnet Properties

  • Belongs to a single VPC
  • Exists in a single Availability Zone (cannot span AZs)
  • Has a CIDR block that is a subset of the VPC’s CIDR
  • Has an associated Route Table (determines public vs private)
  • Has an associated Network ACL

Public vs Private Subnets

AspectPublic SubnetPrivate Subnet
Route to IGWYes (0.0.0.0/0 → igw-xxx)No
Route to NATOptionalYes (0.0.0.0/0 → nat-xxx)
Direct Internet accessYes (with public IP)No
Inbound from InternetPossibleNot possible
Typical resourcesLoad balancers, bastion hosts, NAT GWApp servers, databases, internal services

Key insight: What makes a subnet public or private is purely its route table — specifically whether it has a route to an Internet Gateway.

Reserved IP Addresses

AWS reserves 5 IP addresses in every subnet:

AddressPurpose
First (.0)Network address
Second (.1)VPC router
Third (.2)DNS server
Fourth (.3)Reserved for future use
Last (.255)Broadcast (not used but reserved)

A /24 subnet (256 IPs) has 251 usable addresses.

Example Layout

VPC: 10.0.0.0/16
├── Public subnet:  10.0.25.0/24  (AZ-a) → 251 usable IPs
├── Private subnet: 10.0.50.0/24  (AZ-a) → 251 usable IPs
└── ... room for more subnets in other AZs

Gotchas

  • Subnet CIDR blocks cannot overlap within the same VPC
  • A subnet cannot span multiple AZs — for HA you need one subnet per AZ
  • The default VPC has a public subnet in each AZ (auto-assigns public IPs)
  • Custom VPCs do not auto-assign public IPs — you must enable it per subnet or per instance

See Also

  • [[vpc-fundamentals]]
  • [[vpc-route-tables]]
  • [[vpc-internet-gateway]]
  • [[vpc-nat-gateway]]
  • [[cidr-notation]]

title: “Learnings — Security” created: 2026-07-20 updated: 2026-10-23 type: knowledge tags:

  • aws
  • certification
  • security

Security

Atomic notes on AWS security — IAM, KMS, Secrets Manager, WAF, Shield, GuardDuty.

Notes

IAM Core

  • [[iam-users]] — IAM user identity, credentials, zero-permission default
  • [[iam-groups]] — Group-based permission inheritance, common patterns
  • [[iam-policy-structure]] — Effect/Action/Resource JSON structure, evaluation logic
  • [[iam-managed-vs-inline-policies]] — Managed vs Inline, when to use each
  • [[iam-sign-in-url]] — Account-specific sign-in URL, account alias
  • [[iam-instance-profiles]] — EC2 roles for S3 access, credential delivery via IMDS
  • [[passkeys]] — FIDO2/WebAuthn phishing-resistant sign-in for root & admin (not AWS access keys)

S3 Security

  • [[s3-block-public-access]] — BPA settings, hierarchy, interaction with ACLs/policies
  • [[s3-access-control-lists]] — Legacy ACLs, object ownership, making objects public
  • [[s3-bucket-policies]] — JSON policy structure, Policy Generator, common actions
  • [[aws-arns]] — ARN format, S3-specific ARNs, common patterns
  • [[s3-access-without-public]] — Granting access via bucket policy while keeping BPA ON and ACLs disabled

title: “AWS ARNs (Amazon Resource Names)” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • security
  • iam
  • certification

AWS ARNs (Amazon Resource Names)

What It Is

An ARN is a globally unique identifier for any AWS resource. It is the standard way to reference resources in IAM policies, bucket policies, and API calls.

Why It Matters

You cannot write any IAM or resource policy without using ARNs. Understanding the format lets you quickly construct and debug policy statements.

Key Concepts

General Format

arn:partition:service:region:account-id:resource
FieldDescriptionExample
partitionAWS partitionaws (standard), aws-cn (China), aws-us-gov (GovCloud)
serviceAWS service namespaces3, iam, ec2, lambda
regionAWS Regionus-east-1, eu-west-1 (blank if global)
account-idAWS account number123456789012 (blank if not required)
resourceResource identifierVaries by service

S3 ARN Specifics

S3 is a global service — the region and account-id fields are left blank (but the colons remain):

arn:aws:s3:::mybucket          → the bucket itself
arn:aws:s3:::mybucket/*        → all objects in the bucket
arn:aws:s3:::mybucket/reports/* → objects under the reports/ prefix

IAM Role ARN

arn:aws:iam::123456789012:role/EC2InstanceProfileRole
  • Region is blank (IAM is global)
  • Account ID is present
  • Resource type is role/ followed by role name

Common Patterns

ResourceARN Pattern
S3 bucketarn:aws:s3:::bucket-name
S3 objectsarn:aws:s3:::bucket-name/*
IAM rolearn:aws:iam::account:role/role-name
IAM userarn:aws:iam::account:user/user-name
EC2 instancearn:aws:ec2:region:account:instance/i-xxx
Lambda functionarn:aws:lambda:region:account:function:name

Gotchas

  • Forgetting colons for blank fields is a common mistake: arn:aws:s3:::bucket not arn:aws:s3:bucket
  • S3 bucket ARN vs object ARN: use bucket ARN for ListBucket, object ARN (/*) for GetObject/PutObject
  • ARNs are case-sensitive for the resource portion

See Also

  • [[s3-bucket-policies]]
  • [[iam-instance-profiles]]

title: “IAM Groups” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • iam
  • security
  • certification

IAM Groups

What It Is

An IAM Group is a collection of IAM users. Groups let you specify permissions for multiple users at once, making it easier to manage permissions for sets of users who share the same job function.

Why It Matters

Groups are the recommended mechanism for assigning permissions to users at scale. Instead of attaching policies to individual users (error-prone and hard to audit), you attach policies to groups and then add users to the appropriate groups. When a policy is updated, all group members immediately get the updated permissions.

Key Concepts

How Permission Inheritance Works

IAM Policy ──attached to──► IAM Group ──membership──► IAM User

When a user is added to a group, they inherit all policies attached to that group. A user can be in multiple groups and receives the union of all permissions.

Common Group Patterns

Group NameTypical PolicyUse Case
S3-SupportAmazonS3ReadOnlyAccessRead-only S3 support staff
EC2-SupportAmazonEC2ReadOnlyAccessRead-only EC2 support staff
EC2-AdminCustom inline policy (Start/Stop/Describe)EC2 administrators
AdminsAdministratorAccessFull account administrators

Group Characteristics

  • Groups cannot be nested (no group within a group)
  • A group is not an identity — you cannot sign in as a group
  • A user can belong to multiple groups (up to 10 by default)
  • Groups can have both managed and inline policies attached

Gotchas

  • There is no “default group” that all new users automatically belong to — you must explicitly add users
  • Groups cannot be referenced as a Principal in a resource-based policy (e.g., S3 bucket policy)
  • Removing a user from a group immediately revokes the inherited permissions
  • Maximum of 300 groups per account (soft limit, can be increased)

See Also

  • [[iam-users]]
  • [[iam-managed-vs-inline-policies]]
  • [[iam-policy-structure]]
  • [[iam-instance-profiles]]

title: “IAM Instance Profiles & EC2 Roles” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • iam
  • ec2
  • security
  • certification

IAM Instance Profiles & EC2 Roles

What It Is

An Instance Profile is a container for an IAM Role that allows an EC2 instance to assume that role. The role defines what AWS services the instance can access and what operations it can perform — without embedding credentials on the instance.

Why It Matters

This is the recommended way to grant AWS permissions to EC2 instances. It avoids storing access keys on instances (a security anti-pattern). Heavily tested on exams.

Key Concepts

How It Works

EC2 Instance → Instance Profile → IAM Role → Permissions (Policies)
  1. An IAM Role is created with a trust policy allowing EC2 to assume it
  2. An Instance Profile wraps the role (in the Console, this is created automatically)
  3. The instance profile is attached to the EC2 instance at launch (or after)
  4. The instance gets temporary credentials via the EC2 metadata service
  5. AWS CLI and SDKs automatically use these credentials — no configuration needed

Authentication vs Authorization

ConceptProvided By
Authentication (who am I?)Instance Profile (role assumption)
Authorization (what can I do?)IAM Policies attached to the Role

Example: EC2 Accessing S3

  • Role: EC2InstanceProfileRole
  • Attached policy allows: s3:GetObject, s3:PutObject on arn:aws:s3:::mybucket/*
  • Result: EC2 can read/write objects in that bucket via aws s3 cp without explicit credentials

Credential Delivery

  • Temporary credentials are delivered via the Instance Metadata Service (IMDS)
  • Endpoint: http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
  • Credentials auto-rotate (typically every ~6 hours)

Gotchas

  • An EC2 instance can have only one instance profile (and thus one role) at a time
  • If the role doesn’t have the required permission, the API call fails with “Access Denied” — not “authentication failed”
  • Changing the role’s policies takes effect immediately (no instance restart needed)
  • In the Console, creating a role for EC2 auto-creates the instance profile; via CLI/API you must create them separately

See Also

  • [[s3-bucket-policies]]
  • [[aws-arns]]
  • [[s3-fundamentals]]

title: “IAM Managed vs Inline Policies” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • iam
  • security
  • certification

IAM Managed vs Inline Policies

What It Is

IAM supports two main categories of policies for granting permissions:

  • Managed Policies — Standalone policies that can be attached to multiple users, groups, or roles
  • Inline Policies — Policies embedded directly into a single user, group, or role

Why It Matters

Choosing the right policy type affects maintainability, reusability, and auditability. This is a frequent topic on certification exams, and understanding the distinction helps design proper permission architectures.

Key Concepts

Managed Policies

There are two sub-types:

TypeCreated ByExamples
AWS ManagedAWSAmazonS3ReadOnlyAccess, AmazonEC2ReadOnlyAccess
Customer ManagedYouCustom policies tailored to your needs

Characteristics:

  • Reusable: attach to multiple entities
  • Versioned: up to 5 versions, can roll back
  • Central updates: changing the policy immediately affects all attached entities
  • Visible in the IAM Policies list
  • Maximum of 10 managed policies per user/group/role (default)

Inline Policies

Characteristics:

  • Embedded: lives inside a specific user, group, or role
  • Not reusable: exists only for that one entity
  • Deleted when the entity is deleted
  • Useful for one-off, strict 1-to-1 permission relationships
  • Not visible in the central IAM Policies list

When to Use Each

ScenarioPolicy Type
Standard permissions for a job functionAWS Managed
Company-specific standard permissionsCustomer Managed
One-off permission for a specific entityInline
Permissions that must never accidentally apply elsewhereInline

Example from the Lab

  • EC2-Support group → AmazonEC2ReadOnlyAccess (AWS Managed Policy)
  • S3-Support group → AmazonS3ReadOnlyAccess (AWS Managed Policy)
  • EC2-Admin group → EC2-Admin-Policy (Inline Policy granting Describe + Start + Stop)

Gotchas

  • AWS Managed Policies can be overly broad — always review the JSON before attaching
  • Inline policies are harder to audit at scale (not listed centrally)
  • Deleting a group/user/role also deletes its inline policies permanently
  • You cannot attach an inline policy to multiple entities — if you need that, convert to a customer managed policy

See Also

  • [[iam-policy-structure]]
  • [[iam-groups]]
  • [[iam-users]]
  • [[s3-bucket-policies]]

title: “IAM Policy Structure” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • iam
  • security
  • certification

IAM Policy Structure

What It Is

An IAM Policy is a JSON document that defines permissions. It specifies what actions are allowed or denied on which AWS resources. Policies are the core mechanism for authorization in AWS.

Why It Matters

Every permission decision in AWS goes through policy evaluation. Understanding the JSON structure is critical for writing custom policies, debugging access issues, and passing certification exams.

Key Concepts

Basic Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["service:ActionName"],
      "Resource": ["arn:aws:service:region:account:resource"]
    }
  ]
}

Statement Elements

ElementDescriptionRequiredExample
EffectAllow or DenyYes"Allow"
ActionAPI operations permitted/deniedYes"ec2:DescribeInstances", "s3:GetObject"
ResourceAWS resources the statement applies toYes"arn:aws:s3:::mybucket/*", "*"
ConditionConditions for when the statement appliesNoIP range, time, MFA requirement
PrincipalWho the statement applies to (resource-based policies only)Depends"AWS": "arn:aws:iam::123456789012:root"

Action Format

Actions follow the pattern: service:ActionName

  • ec2:DescribeInstances — describe EC2 instances
  • s3:GetObject — retrieve an object from S3
  • cloudwatch:ListMetrics — list CloudWatch metrics
  • ec2:* — all EC2 actions (wildcard)

Resource Scope

  • "*" — any resource (broad, use carefully)
  • Specific ARN — targets a precise resource (e.g., arn:aws:s3:::mybucket/reports/*)

Multiple Statements

A policy can contain multiple statements. AWS evaluates all applicable policies and statements:

  1. By default, everything is denied (implicit deny)
  2. An explicit Allow overrides the implicit deny
  3. An explicit Deny always wins over any Allow

Real-World Examples

Read-only EC2 (support role):

{
  "Effect": "Allow",
  "Action": [
    "ec2:Describe*",
    "elasticloadbalancing:Describe*",
    "cloudwatch:ListMetrics",
    "cloudwatch:GetMetricStatistics",
    "autoscaling:Describe*"
  ],
  "Resource": "*"
}

EC2 Admin (start/stop):

{
  "Effect": "Allow",
  "Action": [
    "ec2:Describe*",
    "ec2:StartInstances",
    "ec2:StopInstances"
  ],
  "Resource": "*"
}

Gotchas

  • "Version": "2012-10-17" is the current policy language version — always include it
  • An explicit Deny always overrides an Allow (deny wins)
  • Wildcards in Actions (ec2:Describe*) match any action starting with that prefix
  • "Resource": "*" means all resources — fine for Describe actions, dangerous for write actions
  • Identity-based policies (attached to users/groups/roles) don’t have a Principal element — the principal is the entity the policy is attached to

See Also

  • [[iam-managed-vs-inline-policies]]
  • [[iam-groups]]
  • [[iam-users]]
  • [[aws-arns]]
  • [[s3-bucket-policies]]

title: “IAM Sign-In URL” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • iam
  • security
  • certification

IAM Sign-In URL

What It Is

The IAM Sign-In URL is the account-specific URL that IAM users use to sign in to the AWS Management Console. It is different from the root account sign-in page.

Why It Matters

Understanding the sign-in mechanism is important for account governance and for certification exams that test your knowledge of IAM user authentication workflows.

Key Concepts

URL Format

https://<account-id-or-alias>.signin.aws.amazon.com/console
  • Found on the IAM Dashboard in the AWS Console
  • Uses the 12-digit account ID by default
  • Can be customized with an account alias for readability

Examples

  • Default: https://123456789012.signin.aws.amazon.com/console
  • With alias: https://mycompany.signin.aws.amazon.com/console

How to Find It

  1. Open the IAM Console
  2. Go to Dashboard
  3. The sign-in URL is displayed at the top

IAM User Sign-In vs Root User Sign-In

AspectIAM UserRoot User
Sign-in pageAccount-specific URLhttps://console.aws.amazon.com/
IdentifierUsernameEmail address
PermissionsDefined by policiesUnrestricted (full access)
MFAOptional (but recommended)Optional (but strongly recommended)

Account Alias

  • Replaces the account ID in the sign-in URL
  • Must be globally unique across all AWS accounts
  • Set via IAM Console → Dashboard → “Create” under Account Alias
  • Only one alias per account

Gotchas

  • The sign-in URL is not secret — it only identifies the account, not credentials
  • IAM users cannot sign in via the root sign-in page without specifying the account ID
  • If the account alias is taken, you must choose a different one (globally unique)
  • Sharing the sign-in URL with new team members is a standard onboarding step

See Also

  • [[iam-users]]
  • [[iam-groups]]

title: “IAM Users” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • iam
  • security
  • certification

IAM Users

What It Is

An IAM User is an identity within an AWS account that represents a person or application needing to interact with AWS resources. Each user has a unique name within the account and can have credentials (password, access keys) to authenticate.

Why It Matters

IAM users are the foundational identity unit in AWS. Understanding how users work — and how they get permissions — is essential for both day-to-day operations and certification exams. Users alone have no permissions by default; they must be granted access explicitly.

Key Concepts

User Credentials

Credential TypePurpose
Console passwordSign in to the AWS Management Console
Access keys (key ID + secret)Programmatic access via CLI/SDK/API
MFA deviceAdditional authentication factor

Characteristics

  • A new user has zero permissions until policies are attached (directly or via group membership)
  • Users are identified by a friendly name (e.g., user-1) and an ARN (e.g., arn:aws:iam::123456789012:user/user-1)
  • Users can belong to multiple groups simultaneously
  • Users can have policies attached directly (not recommended at scale) or inherit them from groups

IAM Users Sign-In URL

Each AWS account has an account-specific sign-in URL for IAM users:

https://<account-id>.signin.aws.amazon.com/console

This URL is found on the IAM Dashboard and can be customized with an account alias.

Gotchas

  • A brand new user has no permissions at all — not even to view their own account info
  • Users are global (not region-specific) — IAM is a global service
  • There is a default limit of 5,000 IAM users per account
  • Best practice: use groups to assign permissions, not direct user policy attachments

See Also

  • [[iam-groups]]
  • [[iam-policy-structure]]
  • [[iam-managed-vs-inline-policies]]
  • [[iam-instance-profiles]]

title: “Passkeys (FIDO2/WebAuthn)” created: 2026-10-23 updated: 2026-10-23 type: knowledge tags:

  • aws
  • iam
  • security
  • certification
  • authentication
  • mfa

Passkeys (FIDO2/WebAuthn)

What It Is

A passkey is a phishing-resistant authentication credential based on public-key cryptography (the FIDO2 / WebAuthn standard). A key pair is generated: the private key never leaves the authenticator (e.g. 1Password, a hardware key, or the device’s secure enclave), and the public key is registered with the service (e.g. AWS).

Do NOT confuse a passkey with AWS access keys. Access keys (Access Key ID + Secret Access Key) are long-lived programmatic credentials for the CLI/SDK/API. A passkey is an interactive sign-in / MFA credential — a completely different thing.

Why It Matters

Passkeys are the strongest practical sign-in method for the AWS Console because they are resistant to phishing: a fake AWS login page cannot capture a reusable secret, since nothing reusable is ever transmitted. They are recommended for high-value identities such as the root user and admin IAM users.

Key Concepts

TermMeaning
Private keySecret half, stored in the authenticator, never shared
Public keyRegistered with the relying party (AWS) for verification
Relying partyThe service verifying the login (AWS Console)
AuthenticatorWhere the private key lives (1Password, YubiKey, device enclave)
ChallengeRandom value AWS sends; the authenticator signs it with the private key

Passkey vs TOTP (MFA)

  • TOTP (6-digit code, e.g. 1Password Auth-App): a shared secret both sides know; phishable if the user is tricked into typing the code on a fake site.
  • Passkey: origin-bound signature; the authenticator refuses to sign for the wrong domain, so it cannot be phished.

Usage in AWS

A passkey on the AWS Console can be used:

  1. As a phishing-resistant MFA second factor (on top of a password), or
  2. As a full sign-in credential, depending on the AWS sign-in flow and identity type.

Applicable to the root user and IAM users sign-in (signin.aws.amazon.com).

How It Works

  1. Registration: authenticator generates a key pair, sends the public key to AWS.
  2. Sign-in: AWS sends a challenge → authenticator signs it with the private key.
  3. AWS verifies the signature with the stored public key. No password is transmitted.

Examples

  • Root user: register a passkey (in 1Password) as a strong MFA/sign-in method, while keeping the existing TOTP MFA as a backup factor.
  • Admin IAM user (benoitAsAdmin): same approach — passkey plus a fallback factor.

Gotchas

  • Single point of failure: if the passkey lives only in 1Password, access to the 1Password vault becomes the single point of failure for the AWS root. Always keep a second MFA method registered on each identity; never leave root with only one.
  • Recovery: keep the 1Password Emergency Kit and master password stored offline.
  • Not for the CLI: passkeys cover interactive Console sign-in, not aws login (SSO) or programmatic access. Daily CLI access still goes through Identity Center.
  • A passkey is not an AWS access key — different purpose, different lifecycle.

See Also

  • [[iam-users]]
  • [[iam-sign-in-url]]
  • [[iam-groups]]

title: “S3 Access Control Lists (ACLs)” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • security
  • acl
  • certification

S3 Access Control Lists (ACLs)

What It Is

ACLs are a legacy access control mechanism for S3 that grant basic read/write permissions at the object or bucket level to specific AWS accounts or predefined groups.

Why It Matters

While AWS recommends bucket policies over ACLs for most use cases, ACLs still appear on the exam and in legacy architectures. Understanding when they apply (and when they don’t) is important.

Key Concepts

Object Ownership & ACLs

Since April 2023, new buckets default to ACLs disabled (Bucket owner enforced). ACLs only work when explicitly enabled:

Ownership SettingACL Behavior
Bucket owner enforced (default)ACLs disabled — all access via policies only
Bucket owner preferredACLs enabled; bucket owner owns objects with bucket-owner-full-control
Object writerACLs enabled; uploading account retains ownership

Predefined Groups (Grantees)

  • All Users (http://acs.amazonaws.com/groups/global/AllUsers) — public/anonymous access
  • Authenticated Users — any authenticated AWS account (rarely useful)
  • Log Delivery — for S3 access logging

Permissions Available via ACL

  • READ — list objects (bucket) or read object data (object)
  • WRITE — create/delete objects in bucket
  • READ_ACP — read the ACL itself
  • WRITE_ACP — modify the ACL
  • FULL_CONTROL — all of the above

“Make Public Using ACL” in Console

This sets the object ACL to grant READ to the All Users group. It only works when:

  1. ACLs are enabled on the bucket (Object Ownership setting)
  2. Block Public Access is disabled (or IgnorePublicAcls is off)

Gotchas

  • ACLs only grant access at a coarse level — you cannot restrict by IP, time, or condition
  • Bucket policies are more powerful and flexible; AWS recommends them over ACLs
  • BPA settings override ACLs entirely when enabled
  • “Make public” via ACL grants access to ONE object — not the entire bucket

See Also

  • [[s3-block-public-access]]
  • [[s3-bucket-policies]]
  • [[s3-bucket-configuration]]

title: “S3 Access Without Public Exposure” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • security
  • iam
  • bucket-policy
  • best-practice
  • certification

S3 Access Without Public Exposure

What It Is

A pattern where you grant access to an S3 bucket exclusively through bucket policies with explicit principals, while keeping Block Public Access (BPA) fully enabled and ACLs disabled. No public exposure is needed.

Why It Matters

This is the AWS-recommended approach for S3 access control. It eliminates accidental data exposure while maintaining fine-grained access. Understanding this pattern is essential for certification exams and real-world architecture.

Key Concepts

What BPA Actually Blocks

BPA only blocks public access — meaning anonymous or Principal: "*" access. It does NOT block:

  • Access by a specific IAM role or user (identified ARN)
  • Cross-account access to a named principal
  • Access from AWS services (CloudFront OAC, Lambda, etc.)

The Ideal Combination

LayerSettingPurpose
BPAAll 4 settings ONSafety net — prevents any public access
ACLsDisabled (Bucket Owner Enforced)Eliminates legacy complexity
Bucket PolicyExplicit principals onlySingle source of truth for access

Why It Works

A bucket policy with a specific principal (ARN) is not considered “public” by AWS. BPA’s BlockPublicPolicy setting only rejects policies that use Principal: "*" or have conditions that effectively make them public.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/MyAppRole"
      },
      "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

→ BPA will not block this policy because the principal is identified, not anonymous.

BPA Behavior Matrix

Bucket Policy PrincipalBPA ONResult
"*" (everyone)ONBlocked by BlockPublicPolicy
"arn:aws:iam::123456:role/X" (specific role)ONAllowed — not public
"arn:aws:iam::999999:root" (cross-account)ONAllowed — identified principal
{"Service": "cloudfront.amazonaws.com"}ONAllowed — AWS service principal

Common Use Cases

  • EC2 to S3: bucket policy grants access to an EC2 instance role
  • Cross-account: bucket policy grants access to another AWS account’s role
  • CloudFront to S3: bucket policy grants access to CloudFront OAC
  • Lambda to S3: bucket policy grants access to Lambda execution role

Gotchas

  • Principal: "*" with a Condition (e.g., VPC endpoint) may still be considered public by BPA — test carefully
  • Account-level BPA overrides bucket-level settings — check both
  • Disabling BPA is not needed for IAM-based access — if someone says “disable BPA to grant access to a role”, that’s wrong
  • ACLs are legacy — prefer “Bucket Owner Enforced” object ownership to disable them entirely

See Also

  • [[s3-block-public-access]] — The four BPA settings explained
  • [[s3-bucket-policies]] — Policy structure and common patterns
  • [[iam-instance-profiles]] — EC2 roles for S3 access without credentials
  • [[aws-arns]] — ARN format for principals and resources
  • [[s3-access-control-lists]] — Why ACLs are legacy

title: “S3 Block Public Access” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • security
  • certification

S3 Block Public Access

What It Is

Block Public Access (BPA) is a set of four independent bucket-level settings that act as a safety net to prevent any public access to your S3 bucket, regardless of individual object ACLs or bucket policies.

Why It Matters

BPA is the first line of defense against accidental data exposure. It overrides any permissive ACL or policy at a higher level. This is a heavily tested topic on certification exams — understanding how BPA interacts with ACLs and policies is essential.

Key Concepts

The Four Settings

SettingWhat It Blocks
BlockPublicAclsRejects PUT requests that include a public ACL
IgnorePublicAclsIgnores all public ACLs on existing objects
BlockPublicPolicyRejects bucket policies that grant public access
RestrictPublicBucketsRestricts access to accounts/principals only (no anonymous)

Hierarchy

BPA can be set at three levels:

  1. Account level — applies to all buckets in the account
  2. Bucket level — applies to a specific bucket
  3. The most restrictive setting wins

Default Behavior

  • Since April 2023, new buckets have BPA enabled by default (all four settings ON)
  • This means “Make public using ACL” will fail until BPA is explicitly disabled

Interaction with ACLs and Policies

  • BPA ON + public ACL = Access Denied (BPA wins)
  • BPA ON + permissive bucket policy = policy is rejected or ignored
  • BPA OFF + public ACL = object is publicly accessible
  • Best practice: keep BPA ON and use IAM/bucket policies for controlled access

Gotchas

  • Disabling BPA does not automatically make anything public — it only removes the guard
  • Changing BPA requires typing “confirm” in the console (intentional friction)
  • Account-level BPA can block bucket-level permissions even if the bucket BPA is off
  • In production, use least permissive settings — only disable what you specifically need

See Also

  • [[s3-access-control-lists]]
  • [[s3-bucket-policies]]
  • [[s3-fundamentals]]

title: “S3 Bucket Policies” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • security
  • iam
  • certification

S3 Bucket Policies

What It Is

A bucket policy is a resource-based JSON policy attached directly to an S3 bucket. It defines who can do what on which resources within that bucket.

Why It Matters

Bucket policies are the primary mechanism for controlling S3 access in modern AWS. They appear in nearly every exam scenario involving cross-account access, public websites, or EC2-to-S3 connectivity.

Key Concepts

Policy Structure (JSON)

{
  "Version": "2012-10-17",
  "Id": "PolicyId",
  "Statement": [
    {
      "Sid": "StatementId",
      "Effect": "Allow | Deny",
      "Principal": "who",
      "Action": ["what operations"],
      "Resource": "which bucket/objects"
    }
  ]
}

Key Elements

ElementDescriptionExample
EffectAllow or Deny"Allow"
PrincipalWho gets access (ARN, * for everyone)"arn:aws:iam::123456:role/MyRole"
ActionS3 API operations"s3:GetObject", "s3:PutObject"
ResourceBucket and/or objects (ARN)"arn:aws:s3:::mybucket/*"
ConditionOptional constraints (IP, date, etc.)"IpAddress": {"aws:SourceIp": "x.x.x.x"}

Common Actions

  • s3:GetObject — download/read objects
  • s3:PutObject — upload objects
  • s3:DeleteObject — delete objects
  • s3:ListBucket — list objects in bucket (resource = bucket ARN, not /*)
  • s3:GetObjectVersion — read a specific version (versioning)

Resource ARN Patterns

  • Bucket-level: arn:aws:s3:::mybucket (for ListBucket)
  • Object-level: arn:aws:s3:::mybucket/* (for Get/Put/Delete)
  • The /* suffix is critical — without it, object operations won’t match

AWS Policy Generator

A web-based tool at https://awspolicygen.s3.amazonaws.com/policygen.html that helps you build policies visually without writing JSON by hand.

Multiple Statements

A policy can contain multiple statements. Example: one statement granting EC2 role PutObject/GetObject, another granting everyone GetObject (public read).

Gotchas

  • Forgetting /* at the end of the Resource ARN for object operations = policy won’t work
  • Principal: "*" = anyone in the world (use with extreme caution)
  • Explicit Deny always overrides Allow
  • Bucket policies are limited to 20 KB
  • BPA can still block a permissive bucket policy if BlockPublicPolicy is enabled

See Also

  • [[aws-arns]]
  • [[s3-block-public-access]]
  • [[s3-access-control-lists]]
  • [[iam-instance-profiles]]

title: “Learnings — Serverless” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • serverless

Serverless

Atomic notes on AWS serverless — Lambda patterns, API Gateway, Step Functions, EventBridge.

Notes


title: “Learnings — Storage” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • certification
  • storage

Storage

Atomic notes on AWS storage services — S3, EBS, EFS, FSx, Storage Gateway.

Notes

  • [[s3-fundamentals]] — What S3 is, object storage model, durability, key concepts
  • [[s3-bucket-configuration]] — Bucket naming rules, region selection, object ownership
  • [[s3-object-operations]] — Upload, download, metadata, Object URL
  • [[s3-versioning]] — Enable versioning, delete markers, recovering deleted objects

title: “S3 Bucket Configuration” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • storage
  • certification

S3 Bucket Configuration

What It Is

The set of settings you define when creating an S3 bucket: naming, region placement, object ownership, and default encryption.

Why It Matters

Misconfiguring a bucket at creation time can lead to naming conflicts, latency issues, or security gaps. Several settings (like the bucket name) cannot be changed after creation.

Key Concepts

Bucket Naming Rules

  • 3–63 characters
  • Lowercase letters, numbers, and hyphens only
  • Must start with a letter or number
  • Cannot look like an IP address (e.g., 192.168.1.1)
  • Globally unique across all AWS accounts and regions
  • Immutable — cannot be renamed after creation

Region Selection

  • Determines where objects are physically stored
  • Affects latency, cost, and regulatory compliance
  • Objects never leave a region unless you explicitly transfer them (replication, copy)

Object Ownership

SettingBehavior
ACLs disabled (default since Apr 2023)Bucket owner owns all objects; ACLs have no effect
ACLs enabled — Bucket owner preferredBucket owner owns objects if bucket-owner-full-control ACL is applied
ACLs enabled — Object writerUploading account retains ownership

Default Encryption

  • SSE-S3 (AES-256) — enabled by default since Jan 2023
  • SSE-KMS — use a KMS key for more control
  • DSSE-KMS — dual-layer encryption

Gotchas

  • Choosing a region cannot be changed after bucket creation
  • If ACLs are disabled (recommended), you cannot use “Make public via ACL” — use bucket policies instead
  • Bucket names that resemble domain names have extra DNS constraints

See Also

  • [[s3-fundamentals]]
  • [[s3-block-public-access]]
  • [[aws-arns]]

title: “Amazon S3 Fundamentals” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • storage
  • certification

Amazon S3 Fundamentals

What It Is

Amazon Simple Storage Service (Amazon S3) is an object storage service — not block storage (EBS) or file storage (EFS). It stores data as objects within buckets.

  • Object = file + metadata + unique key
  • Bucket = container for objects (flat namespace, no real folders — prefixes simulate hierarchy)

Why It Matters

S3 is one of the most foundational AWS services. It appears in nearly every certification exam and real-world architecture. Use cases span websites, mobile apps, backup/restore, archive, enterprise apps, IoT, and big data analytics.

Key Concepts

ConceptDetail
Durability99.999999999% (11 nines) — data is replicated across multiple AZs
AvailabilityVaries by storage class (99.99% for Standard)
Storage modelObject storage (not hierarchical file system)
Global namespaceBucket names are globally unique across all AWS accounts
Max object size5 TB (single PUT limited to 5 GB; use multipart for larger)
Region-boundObjects stay in a region unless explicitly transferred

How It Works

  1. You create a bucket in a specific AWS Region
  2. You upload objects (files) into the bucket
  3. Each object gets a unique key (its full path within the bucket)
  4. Access is controlled via IAM policies, bucket policies, ACLs, and Block Public Access
  5. Objects are accessed via HTTPS URLs: https://<bucket>.s3.<region>.amazonaws.com/<key>

Examples

  • Static website hosting
  • Data lake for analytics
  • Backup and disaster recovery
  • Log storage (CloudTrail, ELB, CloudFront)
  • Application data storage (reports pushed from EC2)

Gotchas

  • Bucket names are globally unique and immutable once created
  • S3 is eventually consistent for overwrite PUTs and DELETEs (though strong consistency was added in Dec 2020 for all operations)
  • Objects are private by default — you must explicitly grant access
  • Block Public Access (BPA) overrides any permissive ACL or policy

See Also

  • [[s3-bucket-configuration]]
  • [[s3-object-operations]]
  • [[s3-versioning]]
  • [[s3-block-public-access]]
  • [[s3-bucket-policies]]

title: “S3 Object Operations” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • storage
  • certification

S3 Object Operations

What It Is

The core CRUD operations you perform on S3 objects: upload (PUT), download (GET), list, copy, and delete.

Why It Matters

Understanding S3 API operations is essential for both the certification exam and day-to-day cloud work. Permissions are granted at the operation level (e.g., s3:PutObject, s3:GetObject).

Key Concepts

Upload (PutObject)

  • Via Console: upload wizard (drag-and-drop or file picker)
  • Via CLI: aws s3 cp <local-file> s3://<bucket>/
  • Via SDK: putObject() API call
  • Single PUT max: 5 GB
  • Multipart upload recommended for files > 100 MB (required > 5 GB)

Download (GetObject)

  • Via Console: select object → download
  • Via CLI: aws s3 cp s3://<bucket>/<key> <local-path>
  • Via pre-signed URL for temporary access

Object URL

Each object has a URL: https://<bucket>.s3.<region>.amazonaws.com/<key>

Accessing this URL returns the object only if permissions allow it. By default: Access Denied.

Metadata

  • System metadata: Content-Type, Content-Length, Last-Modified, ETag
  • User-defined metadata: key-value pairs prefixed with x-amz-meta-
  • Metadata is immutable after upload (must re-upload to change)

List (ListObjects)

  • aws s3 ls s3://<bucket>/ — lists objects in a bucket
  • Returns key, size, last modified date

Gotchas

  • Uploading an object with the same key overwrites it (unless versioning is enabled)
  • S3 has no native “rename” — you copy to new key and delete the old one
  • Large file uploads should always use multipart to handle network failures gracefully

See Also

  • [[s3-fundamentals]]
  • [[s3-versioning]]
  • [[aws-cli-s3-commands]]
  • [[s3-bucket-policies]]

title: “S3 Versioning” created: 2026-07-20 updated: 2026-07-20 type: knowledge tags:

  • aws
  • s3
  • storage
  • versioning
  • certification

S3 Versioning

What It Is

A bucket-level feature that keeps multiple variants of an object in the same bucket. Every upload of an object with the same key creates a new version rather than overwriting.

Why It Matters

Versioning protects against accidental deletion and overwrites. It is critical for compliance, auditing, and disaster recovery scenarios — all frequent exam topics.

Key Concepts

States

StateBehavior
Unversioned (default)No version tracking; overwrites and deletes are permanent
EnabledAll objects get a unique Version ID; deletions create delete markers
SuspendedStops creating new versions but preserves existing ones

How Versions Work

  • Each upload generates a new Version ID
  • GET without specifying a version always returns the latest version
  • Objects uploaded before versioning was enabled have Version ID = null

Delete Behavior

  • Simple delete (without version ID): inserts a Delete Marker — the object appears deleted but all previous versions remain
  • Permanent delete (specify version ID): removes that specific version permanently; no delete marker created
  • Restoring: delete the delete marker → object reappears with its latest real version

Accessing Older Versions

  • Via Console: toggle “Show versions” → select the version
  • Via API/CLI: specify versionId parameter
  • Requires s3:GetObjectVersion permission (separate from s3:GetObject)

Gotchas

  • Versioning cannot be disabled once enabled — only suspended
  • Every version is a full copy (not a diff) → storage costs multiply
  • Delete markers are lightweight objects but still count
  • MFA Delete can be enabled to require MFA for permanent version deletions

See Also

  • [[s3-fundamentals]]
  • [[s3-object-operations]]
  • [[s3-bucket-policies]]

title: “AWS Certification — Training Materials” created: 2026-07-20 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • training

Training Materials

This folder stores raw training content — course notes, exam prep files, and study resources pasted here for reference.

Resources

  • [[aws-training-portals]] — Where to find AWS courses and labs (Ramp-Up Guides, Skill Builder)

Completed

  • [[Introduction-to-Amazon-Simple-Storage-Service-S3]] — S3 buckets, objects, ACLs, policies, versioning (lab)
  • [[Introduction-to-AWS-Identity-and-Access-Management-IAM]] — IAM users, groups, policies, permission testing (lab)
  • [[Introduction-to-Amazon-Virtual-Private-Cloud-VPC]] — VPC subnets, route tables, IGW, NAT GW, NACLs, security groups (lab)
  1. [[Introduction-to-Amazon-EC2]] — EC2 compute (combines IAM + VPC knowledge)

Introduction to AWS Identity and Access Management (IAM)

SPL-66 - version 3.1.23

Objectives

After completing this lab, you will know how to:

  • Explore pre-created IAM users and groups
  • Inspect IAM policies as applied to pre-created groups
  • Add users to groups with specific capabilities enabled following a real-world business scenario
  • Locate and use the IAM sign-in URL
  • Experiment with the effects of policies on service access

Prerequisites

This lab is an introductory-level lab for AWS Identity and Access Management (IAM).

Duration

This lab requires approximately 30 minutes to complete.

Overview

This lab introduces AWS Identity and Access Management (IAM) by exploring users, groups, and policies that have already been created in an AWS account. You test the permissions of each IAM user by signing in and verifying access to AWS services based on group membership and attached policies.


Task 1: Explore the Users and Groups

In this task, you explore the Users and Groups that have already been created in IAM.

  1. In the AWS Management Console, search for and choose IAM.

  2. In the navigation pane, choose Users.

    The following IAM Users have been created:

    • user-1
    • user-2
    • user-3
  3. Choose user-1.

    The summary page for user-1 displays. The Permissions tab shows that user-1 does not have any permissions.

  4. Choose the Groups tab.

    user-1 is not a member of any groups.

  5. Choose the Security credentials tab.

    user-1 is assigned a Console password.

  6. In the navigation pane, choose User groups.

    The following groups have been created:

    • EC2-Admin
    • EC2-Support
    • S3-Support
  7. Choose the EC2-Support group.

  8. Choose the Permissions tab.

    This group has a Managed Policy associated with it called AmazonEC2ReadOnlyAccess. Managed Policies are pre-built policies (built either by AWS or by your administrators) that can be attached to IAM Users and Groups. When the policy is updated, the changes immediately apply to all Users and Groups that the policy is attached to.

  9. Choose AmazonEC2ReadOnlyAccess and view the JSON.

    This policy grants permission to List and Describe information about EC2, Elastic Load Balancing, CloudWatch, and Auto Scaling. This ability to view resources but not modify them is ideal for a Support role.

    The basic structure of statements in an IAM Policy is:

    • Effect — Whether to Allow or Deny the permissions.
    • Action — The API calls that can be made against an AWS Service (e.g., cloudwatch:ListMetrics).
    • Resource — The scope of entities covered by the policy rule (e.g., a specific S3 bucket, an EC2 instance, or * meaning any resource).
  10. Choose the S3-Support group.

    The S3-Support group has the AmazonS3ReadOnlyAccess policy attached. This policy grants permissions to Get and List resources in Amazon S3.

  11. Choose the EC2-Admin group.

    This group is different from the other two. Instead of a Managed Policy, it has an Inline Policy — a policy assigned to just one User or Group. Inline Policies are typically used for one-off permission situations.

  12. Choose EC2-Admin-Policy and view the JSON.

    This policy grants permission to Describe information about Amazon EC2 and also the ability to Start and Stop instances.


Business Scenario

Your company is growing its use of AWS and is using many EC2 instances and a great deal of S3 storage. You need to give access to new staff depending on their job function:

UserIn GroupPermissions
user-1S3-SupportRead-Only access to Amazon S3
user-2EC2-SupportRead-Only access to Amazon EC2
user-3EC2-AdminView, Start and Stop Amazon EC2 instances

Task 2: Add Users to Groups

Add user-1 to the S3-Support Group

user-1 has been hired to provide support for Amazon S3. Adding them to the S3-Support group grants them the necessary permissions via the attached AmazonS3ReadOnlyAccess policy.

  1. In the navigation pane, choose User groups.
  2. Choose the S3-Support group.
  3. Choose the Users tab.
  4. Choose Add users.
  5. Select user-1 and choose Add users.

Add user-2 to the EC2-Support Group

user-2 has been hired to provide support for Amazon EC2.

  1. Add user-2 to the EC2-Support group using the same steps.

Add user-3 to the EC2-Admin Group

user-3 has been hired as the Amazon EC2 administrator.

  1. Add user-3 to the EC2-Admin group using the same steps.
  2. Verify each group shows 1 in the Users column.

Task 3: Sign-In and Test Users

In this task, you test the permissions of each IAM user by signing in with their credentials.

  1. In the navigation pane, choose Dashboard.

    The IAM users Sign-in URL is displayed (e.g., https://123456789012.signin.aws.amazon.com/console).

  2. Copy the sign-in URL.

  3. Open a private/incognito browser window.

Test user-1 (S3-Support)

  1. Sign in as user-1.

  2. Navigate to S3.

    user-1 can view S3 buckets and their contents because they are in the S3-Support group.

  3. Navigate to EC2 → Instances.

    user-1 cannot see any instances because they have no EC2 permissions.

Test user-2 (EC2-Support)

  1. Sign out and sign in as user-2.

  2. Navigate to EC2 → Instances.

    user-2 can see EC2 instances (Read Only access).

  3. Attempt to Stop an instance.

    Error: You are not authorized to perform this operation. The policy only allows viewing information, not making changes.

  4. Navigate to S3.

    Error: Access Denied. user-2 does not have permission to use Amazon S3.

Test user-3 (EC2-Admin)

  1. Sign out and sign in as user-3.

  2. Navigate to EC2 → Instances.

  3. Choose Stop instance and confirm.

    The instance enters the stopping state. user-3 has full EC2 admin permissions (View, Start, Stop).


Conclusion

In this lab you successfully:

  • Explored pre-created IAM users and groups
  • Inspected IAM policies as applied to the pre-created groups
  • Followed a real-world scenario, adding users to groups with specific capabilities enabled
  • Located and used the IAM sign-in URL
  • Experimented with the effects of policies on service access

Additional Resources


title: “Introduction to Amazon EC2” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • training
  • ec2
  • compute

Introduction to Amazon EC2

Source: https://skillbuilder.aws/learn/9VNGAHHAUU/introduction-to-amazon-ec2/AJZEJRN2BQ

Status: Not started

Overview

AWS Skill Builder lab covering EC2 fundamentals: instance types, launch configuration, security groups, key pairs, and connecting to instances.

Learnings

To be extracted after completing the training.

See Also

  • [[Introduction-to-Amazon-Virtual-Private-Cloud-VPC]] — Previous in sequence
  • [[Introduction-to-AWS-Identity-and-Access-Management-IAM]] — First in sequence
  • [[../learnings/README]] — Learned topics index

Introduction to Amazon Simple Storage Service (S3)

SPL-TF-100-STESS3 - Version 2.4.20

Objectives

After completing this lab, you will know how to:

  • Create a bucket in Amazon S3
  • Add an object to a bucket
  • Manage access permissions on an object and a bucket
  • Create a bucket policy
  • Use bucket versioning

Prerequisites

This lab follows the Amazon Simple Storage Service (Amazon S3) Essentials - Beyond the Basics digital course.

Duration

This lab requires 60 minutes to complete.

Overview

This lab teaches you the basic feature functionality of Amazon S3 using the AWS Management Console.

Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance. Customers of all sizes and industries can use it to store and protect any amount of data for a range of use cases, such as websites, mobile applications, backup and restore, archive, enterprise applications, IoT devices, and big data analytics. Amazon S3 provides easy-to-use management features so you can organize your data and configure finely-tuned access controls to meet your specific business, organizational, and compliance requirements. Amazon S3 is designed for 99.999999999% (11 9’s) of durability and stores data for millions of applications for companies all around the world.

Visit the Amazon S3 product information page for additional details, capabilities, and a short introduction video about the service.

Lab Scenario

You work for a company using Amazon S3 for data storage. An application residing on an EC2 instance needs to push reporting data to an S3 bucket daily. You are tasked with creating an S3 bucket for your company to use for storing this report data. For a successful deployment, you need to ensure the EC2 instance has enough privileges to be able to upload and retrieve data from the S3 bucket. For security reasons, only the EC2 instance can write data to the S3 bucket. The files in the S3 bucket also require protection against accidental deletion.


Task 1: Create a bucket

You are new to Amazon S3 and want to test the features and security of S3 as you configure the environment to hold the EC2 report data. You know that every object in Amazon S3 is stored in a bucket so creating a new bucket to hold the reports is the first thing on your task list.

In this task, you create a bucket to hold your EC2 report data and then examine the different bucket configuration options.

  1. At the top of the AWS Management Console, search for and choose S3.

You can also search for S3 at the top of the services menu.

  1. Choose Create bucket

Caution: Bucket names must be between 3 and 63 characters long and consist of only lowercase letters, numbers, or hyphens. The bucket name must be globally unique across all of Amazon S3, regardless of account or region, and cannot be changed after the bucket is created.

In this lab, you will use your AWSLabUser account number in the bucket name to ensure that it is unique.

  1. At the top right of the Management Console, choose the AWSLabsUser dropdown menu.

  2. Under Account ID, select the copy icon to copy the AWSLabsUser account ID to your clipboard.

  3. Under the General configuration section, name your bucket: reportbucket-<Account ID>

    • Example bucket name: reportbucket-12345678901
    • Replace NUMBER in the bucket name with a random number to ensure a unique name.
    • Example: reportbucket-987987987987
  4. In the Object Ownership section, configure:

    • ACLs enabled
    • Object writer
  5. Leave Region at its default value.

Selecting a particular region allows you to optimize latency, minimize costs, or address regulatory requirements. Objects stored in a region never leave that region unless you explicitly transfer them to another region.

  1. Scroll to the bottom and choose Create bucket

Task 2: Upload an object to the bucket

Now that you have a bucket created for your report data, you are ready to work with objects. An object can be any kind of file: a text file, a photo, a video, a zip file, and so on. When you add an object to Amazon S3, you have the option of including metadata with the object and setting permissions to control access to the object.

In this task you test uploading objects to your reportbucket. You have a screencapture of a daily report and want to upload this image to your S3 bucket.

  1. Right-click this link new-report.png, choose Save link as, and save the file locally.
  2. In the S3 Management Console, find and select the bucket that starts with the name reportbucket.
  3. Choose Upload

This launches an upload wizard. Use this wizard to upload files either by selecting them from a file chooser or by dragging them to the S3 window.

  1. Choose Add files
  2. Browse to and select the new-report.png file that you downloaded previously.
  3. Scroll down and choose Upload

Your file is successfully uploaded when the green bar indicating Upload succeeded appears.

If the file does not display in the bucket within a few seconds of uploading it, you may need to choose the refresh button at the top-right.

  1. In the Upload: status section, choose Close.

Task 3: Make an object public

Security is a priority in Amazon S3. Before you configure your EC2 instance to connect to the reportbucket, you want to test the bucket and object settings for security.

In this task, you configure permissions on your bucket and your object to test accessibility.

First, you attempt to access the object to confirm that it is private by default.

  1. In the reportbucket overview page, on the objects tab, locate the new-report.png object, and choose the new-report.png file name.
  2. In the Object overview section, locate and copy the Object URL link.

The link should look similar to: https://reportbucket987987.s3-us-west-2.amazonaws.com/new-report.png

  1. Open a new browser tab and paste the Object URL link into the address field, and then press Enter.

You receive an Access Denied error. This is because objects in Amazon S3 are private by default.

  1. Keep the browser with the Access Denied error open and return to the web browser tab with the S3 Management Console.
  2. You should still be on the new-report.png Object overview tab.
  3. Choose the Object actions button and Make public using ACL, which will be the last item in the list.

Notice the warning Public access is blocked because Block Public Access settings are turned on for this bucket. This error displays because this bucket is configured not to allow public access. The bucket settings override any permissions applied to individual objects.

  1. Choose Make public and read the warning at the top of the window indicating that it “Failed to edit public access” — this is due to BPA being enabled.
  2. Choose Close to return to the object overview.
  3. Use the navigation at the top to go back to the main reportbucket overview page.
  4. Choose the Permissions tab.
  5. Under Block public access (bucket settings), choose Edit to change the settings.
  6. Deselect the Block all public access option, and then leave all other options deselected.

Notice that all of the individual options remain deselected. When deselecting all public access, you must then select the individual options that apply to your situation and security objectives. In a production environment, it is recommended to use the least permissive settings possible.

  1. Choose Save changes
  2. A dialogue box opens asking you to confirm your changes. Type confirm in the field, and then choose Confirm

✅ A Successfully edited bucket settings for Block Public Access message displays at the top of the window.

  1. Choose the Objects tab.
  2. Choose the new-report.png file name.
  3. On the new-report.png overview page, choose the Object actions button and select Make public using ACL.

Notice the warning: When public read access is enabled and not blocked by Block Public Access settings, anyone in the world can access the specified objects.

  1. Choose Make public and you should see the green banner Successfully edited public access at the top of the window.
  2. Choose Close to return to the object overview.
  3. Return to the other browser tab that displayed Access Denied for the new-report.png and refresh the page.

✅ The new-report.png now displays properly because it is publicly accessible.

  1. Close the web browser tab that displays your new-report.png image and return to the tab with the Amazon S3 Management Console.

In this example, you granted read access to just one specific object. If you wish to grant access to the entire bucket, you need to use a bucket policy, which is covered later in this lab.


Task 4: Test connectivity from the EC2 instance

In this task, you connect to your Amazon EC2 instance to test connectivity and security to the S3 reportbucket.

  1. At the top of the AWS Management Console, search for and choose EC2.
  2. On the EC2 Dashboard, under the Resources section, choose Instances (running).
  3. Select Bastion Host and choose Connect
  4. In the Connect to instance window:
    • For Connection method, select Session Manager.

Session Manager enables you to connect to the bastion host instance without the need for specific ports to be open on your firewall or Amazon VPC security group.

  1. Choose Connect

A new browser tab or window opens with a connection to the bastion host instance.

✅ You are now connected to the EC2 instance that holds the reporting application. Because Session Manager uses https port 443, it does not require you to open SSH port 22 to the outside world.

  1. In the bastion host session, enter the following command to change to home directory:
cd ~
  1. Enter the following command to verify you are in the home directory:
pwd

✅ The output should be:

/home/ssm-user
  1. Enter the following command to list all of your S3 buckets:
aws s3 ls

✅ The output should look similar to this:

2020-11-11 22:27:28 ql-cf-templates-1603924046-5d95cf473a39fe4e-us-west-2
2020-11-11 22:27:49 qltrail-lab-59350-1603924067
2020-11-11 22:34:46 reportbucket987987

Note: During the creating of the lab environment, both an Instance Profile (which defines who you are for authentication) and a Role (which defines what you can do after you authenticate), have been automatically added for the EC2 instance.

  1. Enter the following command to list all objects in your reportbucket:
aws s3 ls s3://reportbucket(NUMBER)

✅ The output should look like this:

2020-11-11 15:46:34      86065 new-report.png
  1. Change directories into the reports directory:
cd reports
  1. List the contents of the directory:
ls

✅ Output:

dolphins.jpg files.zip report-test.txt  report-test1.txt report-test2.txt report-test3.txt  whale.jpg
  1. Try copying a file to the S3 bucket:
aws s3 cp report-test1.txt s3://reportbucket(NUMBER)

✅ The output indicates an error upload failed. This is because we have read-only rights to the bucket and do not have the permissions to perform the PutObject operation.

  1. Leave this window open and go back to the AWS Console tab.

Task 5: Create a bucket policy

A bucket policy is a set of permissions associated with an S3 bucket. It is used to control access to an entire bucket or to specific directories within a bucket.

In this task, you use the AWS Policy Generator to create a bucket policy to enable read and write access from the EC2 instance to the bucket.

  1. Right-click this link sample-file.txt, choose Save link as, and save the file locally.
  2. Return to the AWS Management Console, search for and select S3.
  3. In the S3 Management Console tab, select the name of your bucket.
  4. Choose Upload and use the same upload process to upload the sample-file.txt.
  5. Choose the sample-file.txt file name. The sample-file.txt overview page opens.
  6. Under the Object overview section, locate and copy the Object URL link.
  7. In a new browser tab, paste the link into the address field, and then press Enter.

Once again, Access Denied will be displayed. You need to configure a bucket policy to grant access to all objects in the bucket without having to specify permissions on each object individually.

  1. Keep this browser tab open, but return to the tab with the S3 Management Console.
  2. Search for and go to IAM > Roles.
  3. In the Search field type EC2InstanceProfileRole. This is the Role that the EC2 instance uses to connect to S3.
  4. Select EC2InstanceProfileRole. On the Summary page, copy the Role ARN to a text file.

It should look similar to: arn:aws:iam::596123517671:role/EC2InstanceProfileRole

  1. Search for S3 and return to the S3 Management Console.
  2. Choose the reportbucket.
  3. Choose the Permissions tab.
  4. In the Permissions tab, scroll to the Bucket Policy section, choose Edit

Amazon Resource Names (ARNs) uniquely identify AWS resources across all of AWS. Each section of the ARN is separated by a “:” and represents a specific piece of the path to the specified resource: arn:partition:service:region:account-id:resource

Amazon S3 does not require region or account-id parameters in ARNs, so those sections are left blank. Example: arn:aws:s3:::reportbucket987987

  1. Copy the Bucket ARN to a text file. It looks like this:
arn:aws:s3:::reportbucket987987
  1. Open a new browser tab and go to the AWS Policy Generator at: https://awspolicygen.s3.amazonaws.com/policygen.html

In the AWS Policy Generator window:

  • For Select Type of Policy, select S3 Bucket Policy.
  • For Effect, select Allow.
  • For Principal, paste the EC2InstanceProfileRole ARN.
  • For Actions, select PutObject and GetObject
  • Amazon Resource Name (ARN): Paste the Bucket ARN.
  • At the end of the ARN, append /*

The ARN should look similar to: arn:aws:s3:::reportbucket987987/*

  1. Choose Add Statement.
  2. Choose Generate Policy.

A new window displays the generated policy in JSON format:

{
    "Version": "2012-10-17",
    "Id": "Policy1604361694227",
    "Statement": [
        {
            "Sid": "Stmt1604361692117",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::416159072693:role/EC2InstanceProfileRole"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::reportbucket987987/*"
        }
    ]
}

⚠️ Confirm that /* appears after your bucket name in the Resource line.

  1. Copy the policy you created to your clipboard.
  2. Close the web browser tab and return to the tab with the Bucket policy editor.
  3. Paste the bucket policy you created into the Bucket policy editor.
  4. Choose Save changes

Verify the bucket policy from EC2

  1. Return to the AWS Systems Manager (SSM) window.
  2. Type the following to verify you are in the /home/ssm-user/reports directory:
pwd

✅ Output:

/home/ssm-user/reports
  1. List all objects in your reportbucket:
aws s3 ls s3://reportbucket(NUMBER)

✅ Output:

2020-11-11 18:20:23      86065 new-report.png
2020-11-02 23:57:03         90 sample-file.txt
  1. List the contents of the reports directory:
ls
  1. Try copying the report-test1.txt file to the S3 bucket:
aws s3 cp report-test1.txt s3://reportbucket(NUMBER)

✅ Output:

upload: ./report-test1.txt to s3://reportbucket987987/report-test1.txt
  1. Verify the file uploaded to S3:
aws s3 ls s3://reportbucket(NUMBER)

✅ Output:

2020-11-11 18:20:23      86065 new-report.png
2020-11-11 18:32:18         31 report-test1.txt
2020-11-11 18:20:22         90 sample-file.txt

You have successfully uploaded (PutObject) a file from the EC2 instance to your S3 bucket.

  1. Retrieve (GetObject) a file from S3 to the EC2 Instance:
aws s3 cp s3://reportbucket(NUMBER)/sample-file.txt sample-file.txt

✅ Output:

download: s3://reportbucket987987/sample-file.txt to ./sample-file.txt
  1. Verify the file is now in the /reports directory:
ls

✅ Output:

dolphins.jpg  files.zip  report-test1.txt  report-test2.txt  report-test3.txt  sample-file.txt

You now see the sample-file.txt in your file list. You have successfully uploaded and retrieved a file from EC2 to the S3 bucket.

  1. Return to the browser tab that displayed the Access Denied for the sample-file.txt and refresh the page.

The page still displays an error message because the Bucket Policy only gave rights to the principal called EC2InstanceProfileRole.

Adding public read access

  1. Go back to the policy generator and add another statement to the bucket policy allowing EVERYONE (*), Read access (GetObject).

  2. Test if your policy works by refreshing the Access Denied browser tab.

If not successful, here is the full policy with both statements:

{
    "Version": "2012-10-17",
    "Id": "Policy1604428844058",
    "Statement": [
        {
            "Sid": "Stmt1604428821481",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::285058481724:role/EC2InstanceProfileRole"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::reportbucket987987/*"
        },
        {
            "Sid": "Stmt1604428842806",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::reportbucket987987/*"
        }
    ]
}
  1. Leave the tab open with the sample-file.txt displayed.

Task 6: Explore versioning

Versioning is a means of keeping multiple variants of an object in the same bucket. You can use versioning to preserve, retrieve, and restore every version of every object stored in your Amazon S3 bucket. With versioning, you can easily recover from both unintended user actions and application failures.

For auditing and compliance reasons you need to enable versioning on your reportbucket. Versioning should protect the reports in the reportbucket against accidental deletion.

  1. On the reportbucket overview page, choose the Properties tab.
  2. Under the Bucket Versioning section, choose Edit
  3. Select Enable and then choose Save changes

Versioning is enabled for an entire bucket and all objects within the bucket. It cannot be enabled for individual objects.

There are also cost considerations when enabling versioning.

  1. Right-click this link and save the text file to your computer using the same name as the text file in the previous task: sample-file.txt.

While this file has the same name as the previous file, it contains new text.

  1. In the S3 Management Console, on the reportbucket, choose the Objects tab.
  2. Choose Upload and upload the new sample-file.txt file.
  3. Go to the browser tab that has the contents of the sample-file.txt file.
  4. Make a note of the contents on the page, then refresh the page.

Notice new lines of text appear.

Amazon S3 always returns the latest version of an object if a version is not otherwise specified.

  1. Close the web browser tab with the contents of the text file.
  2. In the S3 Management Console, choose the sample-file.txt file name.
  3. Choose the Versions tab and then select the bottom version which reads null (Note: This is not the latest version).
  4. Select Open.

You should now see the original version of the file.

If you try to access the older version using the object URL link, you will receive an access denied message. This is expected because the bucket policy only allows permission to access the latest version. To access a previous version, you need the s3:GetObjectVersion permission.

Example policy with GetObjectVersion:

{
  "Id": "Policy1557511288767",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1557511286634",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::mybucket45647467/*",
      "Principal": "*"
    }
  ]
}
  1. Return to the bucket Objects tab.
  2. Locate the Show versions toggle and turn it on.

Notice the new-report.png object only has one version with ID null (uploaded before versioning was enabled).

  1. Toggle Show versions off to return to the default object view.
  2. Select the checkbox next to sample-file.txt.
  3. Choose Delete
  4. Type delete to confirm and choose Delete objects.
  5. Choose Close to return to the bucket overview.

The sample-file.txt object is no longer displayed in the bucket. However, versioning can be used to recover it.

  1. Toggle Show versions on.

Notice that the sample-file.txt object is displayed again, but the most recent version is a Delete marker. The two previous versions are listed as well. When versioning is enabled, objects are not immediately deleted — Amazon S3 inserts a delete marker which becomes the current version.

  1. Select the checkbox next to the version with the Delete marker.
  2. Choose Delete
  3. Type permanently delete and choose Delete objects.
  4. Choose Close.
  5. Toggle Show versions off.

Notice that the sample-file.txt object has been restored to the bucket. Removing the delete marker effectively restores the object.

Deleting a specific version

  1. Toggle Show versions on. You should see two versions of sample-file.txt.
  2. Select the checkbox next to the latest version of sample-file.txt.
  3. Choose Delete.
  4. Type permanently delete and choose Delete objects.
  5. Choose Close.

Notice that there is now only one version of the sample-file.txt file. When deleting a specific version, no delete marker is created — the object is permanently deleted.

  1. Toggle Show versions off.
  2. Choose the sample-file.txt file name.
  3. Copy the Object URL link.
  4. In a new browser tab, paste the link and press Enter.

The text of the original version of the sample-file.txt object is displayed.


Summary

You have successfully created an S3 bucket for your company to use to store report data from your EC2 Instance. You created a bucket policy to allow for the EC2 Instance to PutObjects and GetObject from the reportbucket and you successfully tested uploading and downloading files from the EC2 instance to test the bucket policy. You have enabled versioning on the S3 bucket to protect against accidental object deletion.


Conclusion

You have successfully learned how to:

  • Create a bucket in Amazon S3
  • Add an object to your bucket
  • Manage access permissions on an object
  • Create a bucket policy
  • Use bucket versioning

Additional resources

Introduction to Amazon Virtual Private Cloud (VPC)

SPL-84 - Version 2.0.22

Objectives

After completing this lab, you will be able to:

  • Create an Amazon VPC using the VPC Wizard
  • Explore the basic components of a VPC including:
    • Public and private subnets
    • Route tables and routes
    • NAT gateways
    • Network ACLs
    • Security groups

Overview

Amazon Virtual Private Cloud (Amazon VPC) lets you provision a logically isolated section of the AWS cloud where you can launch AWS resources in a virtual network that you define. You have complete control over your virtual networking environment, including selection of your own IP address range, creation of subnets, and configuration of route tables and network gateways. You can use both IPv4 and IPv6 in your VPC.


Task 1: Create an Amazon VPC

In this task you create an Amazon VPC using the VPC wizard. The wizard automatically creates a VPC based upon parameters you specify.

The VPC architecture consists of:

  • A public subnet and a private subnet
  • An Internet Gateway attached to the VPC
  • A NAT Gateway launched in the public subnet

VPC Configuration

  1. In the AWS Management Console, search for and choose VPC.
  2. Choose Create VPC.
  3. Under VPC settings:
    • Choose VPC and more
    • Name tag auto-generation: Lab
    • Number of Availability Zones: 1
    • Number of public subnets: 1
    • Number of private subnets: 1
    • Public subnet CIDR block: 10.0.25.0/24
    • Private subnet CIDR block: 10.0.50.0/24
    • NAT gateways: Zonal → In 1 AZ
    • VPC endpoints: None
  4. Choose Create VPC.

Task 2: Explore your VPC

Internet Gateway

An Internet Gateway connects your VPC to the Internet. Without it, the VPC has no connectivity to the Internet. Key characteristics:

  • Horizontally scaled
  • Redundant and highly available
  • Imposes no availability risks or bandwidth constraints

Subnets

A Subnet is a subset of a VPC with the following properties:

  • Belongs to a specific VPC
  • Exists in a single Availability Zone (while a VPC spans multiple AZs)
  • Has a range of IP addresses (CIDR range — Classless Inter-Domain Routing)

Public Subnet

  • Name: Lab-subnet-public
  • IPv4 CIDR: 10.0.25.0/24 (addresses 10.0.25.0 to 10.0.25.255)
  • 250 available IPs out of 256 (AWS reserves 5 addresses per subnet, plus 1 consumed by NAT gateway)

What makes a subnet “Public”?

A subnet is public when its route table contains a route to an Internet Gateway.

Route Tables

Each subnet is associated with a Route table that specifies routes for outbound traffic. Routes are evaluated from most restrictive (higher CIDR prefix) to least restrictive (0.0.0.0/0).

Public Subnet Route Table

DestinationTargetPurpose
10.0.0.0/16localCommunication within the VPC
0.0.0.0/0igw-xxxAll other traffic → Internet Gateway

Private Subnet Route Table

DestinationTargetPurpose
10.0.0.0/16localCommunication within the VPC
0.0.0.0/0nat-xxxAll other traffic → NAT Gateway

The absence of a route to the Internet Gateway is what defines the subnet as private. Instances cannot be directly accessed from the Internet.

Network ACLs

Network Access Control Lists (NACLs) are an optional stateless firewall controlling traffic in and out of subnets.

Default NACL rules:

Rule #DirectionActionTrafficSource/Destination
100InboundAllowAll0.0.0.0/0
100OutboundAllowAll0.0.0.0/0
*BothDenyAllCatch-all (if no earlier rule matches)

NAT Gateway

A NAT Gateway allows resources in a private subnet to connect to the Internet and other resources outside the VPC.

Key characteristics:

  • Outbound-only — the connection must be initiated from within the private subnet
  • Resources on the Internet cannot initiate inbound connections
  • Keeps resources private while allowing them to reach external services
  • AWS-managed service (no patching required)
  • Deployed in the public subnet (needs Internet Gateway access)

Traffic flow: Private Subnet → NAT Gateway (in public subnet) → Internet Gateway → Internet

Security Groups

Security Groups act as virtual firewalls at the instance level (not subnet level).

Key characteristics:

  • Up to 5 security groups per EC2 instance
  • Stateful — return traffic is automatically allowed
  • VPC comes with a default security group

Default security group behavior:

  • Permits ALL traffic only if the source is the default security group itself (self-referencing)
  • All other inbound traffic is denied
  • All outbound traffic is allowed

This self-reference means EC2 instances in the same security group can communicate with each other, but nothing else can reach them.


Conclusion

In this lab you successfully:

  • Created an Amazon VPC using the VPC Wizard
  • Explored the basic components of a VPC (subnets, route tables, Internet Gateway, NAT Gateway, NACLs, security groups)

Additional Resources


title: “AWS Training Portals — Where to Find Courses and Labs” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:

  • aws
  • certification
  • training
  • skill-builder

AWS Training Portals

Overview of the main AWS training portals and how to navigate them effectively.

Ramp-Up Guides

URL: https://aws.amazon.com/fr/training/ramp-up-guides/

A grid of downloadable guides organized by role/domain (Architect, DevOps, Machine Learning, Networking, Security, Data Analytics, etc.). Each guide provides a curated learning path with links to digital courses, classroom training, videos, whitepapers, and certifications.

Best for: structured, progressive learning paths when starting a new AWS domain.

AWS Skill Builder (Catalog)

URL: https://explore.skillbuilder.aws/learn/catalog

The main course catalog for AWS self-paced digital training (free and paid).

How to Filter

Once logged in, use the left-side panel on the catalog page:

FilterDescription
DomainCloud Essentials, Networking, Security, Storage, Serverless, ML…
LanguageEnglish, French, etc.
Skill LevelFundamental, Intermediate, Advanced
Learning TypeCourse, Lab, Game, Learning Plan

There is no dedicated filter by specific AWS service (EC2, S3, Lambda). To find content about a specific service, use the search bar with the service name.

AWS Training Main Page

URL: https://aws.amazon.com/training/

Entry point for all training options: digital (Skill Builder), classroom, partner, events.

See Also

  • [[README]] — Training materials index
  • [[../learnings/README]] — Learned topics index