» AWS Provider

The Amazon Web Services (AWS) provider is used to interact with the many resources supported by AWS. The provider needs to be configured with the proper credentials before it can be used.

Use the navigation to the left to read about the available resources.

» Example Usage

# Configure the AWS Provider
provider "aws" {
  version = "~> 2.0"
  region  = "us-east-1"

# Create a VPC
resource "aws_vpc" "example" {
  cidr_block = ""

» Authentication

The AWS provider offers a flexible means of providing credentials for authentication. The following methods are supported, in this order, and explained below:

  • Static credentials
  • Environment variables
  • Shared credentials file
  • EC2 Role

» Static credentials

Static credentials can be provided by adding an access_key and secret_key in-line in the AWS provider block:


provider "aws" {
  region     = "us-west-2"
  access_key = "my-access-key"
  secret_key = "my-secret-key"

» Environment variables

You can provide your credentials via the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, environment variables, representing your AWS Access Key and AWS Secret Key, respectively. Note that setting your AWS credentials using either these (or legacy) environment variables will override the use of AWS_SHARED_CREDENTIALS_FILE and AWS_PROFILE. The AWS_DEFAULT_REGION and AWS_SESSION_TOKEN environment variables are also used, if applicable:

provider "aws" {}


$ export AWS_ACCESS_KEY_ID="anaccesskey"
$ export AWS_SECRET_ACCESS_KEY="asecretkey"
$ export AWS_DEFAULT_REGION="us-west-2"
$ terraform plan

» Shared Credentials file

You can use an AWS credentials file to specify your credentials. The default location is $HOME/.aws/credentials on Linux and OS X, or "%USERPROFILE%\.aws\credentials" for Windows users. If we fail to detect credentials inline, or in the environment, Terraform will check this location. You can optionally specify a different location in the configuration by providing the shared_credentials_file attribute, or in the environment with the AWS_SHARED_CREDENTIALS_FILE variable. This method also supports a profile configuration and matching AWS_PROFILE environment variable:


provider "aws" {
  region                  = "us-west-2"
  shared_credentials_file = "/Users/tf_user/.aws/creds"
  profile                 = "customprofile"

If specifying the profile through the AWS_PROFILE environment variable, you may also need to set AWS_SDK_LOAD_CONFIG to a truthy value (e.g. AWS_SDK_LOAD_CONFIG=1) for advanced AWS client configurations, such as profiles that use the source_profile or role_arn configurations.

» ECS and CodeBuild Task Roles

If you're running Terraform on ECS or CodeBuild and you have configured an IAM Task Role, Terraform will use the container's Task Role. Terraform looks for the presence of the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable that AWS injects when a Task Role is configured. If you have not defined a Task Role for your container or CodeBuild job, Terraform will continue to use the EC2 Role.

» EC2 Role

If you're running Terraform from an EC2 instance with IAM Instance Profile using IAM Role, Terraform will just ask the metadata API endpoint for credentials.

This is a preferred approach over any other when running in EC2 as you can avoid hard coding credentials. Instead these are leased on-the-fly by Terraform which reduces the chance of leakage.

You can provide the custom metadata API endpoint via the AWS_METADATA_URL variable which expects the endpoint URL, including the version, and defaults to

The default deadline for the EC2 metadata API endpoint is 100 milliseconds, which can be overidden by setting the AWS_METADATA_TIMEOUT environment variable. The variable expects a positive golang Time.Duration string, which is a sequence of decimal numbers and a unit suffix; valid suffixes are ns (nanoseconds), us (microseconds), ms (milliseconds), s (seconds), m (minutes), and h (hours). Examples of valid inputs: 100ms, 250ms, 1s, 2.5s, 2.5m, 1m30s.

» Assume role

If provided with a role ARN, Terraform will attempt to assume this role using the supplied credentials.


provider "aws" {
  assume_role {
    role_arn     = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
    session_name = "SESSION_NAME"
    external_id  = "EXTERNAL_ID"

» Argument Reference

In addition to generic provider arguments (e.g. alias and version), the following arguments are supported in the AWS provider block:

The nested assume_role block supports the following:

  • role_arn - (Required) The ARN of the role to assume.

  • session_name - (Optional) The session name to use when making the AssumeRole call.

  • external_id - (Optional) The external ID to use when making the AssumeRole call.

  • policy - (Optional) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use the passed policy to grant permissions that are in excess of those allowed by the access policy of the role that is being assumed.

» Getting the Account ID

If you use either allowed_account_ids or forbidden_account_ids, Terraform uses several approaches to get the actual account ID in order to compare it with allowed or forbidden IDs.

Approaches differ per authentication providers:

  • EC2 instance w/ IAM Instance Profile - Metadata API is always used. Introduced in Terraform 0.6.16.
  • All other providers (environment variable, shared credentials file, ...) will try two approaches in the following order
    • iam:GetUser - Typically useful for IAM Users. It also means that each user needs to be privileged to call iam:GetUser for themselves.
    • sts:GetCallerIdentity - Should work for both IAM Users and federated IAM Roles, introduced in Terraform 0.6.16.
    • iam:ListRoles - This is specifically useful for IdP-federated profiles which cannot use iam:GetUser. It also means that each federated user need to be assuming an IAM role which allows iam:ListRoles. Used in Terraform 0.6.16+. There used to be no better way to get account ID out of the API when using federated account until sts:GetCallerIdentity was introduced.