public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH installer v2 1/1] assistant: validate: add verify-password option
@ 2025-09-03 23:18 Peter via pve-devel
  0 siblings, 0 replies; only message in thread
From: Peter via pve-devel @ 2025-09-03 23:18 UTC (permalink / raw)
  To: pve-devel; +Cc: Peter

[-- Attachment #1: Type: message/rfc822, Size: 9397 bytes --]

From: Peter <pjcreath+proxmox@gmail.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH installer v2 1/1] assistant: validate: add verify-password option
Date: Wed,  3 Sep 2025 19:18:28 -0400
Message-ID: <20250903231828.53459-1-pjcreath+proxmox@gmail.com>

Adds an option to interactively verify the hashed root password in
the answer file, so that mistakes can be caught before installation.

Signed-off-by: Peter <pjcreath+proxmox@gmail.com>
---

 changes since v1:
 * revised code to depend on proxmox crates instead of external crypt and rpassword
 * changed flag to --verify-root-password
 * added a check that stdin is a tty before prompting for password

 proxmox-auto-install-assistant/Cargo.toml  |  1 +
 proxmox-auto-install-assistant/src/main.rs | 31 ++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/proxmox-auto-install-assistant/Cargo.toml b/proxmox-auto-install-assistant/Cargo.toml
index 9b4a9c4..eeba42f 100644
--- a/proxmox-auto-install-assistant/Cargo.toml
+++ b/proxmox-auto-install-assistant/Cargo.toml
@@ -17,4 +17,5 @@ proxmox-installer-common = { workspace = true, features = [ "cli" ] }
 serde_json.workspace = true
 toml.workspace = true
 
+proxmox-sys = { version = "1.0.0", features = [ "crypt" ] }
 glob = "0.3"
diff --git a/proxmox-auto-install-assistant/src/main.rs b/proxmox-auto-install-assistant/src/main.rs
index 5d6c1d5..98b4f23 100644
--- a/proxmox-auto-install-assistant/src/main.rs
+++ b/proxmox-auto-install-assistant/src/main.rs
@@ -6,6 +6,9 @@
 
 use anyhow::{Context, Result, bail, format_err};
 use glob::Pattern;
+use proxmox_sys::linux::tty::read_password;
+use proxmox_sys::crypt::verify_crypt_pw;
+use std::io::IsTerminal;
 use std::{
     collections::BTreeMap,
     fmt, fs,
@@ -153,12 +156,15 @@ struct CommandValidateAnswerArgs {
     path: PathBuf,
     /// Whether to also show the full answer as parsed.
     debug: bool,
+    /// Interactively verify the hashed root password.
+    verify_password: bool,
 }
 
 impl cli::Subcommand for CommandValidateAnswerArgs {
     fn parse(args: &mut cli::Arguments) -> Result<Self> {
         Ok(Self {
             debug: args.contains(["-d", "--debug"]),
+            verify_password: args.contains("--verify-root-password"),
             // Needs to be last
             path: args.free_from_str()?,
         })
@@ -176,6 +182,7 @@ ARGUMENTS:
 
 OPTIONS:
   -d, --debug        Also show the full answer as parsed.
+      --verify-root-password  Interactively verify the hashed root password.
   -h, --help         Print this help
   -V, --version      Print version
     "#,
@@ -184,6 +191,10 @@ OPTIONS:
     }
 
     fn run(&self) -> Result<()> {
+        if self.verify_password && !std::io::stdin().is_terminal() {
+            Self::print_usage();
+            bail!("Verifying the root password requires an interactive terminal.");
+        }
         validate_answer(self)
     }
 }
@@ -545,6 +556,20 @@ fn validate_answer_file_keys(path: impl AsRef<Path> + fmt::Debug) -> Result<bool
     }
 }
 
+fn verify_hashed_password_interactive(answer: &Answer) -> Result<()> {
+    if let Some(hashed) = &answer.global.root_password_hashed {
+        println!("Verifying hashed root password.");
+
+        let password = String::from_utf8(read_password("Enter root password to verify: ")?)?;
+        verify_crypt_pw(&password, hashed)?;
+
+        println!("Password matches hashed password.");
+        Ok(())
+    } else {
+        bail!("'root-password-hashed' not set in answer file, cannot verify.");
+    }
+}
+
 fn validate_answer(args: &CommandValidateAnswerArgs) -> Result<()> {
     let mut valid = validate_answer_file_keys(&args.path)?;
 
@@ -553,6 +578,12 @@ fn validate_answer(args: &CommandValidateAnswerArgs) -> Result<()> {
             if args.debug {
                 println!("Parsed data from answer file:\n{:#?}", answer);
             }
+            if args.verify_password {
+                if let Err(err) = verify_hashed_password_interactive(&answer) {
+                    eprintln!("{err:#}");
+                    valid = false;
+                }
+            }
         }
         Err(err) => {
             eprintln!("{err:#}");
-- 
2.47.2



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-09-03 23:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-03 23:18 [pve-devel] [PATCH installer v2 1/1] assistant: validate: add verify-password option Peter via pve-devel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal