AWS OpenTofu #101: AWS Fundamentals Before Infrastructure as Code
Understand AWS core architecture—accounts, regions, availability zones, ARNs, and APIs—and discover why declarative Infrastructure as Code with OpenTofu transforms cloud engineering.
AWS + OpenTofu Level 100: Infrastructure as Code from Zero
Part of the CLI-first comprehensive learning path from foundational setup to production cloud architectures.
Imagine joining a high-growth engineering team on your first day. You are handed a runbook titled “How to Deploy the Staging Environment.”
It is a 42-page Google Doc.
Step 14 reads: “Go to the EC2 console in Singapore, select the VPC with the tag ‘dev-new-final-v2’, click Subnets, find the private subnet in AZ-b, create a route table, and make sure you do NOT attach the Internet Gateway because Dave did that last week and leaked the database.”
By step 29, you hit a dead link. By step 37, a button mentioned in the document no longer exists because AWS refreshed their UI last Tuesday. After three days of tedious clicking, your staging environment is live—except half the microservices fail because three environment variables were typed with trailing spaces, two security group rules were missed, and nobody knows who created the orphaned elastic IP quietly costing $3.60 a day.
This nightmare is called ClickOps. It is fragile, unrepeatable, impossible to audit, and entirely dependent on human memory.
Before we write a single line of OpenTofu (the open-source fork of Terraform governed by the Linux Foundation), we must understand the substrate underneath: Amazon Web Services (AWS). Infrastructure as Code (IaC) is not magic; it is simply automated, version-controlled interaction with cloud provider APIs. If you do not understand the underlying cloud primitives—Regions, Availability Zones, ARNs, and authentication boundaries—IaC will only help you make mistakes faster and at greater scale.
In this foundational lab, we will break down AWS core architecture, examine how cloud APIs work under the hood, interrogate AWS global infrastructure directly from the terminal, and establish the declarative mindset required for OpenTofu mastery.
🎯 What You Will Learn
| AWS Architecture | OpenTofu & IaC Principles | Engineering Best Practices |
|---|---|---|
| • Global Infrastructure (Regions, AZs, Edge) | • Imperative vs. Declarative mental models | • Zero-trust credential isolation |
| • Amazon Resource Names (ARNs) deconstructed | • Desired State vs. Current State vs. Reality | • Auditability through Git version control |
| • AWS REST APIs & SigV4 Authentication | • The Core Workflow (init, plan, apply, destroy) | • Preventing configuration drift before it starts |
| • The Shared Responsibility Model | • OpenTofu State Graph fundamentals | • Understanding Physical AZ IDs vs Logical Names |
💰 Estimated Lab Cost
| Component | Usage in Lab | Free Tier Cost | Standard Account (Past Free Tier) |
|---|---|---|---|
AWS Identity Verification (sts:GetCallerIdentity) | CLI Read Query | $0.00 | $0.00 (Always Free) |
AWS Global Discovery (ec2:DescribeRegions) | CLI Read Query | $0.00 | $0.00 (Always Free) |
Availability Zone Discovery (ec2:DescribeAvailabilityZones) | CLI Read Query | $0.00 | $0.00 (Always Free) |
| OpenTofu CLI | Local Client Machine | $0.00 | $0.00 (Free & Open Source) |
| Total Estimated Cost | Complete Hands-On Session | $0.00 | $0.00 |
[!NOTE] Zero Billable Resources: This lab executes read-only queries against public AWS control plane endpoints. Whether you are on an active Free Tier or operating a mature enterprise account past Free Tier, AWS does not charge for STS caller identity or EC2 describe metadata API calls. Your total cost is $0.00.
📋 Prerequisites
Before proceeding, ensure your development workstation has:
- An AWS Account: A personal sandbox account with standard permissions (Free Tier eligible).
- AWS CLI v2 Installed: Verified with
aws --version. - Configured AWS Credentials: A non-root IAM user or IAM Identity Center profile configured with administrator or read-only exploratory privileges.
- A Terminal: Bash, Zsh, or equivalent Unix shell.
- OpenTofu CLI (Optional for Lab 101, Required for Lab 102): You can install it now via Homebrew (
brew install opentofu) or the official package manager for your OS.
🏛️ Part 1: How AWS Works Under the Hood
When you log into the AWS Management Console, click a blue button, and launch a virtual server, what actually happens?
The AWS Management Console is not the cloud. The Console is just a single-page web application (React/Angular) built by AWS frontend teams. Every button click simply gathers form data and sends an HTTPS REST request to an AWS regional control plane.
+-----------------------------------------------------------------------------------+
| YOUR WORKSTATION |
| |
| [ Web Browser Console ] [ AWS CLI v2 ] [ OpenTofu / Terraform Engine ]|
+-----------------------------------------------------------------------------------+
| | |
| HTTPS + Cookies | HTTPS + SigV4 | HTTPS + SigV4
v v v
+-----------------------------------------------------------------------------------+
| AWS REGIONAL CONTROL PLANE |
| |
| https://ec2.us-east-1.amazonaws.com / https://s3.us-east-1.amazonaws.com |
| |
| +---------------------------------------------------------------------------+ |
| | 1. Authentication & Signature Verification (AWS SigV4) | |
| | 2. Authorization Engine (IAM Policy Evaluation) | |
| | 3. Quota & Rate Limit Validation | |
| | 4. Orchestration Engine (Spawns Nitro hypervisors, allocates EBS, etc.) | |
| +---------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------------+
Whether you use the web console, the CLI, the Python SDK (boto3), or OpenTofu:
- Every client makes an HTTPS call to the service endpoint (e.g.,
ec2.us-east-1.amazonaws.com). - Every request is authenticated using AWS Signature Version 4 (SigV4) with cryptographic HMAC hashes of your Access Key ID and Secret Access Key.
- AWS IAM verifies whether the authenticated identity has permission to perform the action (e.g.,
ec2:RunInstances). - If authorized, the internal AWS orchestration system provisions the physical hardware, allocates hypervisor slices, or creates software-defined network routes.
Why does this matter for OpenTofu? OpenTofu interacts with AWS using the exact same REST APIs as the AWS CLI and console. When OpenTofu provisions infrastructure, it translates your declarative configuration into hundreds of sequenced HTTPS API calls against AWS endpoints.
🌍 Part 2: AWS Global Infrastructure
To design and code reliable infrastructure, you must master the three tiers of AWS geography: Regions, Availability Zones, and Edge Locations.
+-------------------------------------------------------------------------+
| AWS GLOBAL CLOUD |
| |
| +-------------------------------------------------------------------+ |
| | AWS REGION (e.g., ap-southeast-1 - Singapore) | |
| | | |
| | +-----------------------+ +-----------------------+ | |
| | | Availability Zone A | | Availability Zone B | | |
| | | (ap-southeast-1a) | | (ap-southeast-1b) | | |
| | | [Data Center 1] | | [Data Center 3] | | |
| | | [Data Center 2] | | [Data Center 4] | | |
| | +-----------------------+ +-----------------------+ | |
| | \ / | |
| | \ Ultra-Low Latency Fiber (<1ms) | |
| | \ / | |
| | +-------------------------------------------------------+ | |
| | | Availability Zone C (ap-southeast-1c) | | |
| | | [Data Center 5] | | |
| | +-------------------------------------------------------+ | |
| +-------------------------------------------------------------------+ |
+-------------------------------------------------------------------------+
1. AWS Regions
An AWS Region is a distinct, isolated geographic location in the world (e.g., us-east-1 in North Virginia, ap-southeast-1 in Singapore, eu-central-1 in Frankfurt).
- Each region is completely independent of all other regions. A catastrophic flood, earthquake, or power failure in Tokyo will not affect the Dublin region.
- Regions govern data sovereignty and latency. If your users are in Southeast Asia, deploying in
ap-southeast-1ensures low network latency and compliance with regional data residency laws. - In OpenTofu, the region is almost always explicitly configured in your provider block:
provider "aws" { region = "ap-southeast-1" }
2. Availability Zones (AZs)
An Availability Zone (AZ) is one or more discrete data centers, each with redundant power, networking, and connectivity, housed in separate physical facilities.
- A Region contains at least 3 Availability Zones (some, like
us-east-1, have 6). - AZs within the same region are separated by meaningful physical distance (miles/kilometers apart to survive local flood plains or power grid failures) but connected via high-bandwidth, ultra-low latency private fiber networks (typically sub-millisecond).
- Designing for high availability means running instances across multiple AZs. If AZ
asuffers a facility outage, AZbandccontinue processing traffic uninterrupted.
[!WARNING] The AZ Mapping Trap: The logical name
ap-southeast-1adoes NOT map to the same physical building across different AWS accounts! AWS intentionally randomizes AZ naming between accounts to distribute capacity evenly. To identify the true physical facility across accounts, you must check the immutable AZ ID (e.g.,apse1-az1). We will inspect this hands-on in Phase 2.
3. Edge Locations & Point of Presence (PoP)
Separate from Regions and AZs, AWS maintains hundreds of Edge Locations around the globe connected to the AWS private backbone network. These host services like CloudFront (Content Delivery Network), Route 53 (DNS), and AWS Shield (DDoS mitigation), caching data close to end users.
🆔 Part 3: Anatomy of an ARN (Amazon Resource Name)
Every single entity in AWS—from an S3 bucket to an IAM role, an EC2 instance, or a VPC subnet—possesses a globally unique identifier called an ARN (Amazon Resource Name).
In OpenTofu, you will reference, construct, and pass ARNs between resources daily. Understanding the ARN anatomy prevents syntax errors.
arn : partition : service : region : account-id : resource-id
─── ───────── ─────── ────── ────────── ───────────
1 2 3 4 5 6
Let’s dissect each component:
| Segment | Meaning | Example | Notes |
|---|---|---|---|
| 1. Prefix | Identifies the string as an ARN | arn | Constant across all ARNs |
| 2. Partition | The group of AWS regions | aws, aws-cn, aws-us-gov | Standard commercial AWS is always aws |
| 3. Service | The AWS product namespace | s3, iam, ec2, rds | All lowercase service codes |
| 4. Region | The geographic region | ap-southeast-1, us-east-1 | Omitted for global services like IAM and S3! |
| 5. Account ID | 12-digit AWS account number | 123456789012 | Omitted for S3 buckets (which are globally unique) |
| 6. Resource | The resource type and ID/path | instance/i-0123456789abcdef0role/engineering/DevOpsRolemy-production-logs-bucket | Can use slashes (/) or colons (:) depending on the service |
Real-World ARN Examples:
# Regional EC2 Instance:
arn:aws:ec2:ap-southeast-1:123456789012:instance/i-0123456789abcdef0
# Global IAM Role (Region is blank):
arn:aws:iam::123456789012:role/ProductionDatabaseMigrationRole
# Global S3 Bucket (Region and Account ID are blank):
arn:aws:s3:::my-secure-analytics-data-2026
# S3 Object within a bucket:
arn:aws:s3:::my-secure-analytics-data-2026/raw-events/january.parquet
🛡️ Part 4: The Shared Responsibility Model
Before automating infrastructure, every cloud engineer must know what they are responsible for vs. what AWS guarantees:
+-------------------------------------------------------------------------+
| CUSTOMER RESPONSIBILITY: "SECURITY IN THE CLOUD" |
| |
| - Customer Data & Classification |
| - IAM Policies, Least Privilege, MFA, and Credential Management |
| - Operating System Patching, Firewalls, & Security Groups |
| - Network Traffic Filtering & Encryption (In-Transit & At-Rest) |
| - OpenTofu Code Quality, State Security, & Secrets Management |
+-------------------------------------------------------------------------+
============================ BOUNDARY =====================================
+-------------------------------------------------------------------------+
| AWS RESPONSIBILITY: "SECURITY OF THE CLOUD" |
| |
| - Physical Data Center Security (Armed guards, biometric scans) |
| - Physical Hardware, Servers, Disks, Cables, and Power Generators |
| - Hypervisor Isolation (AWS Nitro System) |
| - Undersea and Terrestrial Global Network Backbone |
| - Managed Service Run-times (RDS OS, S3 Storage Durability 99.999999999%)|
+-------------------------------------------------------------------------+
When you write OpenTofu code:
- AWS ensures that the S3 storage hardware will not physically fail and lose your bytes (11 9s durability).
- You ensure that your OpenTofu code does not set
bucket_public_access_blockto false, exposing company databases to the public internet.
⚡ Part 5: Hands-On Exploration from the Terminal
Now, let’s open our terminal and verify these concepts directly against the live AWS control plane using the AWS CLI.
Step 1: Verify Identity and Account ID
The fastest way to test your authentication and discover your 12-digit Account ID is calling the AWS Security Token Service (STS):
aws sts get-caller-identity
Output:
{
"UserId": "AIDASAMPLEUSERIDEXAMPLE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/admin-prawira"
}
Observe the returned ARN:
Partition:awsService:iamRegion: (empty because IAM is global)Account:123456789012Resource:user/admin-prawira
Step 2: Discover Active AWS Regions
How many regions does AWS operate right now? Let’s query the EC2 control plane:
aws ec2 describe-regions \
--all-regions \
--query "Regions[?OptInStatus!='not-opted-in'].{RegionName:RegionName, Endpoint:Endpoint, Status:OptInStatus}" \
--output table
Output:
--------------------------------------------------------------------------------
| DescribeRegions |
+------------------+------------------------------------------+----------------+
| Endpoint | RegionName | Status |
+------------------+------------------------------------------+----------------+
| ec2.af-south-1.amazonaws.com | af-south-1 | opted-in |
| ec2.ap-east-1.amazonaws.com | ap-east-1 | opted-in |
| ec2.ap-northeast-1.amazonaws.com | ap-northeast-1 | opt-in-not-req|
| ec2.ap-northeast-2.amazonaws.com | ap-northeast-2 | opt-in-not-req|
| ec2.ap-south-1.amazonaws.com | ap-south-1 | opt-in-not-req|
| ec2.ap-southeast-1.amazonaws.com | ap-southeast-1 | opt-in-not-req|
| ec2.eu-central-1.amazonaws.com | eu-central-1 | opt-in-not-req|
| ec2.us-east-1.amazonaws.com | us-east-1 | opt-in-not-req|
| ec2.us-west-2.amazonaws.com | us-west-2 | opt-in-not-req|
+------------------+------------------------------------------+----------------+
Notice the Endpoint column: each region has its own dedicated hostname. When OpenTofu manages resources in Singapore, it connects directly to ec2.ap-southeast-1.amazonaws.com.
Step 3: Inspect Availability Zones and Physical AZ IDs
Let’s inspect the Availability Zones in your active region (e.g., ap-southeast-1 or us-east-1):
aws ec2 describe-availability-zones \
--region ap-southeast-1 \
--query "AvailabilityZones[].{Name:ZoneName, ZoneId:ZoneId, State:State}" \
--output table
Output:
------------------------------------------------------
| DescribeAvailabilityZones |
+-----------------+------------------+---------------+
| Name | State | ZoneId |
+-----------------+------------------+---------------+
| ap-southeast-1a | available | apse1-az1 |
| ap-southeast-1b | available | apse1-az2 |
| ap-southeast-1c | available | apse1-az3 |
+-----------------+------------------+---------------+
Pay special attention to the two columns:
Name(e.g.,ap-southeast-1a): The logical name. This is assigned dynamically per AWS account.ZoneId(e.g.,apse1-az1): The physical identifier. This represents the exact physical data center campus. If your organization operates a multi-account AWS Organization and shares subnets or Direct Connect lines across accounts, you must match onZoneId, never onZoneName.
🔄 Part 6: Why Infrastructure as Code? (The Imperative vs. Declarative Shift)
Now that we understand AWS primitives, let’s address the core paradigm shift of this entire series: Why do we need OpenTofu instead of scripts or console clicks?
There are two fundamentally different ways to instruct a computer to build cloud infrastructure:
1. The Imperative Approach (Bash Scripts, Python SDK, AWS CLI)
In an imperative model, you tell the computer step-by-step instructions on HOW to achieve a state:
# Imperative approach: You must manage every sequence, condition, and error
if ! aws s3api head-bucket --bucket my-app-assets 2>/dev/null; then
echo "Creating bucket..."
aws s3api create-bucket --bucket my-app-assets --region ap-southeast-1
aws s3api put-bucket-encryption --bucket my-app-assets ...
aws s3api put-public-access-block --bucket my-app-assets ...
else
echo "Bucket already exists. Checking if encryption is enabled..."
# What if encryption is wrong? Write more code.
# What if someone deleted the public access block manually? Write more code.
fi
Problems with Imperative Scripting:
- No Idempotence by default: Running the script twice often fails with errors like “BucketAlreadyOwnedByYou” or creates duplicate resources.
- No Dependency Graphing: You must manually figure out what order resources must be created (e.g., create VPC before Subnet, create Subnet before Network Interface, create Gateway before Route Table).
- Impossible Teardowns: Writing a script to create 50 resources is hard; writing a script to safely delete those 50 resources in exact reverse dependency order without accidentally deleting something else is nearly impossible.
2. The Declarative Approach (OpenTofu / Terraform)
In a declarative model, you do NOT tell the computer how to do it. You simply describe the DESIRED END STATE:
# main.tf (Declarative)
resource "aws_s3_bucket" "assets" {
bucket = "my-app-assets-production-2026"
tags = {
Environment = "Production"
ManagedBy = "OpenTofu"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "assets" {
bucket = aws_s3_bucket.assets.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
When you execute OpenTofu:
- OpenTofu inspects your code (Desired State).
- OpenTofu inspects your cloud via AWS APIs (Current Reality).
- OpenTofu calculates the exact mathematical delta between Desired State and Current Reality (The Execution Plan).
- OpenTofu generates an internal Directed Acyclic Graph (DAG) to determine dependencies automatically (it knows the bucket must exist before applying encryption to it).
- OpenTofu calls the AWS APIs to bring Reality in alignment with your code.
+------------------+ +------------------+ +------------------+
| CODE (Desired) | vs. | CLOUD (Current) | ==> | OPENTOFU PLAN |
| S3: Enabled | | S3: Not Found | | Action: CREATE |
+------------------+ +------------------+ +------------------+
⚙️ Part 7: The OpenTofu Core Lifecycle Preview
In Lab 102, we will write our first .tf files and run them. Before we do, memorize the Four Golden Steps of the OpenTofu Lifecycle:
+---------------+ +---------------+ +---------------+ +---------------+
| tofu init | ===> | tofu plan | ===> | tofu apply | ===> | tofu destroy |
+---------------+ +---------------+ +---------------+ +---------------+
Download plugins Calculate delta Execute changes Tear down lab
& AWS provider (Dry-run preview) against AWS APIs (Clean zero-$)
tofu init(Initialize):- Scans your working directory for provider requirements.
- Downloads the binary plugin for AWS (
terraform-provider-aws) into a local.terraformcache. - Initializes the state backend.
tofu plan(Dry-Run Preview):- Reads your configuration.
- Queries AWS to check what currently exists.
- Outputs a color-coded preview:
+Green: Resources to be created.~Yellow: Resources to be updated in-place.-Red: Resources to be destroyed.
- Nothing in your AWS account changes during a plan.
tofu apply(Execution):- Asks for explicit user confirmation (
yes). - Executes the API requests against AWS in parallel wherever dependencies allow.
- Records every provisioned resource, ID, and attribute into a local or remote State File (
terraform.tfstate).
- Asks for explicit user confirmation (
tofu destroy(Complete Cleanup):- Reads the state file.
- Deletes all managed resources in reverse dependency order, ensuring you never leave behind forgotten, billable resources.
🔍 Verification & Knowledge Check
Test your understanding of the core concepts covered in this lab:
-
Question: If you run
aws ec2 describe-availability-zoneson two different AWS accounts, willus-east-1arefer to the same physical building?- Answer: No. AWS maps logical names (
us-east-1a) to physical facilities randomly per account to prevent all customers from crowding into the first building. To reference the identical physical facility across multiple accounts, you must use the immutableZoneId(e.g.,use1-az1).
- Answer: No. AWS maps logical names (
-
Question: An S3 bucket ARN is
arn:aws:s3:::company-data-vault. Why are the region and account ID fields empty?- Answer: S3 bucket names are globally unique across all AWS accounts and regions. The S3 control plane can uniquely identify the bucket worldwide without needing the region or 12-digit account number in its ARN.
-
Question: If someone logs into the AWS console and manually deletes a subnet that was created with OpenTofu, what will happen the next time you run
tofu plan?- Answer: OpenTofu will query the AWS API, detect that the subnet is missing from Current Reality (an event called Infrastructure Drift), and plan to recreate the subnet to restore the Desired State described in your code.
🛠️ Troubleshooting & Gotchas
Issue 1: Could not connect to the endpoint URL
Could not connect to the endpoint URL: "https://ec2.invalid-region.amazonaws.com/"
- Cause: Typo in the region code or no internet connectivity.
- Fix: Check your configured region in
~/.aws/configor pass a valid region flag:aws configure get region # Ensure it is a valid code like us-east-1 or ap-southeast-1
Issue 2: AccessDenied: User is not authorized to perform: sts:GetCallerIdentity
An error occurred (AccessDenied) when calling the GetCallerIdentity operation
- Cause: Your IAM credentials may have an explicit deny, or an SCP (Service Control Policy) is blocking requests. Note:
sts:GetCallerIdentityworks even without explicit IAM permissions on valid credentials; if this fails, your Access Key ID or Secret Access Key is invalid or expired. - Fix: Re-run
aws configurewith active, valid credentials.
Issue 3: Stale Credentials in Terminal Environment
If you have multiple AWS profiles or previously exported temporary session tokens in your environment:
# Check if environment variables are overriding your ~/.aws/credentials
env | grep AWS_
If you see stale AWS_ACCESS_KEY_ID or AWS_SESSION_TOKEN, clear them:
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_SECURITY_TOKEN
🏋️ Hands-On Challenge
Solidify your learning before moving to code:
- Multi-Region Inspection: Run
aws ec2 describe-availability-zonesfor two different regions (ap-southeast-1andus-east-1). How many Availability Zones does North Virginia (us-east-1) have compared to Singapore? - ARN Construction Exercise: Without looking at the AWS console, construct the theoretical ARN for an IAM policy named
StrictS3ReadOnlyin account987654321098. (Answer:arn:aws:iam::987654321098:policy/StrictS3ReadOnly) - Verify OpenTofu Installation: If you haven’t already, install OpenTofu on your machine and verify it from the terminal:
You should see output similar to:tofu --versionOpenTofu v1.9.0
🧹 Cleanup & Credential Hygiene
Because this lab only queried AWS metadata via the CLI, no billable resources were created in your AWS account.
However, good cloud engineers practice credential hygiene:
# Ensure strict permissions on your local credentials
chmod 600 ~/.aws/credentials
chmod 600 ~/.aws/config
chmod 700 ~/.aws
📖 Summary & What You Learned
In this inaugural lab of the AWS + OpenTofu Level 100 series, you established the architectural bedrock:
- Cloud APIs: The AWS Console is just an API client; every action resolves to an authenticated HTTPS REST request.
- Global Infrastructure: Regions ensure data sovereignty and low latency; Availability Zones deliver high availability across independent data center campuses.
- Resource Identification: ARNs provide a universal naming scheme across partitions, services, and accounts.
- The IaC Philosophy: Declarative code lets you declare what you want, while OpenTofu builds the dependency graph and executes the how.
- The OpenTofu Workflow:
initprepares the engine,plancalculates deltas,applymakes real changes, anddestroytears down cleanly.
🚀 What’s Next? (Lab 102)
In [AWS OpenTofu #102: Your First OpenTofu Project], we will move from theory to practical code:
- Initialize your first OpenTofu directory structure.
- Configure the AWS Provider block with secure default tags.
- Provision a real AWS S3 bucket with declarative HCL code.
- Inspect the generated
terraform.tfstatefile and experience the completeinit -> plan -> apply -> destroycycle hands-on.