Move cli parser for sq key subkey revoke to its own module.
This commit is contained in:
parent
0dce5d9693
commit
909016e3ae
@ -5,14 +5,10 @@ use openpgp::KeyHandle;
|
||||
|
||||
use crate::cli::types::ClapData;
|
||||
use crate::cli::types::ExpirationArg;
|
||||
use crate::cli::types::FileOrCertStore;
|
||||
use crate::cli::types::FileOrStdout;
|
||||
use crate::cli::types::Time;
|
||||
|
||||
use crate::cli::key::{
|
||||
EncryptPurpose,
|
||||
KeyReasonForRevocation,
|
||||
};
|
||||
use crate::cli::key::EncryptPurpose;
|
||||
|
||||
use crate::cli::examples;
|
||||
use examples::Action;
|
||||
@ -27,6 +23,7 @@ pub mod delete;
|
||||
pub mod expire;
|
||||
pub mod export;
|
||||
pub mod password;
|
||||
pub mod revoke;
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
#[clap(
|
||||
@ -47,197 +44,10 @@ pub enum Command {
|
||||
Delete(delete::Command),
|
||||
Password(password::Command),
|
||||
Expire(expire::Command),
|
||||
Revoke(RevokeCommand),
|
||||
Revoke(revoke::Command),
|
||||
Bind(BindCommand),
|
||||
}
|
||||
|
||||
const SUBKEY_REVOKE_EXAMPLES: Actions = Actions {
|
||||
actions: &[
|
||||
Action::Setup(Setup {
|
||||
command: &[
|
||||
"sq", "key", "import",
|
||||
"alice-secret.pgp",
|
||||
],
|
||||
}),
|
||||
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Revoke Alice's signing subkey.",
|
||||
command: &[
|
||||
"sq", "key", "subkey", "revoke",
|
||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
|
||||
"--reason", "retired",
|
||||
"--message", "Subkey rotation.",
|
||||
],
|
||||
}),
|
||||
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Revoke Alice's signing subkey and encryption subkeys.",
|
||||
command: &[
|
||||
"sq", "key", "subkey", "revoke",
|
||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
|
||||
"--key=74DCDEAF17D9B995679EB52BA6E65EA2C8497728",
|
||||
"--reason", "retired",
|
||||
"--message", "Subkey rotation.",
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
test_examples!(sq_key_subkey_revoke, SUBKEY_REVOKE_EXAMPLES);
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(
|
||||
about = "Revoke a subkey",
|
||||
long_about =
|
||||
"Revoke a subkey.
|
||||
|
||||
Creates a revocation certificate for a subkey.
|
||||
|
||||
If `--revoker` or `--revoker-file` is provided, then that key is used \
|
||||
to create the revocation certificate. If that key is different from \
|
||||
the certificate that is being revoked, this results in a third-party \
|
||||
revocation. This is normally only useful if the owner of the \
|
||||
certificate designated the key to be a designated revoker.
|
||||
|
||||
`sq key subkey revoke` respects the reference time set by the top-level \
|
||||
`--time` argument. When set, it uses the specified time instead of \
|
||||
the current time when determining what keys are valid, and it sets \
|
||||
the revocation certificate's creation time to the reference time \
|
||||
instead of the current time.
|
||||
",
|
||||
after_help = SUBKEY_REVOKE_EXAMPLES,
|
||||
)]
|
||||
pub struct RevokeCommand {
|
||||
#[command(flatten)]
|
||||
pub cert: CertDesignators<
|
||||
cert_designator::CertUserIDEmailFileArgs,
|
||||
cert_designator::NoPrefix,
|
||||
cert_designator::OneValueAndFileRequiresOutput,
|
||||
SubkeyRevokeCertDoc>,
|
||||
|
||||
#[command(flatten)]
|
||||
pub revoker: CertDesignators<
|
||||
cert_designator::CertUserIDEmailFileArgs,
|
||||
cert_designator::RevokerPrefix,
|
||||
cert_designator::OneOptionalValue,
|
||||
SubkeyRevokeRevokerDoc>,
|
||||
|
||||
#[clap(
|
||||
long = "key",
|
||||
value_name = "FINGERPRINT|KEYID",
|
||||
help = "Revoke this subkey",
|
||||
required = true,
|
||||
)]
|
||||
pub keys: Vec<KeyHandle>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = "REASON",
|
||||
required = true,
|
||||
help = "The reason for the revocation",
|
||||
long_help = "\
|
||||
The reason for the revocation.
|
||||
|
||||
If the reason happened in the past, you should specify that using the \
|
||||
`--time` argument. This allows OpenPGP implementations to more \
|
||||
accurately reason about artifacts whose validity depends on the validity \
|
||||
of the user ID.",
|
||||
value_enum,
|
||||
)]
|
||||
pub reason: KeyReasonForRevocation,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = "MESSAGE",
|
||||
required = true,
|
||||
help = "A short, explanatory text",
|
||||
long_help = "\
|
||||
A short, explanatory text.
|
||||
|
||||
The text is shown to a viewer of the revocation certificate, and \
|
||||
explains why the subkey has been revoked. For instance, if Alice has \
|
||||
created a new key, she would generate a `superseded` revocation \
|
||||
certificate for her old key, and might include the message \"I've \
|
||||
created a new subkey, please refresh the certificate.\"",
|
||||
)]
|
||||
pub message: String,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_names = &["NAME", "VALUE"],
|
||||
number_of_values = 2,
|
||||
help = "Add a notation to the certification.",
|
||||
long_help = "\
|
||||
Add a notation to the certification.
|
||||
|
||||
A user-defined notation's name must be of the form \
|
||||
`name@a.domain.you.control.org`. If the notation's name starts with a \
|
||||
`!`, then the notation is marked as being critical. If a consumer of \
|
||||
a signature doesn't understand a critical notation, then it will \
|
||||
ignore the signature. The notation is marked as being human \
|
||||
readable."
|
||||
)]
|
||||
pub notation: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = FileOrCertStore::VALUE_NAME,
|
||||
help = "Write to the specified FILE",
|
||||
long_help = "\
|
||||
Write to the specified FILE.
|
||||
|
||||
If not specified, and the certificate was read from the certificate \
|
||||
store, imports the modified certificate into the cert store. If not \
|
||||
specified, and the certificate was read from a file, writes the \
|
||||
modified certificate to stdout.",
|
||||
)]
|
||||
pub output: Option<FileOrStdout>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Emit binary data",
|
||||
)]
|
||||
pub binary: bool,
|
||||
}
|
||||
|
||||
/// Documentation for the cert designators for the cert argument of
|
||||
/// the key subkey revoke command.
|
||||
pub struct SubkeyRevokeCertDoc {}
|
||||
|
||||
impl cert_designator::AdditionalDocs for SubkeyRevokeCertDoc {
|
||||
fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr {
|
||||
match arg {
|
||||
"file" =>
|
||||
"Revoke the specified (sub)keys on the key read from PATH"
|
||||
.into(),
|
||||
_ => {
|
||||
debug_assert!(help.starts_with("Use certificates"));
|
||||
help.replace("Use certificates",
|
||||
"Revoke the specified (sub)keys on the key")
|
||||
.into()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Documentation for the revoker designators for revoker argument of
|
||||
/// the key subkey revoke command .
|
||||
pub struct SubkeyRevokeRevokerDoc {}
|
||||
|
||||
impl cert_designator::AdditionalDocs for SubkeyRevokeRevokerDoc {
|
||||
fn help(_: &'static str, help: &'static str) -> clap::builder::StyledStr {
|
||||
format!("{} to create the revocation certificate.
|
||||
|
||||
Sign the revocation certificate using the specified key. By default, \
|
||||
the certificate being revoked is used. Using this option, it is \
|
||||
possible to create a third-party revocation.",
|
||||
help.replace("certificates", "key")).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(
|
||||
name = "bind",
|
||||
|
204
src/cli/key/subkey/revoke.rs
Normal file
204
src/cli/key/subkey/revoke.rs
Normal file
@ -0,0 +1,204 @@
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::KeyHandle;
|
||||
|
||||
use clap::Args;
|
||||
|
||||
use crate::cli::examples;
|
||||
use examples::Action;
|
||||
use examples::Actions;
|
||||
use examples::Example;
|
||||
use examples::Setup;
|
||||
|
||||
use crate::cli::key::KeyReasonForRevocation;
|
||||
use crate::cli::types::CertDesignators;
|
||||
use crate::cli::types::ClapData;
|
||||
use crate::cli::types::FileOrCertStore;
|
||||
use crate::cli::types::FileOrStdout;
|
||||
use crate::cli::types::cert_designator;
|
||||
|
||||
/// Documentation for the cert designators for the cert argument of
|
||||
/// the key subkey revoke command.
|
||||
pub struct CertDoc {}
|
||||
|
||||
impl cert_designator::AdditionalDocs for CertDoc {
|
||||
fn help(arg: &'static str, help: &'static str) -> clap::builder::StyledStr {
|
||||
match arg {
|
||||
"file" =>
|
||||
"Revoke the specified (sub)keys on the key read from PATH"
|
||||
.into(),
|
||||
_ => {
|
||||
debug_assert!(help.starts_with("Use certificates"));
|
||||
help.replace("Use certificates",
|
||||
"Revoke the specified (sub)keys on the key")
|
||||
.into()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Documentation for the revoker designators for revoker argument of
|
||||
/// the key subkey revoke command .
|
||||
pub struct RevokerDoc {}
|
||||
|
||||
impl cert_designator::AdditionalDocs for RevokerDoc {
|
||||
fn help(_: &'static str, help: &'static str) -> clap::builder::StyledStr {
|
||||
format!("{} to create the revocation certificate.
|
||||
|
||||
Sign the revocation certificate using the specified key. By default, \
|
||||
the certificate being revoked is used. Using this option, it is \
|
||||
possible to create a third-party revocation.",
|
||||
help.replace("certificates", "key")).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(
|
||||
about = "Revoke a subkey",
|
||||
long_about =
|
||||
"Revoke a subkey.
|
||||
|
||||
Creates a revocation certificate for a subkey.
|
||||
|
||||
If `--revoker` or `--revoker-file` is provided, then that key is used \
|
||||
to create the revocation certificate. If that key is different from \
|
||||
the certificate that is being revoked, this results in a third-party \
|
||||
revocation. This is normally only useful if the owner of the \
|
||||
certificate designated the key to be a designated revoker.
|
||||
|
||||
`sq key subkey revoke` respects the reference time set by the top-level \
|
||||
`--time` argument. When set, it uses the specified time instead of \
|
||||
the current time when determining what keys are valid, and it sets \
|
||||
the revocation certificate's creation time to the reference time \
|
||||
instead of the current time.
|
||||
",
|
||||
after_help = EXAMPLES,
|
||||
)]
|
||||
pub struct Command {
|
||||
#[command(flatten)]
|
||||
pub cert: CertDesignators<
|
||||
cert_designator::CertUserIDEmailFileArgs,
|
||||
cert_designator::NoPrefix,
|
||||
cert_designator::OneValueAndFileRequiresOutput,
|
||||
CertDoc>,
|
||||
|
||||
#[command(flatten)]
|
||||
pub revoker: CertDesignators<
|
||||
cert_designator::CertUserIDEmailFileArgs,
|
||||
cert_designator::RevokerPrefix,
|
||||
cert_designator::OneOptionalValue,
|
||||
RevokerDoc>,
|
||||
|
||||
#[clap(
|
||||
long = "key",
|
||||
value_name = "FINGERPRINT|KEYID",
|
||||
help = "Revoke this subkey",
|
||||
required = true,
|
||||
)]
|
||||
pub keys: Vec<KeyHandle>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = "REASON",
|
||||
required = true,
|
||||
help = "The reason for the revocation",
|
||||
long_help = "\
|
||||
The reason for the revocation.
|
||||
|
||||
If the reason happened in the past, you should specify that using the \
|
||||
`--time` argument. This allows OpenPGP implementations to more \
|
||||
accurately reason about artifacts whose validity depends on the validity \
|
||||
of the user ID.",
|
||||
value_enum,
|
||||
)]
|
||||
pub reason: KeyReasonForRevocation,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = "MESSAGE",
|
||||
required = true,
|
||||
help = "A short, explanatory text",
|
||||
long_help = "\
|
||||
A short, explanatory text.
|
||||
|
||||
The text is shown to a viewer of the revocation certificate, and \
|
||||
explains why the subkey has been revoked. For instance, if Alice has \
|
||||
created a new key, she would generate a `superseded` revocation \
|
||||
certificate for her old key, and might include the message \"I've \
|
||||
created a new subkey, please refresh the certificate.\"",
|
||||
)]
|
||||
pub message: String,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_names = &["NAME", "VALUE"],
|
||||
number_of_values = 2,
|
||||
help = "Add a notation to the certification.",
|
||||
long_help = "\
|
||||
Add a notation to the certification.
|
||||
|
||||
A user-defined notation's name must be of the form \
|
||||
`name@a.domain.you.control.org`. If the notation's name starts with a \
|
||||
`!`, then the notation is marked as being critical. If a consumer of \
|
||||
a signature doesn't understand a critical notation, then it will \
|
||||
ignore the signature. The notation is marked as being human \
|
||||
readable."
|
||||
)]
|
||||
pub notation: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = FileOrCertStore::VALUE_NAME,
|
||||
help = "Write to the specified FILE",
|
||||
long_help = "\
|
||||
Write to the specified FILE.
|
||||
|
||||
If not specified, and the certificate was read from the certificate \
|
||||
store, imports the modified certificate into the cert store. If not \
|
||||
specified, and the certificate was read from a file, writes the \
|
||||
modified certificate to stdout.",
|
||||
)]
|
||||
pub output: Option<FileOrStdout>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
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: "\
|
||||
Revoke Alice's signing subkey.",
|
||||
command: &[
|
||||
"sq", "key", "subkey", "revoke",
|
||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
|
||||
"--reason", "retired",
|
||||
"--message", "Subkey rotation.",
|
||||
],
|
||||
}),
|
||||
|
||||
Action::Example(Example {
|
||||
comment: "\
|
||||
Revoke Alice's signing subkey and encryption subkeys.",
|
||||
command: &[
|
||||
"sq", "key", "subkey", "revoke",
|
||||
"--cert=EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--key=42020B87D51877E5AF8D272124F3955B0B8DECC8",
|
||||
"--key=74DCDEAF17D9B995679EB52BA6E65EA2C8497728",
|
||||
"--reason", "retired",
|
||||
"--message", "Subkey rotation.",
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
test_examples!(sq_key_subkey_revoke, EXAMPLES);
|
@ -25,7 +25,7 @@ use crate::cli::key::subkey::delete::Command as DeleteCommand;
|
||||
use crate::cli::key::subkey::expire::Command as ExpireCommand;
|
||||
use crate::cli::key::subkey::export::Command as ExportCommand;
|
||||
use crate::cli::key::subkey::password::Command as PasswordCommand;
|
||||
use crate::cli::key::subkey::RevokeCommand;
|
||||
use crate::cli::key::subkey::revoke::Command as RevokeCommand;
|
||||
use crate::cli::types::EncryptPurpose;
|
||||
use crate::commands::key::bind;
|
||||
use crate::common;
|
||||
|
Loading…
Reference in New Issue
Block a user