Move cli parser for sq key subkey password to its own module.

This commit is contained in:
Neal H. Walfield 2024-11-05 14:42:27 +01:00
parent 215051da86
commit ea6db79f7b
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
3 changed files with 145 additions and 130 deletions

View File

@ -1,5 +1,3 @@
use std::path::PathBuf;
use clap::{ArgGroup, Args, Subcommand};
use sequoia_openpgp as openpgp;
@ -28,6 +26,7 @@ use crate::cli::types::cert_designator;
pub mod add;
pub mod delete;
pub mod export;
pub mod password;
#[derive(Debug, Subcommand)]
#[clap(
@ -46,117 +45,12 @@ pub enum Command {
Add(add::Command),
Export(export::Command),
Delete(delete::Command),
Password(PasswordCommand),
Password(password::Command),
Expire(ExpireCommand),
Revoke(RevokeCommand),
Bind(BindCommand),
}
const SQ_KEY_SUBKEY_PASSWORD_EXAMPLES: Actions = Actions {
actions: &[
Action::Setup(Setup {
command: &[
"sq", "key", "import", "alice-secret.pgp"
],
}),
Action::Example(Example {
comment: "\
Change the password for Alice's signing key to the password in the \
specified file.",
command: &[
"sq", "key", "subkey", "password",
"--new-password-file=password-file.txt",
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
],
}),
Action::Example(Example {
comment: "\
Clear the password protection for Alice's signing key.",
command: &[
"sq", "key", "subkey", "password",
"--password-file=password-file.txt",
"--clear-password",
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
],
}),
]
};
test_examples!(sq_key_subkey_password, SQ_KEY_SUBKEY_PASSWORD_EXAMPLES);
#[derive(Debug, Args)]
#[clap(
name = "password",
about = "Change the password protecting secret key material",
long_about = "
Change the password protecting secret key material.
Secret key material can be protected by a password. This subcommand \
changes or clears the password of one or more keys.
To strip the password either use `--clear` or supply a zero-length \
password when prompted for the new password.
If a key is password protected, and the correct password was not \
supplied using the `--password-file` argument, the user is \
prompted for the password. Likewise, if the new password isn't \
provided, the user is prompted.
",
after_help = SQ_KEY_SUBKEY_PASSWORD_EXAMPLES,
)]
pub struct PasswordCommand {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::OneValueAndFileRequiresOutput,
SubkeyPasswordDoc>,
#[clap(
long,
help = "Change the password of the specified key",
long_help = "\
Change the password of the specified key.
The key may be either the primary key or a subkey.",
required = true,
)]
pub key: Vec<KeyHandle>,
#[clap(
long,
value_name = "PASSWORD_FILE",
help = "\
File containing password to encrypt the secret key material",
long_help = "\
File containing password to encrypt the secret key material.
Note that the entire key file will be used as the password including \
any surrounding whitespace like a trailing newline."
)]
pub new_password_file: Option<PathBuf>,
#[clap(
long,
help = "Clear the password protecting the secret key material",
)]
pub clear_password: bool,
#[clap(
help = FileOrStdout::HELP_OPTIONAL,
long,
value_name = FileOrStdout::VALUE_NAME,
conflicts_with = "cert",
)]
pub output: Option<FileOrStdout>,
#[clap(
long,
requires = "output",
help = "Emit binary data",
)]
pub binary: bool,
}
const SQ_KEY_SUBKEY_EXPIRE_EXAMPLES: Actions = Actions {
actions: &[
Action::Setup(Setup {
@ -178,27 +72,6 @@ Change Alice's authentication subkey to expire in 6 months.",
};
test_examples!(sq_key_subkey_expire, SQ_KEY_SUBKEY_EXPIRE_EXAMPLES);
/// Documentation for the cert designators for the key password.
pub struct SubkeyPasswordDoc {}
impl cert_designator::AdditionalDocs for SubkeyPasswordDoc {
fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr {
match arg {
"file" =>
"Change the password for the secret key material of the \
specified (sub)keys from the key read from PATH"
.into(),
_ => {
debug_assert!(help.starts_with("Use certificates"));
help.replace("Use certificates",
"Change the password for the secret key material \
of the specified (sub)keys from the key")
.into()
},
}
}
}
#[derive(Debug, Args)]
#[clap(
name = "expire",

View File

@ -0,0 +1,142 @@
use std::path::PathBuf;
use clap::Args;
use sequoia_openpgp as openpgp;
use openpgp::KeyHandle;
use crate::cli::examples;
use examples::Action;
use examples::Actions;
use examples::Example;
use examples::Setup;
use crate::cli::types::CertDesignators;
use crate::cli::types::ClapData;
use crate::cli::types::FileOrStdout;
use crate::cli::types::cert_designator;
pub struct AdditionalDocs {}
impl cert_designator::AdditionalDocs for AdditionalDocs {
fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr {
match arg {
"file" =>
"Change the password for the secret key material of the \
specified (sub)keys from the key read from PATH"
.into(),
_ => {
debug_assert!(help.starts_with("Use certificates"));
help.replace("Use certificates",
"Change the password for the secret key material \
of the specified (sub)keys from the key")
.into()
},
}
}
}
#[derive(Debug, Args)]
#[clap(
name = "password",
about = "Change the password protecting secret key material",
long_about = "
Change the password protecting secret key material.
Secret key material can be protected by a password. This subcommand \
changes or clears the password of one or more keys.
To strip the password either use `--clear` or supply a zero-length \
password when prompted for the new password.
If a key is password protected, and the correct password was not \
supplied using the `--password-file` argument, the user is \
prompted for the password. Likewise, if the new password isn't \
provided, the user is prompted.
",
after_help = EXAMPLES,
)]
pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::OneValueAndFileRequiresOutput,
AdditionalDocs>,
#[clap(
long,
help = "Change the password of the specified key",
long_help = "\
Change the password of the specified key.
The key may be either the primary key or a subkey.",
required = true,
)]
pub key: Vec<KeyHandle>,
#[clap(
long,
value_name = "PASSWORD_FILE",
help = "\
File containing password to encrypt the secret key material",
long_help = "\
File containing password to encrypt the secret key material.
Note that the entire key file will be used as the password including \
any surrounding whitespace like a trailing newline."
)]
pub new_password_file: Option<PathBuf>,
#[clap(
long,
help = "Clear the password protecting the secret key material",
)]
pub clear_password: bool,
#[clap(
help = FileOrStdout::HELP_OPTIONAL,
long,
value_name = FileOrStdout::VALUE_NAME,
conflicts_with = "cert",
)]
pub output: Option<FileOrStdout>,
#[clap(
long,
requires = "output",
help = "Emit binary data",
)]
pub binary: bool,
}
const EXAMPLES: Actions = Actions {
actions: &[
Action::Setup(Setup {
command: &[
"sq", "key", "import", "alice-secret.pgp"
],
}),
Action::Example(Example {
comment: "\
Change the password for Alice's signing key to the password in the \
specified file.",
command: &[
"sq", "key", "subkey", "password",
"--new-password-file=password-file.txt",
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
],
}),
Action::Example(Example {
comment: "\
Clear the password protection for Alice's signing key.",
command: &[
"sq", "key", "subkey", "password",
"--password-file=password-file.txt",
"--clear-password",
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
],
}),
]
};
test_examples!(sq_key_subkey_password, EXAMPLES);

View File

@ -24,7 +24,7 @@ use crate::cli::key::subkey::add::Command as AddCommand;
use crate::cli::key::subkey::delete::Command as DeleteCommand;
use crate::cli::key::subkey::ExpireCommand;
use crate::cli::key::subkey::export::Command as ExportCommand;
use crate::cli::key::subkey::PasswordCommand;
use crate::cli::key::subkey::password::Command as PasswordCommand;
use crate::cli::key::subkey::RevokeCommand;
use crate::cli::types::EncryptPurpose;
use crate::commands::key::bind;