Skip to content

Commit

Permalink
Added a keyCmd option for fetching a key from local command
Browse files Browse the repository at this point in the history
`deployment.keys.*.keyCmd` option executes a command on the local
machine and sends its output as a key to the remote machine.

The use-case is storing NixOps secrets in encrypted form using,
e.g. password-store.

note: rebased and updated against master, and removed a bit of code
around storeKeysOnMachine since that feature no longer exists.

Co-authored-by: Adam Höse <adam.hose@tweag.io>
Co-authored-by: Graham Christensen <graham.christensen@tweag.io>
  • Loading branch information
3 people authored and grahamc committed May 15, 2020
1 parent 907274d commit 6f89831
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
41 changes: 32 additions & 9 deletions nix/keys.nix
Expand Up @@ -15,11 +15,33 @@ let
<filename><replaceable>destDir</replaceable>/<replaceable>password</replaceable></filename>
will be <literal>foobar</literal>.
NOTE: Either <literal>text</literal> or <literal>keyFile</literal> have
to be set.
NOTE: Either <literal>text</literal>, <literal>keyCmd</literal> or
<literal>keyFile</literal> have to be set.
'';
};

options.keyCmd = mkOption {
default = null;
example = "pass show secrettoken";
type = types.nullOr types.str;
description = ''
When non-null, output of this command run on local machine will be
deployed to the specified key on the target machine. If the key name
is
<replaceable>password</replaceable> and <literal>echo secrettoken</literal>
is set here, the contents of the file
<filename><replaceable>destDir</replaceable>/<replaceable>password</replaceable></filename>
deployed will equal the output of the command <literal>echo secrettoken</literal>.
This option is especially useful when you don't want to store the secrets
inside of your NixOps deployment but rather in a well-guarded place such as an
encrypted file. Consider using nixpkgs.password-store as storage for
such sensitive secrets.
NOTE: Either <literal>text</literal>, <literal>keyCmd</literal> or
<literal>keyFile</literal> have to be set.
'';
};
options.keyFile = mkOption {
default = null;
type = types.nullOr types.path;
Expand All @@ -36,8 +58,8 @@ let
are no limits on that content: null bytes, invalid Unicode,
<literal>/dev/random</literal> output -- anything goes.
NOTE: Either <literal>text</literal> or <literal>keyFile</literal> have
to be set.
NOTE: Either <literal>text</literal>, <literal>keyCmd</literal> or
<literal>keyFile</literal> have to be set.
'';
};

Expand Down Expand Up @@ -155,11 +177,12 @@ in

config = {

assertions = flip mapAttrsToList config.deployment.keys (key: opts: {
assertion = (opts.text == null && opts.keyFile != "") ||
(opts.text != null && opts.keyFile == "");
message = "Deployment key '${key}' must have either a 'text' or a 'keyFile' specified.";
});
assertions = (flip mapAttrsToList config.deployment.keys (key: opts: {
assertion = (opts.text == null && opts.keyFile != "" && opts.keyCmd == null) ||
(opts.text != null && opts.keyFile == "" && opts.keyCmd == null) ||
(opts.text == null && opts.keyFile == "" && opts.keyCmd != null);
message = "Deployment key '${key}' must have either a 'text', 'keyCmd' or a 'keyFile' specified.";
}));

system.activationScripts.nixops-keys =
let
Expand Down
8 changes: 6 additions & 2 deletions nixops/backends/__init__.py
Expand Up @@ -11,6 +11,7 @@
class KeyOptions(nixops.resources.ResourceOptions):
text: Optional[str]
keyFile: Optional[str]
keyCmd: Optional[str]
destDir: str
user: str
group: str
Expand Down Expand Up @@ -290,11 +291,14 @@ def send_keys(self) -> None:
).format(destDir)
)

if opts["text"] is not None:
if opts.get("text") is not None:
with open(tmp, "w+") as f:
f.write(opts["text"])
elif opts["keyFile"] is not None:
elif opts.get("keyFile") is not None:
self._logged_exec(["cp", opts["keyFile"], tmp])
elif opts.get("keyCmd") is not None:
with open(tmp, "w+") as f:
subprocess.Popen(opts["keyCmd"], stdout=f, shell=True)
else:
raise Exception(
"Neither 'text' or 'keyFile' options were set for key '{0}'.".format(
Expand Down

0 comments on commit 6f89831

Please sign in to comment.