rage icon indicating copy to clipboard operation
rage copied to clipboard

rage-mount but more like overlayfs

Open benjojo opened this issue 3 years ago • 7 comments

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!

benjojo avatar Jan 12 '21 16:01 benjojo

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.

FiloSottile avatar Jan 12 '21 16:01 FiloSottile

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 and foo.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" as foo.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?

str4d avatar Jan 12 '21 23:01 str4d

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.

FiloSottile avatar Jan 12 '21 23:01 FiloSottile

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...

str4d avatar Jan 13 '21 00:01 str4d

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).

str4d avatar Jan 13 '21 04:01 str4d

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.

str4d avatar Jan 13 '21 18:01 str4d

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.

str4d avatar Feb 06 '21 23:02 str4d