morph icon indicating copy to clipboard operation
morph copied to clipboard

Feature Request: Support for decrypting encrypted secrets at deploy-time

Open Shados opened this issue 7 years ago • 3 comments

I'd like to be able to keep secrets (say, SSH keys) in the same git repo with my host deployment configuration files, but right now that means I have to either manually manage decrypting them prior to any upload-secrets run (and cleaning up the temporarily decrypted files), or write a wrapper of some kind that does the same.

This isn't all that hard to do*, but it would be much better to have support for deploy-time secrets decryption baked in (ala Ansible Vault, say).

Some options that would be nice to have:

  • Decrypt with passphrase(s)
  • Decrypt with keyfile(s)
  • Request secrets from a secrets server (e.g. a HashiCorp Vault instance)

*: For anyone interested, I'm currently playing with a shell.nix that uses cryfs to mount a directory of encrypted secrets.

Shados avatar Nov 22 '18 06:11 Shados

@Shados Maybe you could use post-secret-upload-actions for implementing custom decryption steps? (https://github.com/DBCDK/morph/blob/master/examples/secrets.nix#L23). I'm aware that these commands are not executed interactively, so prompting for a passphrase might be difficult, but since you're in an active SSH-session, you could argue that you've already auth'ed through SSH.

Regarding keyfiles: Since an uploaded secret is already a keyfile, I don't see the difference? Wouldn't you need to encrypt the keyfile as well then? Secrets can originate from any location on the deploying host. Could be an encrypted partition (sounds like you're already working on that), or it could be a designated git submodule for secrets. Maybe we should consider supporting:

  • URL-scheme source syntax? (like https://secrets.example.com/secret.file)
  • Environment variables (like VAULT_TOKEN)
  • or even a way of asking morph to prompt for a secret?

Regarding Vault integrations: Until we have some way to install extensions or plugins in morph, I'd very much prefer to keep features as generic as possible. If you can come up with an implementation that can work for multiple Vaults or decryption schemes, then please PR. :-)

If I were you, I'd consider doing something like this:

{
    deployment = {
      secrets = {
        "vault-token" = {
          source = /path/to/vault/token;
          destination = "/var/secrets/vault.token";
          owner.user = "root";
          owner.group = "root";
          permissions = "0400";
          action = ["sudo" "systemctl" "start" "fetch-vault-secrets-oneshot.service"];
        };
      };
}

johanot avatar Nov 22 '18 09:11 johanot

I'm fine waiting on a plugin/extension mechanism before any of these options happen, primarily I'm bringing it up because it is something that would be needed by a decent chunk of potential users, at some point.

In the meantime, I'll post a small example of my cryfs setup, once I've cleaned it up a bit...


Regarding post-secret-upload-actions: these are executed on the deployment targets, so among other things they'd have to phone-home back to the machine running morph in order to get the decryption passphrase. Not impossible, and you could make use of SSH agent forwarding perhaps, but problematic from my perspective.


Regarding why someone might want to use a separate keyfile to decrypt secrets: you can store a keyfile on a separate physical device, which is arguably easier to manage than a passphrase. Which reminds me: add decryption by smart card/token to the list ^^.

More generally, my goal in having a separate secret-encrypting-secret is to keep everything that contributes to the final deployment configuration state in a single controlled location, like a git repo. Secrets that end up on the deployed systems certainly count, but a secret used to decrypt those secrets pre-deployment does not.

The separation between the two somewhat eases the operational burden of simultaneously keeping my secrets safe and keeping them in sync with configuration, because those two responsibilities are separated out. The encrypted secrets stay naturally in sync with my configuration because they are stored with it, and stay protected because they are only exposed at the time and point of use.

Of course, the configuration repo potentially ending up exposed some day would still be a security issue, but one less catastrophic than if, say, SSH host keys were in it as plaintext :).


Regarding cryfs: it is actually not a partition encryption scheme, it's a layered FUSE filesystem that stores data mounted in it as files in a folder on an arbitrary other filesystem. This makes it a decent fit for keeping encrypted data inside a git repository.

It's rather new, and there have not yet been any independent audits, but reading the developer's master's thesis and subsequent paper on it were sufficient to convince me that the design is sound (...not that my opinion is trustworthy on this; I'm no cryptographer).

Shados avatar Nov 22 '18 11:11 Shados

Here's the aforementioned Morph + cryfs example.

Shados avatar Nov 26 '18 04:11 Shados