Upgrade clap, rpassword and pwhash to prepare for new code using them #5

Merged
brl merged 1 commits from isa/citadel-tools:upgrade_dependencies into master 2024-09-06 11:53:37 +00:00
7 changed files with 3562 additions and 907 deletions
Showing only changes of commit 2a16bd4c41 - Show all commits

1550
Cargo.lock generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,14 +8,14 @@ homepage = "https://subgraph.com"
[dependencies]
libcitadel = { path = "../libcitadel" }
rpassword = "4.0"
clap = "2.33"
rpassword = "7.3"
clap = { version = "4.5", features = ["cargo", "derive"] }
lazy_static = "1.4"
serde_derive = "1.0"
serde = "1.0"
toml = "0.5"
toml = "0.8"
hex = "0.4"
byteorder = "1"
dbus = "0.8.4"
pwhash = "0.3.1"
pwhash = "1.0"
tempfile = "3"

View File

@ -1,89 +1,97 @@
use std::path::Path;
use std::process::exit;
use clap::{App,Arg,SubCommand,ArgMatches};
use clap::AppSettings::*;
use libcitadel::{Result, ResourceImage, Logger, LogLevel, Partition, KeyPair, ImageHeader, util};
use clap::{Arg,ArgMatches};
use clap::{command, ArgAction, Command};
use hex;
pub fn main(args: Vec<String>) {
use libcitadel::{Result, ResourceImage, Logger, LogLevel, Partition, KeyPair, ImageHeader, util};
let app = App::new("citadel-image")
pub fn main() {
let matches = command!()
.about("Citadel update image builder")
.settings(&[ArgRequiredElseHelp,ColoredHelp, DisableHelpSubcommand, DisableVersion, DeriveDisplayOrder])
.arg_required_else_help(true)
.disable_help_subcommand(true)
.subcommand(
Command::new("metainfo")
.about("Display metainfo variables for an image file")
.arg(Arg::new("path").required(true).help("Path to image file")),
)
.subcommand(
Command::new("info")
.about("Display metainfo variables for an image file")
.arg(Arg::new("path").required(true).help("Path to image file")),
)
.subcommand(
Command::new("generate-verity")
.about("Generate dm-verity hash tree for an image file")
.arg(Arg::new("path").required(true).help("Path to image file")),
)
.subcommand(
Command::new("verify")
.about("Verify dm-verity hash tree for an image file")
.arg(
Arg::new("option")
.long("option")
.required(true)
.help("Path to image file"),
),
)
.subcommand(
Command::new("install-rootfs")
.about("Install rootfs image file to a partition")
.arg(
Arg::new("choose")
.long("just-choose")
.action(ArgAction::SetTrue)
.help("Don't install anything, just show which partition would be chosen"),
)
.arg(
Arg::new("skip-sha")
.long("skip-sha")
.action(ArgAction::SetTrue)
.help("Skip verification of header sha256 value"),
)
.arg(
Arg::new("no-prefer")
.long("no-prefer")
.action(ArgAction::SetTrue)
.help("Don't set PREFER_BOOT flag"),
)
.arg(
Arg::new("path")
.required_unless_present("choose")
.help("Path to image file"),
),
)
.subcommand(Command::new("genkeys").about("Generate a pair of keys"))
.subcommand(
Command::new("decompress")
.about("Decompress a compressed image file")
.arg(Arg::new("path").required(true).help("Path to image file")),
)
.subcommand(
Command::new("bless")
.about("Mark currently mounted rootfs partition as successfully booted"),
)
.subcommand(
Command::new("verify-shasum")
.about("Verify the sha256 sum of the image")
.arg(Arg::new("path").required(true).help("Path to image file")),
)
.get_matches();
.subcommand(SubCommand::with_name("metainfo")
.about("Display metainfo variables for an image file")
.arg(Arg::with_name("path")
.required(true)
.help("Path to image file")))
.subcommand(SubCommand::with_name("info")
.about("Display metainfo variables for an image file")
.arg(Arg::with_name("path")
.required(true)
.help("Path to image file")))
.subcommand(SubCommand::with_name("generate-verity")
.about("Generate dm-verity hash tree for an image file")
.arg(Arg::with_name("path")
.required(true)
.help("Path to image file")))
.subcommand(SubCommand::with_name("verify")
.about("Verify dm-verity hash tree for an image file")
.arg(Arg::with_name("path")
.required(true)
.help("Path to image file")))
.subcommand(SubCommand::with_name("install-rootfs")
.about("Install rootfs image file to a partition")
.arg(Arg::with_name("choose")
.long("just-choose")
.help("Don't install anything, just show which partition would be chosen"))
.arg(Arg::with_name("skip-sha")
.long("skip-sha")
.help("Skip verification of header sha256 value"))
.arg(Arg::with_name("no-prefer")
.long("no-prefer")
.help("Don't set PREFER_BOOT flag"))
.arg(Arg::with_name("path")
.required_unless("choose")
.help("Path to image file")))
.subcommand(SubCommand::with_name("genkeys")
.about("Generate a pair of keys"))
.subcommand(SubCommand::with_name("decompress")
.about("Decompress a compressed image file")
.arg(Arg::with_name("path")
.required(true)
.help("Path to image file")))
.subcommand(SubCommand::with_name("bless")
.about("Mark currently mounted rootfs partition as successfully booted"))
.subcommand(SubCommand::with_name("verify-shasum")
.about("Verify the sha256 sum of the image")
.arg(Arg::with_name("path")
.required(true)
.help("Path to image file")));
Logger::set_log_level(LogLevel::Debug);
let matches = app.get_matches_from(args);
let result = match matches.subcommand() {
("metainfo", Some(m)) => metainfo(m),
("info", Some(m)) => info(m),
("generate-verity", Some(m)) => generate_verity(m),
("verify", Some(m)) => verify(m),
("sign-image", Some(m)) => sign_image(m),
("genkeys", Some(_)) => genkeys(),
("decompress", Some(m)) => decompress(m),
("verify-shasum", Some(m)) => verify_shasum(m),
("install-rootfs", Some(m)) => install_rootfs(m),
("install", Some(m)) => install_image(m),
("bless", Some(_)) => bless(),
Some(("metainfo", sub_m)) => metainfo(sub_m),
Some(("info", sub_m)) => info(sub_m),
Some(("generate-verity", sub_m)) => generate_verity(sub_m),
Some(("verify", sub_m)) => verify(sub_m),
Some(("sign-image", sub_m)) => sign_image(sub_m),
Some(("genkeys", _)) => genkeys(),
Some(("decompress", sub_m)) => decompress(sub_m),
Some(("verify-shasum", sub_m)) => verify_shasum(sub_m),
Some(("install-rootfs", sub_m)) => install_rootfs(sub_m),
Some(("install", sub_m)) => install_image(sub_m),
Some(("bless", _)) => bless(),
_ => Ok(()),
};
@ -159,7 +167,9 @@ fn verify_shasum(arg_matches: &ArgMatches) -> Result<()> {
}
fn load_image(arg_matches: &ArgMatches) -> Result<ResourceImage> {
let path = arg_matches.value_of("path").expect("path argument missing");
let path = arg_matches.get_one::<String>("path")
.expect("path argument missing");
if !Path::new(path).exists() {
bail!("Cannot load image {}: File does not exist", path);
}
@ -171,14 +181,14 @@ fn load_image(arg_matches: &ArgMatches) -> Result<ResourceImage> {
}
fn install_rootfs(arg_matches: &ArgMatches) -> Result<()> {
if arg_matches.is_present("choose") {
if arg_matches.get_flag("choose") {
let _ = choose_install_partition(true)?;
return Ok(())
}
let img = load_image(arg_matches)?;
if !arg_matches.is_present("skip-sha") {
if !arg_matches.get_flag("skip-sha") {
info!("Verifying sha256 hash of image");
let shasum = img.generate_shasum()?;
if shasum != img.metainfo().shasum() {
@ -188,7 +198,7 @@ fn install_rootfs(arg_matches: &ArgMatches) -> Result<()> {
let partition = choose_install_partition(true)?;
if !arg_matches.is_present("no-prefer") {
if !arg_matches.get_flag("no-prefer") {
clear_prefer_boot()?;
img.header().set_flag(ImageHeader::FLAG_PREFER_BOOT);
}
@ -212,7 +222,9 @@ fn sign_image(arg_matches: &ArgMatches) -> Result<()> {
}
fn install_image(arg_matches: &ArgMatches) -> Result<()> {
let source = arg_matches.value_of("path").expect("path argument missing");
let source = arg_matches.get_one::<String>("path")
.expect("path argument missing");
let img = load_image(arg_matches)?;
let _hdr = img.header();
let metainfo = img.metainfo();

View File

@ -125,7 +125,7 @@ fn read_passphrase(prompt: &str) -> io::Result<Option<String>> {
loop {
println!("{}", prompt);
println!();
let passphrase = rpassword::read_password_from_tty(Some(" Passphrase : "))?;
let passphrase = rpassword::prompt_password(" Passphrase : ")?;
if passphrase.is_empty() {
println!("Passphrase cannot be empty");
continue;
@ -133,7 +133,7 @@ fn read_passphrase(prompt: &str) -> io::Result<Option<String>> {
if passphrase == "q" || passphrase == "Q" {
return Ok(None);
}
let confirm = rpassword::read_password_from_tty(Some(" Confirm : "))?;
let confirm = rpassword::prompt_password(" Confirm : ")?;
if confirm == "q" || confirm == "Q" {
return Ok(None);
}

View File

@ -34,9 +34,9 @@ fn main() {
} else if exe == Path::new("/usr/libexec/citadel-install-backend") {
install_backend::main();
} else if exe == Path::new("/usr/bin/citadel-image") {
image::main(args);
image::main();
} else if exe == Path::new("/usr/bin/citadel-realmfs") {
realmfs::main(args);
realmfs::main();
} else if exe == Path::new("/usr/bin/citadel-update") {
update::main(args);
} else if exe == Path::new("/usr/libexec/citadel-desktop-sync") {
@ -57,8 +57,8 @@ fn dispatch_command(args: Vec<String>) {
match command.as_str() {
"boot" => boot::main(rebuild_args("citadel-boot", args)),
"install" => install::main(rebuild_args("citadel-install", args)),
"image" => image::main(rebuild_args("citadel-image", args)),
"realmfs" => realmfs::main(rebuild_args("citadel-realmfs", args)),
"image" => image::main(),
"realmfs" => realmfs::main(),
"update" => update::main(rebuild_args("citadel-update", args)),
"mkimage" => mkimage::main(rebuild_args("citadel-mkimage", args)),
"sync" => sync::main(rebuild_args("citadel-desktop-sync", args)),

View File

@ -1,28 +1,24 @@
use clap::App;
use clap::ArgMatches;
use clap::{command, Command};
use clap::{Arg, ArgMatches};
use libcitadel::{Result,RealmFS,Logger,LogLevel};
use libcitadel::util::is_euid_root;
use clap::SubCommand;
use clap::AppSettings::*;
use clap::Arg;
use libcitadel::ResizeSize;
use std::process::exit;
pub fn main(args: Vec<String>) {
pub fn main() {
Logger::set_log_level(LogLevel::Debug);
let app = App::new("citadel-realmfs")
.about("Citadel realmfs image tool")
.settings(&[ArgRequiredElseHelp,ColoredHelp, DisableHelpSubcommand, DisableVersion, DeriveDisplayOrder,SubcommandsNegateReqs])
.subcommand(SubCommand::with_name("resize")
let matches = command!()
.about("citadel-realmfs")
.arg_required_else_help(true)
.subcommand(Command::new("resize")
.about("Resize an existing RealmFS image. If the image is currently sealed, it will also be unsealed.")
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Path or name of RealmFS image to resize")
.required(true))
.arg(Arg::with_name("size")
.arg(Arg::new("size")
.help("Size to increase RealmFS image to (or by if prefixed with '+')")
.long_help("\
The size can be followed by a 'g' or 'm' character \
@ -35,53 +31,53 @@ is the final absolute size of the image.")
.required(true)))
.subcommand(SubCommand::with_name("fork")
.subcommand(Command::new("fork")
.about("Create a new RealmFS image as an unsealed copy of an existing image")
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Path or name of RealmFS image to fork")
.required(true))
.arg(Arg::with_name("forkname")
.arg(Arg::new("forkname")
.help("Name of new image to create")
.required(true)))
.subcommand(SubCommand::with_name("autoresize")
.subcommand(Command::new("autoresize")
.about("Increase size of RealmFS image if not enough free space remains")
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Path or name of RealmFS image")
.required(true)))
.subcommand(SubCommand::with_name("update")
.subcommand(Command::new("update")
.about("Open an update shell on the image")
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Path or name of RealmFS image")
.required(true)))
.subcommand(SubCommand::with_name("activate")
.subcommand(Command::new("activate")
.about("Activate a RealmFS by creating a block device for the image and mounting it.")
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Path or name of RealmFS image to activate")
.required(true)))
.subcommand(SubCommand::with_name("deactivate")
.subcommand(Command::new("deactivate")
.about("Deactivate a RealmFS by unmounting it and removing block device created during activation.")
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Path or name of RealmFS image to deactivate")
.required(true)))
.arg(Arg::with_name("image")
.arg(Arg::new("image")
.help("Name of or path to RealmFS image to display information about")
.required(true));
.required(true))
.get_matches();
let matches = app.get_matches_from(args);
let result = match matches.subcommand() {
("resize", Some(m)) => resize(m),
("autoresize", Some(m)) => autoresize(m),
("fork", Some(m)) => fork(m),
("update", Some(m)) => update(m),
("activate", Some(m)) => activate(m),
("deactivate", Some(m)) => deactivate(m),
Some(("resize", m)) => resize(m),
Some(("autoresize", m)) => autoresize(m),
Some(("fork", m)) => fork(m),
Some(("update", m)) => update(m),
Some(("activate", m)) => activate(m),
Some(("deactivate", m)) => deactivate(m),
_ => image_info(&matches),
};
@ -92,7 +88,7 @@ is the final absolute size of the image.")
}
fn realmfs_image(arg_matches: &ArgMatches) -> Result<RealmFS> {
let image = match arg_matches.value_of("image") {
let image = match arg_matches.get_one::<String>("image") {
Some(s) => s,
None => bail!("Image argument required."),
};
@ -136,10 +132,9 @@ fn parse_resize_size(s: &str) -> Result<ResizeSize> {
fn resize(arg_matches: &ArgMatches) -> Result<()> {
let img = realmfs_image(arg_matches)?;
info!("image is {}", img.path().display());
let size_arg = match arg_matches.value_of("size") {
let size_arg = match arg_matches.get_one::<String>("size") {
Some(size) => size,
None => "No size argument",
};
info!("Size is {}", size_arg);
let mode_add = size_arg.starts_with('+');
@ -165,7 +160,7 @@ fn autoresize(arg_matches: &ArgMatches) -> Result<()> {
fn fork(arg_matches: &ArgMatches) -> Result<()> {
let img = realmfs_image(arg_matches)?;
let forkname = match arg_matches.value_of("forkname") {
let forkname = match arg_matches.get_one::<String>("forkname") {
Some(name) => name,
None => bail!("No fork name argument"),
};
@ -190,7 +185,7 @@ fn update(arg_matches: &ArgMatches) -> Result<()> {
fn activate(arg_matches: &ArgMatches) -> Result<()> {
let img = realmfs_image(arg_matches)?;
let img_arg = arg_matches.value_of("image").unwrap();
let img_arg = arg_matches.get_one::<String>("image").unwrap();
if img.is_activated() {
info!("RealmFS image {} is already activated", img_arg);
@ -203,7 +198,7 @@ fn activate(arg_matches: &ArgMatches) -> Result<()> {
fn deactivate(arg_matches: &ArgMatches) -> Result<()> {
let img = realmfs_image(arg_matches)?;
let img_arg = arg_matches.value_of("image").unwrap();
let img_arg = arg_matches.get_one::<String>("image").unwrap();
if !img.is_activated() {
info!("RealmFS image {} is not activated", img_arg);
} else if img.is_in_use() {