The AWS Provider is by far the most-used Terraform provider. Whether you are preparing for the exam or building real infrastructure, credential precedence, assume_role, and region splitting via aliases are must-know fundamentals.
This article follows the behavior documented by HashiCorp and walks through the Associate-level talking points with minimal code and concrete examples.
Declare the AWS Provider in required_providers and pin its version per project. Major upgrades can introduce breaking changes, so using the ~> operator to track minor and patch versions safely is the standard pattern.
Region resolves in this order: provider argument, then environment variables (AWS_REGION / AWS_DEFAULT_REGION), then the shared config file (~/.aws/config). Setting it explicitly on the provider removes ambiguity. default_tags has been stable since v5 and is a clean way to attach common tags across every resource (when a resource defines the same key in its own tags, the resource-level value wins).
Minimal configuration (version pin + common tags)
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
Project = "nicheelab"
Environment = "dev"
}
}
}The AWS Provider resolves credentials using the AWS SDK default credential chain. When multiple methods are configured at once, explicit provider settings come first, followed by environment variables, then shared profiles, and finally runtime roles (EC2 / ECS). If Web Identity (OIDC) environment variables are present, they take precedence as environment-variable credentials.
The exam frequently asks which method actually gets used. The classic gotcha: even if you set profile on the provider, environment variables set in CI take precedence over it.
| Method | Declaration / Setting | Priority (high → low) | Typical use case and notes |
|---|---|---|---|
| Explicit static credentials | provider aws { access_key/secret_key/token } | 1 | For testing only. Never commit secrets to code. |
| Environment variables (static / session) | AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN | 2 | Common in CI/CD. Takes precedence over profile settings. |
| Environment variables (Web Identity / OIDC) | AWS_ROLE_ARN / AWS_WEB_IDENTITY_TOKEN_FILE | 2 | EKS ServiceAccount and similar setups. No assume_role block required. |
| Shared profile | provider aws { profile = "xxx" } + ~/.aws/{config,credentials} | 3 | Developer machines and SSO. credential_process and source_profile are also resolved. |
| Runtime role | EC2 Instance Profile / ECS Task Role | 4 | Used automatically when nothing else is configured. Stick to least privilege. |
Examples for environment variables and profiles
# 環境変数で認証(推奨: CI/CD)
# export AWS_ACCESS_KEY_ID=AKIA...
# export AWS_SECRET_ACCESS_KEY=...
# export AWS_REGION=ap-northeast-1
provider "aws" {}
# 共有プロファイルで認証(ローカル/SSO)
provider "aws" {
profile = "sandbox"
region = "ap-northeast-1"
}In a multi-account setup, the standard pattern is to start from a source credential (profile or environment variables) and assume a role in the target account via assume_role. Configure external_id and session_name to match your audit and integration requirements.
assume_role is specified as a block inside the provider. The deeper the chain gets, the harder it is to debug, so stick to a single hop whenever possible and keep the trust policy and required permissions clearly scoped to the minimum.
Typical assume_role flow (cross-account)
assume_role configuration on the provider
provider "aws" {
profile = "platform" # source資格情報(共有プロファイル)
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::222222222222:role/TerraformRole"
session_name = "tf-apply"
external_id = "nicheelab-ci"
duration = "3600s"
}
}
# 以降のリソースは上記ロール経由で作成されるMost AWS services are region-scoped. In Terraform you can attach an alias to a provider and split things explicitly by region or account, which makes plans more readable and safer. Specifying provider on each resource prevents accidental creation in the wrong place.
Some resources, like IAM and parts of Route 53, are global and largely unaffected by region settings. Check the docs for the target region or partition so you are not surprised by plan-vs-apply differences.
Example: per-region alias usage
provider "aws" {
alias = "tokyo"
region = "ap-northeast-1"
profile = "prod"
}
provider "aws" {
alias = "virginia"
region = "us-east-1"
profile = "prod"
}
resource "aws_s3_bucket" "logs_tokyo" {
provider = aws.tokyo
bucket = "nicheelab-logs-apne1"
}
resource "aws_s3_bucket" "logs_virginia" {
provider = aws.virginia
bucket = "nicheelab-logs-use1"
}aws_caller_identity and aws_partition dynamically resolve the account ID and partition (aws / aws-cn / aws-us-gov), which is great for smoothing over environment differences. They let you write EKS and S3 ARNs in an environment-agnostic way.
aws_iam_policy_document is a data source that assembles JSON policies locally without any API calls. Diffs become clearer and it prevents the kinds of mistakes you get when hand-writing JSON.
Generate an IAM policy with data sources
data "aws_caller_identity" "current" {}
data "aws_partition" "current" {}
data "aws_iam_policy_document" "s3_readonly" {
statement {
actions = ["s3:GetObject", "s3:ListBucket"]
resources = [
"arn:${data.aws_partition.current.partition}:s3:::nicheelab-data",
"arn:${data.aws_partition.current.partition}:s3:::nicheelab-data/*"
]
}
}
resource "aws_iam_policy" "s3_readonly" {
name = "S3ReadOnly"
policy = data.aws_iam_policy_document.s3_readonly.json
}Never hardcode credentials. Use environment variables, shared profiles, or assume_role instead. Split State along account and region boundaries and switch explicitly with aliases.
To keep dependencies reproducible, pinning the provider version and tracking .terraform.lock.hcl are non-negotiable. Plan upgrades deliberately: read the breaking-change notes first, then run terraform init -upgrade.
Provider version pinning and lock file workflow
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.50"
}
}
}
# 初回: terraform init
# アップグレード時: terraform init -upgrade
# .terraform.lock.hcl はVCSで管理するAssociate
問題 1
In CI, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set as environment variables, while the Terraform provider "aws" block specifies profile = "sandbox". Which credentials does terraform apply actually use?
正解: A
The AWS Provider resolves credentials in this order: explicit settings > environment variables > shared profile > runtime role. Here, the provider has no explicit static credentials, and environment variables outrank the shared profile — so the environment variables are used.
If default_tags and resource tags conflict, which one wins? Can I disable default_tags for a specific resource?
When the same key is set in both, the resource-level tags win. There is no explicit switch to turn off default_tags for a single resource. If you really need to exclude one, the safest pattern is to define a separate provider (with a different alias) that has no default_tags and use it for the exception.
How do I use AWS SSO with Terraform?
Configure an SSO profile in ~/.aws/config with AWS CLI v2, then run aws sso login to authenticate. On the Terraform side, you only need provider aws { profile = "your-sso-profile" } — the SSO credentials resolve from the shared config automatically.
What is the region resolution order? What if both provider.region and AWS_REGION are set?
Region is resolved in this order: provider argument > environment variables (AWS_REGION / AWS_DEFAULT_REGION) > shared config file. If both are set, the provider argument wins.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...