canonical / lxd

Powerful system container and virtual machine manager
https://canonical.com/lxd
GNU Affero General Public License v3.0
4.39k stars 930 forks source link

Encrypt container #2118

Open eumel8 opened 8 years ago

eumel8 commented 8 years ago

I want to store some confidential data into container and looking for a feature to encrypt them. Workaround would be 'lxc config device add' but I want encrypt the whole container. Feasible or not?

stgraber commented 8 years ago

Not trivially until we have per-container storage.

What I typically do is have a path on my host which is encrypted (usually using LUKS) and that I then bind-mount into my container. But that doesn't encrypt the entire container, just whatever paths you want.

You could manually set up a mount for your container rootfs on /var/lib/lxd/containers/NAME/rootfs which LXD would then use, but that'd likely break a bunch of features like container migration, publishing, snapshots, file transfer, ...

eumel8 commented 8 years ago

thanks for the hints, but that's not similar to hold the data in the container (instead providing them). I would like to migrate the container or export them as an image to colleagues. Other idea: using gpg and inject the key with

lxc config device add mycontainer sharedgpg disk  path=/home/user/.gnupg source=/home/user/.gnupg

but that's not so comfortable.

stgraber commented 8 years ago

You may be able to use ecryptfs from inside the container, that or if you're running on the Ubuntu 4.4 kernel, you may be able to turn on unprivileged fuse mounts and then do the encrypted layer through a fuse filesystem in the container.

Other than that, you'd indeed be left with pure userspace solutions like gpg.

eumel8 commented 8 years ago

Okay, l'll try ecryptfs. That could work for me. Otherwise, someday I want to have the feature in LXD. You can close the issue or mark as feature request. as you like.thx!

naisanza commented 8 years ago

@stgraber I just tried mounting an ecryptfs directory inside a container, but haven't gotten it to work, yet

All I've tried so far are from these sources, 1 and 2:

Editing, and reloading, /etc/apparmor.d/lxc/lxc-default:

mount options=(rw, bind),
mount fstype=(ecryptfs),

After reloading apparmor I still get this error message:

Exiting. Unable to obtain passwd info

The closest I can get to is the line that generates the error message from mount.ecryptfs.c https://github.com/dustinkirkland/ecryptfs-utils/blob/master/src/utils/mount.ecryptfs.c#L555

    pw = getpwuid(getuid());
    if (!pw) {
        fprintf(stderr, "Exiting. Unable to obtain passwd info\n");
        rc = -EIO;
        goto out;
    }

I'm hoping it doesn't have to be run in privileged mode, as answered in an identical Docker question: https://answers.launchpad.net/ubuntu/+source/ecryptfs-utils/+question/269753

varks (var-kulkarni) said on 2015-07-28:    #1
need to run docker in privileged mode.
prasannashah1 commented 7 years ago

issue on encrypting whole container as we encrypt physical ubuntu server

RAOF commented 5 years ago

With ZFS-native encryption coming in the not-too-distant future (zfslinux 0.8.0-rc3 was released a couple of months ago, and the 0.8 rc series contain the encryption work), this could reasonably be implemented as a feature of the zfs storage backend. Indeed, you can actually do this now (I've got an LXD instance with the storage on a zfs-encrypted dataset), but it would be convenient for LXD to have some idea about the encryption - to be able to ask for encryption keys on container start, for example, rather than freaking out that the storage is unreadable.

stgraber commented 5 years ago

Been thinking a bit about this issue lately. In theory we could do something with:

btrfs and cephfs would be left without support for now anyway.

The main issue we have is with the interactive prompting for key material as LXD does a lot of filesystem operations at various times and it would be very impractical to have all those calls suddenly start blocking and having to come up with a way to prompt through the client.

Instead, my current thinking is that we could have a /1.0/instances/NAME/keyring endpoint where key material can be pushed by the client. So the storage of the container would effectively be tied to a key id and that key id is then expected to be found in the container keyring, if it's not there, the operation fails immediately.

The API would let you discover what keys a particular container requires and whether they have been set. It obviously would not let you read them back once set and their value would remain in memory on the server side. Keyring entries would also have an expiry so that they can be flushed from memory after some time.

With this in place, calls to operations which require missing key material would return an error indicating what key is missing from the keyring. For common operations, the CLI could also pull the list of keys missing for a given container and prompt the user ahead of performing the requested operation.

It should also be possible to share keys within a project such that all containers are effectively encrypted using the same key. And we should probably also allow for multiple keys to be valid, allowing for implementation of standard company policies in that regard.

I would expect keys to be either plain text PSK or some kind of blobs, depending on what's allowed by the technology used.

Migration is one aspect that may get a bit funny with all that though. We don't transfer block data and instead rely on rsync for most of our migration story. ZFS could transfer encrypted data in theory but we'd have to see how this would work in practice with key management on the target.

markstos commented 4 years ago

@stgraber I like the API idea. Of the options you mentioned for encryption ZFS seems like the best fit and is I believe already the default storage backend of LXD.