Output of restic version
restic 0.9.2 (v0.9.2-1-g3c8bab2b-dirty) compiled with go1.11 on windows/amd64
(yes, I know, doesn't really matter though ;))
What should restic do differently? Which functionality do you think we should add?
The B2 back-end should use b2_hide_file instead of b2_delete_file_version to remove locks, and possibly for all file removals, or offer an option to enable such behavior.
What are you trying to do?
As many others who also created feature requests for similar suggestions, I want to prevent an attacker who succeeds in breaking into my system from deleting / corrupting my backup. One scenario is a manual attack, but it is also not unthinkable that a crypto trojan will be written to search for credentials of common cloud backup providers on machines that it infects.
This particular suggestion solves the problem in a manner specific to the B2 back-end. It may be superseded by a more general solution but is very simple. First some background though.
1. Versioning
B2 has a concept of file versions. API functions such as b2_list_file_names and b2_download_file_by_name only show you the current contents of directories and files, but previous versions of files as well as the contents of removed files may still be available through the use of b2_list_file_versions and b2_download_file_by_id. To make it clear that the file contents are not actually deleted and are still available through the versions API, the file remove operation is called "b2_hide_file". It is possible to set life-cycle rules to automatically delete these old versions after a given number of days, but any version (old or current) can also be deleted manually through b2_delete_file_version.
2. Permissions
In B2, permissions (capabilities) are set on a per-access-key-basis, and are fairly coarse-grained. Of particular interest here are the capabilities "writeFiles" and "deleteFiles". writeFiles allows the application key to write/overwrite/remove files, but not to delete anything from the version history. In particular, it does not allow b2_delete_file_version - the "deleteFiles" capability is needed for that.
In short, application keys without the deleteFiles capability cannot irrevocably destroy information from the bucket, since they cannot meddle with the version history.
3. Ok, so?
The versioning feature of B2 would allow me to protect my restic backup by only giving the automated backup an application key without the "deleteFiles" capability. However, restic currently uses the b2_delete_file_version call to delete locks, so this currently does not work without errors. This could be fixed though by deleting the locks with b2_hide_file instead - it would keep the lock around in the version history, but that should not really cause much bother since lock files are tiny, and you can set up your bucket to automatically delete hidden files after a while.
Maybe it would even be a good idea to embrace the versioning and replace all calls to b2_delete_file_version with b2_hide_file (from what I understand that would actually be much easier to implement). This way, B2 would keep a version history for all operations, which would even make it possible to use commands like prune and forget with restricted access keys, and to recover some earlier state of the bucket in case the repository gets corrupted.
Did restic help you or made you happy in any way?
Restic gives me peace of mind by safeguarding not just my data, but also that on my parents' PC. When they call about strange noises, weird popups and the thing not booting anymore at all, I can always calmly say: Relax, everything is backed up.
Output of
restic versionrestic 0.9.2 (v0.9.2-1-g3c8bab2b-dirty) compiled with go1.11 on windows/amd64
(yes, I know, doesn't really matter though ;))
What should restic do differently? Which functionality do you think we should add?
The B2 back-end should use b2_hide_file instead of b2_delete_file_version to remove locks, and possibly for all file removals, or offer an option to enable such behavior.
What are you trying to do?
As many others who also created feature requests for similar suggestions, I want to prevent an attacker who succeeds in breaking into my system from deleting / corrupting my backup. One scenario is a manual attack, but it is also not unthinkable that a crypto trojan will be written to search for credentials of common cloud backup providers on machines that it infects.
This particular suggestion solves the problem in a manner specific to the B2 back-end. It may be superseded by a more general solution but is very simple. First some background though.
1. Versioning
B2 has a concept of file versions. API functions such as b2_list_file_names and b2_download_file_by_name only show you the current contents of directories and files, but previous versions of files as well as the contents of removed files may still be available through the use of b2_list_file_versions and b2_download_file_by_id. To make it clear that the file contents are not actually deleted and are still available through the versions API, the file remove operation is called "b2_hide_file". It is possible to set life-cycle rules to automatically delete these old versions after a given number of days, but any version (old or current) can also be deleted manually through b2_delete_file_version.
2. Permissions
In B2, permissions (capabilities) are set on a per-access-key-basis, and are fairly coarse-grained. Of particular interest here are the capabilities "writeFiles" and "deleteFiles". writeFiles allows the application key to write/overwrite/remove files, but not to delete anything from the version history. In particular, it does not allow b2_delete_file_version - the "deleteFiles" capability is needed for that.
In short, application keys without the deleteFiles capability cannot irrevocably destroy information from the bucket, since they cannot meddle with the version history.
3. Ok, so?
The versioning feature of B2 would allow me to protect my restic backup by only giving the automated backup an application key without the "deleteFiles" capability. However, restic currently uses the b2_delete_file_version call to delete locks, so this currently does not work without errors. This could be fixed though by deleting the locks with b2_hide_file instead - it would keep the lock around in the version history, but that should not really cause much bother since lock files are tiny, and you can set up your bucket to automatically delete hidden files after a while.
Maybe it would even be a good idea to embrace the versioning and replace all calls to b2_delete_file_version with b2_hide_file (from what I understand that would actually be much easier to implement). This way, B2 would keep a version history for all operations, which would even make it possible to use commands like prune and forget with restricted access keys, and to recover some earlier state of the bucket in case the repository gets corrupted.
Did restic help you or made you happy in any way?
Restic gives me peace of mind by safeguarding not just my data, but also that on my parents' PC. When they call about strange noises, weird popups and the thing not booting anymore at all, I can always calmly say: Relax, everything is backed up.