From 52622ecd27b86f753053bcbb6327dfccc4e8a9fa Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Wed, 10 Feb 2021 18:08:47 -0800 Subject: [PATCH] Add 'deployment.keys..keyCommand' support Fixes #3. --- src/nix/eval.nix | 22 +++++++++++++++++----- src/nix/key.rs | 22 +++++++++++++++++++--- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/nix/eval.nix b/src/nix/eval.nix index 07c760a..d0756d0 100644 --- a/src/nix/eval.nix +++ b/src/nix/eval.nix @@ -103,7 +103,7 @@ let text = lib.mkOption { description = '' Content of the key. - Either `keyFile` or `text` must be set. + One of `text`, `keyCommand` and `keyFile` must be set. ''; default = null; type = types.nullOr types.str; @@ -111,12 +111,22 @@ let keyFile = lib.mkOption { description = '' Path of the local file to read the key from. - Either `keyFile` or `text` must be set. + One of `text`, `keyCommand` and `keyFile` must be set. ''; default = null; apply = value: if value == null then null else toString value; type = types.nullOr types.path; }; + keyCommand = lib.mkOption { + description = '' + Command to run to generate the key. + One of `text`, `keyCommand` and `keyFile` must be set. + ''; + default = null; + type = let + nonEmptyList = types.addCheck (types.listOf types.str) (l: length l > 0); + in types.nullOr nonEmptyList; + }; destDir = lib.mkOption { description = '' Destination directory on the host. @@ -190,11 +200,13 @@ let else pkgs; evalConfig = import (npkgs.path + "/nixos/lib/eval-config.nix"); assertionModule = { config, ... }: { - assertions = lib.mapAttrsToList (key: opts: { - assertion = (opts.text == null) != (opts.keyFile == null); + assertions = lib.mapAttrsToList (key: opts: let + nonNulls = l: filter (x: x != null) l; + in { + assertion = length (nonNulls [opts.text opts.keyCommand opts.keyFile]) == 1; message = let prefix = "${name}.deployment.keys.${key}"; - in "Exactly one of `${prefix}.text` and `${prefix}.keyFile` must be set."; + in "Exactly one of `${prefix}.text`, `${prefix}.keyCommand` and `${prefix}.keyFile` must be set."; }) config.deployment.keys; }; in evalConfig { diff --git a/src/nix/key.rs b/src/nix/key.rs index 2cf637a..93217c4 100644 --- a/src/nix/key.rs +++ b/src/nix/key.rs @@ -1,11 +1,16 @@ use std::{ io::{self, Cursor}, path::{Path, PathBuf}, + process::Stdio, }; use regex::Regex; use serde::{Deserialize, Serialize}; -use tokio::{fs::File, io::AsyncRead}; +use tokio::{ + fs::File, + io::AsyncRead, + process::Command, +}; use validator::{Validate, ValidationError}; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -44,8 +49,19 @@ impl Key { KeySource::Text(content) => { Ok(Box::new(Cursor::new(content))) } - KeySource::Command(_command) => { - todo!("Implement keyCommand support") + KeySource::Command(command) => { + let pathname = &command[0]; + let argv = &command[1..]; + + let stdout = Command::new(pathname) + .args(argv) + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .spawn()? + .stdout.take().unwrap(); + + Ok(Box::new(stdout)) } KeySource::File(path) => { Ok(Box::new(File::open(path).await?))