github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/website/docs/language/settings/backends/s3.mdx (about)

     1  ---
     2  page_title: 'Backend Type: s3'
     3  description: Terraform can store state remotely in S3 and lock that state with DynamoDB.
     4  ---
     5  
     6  # S3
     7  
     8  Stores the state as a given key in a given bucket on
     9  [Amazon S3](https://aws.amazon.com/s3/).
    10  This backend also supports state locking and consistency checking via
    11  [Dynamo DB](https://aws.amazon.com/dynamodb/), which can be enabled by setting
    12  the `dynamodb_table` field to an existing DynamoDB table name.
    13  A single DynamoDB table can be used to lock multiple remote state files. Terraform generates key names that include the values of the `bucket` and `key` variables.
    14  
    15  ~> **Warning!** It is highly recommended that you enable
    16  [Bucket Versioning](https://docs.aws.amazon.com/AmazonS3/latest/userguide/manage-versioning-examples.html)
    17  on the S3 bucket to allow for state recovery in the case of accidental deletions and human error.
    18  
    19  ## Example Configuration
    20  
    21  ```hcl
    22  terraform {
    23    backend "s3" {
    24      bucket = "mybucket"
    25      key    = "path/to/my/key"
    26      region = "us-east-1"
    27    }
    28  }
    29  ```
    30  
    31  This assumes we have a bucket created called `mybucket`. The
    32  Terraform state is written to the key `path/to/my/key`.
    33  
    34  Note that for the access credentials we recommend using a
    35  [partial configuration](/terraform/language/settings/backends/configuration#partial-configuration).
    36  
    37  ### S3 Bucket Permissions
    38  
    39  Terraform will need the following AWS IAM permissions on
    40  the target backend bucket:
    41  
    42  * `s3:ListBucket` on `arn:aws:s3:::mybucket`
    43  * `s3:GetObject` on `arn:aws:s3:::mybucket/path/to/my/key`
    44  * `s3:PutObject` on `arn:aws:s3:::mybucket/path/to/my/key`
    45  * `s3:DeleteObject` on `arn:aws:s3:::mybucket/path/to/my/key`
    46  
    47  This is seen in the following AWS IAM Statement:
    48  
    49  ```json
    50  {
    51    "Version": "2012-10-17",
    52    "Statement": [
    53      {
    54        "Effect": "Allow",
    55        "Action": "s3:ListBucket",
    56        "Resource": "arn:aws:s3:::mybucket"
    57      },
    58      {
    59        "Effect": "Allow",
    60        "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
    61        "Resource": "arn:aws:s3:::mybucket/path/to/my/key"
    62      }
    63    ]
    64  }
    65  ```
    66  
    67  -> **Note:** AWS can control access to S3 buckets with either IAM policies
    68  attached to users/groups/roles (like the example above) or resource policies
    69  attached to bucket objects (which look similar but also require a `Principal` to
    70  indicate which entity has those permissions). For more details, see Amazon's
    71  documentation about
    72  [S3 access control](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).
    73  
    74  ### DynamoDB Table Permissions
    75  
    76  If you are using state locking, Terraform will need the following AWS IAM
    77  permissions on the DynamoDB table (`arn:aws:dynamodb:::table/mytable`):
    78  
    79  * `dynamodb:DescribeTable`
    80  * `dynamodb:GetItem`
    81  * `dynamodb:PutItem`
    82  * `dynamodb:DeleteItem`
    83  
    84  This is seen in the following AWS IAM Statement:
    85  
    86  ```json
    87  {
    88    "Version": "2012-10-17",
    89    "Statement": [
    90      {
    91        "Effect": "Allow",
    92        "Action": [
    93          "dynamodb:DescribeTable",
    94          "dynamodb:GetItem",
    95          "dynamodb:PutItem",
    96          "dynamodb:DeleteItem"
    97        ],
    98        "Resource": "arn:aws:dynamodb:*:*:table/mytable"
    99      }
   100    ]
   101  }
   102  ```
   103  
   104  ## Data Source Configuration
   105  
   106  To make use of the S3 remote state in another configuration, use the
   107  [`terraform_remote_state` data
   108  source](/terraform/language/state/remote-state-data).
   109  
   110  ```hcl
   111  data "terraform_remote_state" "network" {
   112    backend = "s3"
   113    config = {
   114      bucket = "terraform-state-prod"
   115      key    = "network/terraform.tfstate"
   116      region = "us-east-1"
   117    }
   118  }
   119  ```
   120  
   121  The `terraform_remote_state` data source will return all of the root module
   122  outputs defined in the referenced remote state (but not any outputs from
   123  nested modules unless they are explicitly output again in the root). An
   124  example output might look like:
   125  
   126  ```
   127  data.terraform_remote_state.network:
   128    id = 2016-10-29 01:57:59.780010914 +0000 UTC
   129    addresses.# = 2
   130    addresses.0 = 52.207.220.222
   131    addresses.1 = 54.196.78.166
   132    backend = s3
   133    config.% = 3
   134    config.bucket = terraform-state-prod
   135    config.key = network/terraform.tfstate
   136    config.region = us-east-1
   137    elb_address = web-elb-790251200.us-east-1.elb.amazonaws.com
   138    public_subnet_id = subnet-1e05dd33
   139  ```
   140  
   141  ## Configuration
   142  
   143  This backend requires the configuration of the AWS Region and S3 state storage. Other configuration, such as enabling DynamoDB state locking, is optional.
   144  
   145  ### Credentials and Shared Configuration
   146  
   147  !> **Warning:**  We recommend using environment variables to supply credentials and other sensitive data. If you use `-backend-config` or hardcode these values directly in your configuration, Terraform will include these values in both the `.terraform` subdirectory and in plan files. Refer to [Credentials and Sensitive Data](/terraform/language/settings/backends/configuration#credentials-and-sensitive-data) for details.
   148  
   149  The following configuration is required:
   150  
   151  * `region` - (Required) AWS Region of the S3 Bucket and DynamoDB Table (if used). This can also be sourced from the `AWS_DEFAULT_REGION` and `AWS_REGION` environment variables.
   152  
   153  The following configuration is optional:
   154  
   155  * `access_key` - (Optional) AWS access key. If configured, must also configure `secret_key`. This can also be sourced from the `AWS_ACCESS_KEY_ID` environment variable, AWS shared credentials file (e.g. `~/.aws/credentials`), or AWS shared configuration file (e.g. `~/.aws/config`).
   156  * `secret_key` - (Optional) AWS access key. If configured, must also configure `access_key`. This can also be sourced from the `AWS_SECRET_ACCESS_KEY` environment variable, AWS shared credentials file (e.g. `~/.aws/credentials`), or AWS shared configuration file (e.g. `~/.aws/config`).
   157  * `iam_endpoint` - (Optional) Custom endpoint for the AWS Identity and Access Management (IAM) API. This can also be sourced from the `AWS_IAM_ENDPOINT` environment variable.
   158  * `max_retries` - (Optional) The maximum number of times an AWS API request is retried on retryable failure. Defaults to 5.
   159  * `profile` - (Optional) Name of AWS profile in AWS shared credentials file (e.g. `~/.aws/credentials`) or AWS shared configuration file (e.g. `~/.aws/config`) to use for credentials and/or configuration. This can also be sourced from the `AWS_PROFILE` environment variable.
   160  * `shared_credentials_file`  - (Optional) Path to the AWS shared credentials file. Defaults to `~/.aws/credentials`.
   161  * `skip_credentials_validation` - (Optional) Skip credentials validation via the STS API.
   162  * `skip_region_validation` - (Optional) Skip validation of provided region name.
   163  * `skip_metadata_api_check` - (Optional) Skip usage of EC2 Metadata API.
   164  * `sts_endpoint` - (Optional) Custom endpoint for the AWS Security Token Service (STS) API. This can also be sourced from the `AWS_STS_ENDPOINT` environment variable.
   165  * `token` - (Optional) Multi-Factor Authentication (MFA) token. This can also be sourced from the `AWS_SESSION_TOKEN` environment variable.
   166  
   167  #### Assume Role Configuration
   168  
   169  The following configuration is optional:
   170  
   171  * `assume_role_duration_seconds` - (Optional) Number of seconds to restrict the assume role session duration.
   172  * `assume_role_policy` - (Optional) IAM Policy JSON describing further restricting permissions for the IAM Role being assumed.
   173  * `assume_role_policy_arns` - (Optional) Set of Amazon Resource Names (ARNs) of IAM Policies describing further restricting permissions for the IAM Role being assumed.
   174  * `assume_role_tags` - (Optional) Map of assume role session tags.
   175  * `assume_role_transitive_tag_keys` - (Optional) Set of assume role session tag keys to pass to any subsequent sessions.
   176  * `external_id` - (Optional) External identifier to use when assuming the role.
   177  * `role_arn` - (Optional) Amazon Resource Name (ARN) of the IAM Role to assume.
   178  * `session_name` - (Optional) Session name to use when assuming the role.
   179  
   180  ### S3 State Storage
   181  
   182  The following configuration is required:
   183  
   184  * `bucket` - (Required) Name of the S3 Bucket.
   185  * `key` - (Required) Path to the state file inside the S3 Bucket. When using a non-default [workspace](/terraform/language/state/workspaces), the state path will be `/workspace_key_prefix/workspace_name/key` (see also the `workspace_key_prefix` configuration).
   186  
   187  The following configuration is optional:
   188  
   189  * `acl` - (Optional) [Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl) to be applied to the state file.
   190  * `encrypt` - (Optional) Enable [server side encryption](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingServerSideEncryption.html) of the state file.
   191  * `endpoint` - (Optional) Custom endpoint for the AWS S3 API. This can also be sourced from the `AWS_S3_ENDPOINT` environment variable.
   192  * `force_path_style` - (Optional) Enable path-style S3 URLs (`https://<HOST>/<BUCKET>` instead of `https://<BUCKET>.<HOST>`).
   193  * `kms_key_id` - (Optional) Amazon Resource Name (ARN) of a Key Management Service (KMS) Key to use for encrypting the state. Note that if this value is specified, Terraform will need `kms:Encrypt`, `kms:Decrypt` and `kms:GenerateDataKey` permissions on this KMS key.
   194  * `sse_customer_key` - (Optional) The key to use for encrypting state with [Server-Side Encryption with Customer-Provided Keys (SSE-C)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerSideEncryptionCustomerKeys.html). This is the base64-encoded value of the key, which must decode to 256 bits. This can also be sourced from the `AWS_SSE_CUSTOMER_KEY` environment variable, which is recommended due to the sensitivity of the value. Setting it inside a terraform file will cause it to be persisted to disk in `terraform.tfstate`.
   195  * `workspace_key_prefix` - (Optional) Prefix applied to the state path inside the bucket. This is only relevant when using a non-default workspace. Defaults to `env:`.
   196  
   197  ### DynamoDB State Locking
   198  
   199  The following configuration is optional:
   200  
   201  * `dynamodb_endpoint` - (Optional) Custom endpoint for the AWS DynamoDB API. This can also be sourced from the `AWS_DYNAMODB_ENDPOINT` environment variable.
   202  * `dynamodb_table` - (Optional) Name of DynamoDB Table to use for state locking and consistency. The table must have a partition key named `LockID` with type of `String`. If not configured, state locking will be disabled.
   203  
   204  ## Multi-account AWS Architecture
   205  
   206  A common architectural pattern is for an organization to use a number of
   207  separate AWS accounts to isolate different teams and environments. For example,
   208  a "staging" system will often be deployed into a separate AWS account than
   209  its corresponding "production" system, to minimize the risk of the staging
   210  environment affecting production infrastructure, whether via rate limiting,
   211  misconfigured access controls, or other unintended interactions.
   212  
   213  The S3 backend can be used in a number of different ways that make different
   214  tradeoffs between convenience, security, and isolation in such an organization.
   215  This section describes one such approach that aims to find a good compromise
   216  between these tradeoffs, allowing use of
   217  [Terraform's workspaces feature](/terraform/language/state/workspaces) to switch
   218  conveniently between multiple isolated deployments of the same configuration.
   219  
   220  Use this section as a starting-point for your approach, but note that
   221  you will probably need to make adjustments for the unique standards and
   222  regulations that apply to your organization. You will also need to make some
   223  adjustments to this approach to account for _existing_ practices within your
   224  organization, if for example other tools have previously been used to manage
   225  infrastructure.
   226  
   227  Terraform is an administrative tool that manages your infrastructure, and so
   228  ideally the infrastructure that is used by Terraform should exist outside of
   229  the infrastructure that Terraform manages. This can be achieved by creating a
   230  separate _administrative_ AWS account which contains the user accounts used by
   231  human operators and any infrastructure and tools used to manage the other
   232  accounts. Isolating shared administrative tools from your main environments
   233  has a number of advantages, such as avoiding accidentally damaging the
   234  administrative infrastructure while changing the target infrastructure, and
   235  reducing the risk that an attacker might abuse production infrastructure to
   236  gain access to the (usually more privileged) administrative infrastructure.
   237  
   238  ### Administrative Account Setup
   239  
   240  Your administrative AWS account will contain at least the following items:
   241  
   242  * One or more [IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)
   243    for system administrators that will log in to maintain infrastructure in
   244    the other accounts.
   245  * Optionally, one or more [IAM groups](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html)
   246    to differentiate between different groups of users that have different
   247    levels of access to the other AWS accounts.
   248  * An [S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html)
   249    that will contain the Terraform state files for each workspace.
   250  * A [DynamoDB table](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.TablesItemsAttributes)
   251    that will be used for locking to prevent concurrent operations on a single
   252    workspace.
   253  
   254  Provide the S3 bucket name and DynamoDB table name to Terraform within the
   255  S3 backend configuration using the `bucket` and `dynamodb_table` arguments
   256  respectively, and configure a suitable `workspace_key_prefix` to contain
   257  the states of the various workspaces that will subsequently be created for
   258  this configuration.
   259  
   260  ### Environment Account Setup
   261  
   262  For the sake of this section, the term "environment account" refers to one
   263  of the accounts whose contents are managed by Terraform, separate from the
   264  administrative account described above.
   265  
   266  Your environment accounts will eventually contain your own product-specific
   267  infrastructure. Along with this it must contain one or more
   268  [IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)
   269  that grant sufficient access for Terraform to perform the desired management
   270  tasks.
   271  
   272  ### Delegating Access
   273  
   274  Each Administrator will run Terraform using credentials for their IAM user
   275  in the administrative account.
   276  [IAM Role Delegation](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html)
   277  is used to grant these users access to the roles created in each environment
   278  account.
   279  
   280  Full details on role delegation are covered in the AWS documentation linked
   281  above. The most important details are:
   282  
   283  * Each role's _Assume Role Policy_ must grant access to the administrative AWS
   284    account, which creates a trust relationship with the administrative AWS
   285    account so that its users may assume the role.
   286  * The users or groups within the administrative account must also have a
   287    policy that creates the converse relationship, allowing these users or groups
   288    to assume that role.
   289  
   290  Since the purpose of the administrative account is only to host tools for
   291  managing other accounts, it is useful to give the administrative accounts
   292  restricted access only to the specific operations needed to assume the
   293  environment account role and access the Terraform state. By blocking all
   294  other access, you remove the risk that user error will lead to staging or
   295  production resources being created in the administrative account by mistake.
   296  
   297  When configuring Terraform, use either environment variables or the standard
   298  credentials file `~/.aws/credentials` to provide the administrator user's
   299  IAM credentials within the administrative account to both the S3 backend _and_
   300  to Terraform's AWS provider.
   301  
   302  Use conditional configuration to pass a different `assume_role` value to
   303  the AWS provider depending on the selected workspace. For example:
   304  
   305  ```hcl
   306  variable "workspace_iam_roles" {
   307    default = {
   308      staging    = "arn:aws:iam::STAGING-ACCOUNT-ID:role/Terraform"
   309      production = "arn:aws:iam::PRODUCTION-ACCOUNT-ID:role/Terraform"
   310    }
   311  }
   312  
   313  provider "aws" {
   314    # No credentials explicitly set here because they come from either the
   315    # environment or the global credentials file.
   316  
   317    assume_role {
   318      role_arn = "${var.workspace_iam_roles[terraform.workspace]}"
   319    }
   320  }
   321  ```
   322  
   323  If workspace IAM roles are centrally managed and shared across many separate
   324  Terraform configurations, the role ARNs could also be obtained via a data
   325  source such as [`terraform_remote_state`](/terraform/language/state/remote-state-data)
   326  to avoid repeating these values.
   327  
   328  ### Creating and Selecting Workspaces
   329  
   330  With the necessary objects created and the backend configured, run
   331  `terraform init` to initialize the backend and establish an initial workspace
   332  called "default". This workspace will not be used, but is created automatically
   333  by Terraform as a convenience for users who are not using the workspaces
   334  feature.
   335  
   336  Create a workspace corresponding to each key given in the `workspace_iam_roles`
   337  variable value above:
   338  
   339  ```
   340  $ terraform workspace new staging
   341  Created and switched to workspace "staging"!
   342  
   343  ...
   344  
   345  $ terraform workspace new production
   346  Created and switched to workspace "production"!
   347  
   348  ...
   349  ```
   350  
   351  Due to the `assume_role` setting in the AWS provider configuration, any
   352  management operations for AWS resources will be performed via the configured
   353  role in the appropriate environment AWS account. The backend operations, such
   354  as reading and writing the state from S3, will be performed directly as the
   355  administrator's own user within the administrative account.
   356  
   357  ```
   358  $ terraform workspace select staging
   359  $ terraform apply
   360  ...
   361  ```
   362  
   363  ### Running Terraform in Amazon EC2
   364  
   365  Teams that make extensive use of Terraform for infrastructure management
   366  often [run Terraform in automation](/terraform/tutorials/automation/automate-terraform?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS)
   367  to ensure a consistent operating environment and to limit access to the
   368  various secrets and other sensitive information that Terraform configurations
   369  tend to require.
   370  
   371  When running Terraform in an automation tool running on an Amazon EC2 instance,
   372  consider running this instance in the administrative account and using an
   373  [instance profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html)
   374  in place of the various administrator IAM users suggested above. An IAM
   375  instance profile can also be granted cross-account delegation access via
   376  an IAM policy, giving this instance the access it needs to run Terraform.
   377  
   378  To isolate access to different environment accounts, use a separate EC2
   379  instance for each target account so that its access can be limited only to
   380  the single account.
   381  
   382  Similar approaches can be taken with equivalent features in other AWS compute
   383  services, such as ECS.
   384  
   385  ### Protecting Access to Workspace State
   386  
   387  In a simple implementation of the pattern described in the prior sections,
   388  all users have access to read and write states for all workspaces. In many
   389  cases it is desirable to apply more precise access constraints to the
   390  Terraform state objects in S3, so that for example only trusted administrators
   391  are allowed to modify the production state, or to control _reading_ of a state
   392  that contains sensitive information.
   393  
   394  Amazon S3 supports fine-grained access control on a per-object-path basis
   395  using IAM policy. A full description of S3's access control mechanism is
   396  beyond the scope of this guide, but an example IAM policy granting access
   397  to only a single state object within an S3 bucket is shown below:
   398  
   399  ```json
   400  {
   401    "Version": "2012-10-17",
   402    "Statement": [
   403      {
   404        "Effect": "Allow",
   405        "Action": "s3:ListBucket",
   406        "Resource": "arn:aws:s3:::myorg-terraform-states"
   407      },
   408      {
   409        "Effect": "Allow",
   410        "Action": ["s3:GetObject", "s3:PutObject"],
   411        "Resource": "arn:aws:s3:::myorg-terraform-states/myapp/production/tfstate"
   412      }
   413    ]
   414  }
   415  ```
   416  
   417  It is also possible to apply fine-grained access control to the DynamoDB
   418  table used for locking. When Terraform puts the state lock in place during `terraform plan`, it stores the full state file as a document and sets the s3 object key as the partition key for the document. After the state lock is released, Terraform places a digest of the updated state file in DynamoDB. The key is similar to the one for the original state file, but is suffixed with `-md5`.
   419  
   420  The example below shows a simple IAM policy that allows the backend operations role to perform these operations:
   421  
   422  ```json
   423  {
   424    "Version": "2012-10-17",
   425    "Statement": [
   426        {
   427          "Effect" : "Allow",
   428          "Action" : [
   429            "dynamodb:DeleteItem",
   430            "dynamodb:GetItem",
   431            "dynamodb:PutItem",
   432            "dynamodb:Query",
   433            "dynamodb:UpdateItem"
   434          ],
   435          "Resource" : ["arn:aws:dynamodb:*:*:table/myorg-state-lock-table"],
   436          "Condition" : {
   437            "ForAllValues:StringEquals" : {
   438              "dynamodb:LeadingKeys" : [
   439                "myorg-terraform-states/myapp/production/tfstate", // during a state lock the full state file is stored with this key
   440                "myorg-terraform-states/myapp/production/tfstate-md5" // after the lock is released a hash of the statefile's contents are stored with this key
   441              ]
   442            }
   443          }
   444        }
   445    ]
   446  }
   447  ```
   448  
   449  Refer to the [AWS documentation on DynamoDB fine-grained locking](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html) for more details.
   450  
   451  ### Configuring Custom User-Agent Information
   452  
   453  Note this feature is optional and only available in Terraform v0.13.1+.
   454  
   455  By default, the underlying AWS client used by the Terraform AWS Provider creates requests with User-Agent headers including information about Terraform and AWS Go SDK versions. To provide additional information in the User-Agent headers, the `TF_APPEND_USER_AGENT` environment variable can be set and its value will be directly added to HTTP requests. e.g.
   456  
   457  ```sh
   458  $ export TF_APPEND_USER_AGENT="JenkinsAgent/i-12345678 BuildID/1234 (Optional Extra Information)"
   459  ```