Skip to content
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

rage-mount but more like overlayfs #188

Open
benjojo opened this issue Jan 12, 2021 · 7 comments
Open

rage-mount but more like overlayfs #188

benjojo opened this issue Jan 12, 2021 · 7 comments

Comments

@benjojo
Copy link

benjojo commented Jan 12, 2021

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!

@FiloSottile
Copy link
Contributor

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.

@str4d
Copy link
Owner

str4d commented Jan 12, 2021

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?

@FiloSottile
Copy link
Contributor

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.

@str4d
Copy link
Owner

str4d commented Jan 13, 2021

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
Copy link
Owner

str4d commented Jan 13, 2021

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 added a commit that referenced this issue Jan 13, 2021
This behaves similarly to `mount --bind source_file target_file`, except
that `source_file` is transparently decrypted, and `target_file` is
created as a symbolic link instead of a bind-mount.

Part of #188.
str4d added a commit that referenced this issue Jan 13, 2021
This behaves similarly to `mount --bind source_file target_file`, except
that `source_file` is transparently decrypted, and `target_file` is
created as a symbolic link instead of a bind-mount.

Part of #188.
@str4d
Copy link
Owner

str4d commented Jan 13, 2021

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
Copy link
Owner

str4d commented Feb 6, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants