hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
41.58k stars 9.4k forks source link

Ability to add auto-apply protection #35339

Open bryan-rhm opened 1 week ago

bryan-rhm commented 1 week ago

Terraform Version

1.5.0

Use Cases

We sometimes runs auto-apply option, however there has been cases where the -auto-apply flag was enabled on production workspaces/projects applying unexpected changes, we would like the ability to add some kind of auto-apply protection which will not allow the auto-apply flag if protection is enabled for the workspace or project we are running, ideally for teams that runs terraform locally

Attempted Solutions

No

Proposal

Maybe we could add it at the terraform configuration level

terraform {
  auto-apply-protection = true
}

References

No response

crw commented 1 week ago

Thanks for this feature request! If you are viewing this issue and would like to indicate your interest, please use the 👍 reaction on the issue description to upvote this issue. We also welcome additional use case descriptions. Thanks again!

apparentlymart commented 1 week ago

Hi @bryan-rhm! Thanks for sharing this use-case.

From your framing of the problem I understood this as something you'd likely want to set only for production and not for staging/development environments. Is that right?

If so, doing this in the configuration doesn't feel quite right to me: Terraform modules are usually shared between multiple environments, and so anything which needs to vary per environment either needs to be expressed in the configuration as a rule rather than as a fixed setting, or recorded in some other location separate from the configuration.

Setting it in the configuration also raises the question of what ought to happen if a shared module (called by a module block) includes this setting. Should someone who has published a general-purpose module in the public registry have the ability to rule on your behalf that auto-apply should be disabled?

Based on your description and on the considerations I described above, this seems to me like something that would ideally be set in the Terraform state, controlling whether it's acceptable to auto-apply any changes that would affect that particular state. If we did that then I expect it would be something you'd enable or disable using a separate CLI command, outside of the normal plan/apply flow, which would also mean that anyone wishing to change it would need to take an explicit action beyond just modifying the configuration.

However, it's true that we don't currently have any precedent for using Terraform state for behaviors like this. The closest analog would be HCP Terraform-specific functionality like deciding whether a particular workspace should use remote operations or not, but that's not actually stored in the Terraform state because HCP Terraform is able to store its own metadata on a per-workspace basis, whereas non-Terraform-specific storage locations like S3 have nothing except the state snapshots.


Teams typically try to mitigate mistakes like this today by requiring Terraform to be run only indirectly through some kind of automation that enforces the organization's policies outside the scope of Terraform configuration or state.

In that case nobody runs Terraform CLI on their own computer except for development tasks, and so a mistake of this sort would manifest through someone changing the rules followed by the automation rather than just accidentally specifying the wrong command line arguments when running locally.

We don't really recommend that teams run Terraform CLI locally for production infrastructure. The local working modes are primarily intended to support module development in separate environments used only for development.

bryan-rhm commented 1 week ago

@apparentlymart I was not talking about adding it to a module, I was talking to add this as a flag we could define and change through a variable or something between environments,

var.enable_protection = true

terraform {
 auto-apply-protection = var.enable_protection
}

I know running this locally is not the best practice but will mitigate human errors, I know lot of people and companies runs terraform locally and manage state trhough s3 and dynamodb locking

apparentlymart commented 1 week ago

Hi @bryan-rhm,

You've illustrated a terraform block, which I understood as being in a .tf file and therefore part of Terraform's modules language. That was what I meant by "in a module". Did you have something else in mind, or do you think we're talking about the same thing?

Today most things in the terraform block belong to terraform init rather than to the plan/apply phase and so there's currently nothing in the terraform block that supports expression evaluation like references to variables. This could potentially be the first example of such a thing in theory, but people already seem quite confused about the fact that the terraform block is treated differently than the rest of the language and so I worry that having the language runtime evaluate only this one part would make things more confusing. If we do decide that having this be declared as part of a module is the right approach, I expect we'd probably want to find somewhere other than the terraform block to specify it.

bryan-rhm commented 1 week ago

@apparentlymart that was just an idea, where do you think that this could be added? is not possible at the state level?