Working with AWS Provider
1. Configuring AWS Provider
| Property | Description | Example | Notes |
|---|---|---|---|
| region | The AWS region to use | "us-west-2" |
Required for most resources |
| access_key | Static AWS access key ID | "AKIAIOSFODNN7EXAMPLE" |
Not recommended for production |
| secret_key | Static AWS secret access key | "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" |
Not recommended for production |
| profile | Named profile in AWS credentials file | "default" |
Used with ~/.aws/credentials |
| shared_credentials_files | List of credential files to use | ["~/.aws/credentials", "~/.aws/config"] |
Overrides default search path |
| assume_role | Role to assume for credentials | |
Use for cross-account access |
| external_id | External ID for role assumption | "123456789" |
Required for some roles |
| token | STS token for MFA-enabled accounts | "AQoEXAMPLEH4..." |
Needed when MFA is enabled |
| skip_credentials_validation | Disable credential validation | true |
Use with caution in production |
| skip_metadata_api_check | Disable metadata API check | true |
Use in environments without metadata API |
Example: Basic AWS Provider Configuration
provider "aws" {
region = "us-west-2"
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
Example: Assume Role Configuration
provider "aws" {
region = "us-west-2"
assume_role {
role_arn = "arn:aws:iam::123456789012:role/TerraformAdmin"
session_name = "terraform-session"
external_id = "123456789"
}
}
Note: For production environments, it's recommended to use IAM roles or environment variables instead of static credentials.
2. Using AWS Authentication
| Method | Description | Configuration | Notes |
|---|---|---|---|
| Access Key ID | Static credentials for AWS access | access_key = "AKIAIOSFODNN7EXAMPLE" |
Requires secret key; not recommended for production |
| Secret Access Key | Static credentials for AWS access | secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" |
Must be used with Access Key ID |
| Assume Role | Assume an IAM role to gain temporary credentials | |
Useful for cross-account access |
| EC2 Instance Metadata | Use IAM roles attached to EC2 instances | token = "AWS_TOKEN" |
Requires instance to have IAM role attached |
| Environment Variables | Use AWS CLI credentials from environment | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY |
Useful for local development and CI/CD |
| Shared Credentials File | Use credentials stored in ~/.aws/credentials | profile = "my-profile" |
Supports named profiles |
Example: Using Static Credentials
provider "aws" {
region = "us-west-2"
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
Example: Using IAM Role from EC2 Instance
provider "aws" {
region = "us-west-2"
assume_role {
role_arn = "arn:aws:iam::123456789012:role/AssumeRole"
session_name = "TerraformSession"
}
}
Note: For production environments, prefer using IAM roles or environment variables over hardcoded credentials.
3. Managing AWS Resources
| Resource Type | Properties | Description | Notes |
|---|---|---|---|
| aws_instance | ami, instance_type, key_name |
Creates an EC2 instance | Required fields: ami, instance_type |
| aws_s3_bucket | bucket, acl |
Creates an S3 bucket | Use bucket for the bucket name |
| aws_iam_role | name, assume_role_policy |
Creates an IAM role | Policy must be a valid JSON string |
Example: Creating an EC2 Instance
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1d0"
instance_type = "t2.micro"
key_name = "my-key-pair"
tags = {
Name = "WebServer"
}
}
Example: Creating an S3 Bucket
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-unique-bucket-name"
acl = "private"
}
Example: Creating an IAM Role
resource "aws_iam_role" "my_role" {
name = "MyRole"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
Note: Ensure that the AWS credentials are configured correctly in your environment or through Terraform's credential provider.
4. Using AWS Data Sources
AWS data sources in Terraform allow you to fetch information from AWS services without creating or managing any resources. This is useful for referencing existing resources or retrieving metadata.
| Field | Description | Example |
|---|---|---|
| aws_ami | Retrieve information about an AMI (Amazon Machine Image) in AWS. | data "aws_ami" "my_ami" { filter { name = "name" values = ["ubuntu/images/ubuntu-20.04/*"] } } |
| aws_availability_zones | Fetch availability zones for a specified region. | data "aws_availability_zones" "available" { state = "available" } |
| aws_caller_identity | Retrieve information about the AWS caller identity. | data "aws_caller_identity" "current" { } |
| aws_region | Fetch the current AWS region. | data "aws_region" "current" { } |
| aws_s3_bucket | Retrieve information about an S3 bucket. | data "aws_s3_bucket" "my_bucket" { bucket = "my-bucket-name" } |
Example: Fetching AMI ID from a specific AMI name
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/ubuntu-20.04/*"]
}
owners = ["099720109477"]
}
output "ami_id" {
value = data.aws_ami.ubuntu.id
}
Example: Using availability zones to create subnets
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "subnet_1" {
count = length(data.aws_availability_zones.available.names)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
}
5. Configuring Multiple Regions
| Property | Description | Example |
|---|---|---|
| provider.aws | Defines the AWS provider with region configuration | provider "aws" { region = "us-west-2"} |
| provider.aws.<alias> | Defines an alias for a specific region | provider "aws" { alias = "us-east-1" region = "us-east-1"} |
| aws_instance.<name>.provider | Assigns a specific provider alias to a resource | resource "aws_instance" "example" { provider = aws.us-east-1 ami = "ami-12345678" instance_type = "t2.micro"} |
Example: Using Multiple Regions with Aliases
provider "aws" {
alias = "us_west"
region = "us-west-2"
}
provider "aws" {
alias = "us_east"
region = "us-east-1"
}
resource "aws_instance" "web_server_west" {
provider = aws.us_west
ami = "ami-12345678"
instance_type = "t2.micro"
}
resource "aws_instance" "web_server_east" {
provider = aws.us_east
ami = "ami-12345678"
instance_type = "t2.micro"
}
Note: When using multiple regions, ensure that the IAM roles and policies have appropriate permissions for each region.
6. Using AWS Assume Role
| Property | Description | Example |
|---|---|---|
| assume_role | Configuration block to assume a role in another AWS account | {\n role_arn = "arn:aws:iam::123456789012:role/AssumeRole"\n} |
Example: Assume Role Configuration
{\n assume_role {\n role_arn = "arn:aws:iam::123456789012:role/AssumeRole"\n session_name = "TerraformSession"\n external_id = "external-id-12345"\n }\n}
Note: The
assume_role block is used when you need to assume a role in a different AWS account or for cross-account access.
7. Managing AWS Tags
| Property | Description | Example |
|---|---|---|
| tags | Map of key-value pairs to assign as tags to the resource | {<br> "Environment": "production",<br> "Owner": "team-a"<br>} |
| tag | Block to define individual tag key-value pairs | tag {<br> key = "Name"<br> value = "web-server"<br>} |
Example: Tagging an EC2 Instance
resource "aws_instance" "web_server" {<br> ami = "ami-0c55b159cbfafe1d0"<br> instance_type = "t3.micro"<br><br> tags = {<br> Name = "web-server"<br> Environment = "production"<br> }<br>}
Note: AWS requires tag keys to be unique within a resource. Use
tag blocks for more complex tagging logic or conditional tags.Warning: Tags are not automatically propagated to child resources. You must explicitly define tags for each resource.
Tagging Best Practices
- Use consistent tag names across resources for easier filtering and cost allocation
- Include metadata like
Environment,Project, andOwner - Avoid special characters in tag keys/values to prevent issues with AWS CLI or SDKs
8. Using AWS-Specific Functions
| Function | Description | Example | Notes |
|---|---|---|---|
| aws_ami_id() | Retrieves the ID of an AMI by name | |
Useful for referencing AMIs in launch configurations |
| aws_region() | Returns the current AWS region | |
Can be used to dynamically set region-specific resources |
| aws_caller_identity() | Retrieves details about the caller identity | |
Useful for cross-account resource management |
| aws_availability_zones() | Lists all availability zones for a region | |
Helps in distributing resources across zones |
| aws_elastic_ip() | Allocates or retrieves an Elastic IP address | |
Useful for assigning static IPs to EC2 instances |
| aws_s3_bucket() | Retrieves S3 bucket information | |
Allows referencing bucket properties in other resources |
Example: Using aws_ami_id in a launch configuration
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-*"]
}
}
resource "aws_launch_configuration" "example" {
image_id = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
}
Example: Using aws_caller_identity to get account ID
data "aws_caller_identity" "current" {}
resource "aws_s3_bucket" "example" {
bucket = "my-bucket-${data.aws_caller_identity.current.account_id}"
}
9. Configuring S3 Backend
| Option | Values | Description |
|---|---|---|
| bucket | string |
Name of the S3 bucket to use for state storage |
| key | string |
Path within the bucket to store the state file |
| region | string |
AWS region where the S3 bucket is located |
| access_key | string |
AWS access key ID (optional if using IAM roles) |
| secret_key | string |
AWS secret access key (optional if using IAM roles) |
| dynamodb_table | string |
Name of DynamoDB table for state locking (optional) |
| encrypt | bool |
Enable server-side encryption of the state file (default: false) |
Example: S3 Backend Configuration
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-lock-table"
encrypt = true
}
}
Note: Ensure that the IAM role or credentials used have appropriate permissions to read/write to the specified S3 bucket and DynamoDB table.
10. Handling AWS API Throttling
| Option | Values | Notes |
|---|---|---|
| max_retries | 3 |
Maximum number of retry attempts for AWS API calls |
| retry_wait_min | 1s |
Minimum wait time between retries (default: 1 second) |
| retry_wait_max | 30s |
Maximum wait time between retries (default: 30 seconds) |
| retry_mode | adaptive |
Retry mode: legacy, standard, or adaptive |
Example: Configuring Retry Settings
provider "aws" {
region = "us-west-2"
max_retries = 5
retry_wait_min = "2s"
retry_wait_max = "60s"
retry_mode = "adaptive"
}
Note: AWS API throttling typically occurs when making too many requests in a short period. Terraform's retry mechanism helps mitigate this by automatically backing off and retrying failed requests.
Warning: Setting
max_retries too high can lead to long execution times or hitting AWS limits. Use with caution in production environments.