Use --cert- prefix for all cert designators.

- Resolves a conflict with the user ID designators, and makes the
    interface more consistent.

  - Fixes #385.
This commit is contained in:
Justus Winter 2024-11-18 14:57:09 +01:00
parent e61a03f863
commit 91f4400c26
No known key found for this signature in database
GPG Key ID: 686F55B4AB2B3386
33 changed files with 95 additions and 91 deletions

4
NEWS
View File

@ -97,6 +97,10 @@
- `sq key approvals --add-authenticated` is now a simple flag, and
we always require full authentication.
- `sq toolbox strip-userid` has been removed.
- All cert designators now use the `--cert-` prefix, e.g. `sq key
export --email` has been changed to `sq key export --cert-email`
for consistency reasons, and to free `--name`, `--email`, and
`--userid` for user ID designators.
* Changes in 0.39.0
** Notable changes

View File

@ -3,7 +3,7 @@ use clap::Parser;
use crate::cli::types::*;
use crate::cli::types::cert_designator::CertUserIDEmailDomainGrepArgs;
use crate::cli::types::cert_designator::NoPrefix;
use crate::cli::types::cert_designator::CertPrefix;
use crate::cli::types::cert_designator::OptionalValue;
use crate::cli::examples::*;
@ -38,7 +38,7 @@ signatures are checked, and the User IDs are authenticated. \
Note: this check is case sensitive.",
command: &[
"sq", "cert", "export",
"--userid", "Alice <alice@example.org>",
"--cert-userid", "Alice <alice@example.org>",
],
}),
Action::Example(Example {
@ -47,7 +47,7 @@ Export certificates with a User ID containing the email address. \
The binding signatures are checked, and the User IDs are \
authenticated. Note: this check is case insensitive.",
command: &[
"sq", "cert", "export", "--email", "alice@example.org",
"sq", "cert", "export", "--cert-email", "alice@example.org",
],
}),
Action::Example(Example {
@ -64,8 +64,8 @@ Export certificates that contain a User ID with *either* (not both!) \
email address. Note: this check is case insensitive.",
command: &[
"sq", "cert", "export",
"--email", "alice@example.org",
"--email", "bob@example.org",
"--cert-email", "alice@example.org",
"--cert-email", "bob@example.org",
],
}),
],
@ -98,7 +98,7 @@ no search criteria are specified, then this will return success.
after_help = EXAMPLES,
)]
#[clap(group(ArgGroup::new("some-designator")
.args(&["cert", "userid", "email", "domain", "grep", "all"])
.args(&["cert", "cert-userid", "cert-email", "cert-domain", "cert-grep", "all"])
.required(true)
.multiple(true)))]
pub struct Command {
@ -136,7 +136,7 @@ for example.",
#[clap(
long,
conflicts_with_all = [
"cert", "userid", "email", "domain", "grep",
"cert", "cert-userid", "cert-email", "cert-domain", "cert-grep",
],
help = "Export all certificates",
)]
@ -144,6 +144,6 @@ for example.",
#[command(flatten)]
pub certs: CertDesignators<CertUserIDEmailDomainGrepArgs,
NoPrefix,
CertPrefix,
OptionalValue>,
}

View File

@ -55,7 +55,7 @@ pub struct Command {
#[command(flatten)]
pub certs: CertDesignators<FileCertUserIDEmailDomainGrepArgs,
NoPrefix,
CertPrefix,
NoOptions>,
#[clap(
@ -96,7 +96,7 @@ const EXAMPLES: Actions = Actions {
Gather statistics on the certificates in a keyring.",
command: &[
"sq", "cert", "lint",
"--file", "certs.pgp",
"--cert-file", "certs.pgp",
],
}),
@ -106,7 +106,7 @@ Fix a key with known problems.",
command: &[
"sq", "key", "export",
"--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
"|", "sq", "cert", "lint", "--fix", "--file=-",
"|", "sq", "cert", "lint", "--fix", "--cert-file=-",
"|", "sq", "cert", "import"
],
}),

View File

@ -68,13 +68,13 @@ pub struct Command {
default_value_t = FileOrStdin::default(),
help = FileOrStdin::HELP_OPTIONAL,
value_name = FileOrStdin::VALUE_NAME,
conflicts_with_all = ["file", "cert", "userid", "email", "domain", "grep"],
conflicts_with_all = ["cert-file", "cert", "cert-userid", "cert-email", "cert-domain", "cert-grep"],
)]
pub input: FileOrStdin,
#[command(flatten)]
pub certs: CertDesignators<FileCertUserIDEmailDomainGrepArgs,
NoPrefix,
CertPrefix,
OptionalValue,
ToInspectDoc>,

View File

@ -15,7 +15,7 @@ use crate::cli::types::cert_designator::*;
pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OneValueAndFileRequiresOutput,
DeleteKeyDoc>,
@ -72,7 +72,7 @@ Delete any secret key associated with Alice's certificate \
selected by user ID.",
command: &[
"sq", "key", "delete",
"--email=alice@example.org",
"--cert-email=alice@example.org",
],
}),
]

View File

@ -56,7 +56,7 @@ expire` subcommand.
pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OneValueAndFileRequiresOutput,
KeyExpireDoc>,

View File

@ -30,7 +30,7 @@ with a certificate, use `sq key subkey export`.
pub struct Command {
#[command(flatten)]
pub certs: CertDesignators<CertUserIDEmailDomainGrepArgs,
NoPrefix,
CertPrefix,
NoOptions,
ExportKeyDoc>,
@ -80,7 +80,7 @@ Export Alice's certificate with all available secret key material \
identified by email address.",
command: &[
"sq", "key", "export",
"--email", "alice@example.org",
"--cert-email", "alice@example.org",
],
}),
]

View File

@ -13,7 +13,7 @@ use crate::cli::types::cert_designator::*;
pub struct Command {
#[command(flatten)]
pub certs: CertDesignators<CertUserIDEmailDomainGrepArgs,
NoPrefix,
CertPrefix,
OptionalValue,
ListKeyDoc>,
@ -56,7 +56,7 @@ List the keys managed by the keystore server \
with a user ID in example.org.",
command: &[
"sq", "key", "list",
"--domain=example.org",
"--cert-domain=example.org",
],
}),
]

View File

@ -31,7 +31,7 @@ provided, the user is prompted.
pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OneValueAndFileRequiresOutput,
KeyPasswordDoc>,

View File

@ -66,7 +66,7 @@ instead of the current time.
pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OneValueAndFileRequiresOutput,
KeyRevokeCertDoc>,

View File

@ -82,7 +82,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValueAndFileRequiresOutput,
AdditionalDocs>,

View File

@ -65,7 +65,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValueAndFileRequiresOutput,
AdditionalDocs>,

View File

@ -63,7 +63,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValueAndFileRequiresOutput,
CertAdditionalDocs>,

View File

@ -57,7 +57,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValueAndFileRequiresOutput,
AdditionalDocs>,

View File

@ -46,7 +46,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValue>,
#[command(flatten)]

View File

@ -70,7 +70,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValueAndFileRequiresOutput,
CertAdditionalDocs>,

View File

@ -86,7 +86,7 @@ pub struct Command {
#[command(flatten)]
pub cert: CertDesignators<
cert_designator::CertUserIDEmailFileArgs,
cert_designator::NoPrefix,
cert_designator::CertPrefix,
cert_designator::OneValueAndFileRequiresOutput,
CertDoc>,

View File

@ -9,7 +9,7 @@ use crate::cli::types::cert_designator::{
CertDesignators,
CertUserIDEmailFileArgs,
OptionalValue,
NoPrefix,
CertPrefix,
};
use crate::cli::examples::*;
@ -63,7 +63,7 @@ Generate DANE records from juliet.pgp for example.org.",
command: &[
"sq", "network", "dane", "generate",
"--domain=example.org",
"--file=juliet.pgp",
"--cert-file=juliet.pgp",
],
}),
@ -100,7 +100,7 @@ records instead.
pub struct GenerateCommand {
#[command(flatten)]
pub certs: CertDesignators<CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OptionalValue>,
#[clap(

View File

@ -117,7 +117,7 @@ default, the certificates are sent to {}. This can be tweaked using \
pub struct PublishCommand {
#[command(flatten)]
pub certs: CertDesignators<FileCertUserIDEmailDomainArgs,
NoPrefix>,
CertPrefix>,
}
/// Joins the given key server URLs into a list.

View File

@ -9,7 +9,7 @@ use crate::cli::types::FileOrStdout;
use crate::cli::types::cert_designator::{
CertDesignators,
CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OptionalValue,
};
@ -178,7 +178,7 @@ be taken to avoid concurrent updates.
pub struct PublishCommand {
#[command(flatten)]
pub certs: CertDesignators<CertUserIDEmailFileArgs,
NoPrefix,
CertPrefix,
OptionalValue>,
#[clap(

View File

@ -591,7 +591,7 @@ retracted.
pub struct ListCommand {
#[command(flatten)]
pub certs: CertDesignators<CertUserIDEmailDomainGrepArgs,
NoPrefix,
CertPrefix,
OptionalValue>,
#[clap(
@ -628,7 +628,7 @@ with the email address alice@example.org.",
comment: "List all links in the example.org domain.",
command: &[
"sq", "pki", "link", "list",
"--domain=example.org",
"--cert-domain=example.org",
],
}),
],

View File

@ -330,7 +330,7 @@ fn update(
so that others can find it, for example using:",
path.display()))
.sq().arg("network").arg("keyserver").arg("publish")
.arg_value("--file", path.display())
.arg_value("--cert-file", path.display())
.done();
} else {
sq.hint(format_args!(

View File

@ -391,7 +391,7 @@ pub fn bind(sq: Sq, command: cli::key::subkey::bind::Command) -> Result<()>
so that others can find it, for example using:",
path.display()))
.sq().arg("network").arg("keyserver").arg("publish")
.arg_value("--file", path.display())
.arg_value("--cert-file", path.display())
.done();
} else {
sq.hint(format_args!(

View File

@ -230,7 +230,7 @@ where P: cert_designator::ArgumentPrefix,
so that others can find it, for example using:",
path.display()))
.sq().arg("network").arg("keyserver").arg("publish")
.arg_value("--file", path.display())
.arg_value("--cert-file", path.display())
.done();
} else {
sq.hint(format_args!(

View File

@ -448,7 +448,7 @@ The certifier is the same as the certificate to certify."));
so that others can find it, for example using:",
path.display()))
.sq().arg("network").arg("keyserver").arg("publish")
.arg_value("--file", path.display())
.arg_value("--cert-file", path.display())
.done();
} else {
sq.hint(format_args!(

View File

@ -2321,7 +2321,7 @@ impl<'store: 'rstore, 'rstore> Sq<'store, 'rstore> {
"--cert"
}
FileStdinOrKeyHandle::FileOrStdin(_file) => {
"--file"
"--cert-file"
}
},
match &cert_handle {

View File

@ -817,7 +817,7 @@ impl Sq {
match &cert_handle {
FileOrKeyHandle::FileOrStdin(path) => {
cmd.arg("--file").arg(path);
cmd.arg("--cert-file").arg(path);
assert!(output_file.is_some());
}
FileOrKeyHandle::KeyHandle((_kh, s)) => {
@ -859,7 +859,7 @@ impl Sq {
match &cert_handle {
FileOrKeyHandle::FileOrStdin(path) => {
cmd.arg("--file").arg(path);
cmd.arg("--cert-file").arg(path);
assert!(output_file.is_some());
}
FileOrKeyHandle::KeyHandle((_kh, s)) => {
@ -948,7 +948,7 @@ impl Sq {
cmd.arg("key").arg("password");
if cert_handle.is_file() {
cmd.arg("--file").arg(&cert_handle);
cmd.arg("--cert-file").arg(&cert_handle);
assert!(output_file.is_some());
} else {
cmd.arg("--cert").arg(&cert_handle);
@ -1011,7 +1011,7 @@ impl Sq {
}
if target.is_file() {
cmd.arg("--file").arg(&target);
cmd.arg("--cert-file").arg(&target);
} else {
cmd.arg("--cert").arg(&target);
};
@ -1114,7 +1114,7 @@ impl Sq {
.arg("--expiration").arg(expire);
if cert_handle.is_file() {
cmd.arg("--file").arg(&cert_handle);
cmd.arg("--cert-file").arg(&cert_handle);
assert!(output_file.is_some());
} else {
cmd.arg("--cert").arg(&cert_handle);
@ -1196,7 +1196,7 @@ impl Sq {
match &cert_handle {
FileOrKeyHandle::FileOrStdin(path) => {
cmd.arg("--file").arg(path);
cmd.arg("--cert-file").arg(path);
assert!(output_file.is_some());
}
FileOrKeyHandle::KeyHandle((_kh, s)) => {
@ -1250,7 +1250,7 @@ impl Sq {
match &cert_handle {
FileOrKeyHandle::FileOrStdin(path) => {
cmd.arg("--file").arg(path);
cmd.arg("--cert-file").arg(path);
assert!(output_file.is_some());
}
FileOrKeyHandle::KeyHandle((_kh, s)) => {
@ -1292,7 +1292,7 @@ impl Sq {
cmd.arg("key").arg("subkey").arg("password");
if cert_handle.is_file() {
cmd.arg("--file").arg(&cert_handle);
cmd.arg("--cert-file").arg(&cert_handle);
assert!(output_file.is_some());
} else {
cmd.arg("--cert").arg(&cert_handle);
@ -1341,7 +1341,7 @@ impl Sq {
.arg("--expiration").arg(expire);
if cert_handle.is_file() {
cmd.arg("--file").arg(&cert_handle);
cmd.arg("--cert-file").arg(&cert_handle);
assert!(output_file.is_some());
} else {
cmd.arg("--cert").arg(&cert_handle);

View File

@ -158,58 +158,58 @@ fn sq_cert_export() -> Result<()>
ua.userid().value()).into_owned();
let email = ua.userid().email2().unwrap().unwrap();
call(&["--userid", &userid], true && authenticated, &[data]);
call(&["--userid", &email], false, &[]);
call(&["--cert-userid", &userid], true && authenticated, &[data]);
call(&["--cert-userid", &email], false, &[]);
// Should be case sensitive.
call(&["--userid", &userid.deref().to_uppercase()], false, &[]);
call(&["--cert-userid", &userid.deref().to_uppercase()], false, &[]);
// Substring should fail.
call(&["--userid", &userid[1..]], false, &[]);
call(&["--cert-userid", &userid[1..]], false, &[]);
call(&["--email", &userid], false, &[]);
call(&["--email", &email], true && authenticated, &[data]);
call(&["--cert-email", &userid], false, &[]);
call(&["--cert-email", &email], true && authenticated, &[data]);
// Email is case insensitive.
call(&["--email", &email.to_uppercase()], true && authenticated,
call(&["--cert-email", &email.to_uppercase()], true && authenticated,
&[data]);
// Substring should fail.
call(&["--email", &email[1..]], false, &[]);
call(&["--cert-email", &email[1..]], false, &[]);
call(&["--grep", &userid], true && authenticated, &[data]);
call(&["--grep", &email], true && authenticated, &[data]);
call(&["--cert-grep", &userid], true && authenticated, &[data]);
call(&["--cert-grep", &email], true && authenticated, &[data]);
// Should be case insensitive.
call(&["--grep", &userid.deref().to_uppercase()],
call(&["--cert-grep", &userid.deref().to_uppercase()],
true && authenticated, &[data]);
// Substring should succeed.
call(&["--grep", &userid[1..]], true && authenticated, &[data]);
call(&["--cert-grep", &userid[1..]], true && authenticated, &[data]);
}
}
}
// By domain.
call(&["--domain", "example.org"], true, &[alice, bob]);
call(&["--domain", "EXAMPLE.ORG"], true, &[alice, bob]);
call(&["--domain", "sub.example.org"], true, &[carol]);
call(&["--domain", "SUB.EXAMPLE.ORG"], true, &[carol]);
call(&["--domain", "other.org"], true, &[carol]);
call(&["--cert-domain", "example.org"], true, &[alice, bob]);
call(&["--cert-domain", "EXAMPLE.ORG"], true, &[alice, bob]);
call(&["--cert-domain", "sub.example.org"], true, &[carol]);
call(&["--cert-domain", "SUB.EXAMPLE.ORG"], true, &[carol]);
call(&["--cert-domain", "other.org"], true, &[carol]);
call(&["--domain", "hello.com"], false, &[]);
call(&["--domain", "me@hello.com"], false, &[]);
call(&["--domain", "alice@example.org"], false, &[]);
call(&["--domain", "xample.org"], false, &[]);
call(&["--domain", "example.or"], false, &[]);
call(&["--domain", "@example.org"], false, &[]);
call(&["--cert-domain", "hello.com"], false, &[]);
call(&["--cert-domain", "me@hello.com"], false, &[]);
call(&["--cert-domain", "alice@example.org"], false, &[]);
call(&["--cert-domain", "xample.org"], false, &[]);
call(&["--cert-domain", "example.or"], false, &[]);
call(&["--cert-domain", "@example.org"], false, &[]);
// Match a cert in many ways. It should only be exported
// once.
call(&["--cert", &carol.cert().fingerprint().to_string(),
"--userid", carol.userids[0],
"--email", "carol@sub.example.org",
"--domain", "other.org"
"--cert-userid", carol.userids[0],
"--cert-email", "carol@sub.example.org",
"--cert-domain", "other.org"
], true, &[carol]);
// Match multiple certs in different ways.
call(&["--cert", &alice.cert().fingerprint().to_string(),
"--cert", &bob.cert().fingerprint().to_string(),
"--email", "carol@sub.example.org",
"--cert-email", "carol@sub.example.org",
], true, &[alice, bob, carol]);
Ok(())

View File

@ -89,7 +89,7 @@ fn t(base: &str, prv: Option<&str>, passwords: &[&str],
if keystore {
cmd.arg("--cert").arg(&cert.fingerprint().to_string());
} else {
cmd.arg("--file").arg(filename);
cmd.arg("--cert-file").arg(filename);
}
cmd
@ -135,7 +135,7 @@ fn t(base: &str, prv: Option<&str>, passwords: &[&str],
]);
} else {
cmd.args([
"--file", &format!("{}-{}.pgp", base, suffix),
"--cert-file", &format!("{}-{}.pgp", base, suffix),
]);
}
for p in passwords.iter() {
@ -159,7 +159,7 @@ fn t(base: &str, prv: Option<&str>, passwords: &[&str],
cmd.arg("--cert")
.arg(&cert.fingerprint().to_string());
} else {
cmd.arg("--file").arg("-")
cmd.arg("--cert-file").arg("-")
.write_stdin(output);
}
@ -483,7 +483,7 @@ fn signature() {
.args(&[
"cert", "lint",
"--time", FROZEN_TIME,
"--file", "msg.sig",
"--cert-file", "msg.sig",
])
.assert()
// If there are issues, the command fails.

View File

@ -39,7 +39,7 @@ fn sq_key_expire() -> Result<()> {
} else {
cmd
.arg("--overwrite")
.arg("--file").arg(&cert_path)
.arg("--cert-file").arg(&cert_path)
.arg("--output").arg(&updated_path);
}
sq.run(cmd, true);
@ -81,7 +81,7 @@ fn sq_key_expire() -> Result<()> {
cmd.args([ "--cert", &fpr ]);
} else {
cmd.args([
"--file", &updated_path.to_string_lossy(),
"--cert-file", &updated_path.to_string_lossy(),
"--output", &updated2_path.to_string_lossy(),
]);
}

View File

@ -56,7 +56,7 @@ fn sq_key_subkey() -> Result<()> {
"--overwrite",
"--output",
&modified_cert_path.to_string_lossy(),
"--file", &cert_path.to_string_lossy(),
"--cert-file", &cert_path.to_string_lossy(),
]);
}
cmd.assert().success();
@ -112,7 +112,7 @@ fn sq_key_subkey_add_with_password() -> Result<()> {
"subkey",
"add",
"--can-authenticate",
"--file", &cert_path.display().to_string(),
"--cert-file", &cert_path.display().to_string(),
"--password-file", &path2.display().to_string(),
"--new-password-file", &path3.display().to_string(),
"--output", &output.display().to_string(),
@ -264,7 +264,7 @@ fn sq_key_subkey_revoke() -> Result<()> {
]);
} else {
cmd.arg("--output").arg(&revocation)
.arg("--file").arg(&cert_path);
.arg("--cert-file").arg(&cert_path);
}
for (k, v) in notations {
@ -518,7 +518,7 @@ fn sq_key_subkey_revoke_thirdparty() -> Result<()> {
]);
} else {
cmd.arg("--output").arg(&revocation)
.arg("--file").arg(&cert_path)
.arg("--cert-file").arg(&cert_path)
.arg("--revoker-file").arg(&thirdparty_path);
}

View File

@ -57,7 +57,7 @@ fn sq_key_subkey_expire() -> Result<()> {
} else {
cmd
.arg("--overwrite")
.arg("--file").arg(&cert_path)
.arg("--cert-file").arg(&cert_path)
.arg("--output").arg(&updated_path);
}
for k in expiring.iter() {
@ -118,7 +118,7 @@ fn sq_key_subkey_expire() -> Result<()> {
} else {
cmd
.arg("--overwrite")
.arg("--file").arg(&updated_path)
.arg("--cert-file").arg(&updated_path)
.arg("--output").arg(&updated2_path);
}
for k in expiring.iter() {

View File

@ -81,7 +81,7 @@ fn by_email() {
let mut cmd = sq.command();
cmd.args([
"key", "subkey", "export",
"--email", "alice@example.org",
"--cert-email", "alice@example.org",
"--key", &cert1.fingerprint().to_string(),
]);
let output = sq.run(cmd, i == 1);