From 1c187f51474a049750819d2bcfeada9844df7223 Mon Sep 17 00:00:00 2001 From: oluceps Date: Mon, 4 Nov 2024 21:49:51 +0800 Subject: [PATCH] + interface optimization ~ trival improv --- README.md | 28 ++++++++++++++++------------ module/default.nix | 35 ++++++++++++----------------------- src/cmd/deploy.rs | 2 +- src/cmd/renc.rs | 21 +++++++-------------- src/helper/parse_identity.rs | 17 +++++++++-------- src/profile.rs | 8 ++++---- 6 files changed, 49 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 88ea4e2..abf8978 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ outputs = inputs@{ flake-parts, self, ... }: inputs.vaultix.url = "github:oluceps/vaultix"; ``` +Adding nixosModule config: + ```nix # configuration.nix { @@ -50,13 +52,14 @@ inputs.vaultix.url = "github:oluceps/vaultix"; settings = { # relative to flake root, used for storing host public key - # re-encrypted secrets. - storageDirRelative = "./secret/renc/${config.networking.hostName}"; - # extraRecipients = [ data.keys.ageKey ]; # not supported yet - masterIdentities = [ + storageLocation = "./secret/renc/${config.networking.hostName}"; + # extraRecipients = + # not supported yet, plain to used in edit command + # [ data.keys.ageKey ]; + identity = # See https://github.com/str4d/age-plugin-yubikey - # Also supports age native secrets - (self + "/secret/age-yubikey-identity-0000ffff.txt.pub") - ]; + # Also supports age native secrets (with password encrypted) + (self + "/secret/age-yubikey-identity-0000ffff.txt.pub"); }; secrets = { example = { @@ -65,7 +68,8 @@ inputs.vaultix.url = "github:oluceps/vaultix"; owner = "root"; group = "users"; name = "example.toml"; - # path = "/some/place"; # not supported yet + # symlink = true; # both not supported yet + # path = "/some/place"; }; # ... }; @@ -74,15 +78,15 @@ inputs.vaultix.url = "github:oluceps/vaultix"; ``` > [!TIP] -> During first setup, you need to manually create `storageDirRelative` and +> During first setup, you need to manually create `storageLocation` and > add it to git (create an placeholder since git ignores empty directory). ```bash -mkdir -p ./secret/renc/YOUR_HOSTNAME_HERE -touch ./secret/renc/YOUR_HOSTNAME_HERE/.placeholder -# so that you could add the directory to git (for recognizing by flake) +mkdir -p ./secret/renc/HOSTNAME_HERE +touch ./secret/renc/HOSTNAME_HERE/.placeholder +# So that you could add the directory to git (for recognizing by flake). git add . -# after this step you could remove placeholder +# Freely could remove placeholder once complete this step. nix run .#vaultix.x86_64-linux.renc ``` diff --git a/module/default.nix b/module/default.nix index 1ca031a..22c25fc 100644 --- a/module/default.nix +++ b/module/default.nix @@ -28,23 +28,23 @@ let options.systemd ? sysusers && (config.systemd.sysusers.enable || config.services.userborn.enable) ) "`systemd.sysusers` or `services.userborn` must be enabled."; - storagePath = self + "/" + cfg.settings.storageDirRelative; + storagePath = self + "/" + cfg.settings.storageLocation; storageExist = assertMsg (builtins.pathExists storagePath) "${storagePath} doesn't exist plz manually create and add to git first (may need a placeholder for git to recognize it)"; settingsType = types.submodule (submod: { options = { - storageDirRelative = mkOption { + storageLocation = mkOption { type = types.str; example = literalExpression ''./. /* <- flake root */ + "/secrets/renced/myhost" /* separate folder for each host */''; description = '' The local storage directory for re-encrypted secrets. MUST be a str of path related to flake root. ''; }; - storageDirStore = mkOption { + storageInStore = mkOption { type = types.path; readOnly = true; - default = builtins.path { path = self + "/" + submod.config.storageDirRelative; }; + default = builtins.path { path = self + "/" + submod.config.storageLocation; }; example = literalExpression ''./. /* <- flake root */ + "/secrets/renced/myhost" /* separate folder for each host */''; description = '' The local storage directory for re-encrypted secrets. MUST be a str of path related to flake root. @@ -104,21 +104,13 @@ let ''; }; - masterIdentities = mkOption { + identity = mkOption { type = with types; let identityPathType = coercedTo path toString str; in - listOf ( - # By coercing the old identityPathType into a canonical submodule of the form - # ``` - # { - # identity = ; - # pubkey = ...; - # } - # ``` - # we don't have to worry about it at a later stage. + nullOr ( coercedTo identityPathType ( p: @@ -139,14 +131,11 @@ let }; }) ); - default = [ ]; - example = [ - ./secrets/my-public-yubikey-identity.txt.pub - { - identity = ./password-encrypted-identity.pub; - pubkey = "age1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq"; - } - ]; + default = null; + example = { + identity = ./password-encrypted-identity.pub; + pubkey = "age1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq"; + }; }; extraRecipients = mkOption { @@ -281,7 +270,7 @@ in serviceConfig = { Type = "oneshot"; Environment = [ - ("STORAGE:" + cfg.settings.storageDirStore) + ("STORAGE=" + cfg.settings.storageInStore) checkRencSecsReport ]; ExecStart = "${lib.getExe cfg.package} ${profile} deploy"; diff --git a/src/cmd/deploy.rs b/src/cmd/deploy.rs index 90bb8fb..b438b9e 100644 --- a/src/cmd/deploy.rs +++ b/src/cmd/deploy.rs @@ -144,7 +144,7 @@ impl Profile { let sec_ciphertext_map: HashMap> = SecMap::>::from(self.secrets.clone()) .renced( - self.settings.storage_dir_store.clone().into(), + self.settings.storage_in_store.clone().into(), self.settings.host_pubkey.clone(), ) .bake_ctx()? diff --git a/src/cmd/renc.rs b/src/cmd/renc.rs index 0c58213..a8214b7 100644 --- a/src/cmd/renc.rs +++ b/src/cmd/renc.rs @@ -1,18 +1,15 @@ -use eyre::{eyre, ContextCompat, Result}; +use eyre::{eyre, Result}; use spdlog::{error, info}; use std::{fs, path::PathBuf}; use crate::helper::stored::Renc; use crate::interop::add_to_store; -use crate::profile::{MasterIdentity, Profile}; +use crate::profile::Profile; use crate::helper::parse_identity::ParsedIdentity; impl Profile { - pub fn get_key_pair_iter<'a>(&'a self) -> impl Iterator> + 'a { - self.settings - .master_identities - .iter() - .map(MasterIdentity::parse) + pub fn get_parsed_ident(&self) -> Result { + self.settings.identity.parse_from_raw() } /** @@ -24,7 +21,6 @@ impl Profile { and add to nix store. */ pub fn renc(self, _all: bool, flake_root: PathBuf) -> Result<()> { - let mut key_pair_list = self.get_key_pair_iter(); info!( "rencrypt for host {}", self.settings.host_identifier.clone() @@ -47,7 +43,7 @@ impl Profile { // absolute path, in config directory, suffix host ident let renc_path = { let mut p = flake_root.clone(); - p.push(self.settings.storage_dir_relative.clone()); + p.push(self.settings.storage_location.clone()); let p = p.canonicalize()?; info!( "reading user identity encrypted dir under flake root: {}", @@ -64,11 +60,8 @@ impl Profile { ) .filter_exist(); - let parsed_ident = key_pair_list - .find(|k| k.is_ok()) - .wrap_err_with(|| eyre!("available keypair not found"))??; - - let key = parsed_ident.get_identity(); + let key_pair = self.get_parsed_ident()?; + let key = key_pair.get_identity(); let recip = self.get_host_recip()?; if let Err(e) = data.map.makeup(vec![recip], &**key) { diff --git a/src/helper/parse_identity.rs b/src/helper/parse_identity.rs index 912defc..90281f3 100644 --- a/src/helper/parse_identity.rs +++ b/src/helper/parse_identity.rs @@ -1,4 +1,4 @@ -use crate::profile::MasterIdentity; +use crate::profile::RawIdentity; use age::{Identity, IdentityFile, Recipient}; use eyre::{eyre, ContextCompat, Result}; @@ -24,18 +24,19 @@ impl ParsedIdentity { } } -impl MasterIdentity { +impl RawIdentity { // get identiy and recipient from identity file, // only file that contains info of identity and recip supported at present // which is expected while using age generated identity - pub fn parse( - Self { + pub fn parse_from_raw(&self) -> Result { + let Self { identity, - pubkey: _, // not required. trans from prv key so fast. - }: &Self, - ) -> Result { + pubkey: _, // not required. gen from prv key so fast. + } = self; if identity.is_empty() { - return Err(eyre!("No identity found")); + return Err(eyre!( + "No identity found, require `vaultix.settings.identity`." + )); } else { macro_rules! create { ($method:ident, $err_context:expr) => {{ diff --git a/src/profile.rs b/src/profile.rs index c0ed5ec..1f9b608 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -32,13 +32,13 @@ pub struct Settings { pub extra_recipients: Vec, pub host_pubkey: String, pub host_keys: Vec, - pub storage_dir_relative: String, - pub storage_dir_store: String, - pub master_identities: Vec, + pub storage_location: String, + pub storage_in_store: String, + pub identity: RawIdentity, } #[derive(Debug, Deserialize)] -pub struct MasterIdentity { +pub struct RawIdentity { pub identity: String, #[allow(dead_code)] pub pubkey: String,