-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Make restic work without permission to delete files on GCS #1544
Comments
Hey, thanks for raising this issue. The Is it maybe an option to grant the service account deletion on the Or backup to a local directory, and then use e.g. |
That is not possible in GCS. |
@fd0 restic backup with --no-lock works here though and i'm deleting everything under /locks after a few hours automatically.
no, that's not posible because of size constraints. |
@gebi "it works" means restic does not return an error when you specify I understand your use case, but I must say that I'm very reluctant to add support for How do you make sure that there's no |
@fd0 The service account used by restic is simply not allowed to delete files on the GCS bucket. So a collision between those two commands is not possible. IMHO it would be a very important property and worthwhile goal to support GCS as a tamper-proof storage in restic because intruders more often than not go on and delete everything they can find including backups, with a service account with full delete/rewrite permissions the backup is effectively worthless. @fd0 but as you said, there should be a warning printed that there is a possibility for data corruption if some priviledged account executes ah... and |
@fd0 Any idea to my suggestion? Supporting tamper proof backups in restic would be awesome as pretty few backup systems support such a mode and it is a property you nearly always want. As for parallel prunes, why not use a two-phase "commit' for prunes? |
See #1141 for lock-less prune discussion. |
@ifedorenko yes, i've read the discussion, but as already mentioned there the |
I was merely suggesting to discuss lock-free prune in #1141, so we have all ideas in one place. |
I've decided to not add support for |
@fd0 that's unfortunately as we really require the functionality for WORM backups (write once read many), and most backup users do so too, they just don't realize it, or only after their first compromise where most backups are then deleted too. I've forked restic and made the first release of restic-worm that we have to use and will keep up to date to your upstream restic as it makes sense for our usecase. https://github.com/mgit-at/restic/tree/v0.8.3-worm |
@gebi I can understand your use case and what you're trying to do. In my opinion, just adding the small patch to allow In general, the pruning process is not optimal, and even using lock files is unfortunate, especially for your use case. It was what I came up with during the initial design phase, and it's the simplest to implement. We will change it and move to something better in the long run, for sure. I agree that a fork is unfortunate and won't help us both, even if it is only the added I'm very interested in your results of working with 10PB within a restic repo, that's awesome! |
@fd0 hmm... the more i think about that the more i came to the conclusion that maybe we should just refuse to allow restic prune on such backends receiving snapshots with no-lock. So why not let the If the user want's to prune such storage backends he has to ensure no one is writing to it concurrently, which is totally fine for the intended usecase. If we get #1141 into usable shape that might lift that restriction later on, but for now i would be totally fine to restrict it, it would just be awesome to have the functionallity for writing with snaphots to WORN GCS buckets in upstream. would this path work for you? |
I assume you mean For other operations (such as |
@fd0 yea i meant And for operations such as |
Hm. Maybe we can really do that: Not exit with an error if the lock file could not be removed. That'd work in most cases, especially in the ones you're interested in. |
Yea that would be awesome! btw... the current behaviour is a loop with error output where restic can't be killed normally but only with |
Uh, that's not good, thanks for pointing it out again. |
I think you should be able to add full write and delete permissions only for the lock folder by using ACL's: I did not test it myself though and could be mistaken. |
@lukastribus it would be awesome if that works, but it doesn't. There is no "folder" lock/ to put ACLs on it, google cloud storage buckets don't work like that, sorry. |
@fd0 any news on the feature "Hm. Maybe we can really do that: Not exit with an error if the lock file could not be removed. That'd work in most cases, especially in the ones you're interested in." It would be really awesome if you could add this to restic, would make our life a whole lot easier and it would IMHO be a worthwhile addition. |
What if it was a specific exit code? It could be useful to know that there's a stale lock in the repo... |
Nope, no news unfortunately. I don't have much time at the moment, so somebody needs to actually do the work here and build a prototype ;) One small issue which isn't mentioned here (as far as I can see) is that when long-running operations such as
Good point, hm. |
The base of this discussion is making the @fd0 what would be your preferred way? i've submitted the patch we are using on top of restic (which was thankfully provided by you, i've just rebased it to master). #1917 |
Maybe another way could be option of having lock files stored separately (for example in a bucket that you DO have write access to)? I wonder what everyone else does to resolve this security situation? If backuping machine gets compromise how do you make sure attacker does not just delete all the backups? |
I'm running into this same issue as well. I have no need to (and because of data requirements can't) prune backups. Running backup --no-lock would be the perfect solution for me. Is there a viable workaround out there? |
@parkerp1 We're using effectively the method suggested here, which is to have restic talking to two copies of rclone fronted by tinyproxy, and having one read/write bucket for the lock files and one write-only bucket for the data. The article is about Wasabi, but the back end is irrelevant and we're using it with GCS. While not particularly clean, Dockerizing this solution helps to hide the complexity. |
@parkerp1 we are still using a small patch on top of restic https://github.com/mgit-at/restic/tree/backup-nolock to backup a few hundred TB of data. Works like a charm. |
I agree with @fd0 that adding a Instead perhaps on init there could be an alternate lock file location specified (with the fact that an alternate lock location is being used stored in the original repo). Then any command that is invoked and forgets to specify the alternate lock location could fail (e.g. "error: repo uses alternate lock location and no alternate location given"). The commands would also fail if an alternate lock location was provided but the original repo wasn't setup to use an alternate lock location. This would make the advanced behavior possible and also keep the regular commands pretty foolproof for those not using the advanced behavior. |
Two options off the top of my head:
|
Another approach would be to use object versioning. With that enabled, deletions may be allowed for the service account used by restic as they only actually add deletion markers to the version history. Only permission for the DeleteObjectVersion action must be refused in order to prevent an attacker from doing permanent damage. |
@fd0 Would an environment variable ala |
No, I don't think so. I've outlined in #1544 (comment):
|
Sounds like this 95% works, just runs into a small bump at the end. If there was a way to get around cleaning up this lock file after completing the backup, this approach to immutable backups based on lack of deletion privilege would work, and restic would not even need to know/do anything to support immutability. #1141 and https://gist.github.com/fd0/d24abf8301724988919c80e65aba9b6d describe some ideas for operation without locks, but in the context of this issue (the cloud storage credential stored on the system does not have delete privilege, effectively achieving immutable backups if an attacker compromises the server), couldn't locking be implemented in an alternative way that works on immutable storage? Instead of creating a lock file and then removing it when done, restic could create a lock file (named with some ID, e.g. Anyway this should be considered in the larger context of immutable backups and potential lock-free operation. |
Another workaround for this is: https://www.howtoforge.com/economical-append-only-offsite-backups-with-restic-and-wasabi-debian/ It relies on having 2 buckets (an immutable one for data and a regular one for locks), running a local rclone server as a gateway, and a local tinyproxy server to alternate between the regular and immutable buckets depending on whether a data file or lock file needs to be written, which is a lot of extra hoops to jump through. Another alternative is: https://blog.heimsbakk.net/posts/20190911-restic/ So it would be nice if restic could natively support an approach to locking that would work on immutable storage , if possible. |
When backing up to a storage backend that permits deletion of files, there is no risk that a So the best solution would be to enable the if !gopts.JSON {
p.V("lock repository")
}
lock, err := lockRepo(gopts.ctx, repo)
defer unlockRepo(lock)
if err != nil {
return err
} to if !gopts.NoLock {
if !gopts.JSON {
p.V("lock repository")
}
lock, err := lockRepo(gopts.ctx, repo)
defer unlockRepo(lock)
if err != nil {
return err
}
} The only point here is: If we allow this, how many bug reports from users do we get who end up using this option in unsafe environments (for whatever reason...)? And the locks also ensure that |
Kudos for creativity but this has to be the most complicated solution one can think of. 😉 A single bucket and this policy should be enough for append-only backups with restic and Wasabi (or other compatible backends). It allows to add (and read) all objects but disallows to remove any objects except within the
|
Nice, good to know there is a way to do that with some S3-compatible APIs. |
Would it help if perhaps the option is instead enabled at the repository level, when you do |
There is almost no config saved on the repository level, so this would mean changing the repo format... I would rather allow the An interesting fact is that But in fact it's not a question about the implementation which is easy, but about directions from the maintainers if restic should be able to solve this problem and if in which way. |
Could we use the approach of manually creating a file in the lock folder with a special name suck as WRITEONLY.LOCK. Restic could check for the existence of such a file prior to creating any locks, and if a file with such a name exists, treats the repository as write only, allowing backup and restore but not prune or any other operation that would require deletions. This in practice would remove the prune flag for such a repository, until the special lock file is manually removed at which point restic would use the normal locking mechanism for any operations. |
Wouldn't it be possible on GCS to let restic just hide files and cleanup old ones with a lifecycle policy as e.g. on B2 #2134 ? |
FWIW, rustic implements a completely lock-free pruning. As a consequence, there are no lock files needed and thus not created/deleted by rustic. This makes this problem vanish: If you don't have the permissions to delete files, you can still backup to a repository (this only adds new pack/index/snapshot files). |
@aawsome What happens if two prune tasks run in parallel? Are they going to delete not indexed files created by the other prune instance? And without a session concept (aka. something similar to lock files), pruning will have to rely on guesswork whether there are long-running backup tasks etc. that are still in progress. |
No. The prune is done two-phase, i.e. packs are marked for removal but still exist (even in the index where there is an extra section for those marked pack files.) So, unindexed files are marked for removal but only removed (by a future prune run) if they are marked long enough and are still not needed after that time.
This is true. The "long enough" which I wrote before must be long enough such that all parallel runs creating or relying on existing files are finished. rustic allows to define a user-provided time interval and defaults to 23h. |
any plans for this feature? |
Output of
restic version
restic 0.8.1
compiled with go1.9.2 on linux/amd64
How did you run restic exactly?
export GOOGLE_PROJECT_ID=xxx
export GOOGLE_APPLICATION_CREDENTIALS=
restic --no-lock -p -r gs::/ ~/doc
password is correct
scan [/home/gebi/doc]
scanned 1852 directories, 5764 files in 0:00
Remove(<lock/991ceef8fd>) returned error, retrying after 424.215262ms: client.RemoveObject: googleapi: Error 403: SERVICE-ACCOUNT does not have storage.objects.delete access to /locks/991ceef8fd55609bb08303bf43c637d12de122800627e71492d10be6474334f0., forbidden
What backend/server/service did you use to store the repository?
GCS (google cloud storage bucket)
Expected behavior
not creating lock files when called with --no-lock, because the service account has actually no permission to delete objects in the GCS bucket.
Actual behavior
restic creates lock files which is then not able to delete.
The backup is successfully created, but restic hangs on deleting the lock file needing a kill. (strg+c does not work)
Steps to reproduce the behavior
Create GCS bucket and service account with service account having only the following permissions in the bucket:
Do you have any idea what may have caused this?
yes, missing permissions and --no-lock which creates lock files
Do you have an idea how to solve the issue?
not create lock files :)?
Did restic help you or made you happy in any way?
AWESOME tool, i use it daily, especially since GCS support was added (thx again for the effort!).
We are currently testing the new permissions in GCS and try to get a setup where the local machine is not able to delete it's own backups anymore.
(GC not working is a non-issue in this case for me).
The text was updated successfully, but these errors were encountered: