-
Notifications
You must be signed in to change notification settings - Fork 9.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
prevent_destroy does not prevent destruction when removing a resource from the configuration #17599
Comments
Hi @theflyingnerd! Thanks for pointing this out. Currently removing a resource from configuration is treated as intent to remove the resource, since that's an explicit action on your part rather than it happening as a part of some other action, such as resource replacement or a whole-configuration destroy. However, your idea of retaining this in the state and requiring multiple steps to actually destroy is an interesting one:
I'd like to think about this some more because while this does seem safer it also feels like this flow could be quite frustrating if e.g. you've already committed some reorganization to your version control that includes removing a resource and then Terraform refuses to apply it until you revert and do steps 1 and 2 from the above. In the mean time, we should at least update the documentation to be more explicit about how |
Great, thanks for your quick and thorough reply @apparentlymart . I agree that a documentation update would be sufficient for now and the proposed functionality could be left open for debate. My comments about this process were a mixture of how I might expect it to work if I didn't read any more documentation as well as a proposal. It's influenced by the idea of AWS instance termination protection. This protection must be explicitly removed first before the instance may be terminated, even if the instance is explicitly terminated by id. |
Please see: #16392 |
Any further thoughts on this? |
Potential duplicate of #3468 |
Strange that 17599 closes 3468 and not the opposite but that is still a very wanted feature. |
This was (is) a major risk factor of accidental deletion and was unacceptable for us using terraform in production. This is our workaround for this that runs in our Azure DevOps pipeline on every commit before application, I'll see if I can get the code (Powershell Pester Test) approved to be shared.
In addition to this all production changes have an approval step that formats the terraform apply state very clearly and has to be approved by all the team members. |
I currently don't intend to manage certain things with Terraform due to this. As part of deployment of new code (i.e. lambda, ECS containers, api gateway, etc...) my Terraform files are built dynamically, so although it seems like removing it from the .tf files is explicit approval, it could just as easily be a coding error. As such, managing any type of Dynamo table or RDS or something is out of the question, and those will just have to be managed manually. While I'm kind of ok with this, it certainly would be nice to just manage the entire application and still be able to sleep. |
Any update on this? It seems like quite an important feature... |
I would imagine all their energies are on getting 0.12 out the door right
now.
…On Mon, Mar 4, 2019 at 7:37 PM simlu ***@***.***> wrote:
Any update on this? It seems like quite an important feature...
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#17599 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AOjVUmLqlNPxCZNSo6y4R-PqzZVILSSXks5vTeZcgaJpZM4StAww>
.
|
+2 |
omg. I'm looking at how to just prevent helm provider from destroying a chart every time I deploy. I came here to see this amazing prevent_destroy trait that I want to try out, but judging from this, it doesnt even work? You are willing to wipe out a whole database created with prevent_destroy flag on? What the heck? |
@CodeSwimBikeRun Your comment before the edit was more correct - it works, but not if you remove the resource from your You can, however, set flags on some resources (such as AWS EC2 and RDS instances) to prevent deletion at the AWS API level, which will help you no matter what. Not sure the language is warranted. |
@CodeSwimBikeRun This issue is about a specific case, in which the configuration block for the resource no longer exists. In which case, Terraform is following instructions in the strict sense that the resource is no longer configured with Terraform interprets the configuration files as your desired state, and the state file (and/or refreshed in-memory state) as the current state. Destruction becomes a complex edge-case in this way because the absence of a resource implicitly means that you desired it to be destroyed, but in practice this may not always be true. There are other cases to watch out for which are similar, but are consequences of the basic design. For example, #13549. The feature works - in the general sense - and is worth using. But it's still pretty important to examine the plan before applying changes. Declarative configuration systems in general are very powerful, but also come with an inherent risk of accidentally automating failure (see: Automation: Enabling Failure at Scale for an example outside Terraform). I personally find that Terraform's |
we had part of our production deleted because of this :( |
Storing last set |
seems like a no-brainer safety-critical feature ... prevent destroy should work |
Would be nice to have a feature added like Cloudformations Retain. If the resource is removed from the file, CF doesn't try to remove the resource, and just removes it from the state file. |
I'm looking at configuring Azure FrontDoor which means that I'll need to reference Azure DNS zone. As I currently use the same domain (different sub-domains) for live and test environments, then I run the risk of destroying live the DNS zone when I clean down a test environment. Is there any thought on implementing the change that @apparentlymart suggested at the start of the thread? |
@penfold Your case sounds like https://www.terraform.io/language/state/remote-state-data You could put your shared resources in a separate state project to protect the dependant Terraform runs from clobbering it's resources, but still benefit from referencing values from it's resources across environments. |
This is still such a huge problem for everything containing state/data - from Databases to GitHub repos. Terraform is simply not production-grade for these use cases until it records the |
Hi @apparentlymart, as an alternative to the following workflow to remove a protected resource:
we could also think about an alternative workflow:
The order of steps 1 and 2 is not relevant. The step 2 removes the destroy prevention from the state. If the the step 1 is not executed, so that the resource remains in the configuration entirely, but the step 2 is executed, then the |
I think the problem with this solution is that if this policy attachment is accidentally getting removed from the I think another way is to limit the IAM user that Terraforms itself is using. You can add this policy to the user: {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": [
"cognito-idp:AdminDeleteUser",
"cognito-idp:DeleteGroup",
"cognito-idp:AdminDeleteUserAttributes",
"cognito-idp:DeleteUserPool",
"cognito-idp:DeleteIdentityProvider",
"cognito-idp:DeleteResourceServer",
"cognito-idp:DeleteUserPoolClient",
"cognito-identity:UnlinkDeveloperIdentity",
"cognito-idp:DeleteUserPoolDomain",
"cognito-identity:DeleteIdentityPool",
"cognito-idp:DeleteUserAttributes",
"cognito-identity:DeleteIdentities",
"cognito-identity:UnlinkIdentity",
"cognito-idp:DeleteUser"
],
"Resource": ["*"]
}
]
} But anyway, I think Terraform itself should not delete any user pool that has at least one user in it. It does the same for the S3 bucket that can't get destroyed if there is an object in it. |
Hi gang. We got bit by this yesterday. Is there a workaround yet? |
I'm trying to automate a CI/CD solution for terraform, but am deeply concerned with auto-applying changes on merges to main because of this issue. If someone doesn't look over a plan properly, they could cause a pretty drastic outage, and we could lose a lot of data. I suppose my real concern is managing anything with terraform that contains persistent data, and doesn't have a prevent deletion flag available to be set. The best solution (workaround) I see in these comments is checking previous terraform state before doing a deploy as #17599 (comment) suggested, or perhaps not being very permissive with terraform's permissions through IAM. But I'd much rather a first class solution. There are multiple good (and seemingly easy) solutions that could be implemented here. I liked the Tombstone idea, or doing something like a Cloudformation Retain, or ensuring that the lifecycle is negated in the previous apply, or another terraform apply flag like Is HashiCorp not worried about this issue? |
@koreyGambill surprisingly dangerous, isn't it? I've automated Terraform CI/CD for 2 companies in 2 different ways for you to consider:
Even with this 2nd stronger option, there is still always the possibility of human error that somebody will approve without checking properly and it'll destroy something critical. For such critical data resources, you might have to keep them outside of Terraform until this issue is solved. |
Just adding a +1 to this. I'm really struggling to recommend Terraform to our clients for this reason. |
@Harrisonbro terraform is not perfect, but what is the better alternative that has no downsides of it's own? |
Nothing has no downsides, of course. We do recommend terraform for stateless resources that can be recreated, but for databases and such we have to recommend clients use other approaches (often just manual config) because they can't accept the risk of a Git commit wiping out data. |
The way we deal with this in our company is twofold:
|
There are undoubtedly many possibly workarounds. Indeed, where I work, we've resorted to patching terraform-provider-github to embed the feature at the provider level specifically for github_repo resources. However given the outpouring of supportive sentiment, @apparentlymart could you give us an update on your comment from 2018? |
I use delete protection and final snapshots, this prevents the DB from being deleted by mistake... |
@maxb any chance the patch to terraform-provider-github is open source? My org has the same use case and we don't want to reinvent the wheel. |
It is not (and I no longer work at that employer). However, the modern |
I made a proof-of-concept (#33229) to implement storing the flag in the state. You can try it using: git clone https://github.com/WATonomous/terraform.git
git checkout prevent_removal
go install . and using the |
This is very surprising behaviour IMO. I'd have expected the policy to be stored in state and applied in all destroy contexts. Does anyone actually want it to apply only part of the time? Having a second similar policy will add confusion; maybe then the original should be deprecated? |
It would be better for Hashicorp to just fix the behaviour of |
The documentation for prevent_destroy says
However, removing or commenting out a resource seems to still destroy it with no warning, even though technically it was a plan that includes the destruction of the resource. What I expected was that the state file would remember that it was created with prevent_destroy, and prevent its destruction even if it was no longer part of the parsed configuration. It would be reasonable to expect that the user would be forced to remove the prevent_destroy flag, terraform apply, then remove it from the configuration if they were absolutely sure they wanted to go ahead.
Terraform Version
Terraform Configuration Files
Expected Behavior
Resource is prevented from being destroyed because it was created with lifecycle { prevent_destroy = true }
Actual Behavior
Resource with prevent_destroy set to true is destroyed when commenting out or removing from configuration.
Steps to Reproduce
Additional Context
References
The text was updated successfully, but these errors were encountered: