Skip to main content

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
{
  role_arn = "arn:aws:iam::123456789012:role/ExampleRole"
  session_name = "TerraformSession"
}
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: Using Named Profile

provider "aws" {
  region = "us-east-1"
  profile = "terraform-user"
}

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
assume_role {
  role_arn = "arn:aws:iam::123456789012:role/AssumeRole"
  session_name = "TerraformSession"
}
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, and Owner
  • 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
data "aws_ami" "my_ami" {
  most_recent = true
  owners      = ["self"]
  filter {
    name   = "name"
    values = ["my-ami-*"]
  }
}
Useful for referencing AMIs in launch configurations
aws_region() Returns the current AWS region
data "aws_region" "current" {
  name = "us-west-2"
}
Can be used to dynamically set region-specific resources
aws_caller_identity() Retrieves details about the caller identity
data "aws_caller_identity" "current" {}

output "account_id" {
  value = data.aws_caller_identity.current.account_id
}
Useful for cross-account resource management
aws_availability_zones() Lists all availability zones for a region
data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_instance" "example" {
  count         = length(data.aws_availability_zones.available.names)
  availability_zone = data.aws_availability_zones.available.names[count.index]
}
Helps in distributing resources across zones
aws_elastic_ip() Allocates or retrieves an Elastic IP address
resource "aws_eip" "example" {
  vpc = true
}

output "public_ip" {
  value = aws_eip.example.public_ip
}
Useful for assigning static IPs to EC2 instances
aws_s3_bucket() Retrieves S3 bucket information
data "aws_s3_bucket" "my_bucket" {
  bucket = "my-bucket-name"
}

output "bucket_domain" {
  value = data.aws_s3_bucket.my_bucket.bucket_domain
}
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.

Was this article helpful?