January 31, 2018·4 min read·engineeringterraformstates3

Terraform 0.11.3 repairs state backend edge cases

Terraform 0.11.3 adds Paris-region support and fixes workspace handling. The changes expose the operational responsibilities behind remote state.

A backend can prevent an infrastructure operation before a provider gets an opportunity to change anything. Terraform needs access to its state, and a valid storage configuration is part of that requirement. Terraform 0.11.3, released on January 31, addresses this boundary with support for the S3 backend's eu-west-3 region and a correction to workspace-name handling. Its release notes also identify crashes during refresh and invalid module-source handling. These are small changes with consequences for the reliability of ordinary commands.

I value Terraform's general approach to infrastructure APIs, but the state backend deserves the same architectural attention as the resources in a configuration. A useful declarative language still depends on being able to find and preserve its records. The S3 fixes are a good occasion to examine what that dependency actually requires.

The backend has its own configuration

The S3 documentation shipped with 0.11.3 describes a backend that writes state to a key in an existing bucket. The bucket name, object key, and bucket region identify the storage location. With this release, a configuration can use eu-west-3 without the backend rejecting that supported region.

terraform {
  backend "s3" {
    bucket = "example-infrastructure-state"
    key    = "network/terraform.tfstate"
    region = "eu-west-3"
  }
}

The example assumes that the named bucket already exists. It does not declare a bucket resource, and it does not tell the AWS provider where application resources belong. Those are separate responsibilities. This distinction becomes useful when state lives in an administrative account while the infrastructure described by the configuration lives in another account.

The versioned documentation develops exactly that arrangement. Administrators authenticate in an administrative account, which contains the state bucket and optional locking table. The AWS provider assumes a role in an environment account to manage resources there. Backend operations continue under the administrative identity. Consequently, permission to change a compute resource and permission to write its Terraform state can follow different authorization paths.

That separation makes a region-validation fix more consequential than its one-line changelog entry suggests. A valid provider configuration cannot compensate for a backend that rejects its own storage location. The backend must initialize successfully before the configuration can participate in the intended workflow. Supporting the region directly also avoids treating a normal AWS configuration as an exception requiring skipped validation.

Workspace names become object paths

The other S3 correction allows a workspace name to be a prefix of workspace_key_prefix. The release notes describe that specific relationship, not a general change to workspace identity. It is an edge case in the names supplied to the storage backend.

For a non-default workspace, the documented state path combines the workspace prefix, workspace name, and configured key. The default prefix is env:. Those components matter when an operator investigates a state object or writes an IAM policy for it. A workspace is represented through a storage path, and the backend must interpret the components consistently even when their strings overlap.

The documentation also permits object-level access policies. An administrator can grant access to a particular state path without granting equivalent read and write access to every object in the bucket. This makes naming part of the authorization design. A naming convention needs to produce paths that both Terraform and the access policy interpret as intended.

I find this a useful limit on the convenience of workspaces. Switching a workspace is easy at the command line, but the underlying isolation still depends on account roles and object permissions. A workspace name alone does not establish a separate security boundary. The backend's storage rules explain where that boundary can actually be enforced.

Locking and recovery are separate services

The S3 backend supports locking and consistency checking through DynamoDB. The documented dynamodb_table argument names an existing table whose primary key is LockID. Without that configuration, locking is disabled. Storing the state remotely therefore does not, by itself, configure protection against concurrent operations.

terraform {
  backend "s3" {
    bucket         = "example-infrastructure-state"
    key            = "network/terraform.tfstate"
    region         = "eu-west-3"
    dynamodb_table = "example-terraform-locks"
  }
}

This example adds a dependency on a second existing AWS resource. Bucket permissions and table permissions need to match the intended operating model. The documentation notes a further limitation in its access-control discussion. Fine-grained restrictions on state objects do not translate into equivalent restrictions on the shared locking table, so an identity with locking access can interfere with workspaces whose state it cannot read.

Recovery requires another explicit choice. The S3 backend documentation recommends bucket versioning for accidental deletion and human error. Locking coordinates operations, while object history supports recovery of earlier state. These solve different problems, so a configured locking table does not remove the reason to retain previous state objects.

The refresh crash fix belongs to the same concern for reliable operation, although the changelog does not claim that it changes S3 persistence or recovery. It says Terraform now handles an error encountered during refresh without crashing. The invalid module-source fix similarly improves the handling of a bad input. Neither should be interpreted as a new guarantee about resource transactions.

For an infrastructure tool, these distinctions affect how failures are diagnosed. An invalid source, a refresh error, and denied access to a state object need different remedies. Terraform 0.11.3 removes several ways those cases could fail unnecessarily, while its backend documentation makes the remaining storage and permission requirements explicit.