rage
rage copied to clipboard
rage-mount but more like overlayfs
This is a feature request/change to rage-mount.
Problem space:
I have a set of directories that are full of encrypt tar.gz / tar / zip files:
# ls -alh
total 58G
drwxr-xr-x 1 root root 4.0K Jan 11 23:00 .
drwxr-xr-x 1 root root 4.0K Dec 23 14:13 ..
-rw-r--r-- 1 root root 1.8G Nov 11 22:23 xxxxxxxxxxxxxxxxxxxxxx.zip.age
-rw-r--r-- 1 root root 976M Nov 11 22:21 xxxxxxxxxxxxxxxxxxx.zip.age
-rw-r--r-- 1 ben ben 2.0G Nov 11 22:17 xxxxxxxxxxxxxxx.tgz.age
-rw-r--r-- 1 root root 12G Nov 12 00:10 xxxxxxxxxxxxxxxx.tgz.age
-rw-r--r-- 1 root root 24G Jan 11 20:13 xxxxxxxxxxxxxxxx.age
I would like to open these tar.gz / zip files natively, without having to teach tools like file-roller how to decrypt the age wrapper.
I noticed rage-mount
exists, and it's sort of close to what I would want, except I don't want mount the actual files, I would prefer an overlay FS instead that just decrypts the files transparently, and leaves non age files around.
So in my above example, the overlay directory would look like:
# ls -alh
total 58G
drwxr-xr-x 1 root root 4.0K Jan 11 23:00 .
drwxr-xr-x 1 root root 4.0K Dec 23 14:13 ..
-rw-r--r-- 1 root root 1.8G Nov 11 22:23 xxxxxxxxxxxxxxxxxxxxxx.zip
-rw-r--r-- 1 root root 976M Nov 11 22:21 xxxxxxxxxxxxxxxxxxx.zip
-rw-r--r-- 1 ben ben 2.0G Nov 11 22:17 xxxxxxxxxxxxxxx.tgz
-rw-r--r-- 1 root root 12G Nov 12 00:10 xxxxxxxxxxxxxxxx.tgz
-rw-r--r-- 1 root root 24G Jan 11 20:13 xxxxxxxxxxxxxxxx
So I can then use other tools easily, obviously this only has to be read only. In fact it's preferable to be that way!
I think this would be cleaner implemented as an individual file mount, so that the whole directory doesn't have to be implemented with the same key, and so that the fuse filesystem doesn't have to proxy plaintext files.
It should also match the rage-mount CLI better, as the input would still be a single age file.
I can see a benefit for both kinds of approaches, and technically both could work in rage-mount
. I intended its UX to basically be close to mount
for familiarity, so while its current API is:
rage-mount [-i IDENTITY] -t TYPE AGE_FILE MOUNT_DIR
it could be generalised to:
rage-mount [-i IDENTITY] [-t TYPE] AGE_FILE|MOUNT_DIR
rage-mount [-i IDENTITY] [-t TYPE] AGE_FILE MOUNT_POINT
for parity with:
mount [-o options] device|dir
mount [-o options] [-t fstype] device dir
I'm also amenable to keeping rage-mount
focused on a single file, and instead doing:
rage-mount [-i IDENTITY] -t TYPE AGE_FILE [MOUNT_POINT]
where omission of MOUNT_POINT
triggers a bind mount on the same file. UX suggestions absolutely welcome!
Bind mounts
This would require an explicit user action to enable, but once done there would be a file object that could be read like any other. Main question is how the file object should be presented:
- Alongside the age file (i.e. you see both
foo.zip.age
andfoo.zip
in the directory listing) - Replacing the age file (i.e. you see
foo.zip.age
but while the mount is active its contents is plaintext) - Hide the age file (i.e. you see only
foo.zip
until you stop the mount)- I'm not sure whether this can be done without an OverlayFS
OverlayFS approach
I think the ideal UX for this would be that you have some write-through process that you configure with:
- the set of identities you are willing to decrypt age files with.
- the filesystem subtree you are willing to have this behaviour occur under (which could be the root).
Then any time you go to interact with any age file in that subtree, the write-through process intercepts it and attempts a decryption (which ideally then pops up a pinentry
window requesting a passphrase or a YubiKey PIN). The process could cache successful decryptions for some (potentially configurable) period of time since last access.
The main design decision here (I think) is how the filenames are presented:
- Always show as
foo.zip.age
but have the (decryptable) files return their plaintext bytes.- This makes it clear when you are reading an encrypted file vs a plaintext file, but the extensions are all wrong.
- Show as
foo.zip.age
until first successful decryption, then "rename" asfoo.zip
- IDK how this would even work nicely with path-based APIs.
- Always show as
foo.zip
- This makes interop with other tools easy (extensions will trigger the correct behaviour), but makes it non-obvious in the filesystem which files are encrypted. Is there a way to leverage FS attributes to cause e.g. file explorers to show annotations?
Oh, I was thinking of keeping the mount point explicit, which bypasses all of the choices above and fits in the current CLI as-is.
rage-mount [-i IDENTITY] -t file foo.age foo
mount
only works with a single device|dir
argument when the other is already specified in a config file, so there is no precedent to get an expected behavior for rage-mount foo.age
without a target.
rage-mount [-i IDENTITY] -t file foo.age foo
Yep, this matches what I was envisaging as a bind-style mount alongside the age file. It's also probably the easiest to get going...
LOL NOPE
Mounting an age file inside a single-file FUSE filesystem was relatively easy. However, I cannot get a bind mount to work from that fuse FS to the target mount point. And even if I could, bind mounts require root. (Tools like bindfs emulate bind mounts via FUSE, and similarly only support directories).
I decided to give up on bind-mount, and instead just use a symbolic link (that I clean up on exit). This is implemented in #190.
UX notes:
- Use command symlinks for the three cases:
- Encrypted archive to tree
- Encrypted file to unencrypted file
- Directory tree containing encrypted files, to transparent tree with unencrypted files
For dir-to-dir:
- If we detect an age file and can't decrypt it with a given identity, print a warning.
- Warn and ignore passphrase-encrypted files.
- Batch decryptions per-folder to enable caching for e.g. YubiKeys.