| --- |
| page_title: Upgrading to Terraform v1.1 |
| description: Upgrading to Terraform v1.1 |
| --- |
| |
| # Upgrading to Terraform v1.1 |
| |
| Terraform v1.1 is the first minor release after establishing a compatibility |
| baseline in Terraform v1.0, and so this release should not require any |
| unusual upgrade steps for most users. |
| |
| However, if you are upgrading from a version earlier than v1.0 then please |
| refer to [the Terraform v1.0 upgrade guide](/language/upgrade-guides/1-0) for how to upgrade through |
| the v0 releases to reach the v1 release series. Because v1.1 is |
| backward-compatible with the v1.0 series, you can upgrade directly to the |
| latest v1.1 release, skipping the v1.0 series entirely, at any point where the |
| v1.0 upgrade guide calls for upgrading to Terraform v1.0. |
| |
| Terraform v1.1 continues to honor |
| [the Terraform v1.0 Compatibility Promises](/language/v1-compatibility-promises), |
| but there are some behavior changes outside of those promises that may affect a |
| small number of users, described in the following sections. |
| |
| * [Terraform requires macOS 10.13 High Sierra or later](#terraform-requires-macos-1013-high-sierra-or-later) |
| * [Preparation for removing Azure AD Graph support in the AzureRM Backend](#preparation-for-removing-azure-ad-graph-support-in-the-azurerm-backend) |
| * [Interpretation of remote file paths in the `remote-exec` and `file` provisioners](#interpretation-of-remote-file-paths-in-the-remote-exec-and-file-provisioners) |
| * [Changes to `terraform graph`](#changes-to-terraform-graph) |
| * [Changes to `terraform state mv`](#changes-to-terraform-state-mv) |
| * [Provider checksum verification in `terraform apply`](#provider-checksum-verification-in-terraform-apply) |
| |
| ## Terraform requires macOS 10.13 High Sierra or later |
| |
| As operating system vendors phase out support for older versions of their |
| software, the Terraform team must also phase out support in order to focus |
| on supporting newer releases. |
| |
| With that in mind, the official releases of Terraform v1.1 now require |
| macOS 10.13 High Sierra or later. Earlier versions of macOS are no longer |
| supported, and Terraform CLI behavior on those earlier versions is undefined. |
| |
| ## Preparation for removing Azure AD Graph support in the AzureRM Backend |
| |
| [Microsoft has announced the deprecation of Azure AD Graph](https://docs.microsoft.com/en-us/graph/migrate-azure-ad-graph-faq), |
| and so Terraform v1.1 marks the first phase of a deprecation process for |
| that legacy system in [the AzureRM state storage backend](/language/settings/backends/azurerm). |
| |
| During the Terraform v1.1 release the default behavior is unchanged, but you |
| can explicitly opt in to Microsoft Graph by setting |
| `use_microsoft_graph = true` inside your `backend "azurerm` block and then |
| reinitializing your working directory with `terraform init -reconfigure`. |
| |
| In Terraform v1.2 we plan to change this argument to default to `true` when |
| not set, and so we strongly recommend planning to migrate to Microsoft Graph |
| in the near future to prepare for the final removal of Azure AD Graph support |
| in a later Terraform release. However, no immediate change is required before |
| upgrading to Terraform v1.1. |
| |
| ## Interpretation of remote file paths in the `remote-exec` and `file` provisioners |
| |
| When using Terraform's built-in `remote-exec` and `file` provisioners, there |
| are two situations where Terraform internally uses |
| [Secure Copy Protocol](https://en.wikipedia.org/wiki/Secure_copy_protocol) |
| (SCP) to upload files to the remote system at a configuration-specified |
| location: |
| |
| * For [the `file` provisioner](/language/resources/provisioners/file), |
| the primary functionality is to upload a file using SCP, and the |
| `destination` argument specifies the remote path where the file is to be |
| written. |
| * For [the `remote-exec` provisioner](/language/resources/provisioners/remote-exec), |
| internally the provisioner works by uploading the given scripts to files |
| on the remote system and then executing them. By default the provisioner |
| selects a temporary filename automatically, but a module author can |
| potentially override that location using the `script_path` argument in the |
| associated [`connection` block](https://www.terraform.io/language/resources/provisioners/connection). |
| |
| If you are not using either of the specific arguments mentioned above, no |
| configuration changes will be required to upgrade to Terraform v1.1. |
| |
| These provisioners both passing the specified remote paths to the `scp` service |
| program on the remote system. In Terraform v1.0 and earlier, the provisioners |
| were passing the paths to `scp` in a way that was inadvertently subject to |
| _shell expansion_. That inadvertently allowed for convenient shorthands |
| such as `~/example` and `$HOME/example` to write into the target user's |
| home directory, but also offered an undesirable opportunity for accidental |
| remote code execution, such as `$(arbitrary-program)`. |
| |
| In Terraform v1.1 both of the above remote path arguments are passed _verbatim_ |
| to the remote `scp` service, without any prior shell expansion. For that reason, |
| shell-defined expansion tokens such as `~` and environment variable references |
| will no longer be evaluated. |
| |
| By default, the OpenSSH server and the program `scp` together already interpret |
| relative paths as relative to the target user's home directory, and so |
| module authors can specify relative paths without any special metacharacters |
| in order to request uploading into that default location: |
| |
| ```hcl |
| provisioner "file" { |
| source = "local.txt" |
| destination = "remote.txt" |
| } |
| ``` |
| |
| If you maintain a module that was depending on expansion of `~/`, `$HOME/`, |
| `${HOME}`/ or similar, remove that prefix so that your module instead specifies |
| just a relative path. |
| |
| This is an intentional compatibility regression which we accepted after due |
| consideration of |
| [the pragmatic exceptions to our compatibility promises](/language/v1-compatibility-promises#pragmatic-exceptions). |
| Specifically, this behavior offered an unintended and non-obvious avenue for |
| arbitrary code execution on the remote system if either of the above arguments |
| were populated from outside input, and an alternative approach is available |
| which doesn't have that drawback, and this is therefore justified on security |
| grounds. |
| |
| ## Changes to `terraform graph` |
| |
| The `terraform graph` command exists to help with debugging and so it |
| inherently exposes some of Terraform Core's implementation details. For that |
| reason it isn't included in the v1.0 Compatibility Promises, but we still |
| aim to preserve its behavior in spirit even as Terraform Core's internal |
| design changes. |
| |
| In previous releases, `terraform graph` exposed the implementation detail that |
| Terraform internally knows how to build graph types called "validate" and |
| "eval", but Terraform Core no longer exposes those graph types externally |
| and so consequently the graph command will no longer accept the options |
| `-type=validate` or `-type=eval`. |
| |
| You can see a similar result to what those graph types would previously |
| produce by generating a _plan_ graph, which is the default graph type and |
| therefore requires no special `-type=...` option. |
| |
| ## Changes to `terraform state mv` |
| |
| Terraform's local state storage backend supports a number of |
| [legacy command line options](/language/settings/backends/local#command-line-arguments) |
| for backward-compatibility with workflows from much older versions of Terraform, |
| prior to the introduction of Backends. |
| |
| Those options are not supported when using any other backend, but for many |
| commands they are simply silently ignored rather than returning an error. |
| |
| Because `terraform state mv` has some extra use-cases related to migrating |
| between states, it historically had some slightly different handling of those |
| legacy options, but was not fully consistent. |
| |
| From Terraform v1.1, the behavior of these options has changed as follows: |
| |
| * The `-state=...` argument is allowed even when a remote backend is specified |
| in the configuration. If present, it forces the command to work in local |
| mode. |
| * The `-backup=...` and `-backup-out=...` options are allowed only if either |
| the local backend is the configuration's selected backend _or_ if you |
| specify `-state=...` to force local state operation. These options will now |
| return an error if used against a remote backend, whereas previous Terraform |
| versions ignored them entirely in that case. |
| |
| There are no breaking changes to `terraform state mv`'s normal usage pattern, |
| without any special options overriding the state storage strategy. |
| |
| ## Provider checksum verification in `terraform apply` |
| |
| This section applies only to situations where you might generate a saved |
| plan file using `terraform plan -out=tfplan` and then separately apply it |
| using `terraform apply tfplan`. |
| |
| You do not need to consider this section unless you are using a custom |
| Terraform provider which somehow modifies its own provider package contents |
| during execution. That is hypothetically possible, but not true in practice for |
| any publicly-available providers we are aware of at the time of writing this |
| guide. |
| |
| Our design intent for this two-step run workflow is that the saved plan |
| records enough information for Terraform to guarantee that it's running |
| against an identical set of providers during the apply step as it was during |
| the plan step, because otherwise the different provider plugins may disagree |
| about the meaning of the planned actions. |
| |
| However, prior versions of Terraform verified consistency only for the main |
| executable file representing a provider plugin, and didn't consider other |
| files that might appear alongside in the plugin package. Terraform v1.1 now |
| uses the same strategy for provider checking during apply as it does when |
| verifying provider consistency against |
| [the dependency lock file](/language/files/dependency-lock) |
| during `terraform init`, which means `terraform apply` will return an error |
| if it detects that _any_ of the files in a provider's plugin package have |
| changed compared to when the plan was created. |
| |
| In the unlikely event that you _do_ use a self-modifying provider plugin, |
| please consider other solutions to achieve the goals which motivated that, |
| which do not involve the provider modifying itself at runtime. If you aren't |
| sure, please open a GitHub issue to discuss your use-case. |