Make sq pki path's user ID argument a named argument.

- See #318.
This commit is contained in:
Neal H. Walfield 2024-11-14 13:02:02 +01:00
parent 428e4dbde3
commit 0e36a20d97
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
4 changed files with 78 additions and 175 deletions

3
NEWS
View File

@ -60,6 +60,9 @@
should be used even if there is no corresponding self-signed user
ID. This functionality is replaced by the `--add-userid`,
`--add-email` and `--add-name` arguments.
- `sq pki path` previously interpreted the last positional argument
as the user ID to authenticate. Make it a named argument
instead, `--userid`.
* Changes in 0.39.0
** Notable changes

View File

@ -9,8 +9,6 @@ use examples::Action;
use examples::Actions;
use examples::Example;
use crate::Result;
use super::CertificationNetworkArg;
use super::RequiredTrustAmountArg;
@ -32,22 +30,33 @@ use super::RequiredTrustAmountArg;
after_help = EXAMPLES,
)]
pub struct Command {
#[clap(
value_name = "FINGERPRINT|KEYID",
required = true,
num_args = 1..,
help = "The path to authenticate",
long_help = "\
The path to authenticate.
A path consists of one or more certificates. The first certificate is \
the root, and the last certificate is the one being authenticated for \
the specified user ID.
",
)]
pub path: Vec<KeyHandle>,
#[clap(
long = "userid",
value_name = "USERID",
help = "The user ID to authenticate",
)]
pub userid: UserID,
#[command(flatten)]
pub certification_network: CertificationNetworkArg,
#[command(flatten)]
pub trust_amount: RequiredTrustAmountArg,
// This should actually be a repeatable positional argument
// (Vec<Cert>) followed by a manadatory positional argument (a
// User ID), but that is not allowed by Clap v3 and Clap v4
// even though it worked fine in Clap v2. (Curiously, it
// works in `--release` mode fine and the only error appears
// to be one caught by a `debug_assert`).
//
// https://github.com/clap-rs/clap/issues/3281
#[command(flatten)]
pub path: PathArg,
}
const EXAMPLES: Actions = Actions {
@ -59,75 +68,9 @@ Verify that Alice ceritified a particular User ID for Bob's certificate.",
"sq", "pki", "path",
"EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
"511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
"Bob <bob@example.org>",
"--userid", "Bob <bob@example.org>",
],
})
],
};
test_examples!(sq_pki_path, EXAMPLES);
#[derive(clap::Args, Debug)]
pub struct PathArg {
/// A path consists of one or more certificates (designated by
/// their fingerprint or Key ID) and ending in the User ID that is
/// being authenticated.
#[arg(value_names=["FINGERPRINT|KEYID", "USERID"])]
elements: Vec<String>,
}
const PATH_DESC: &str = "\
A path consists of one or more certificates (identified by their
respective fingerprint or Key ID) and a User ID.";
impl PathArg {
fn check(&self) -> Result<()> {
if self.elements.len() < 2 {
Err(anyhow::anyhow!(
"\
The following required arguments were not provided:
{}<USERID>
{}
Usage: sq pki path <FINGERPRINT|KEYID>... <USERID>
For more information try '--help'",
if self.elements.len() == 0 {
"<FINGERPRINT|KEYID>\n "
} else {
""
},
PATH_DESC))
} else {
Ok(())
}
}
pub fn certs(&self) -> Result<Vec<KeyHandle>> {
self.check()?;
// Skip the last one. That's the User ID.
self.elements[0..self.elements.len() - 1]
.iter()
.map(|e| {
e.parse()
.map_err(|err| {
anyhow::anyhow!(
"Invalid value {:?} for '<FINGERPRINT|KEYID>': {}
{}
For more information try '--help'",
e, err, PATH_DESC)
})
})
.collect::<Result<Vec<KeyHandle>>>()
}
pub fn userid(&self) -> Result<UserID> {
self.check()?;
let userid = self.elements.last().expect("just checked");
Ok(UserID::from(userid.as_bytes()))
}
}

View File

@ -16,7 +16,7 @@ pub fn path(sq: Sq, c: Command)
-> Result<()>
{
let Command {
certification_network, trust_amount, path,
certification_network, trust_amount, path, userid,
} = c;
// Build the network.
@ -39,12 +39,11 @@ pub fn path(sq: Sq, c: Command)
let required_amount =
required_trust_amount(*trust_amount, *certification_network)?;
let (khs, userid) = (path.certs()?, path.userid()?);
assert!(khs.len() > 0, "guaranteed by clap");
assert!(path.len() > 0, "guaranteed by clap");
let r = q.lint_path(&khs, &userid, required_amount, sq.policy);
let r = q.lint_path(&path, &userid, required_amount, sq.policy);
let target_kh = khs.last().expect("have one");
let target_kh = path.last().expect("have one");
let trust_amount = match r {
Ok(path) => {

View File

@ -116,6 +116,9 @@ where
cmd.arg(&target.to_string());
}
if let Some(userid) = userid {
if command == "path" {
cmd.arg("--userid");
}
cmd.arg(format!("{}", String::from_utf8_lossy(userid.value())));
}
for arg in args {
@ -1677,10 +1680,9 @@ fn path_simple() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&String::from_utf8_lossy(bob_uid.value()),
],
120,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),
@ -1696,10 +1698,9 @@ fn path_simple() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&String::from_utf8_lossy(bob_uid.value()),
],
100,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -1718,10 +1719,9 @@ fn path_simple() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(bob_uid.value()),
],
100,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),
@ -1740,10 +1740,9 @@ fn path_simple() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
100,
None,
Some(&carol_uid),
None,
true,
&output_map(&human_output),
@ -1764,10 +1763,9 @@ fn path_simple() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&String::from_utf8_lossy(dave_uid.value()),
],
100,
None,
Some(&dave_uid),
None,
true,
&output_map(&human_output),
@ -1790,10 +1788,9 @@ fn path_simple() -> Result<()> {
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&ellen_fpr.to_string(),
&String::from_utf8_lossy(ellen_uid.value()),
],
100,
None,
Some(&ellen_uid),
None,
false,
&output_map(&human_output),
@ -1814,10 +1811,9 @@ fn path_simple() -> Result<()> {
&bob_fpr.to_string(),
&dave_fpr.to_string(),
&ellen_fpr.to_string(),
&String::from_utf8_lossy(ellen_uid.value()),
],
100,
None,
Some(&ellen_uid),
None,
false,
&output_map(&human_output),
@ -1892,10 +1888,9 @@ fn path_missing_certs() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
100,
None,
Some(&carol_uid),
None,
true,
&output_map(&human_output),
@ -1912,10 +1907,9 @@ fn path_missing_certs() -> Result<()> {
&missing_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
100,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -1932,10 +1926,9 @@ fn path_missing_certs() -> Result<()> {
&alice_fpr.to_string(),
&missing_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
100,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -1952,10 +1945,9 @@ fn path_missing_certs() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&missing_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
100,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2027,10 +2019,9 @@ fn path_singleton() -> Result<()> {
command,
&[
&alice_fpr.to_string(),
&String::from_utf8_lossy(alice_uid.value()),
],
120,
None,
Some(&alice_uid),
None,
true,
&output_map(&human_output),
@ -2046,10 +2037,9 @@ fn path_singleton() -> Result<()> {
command,
&[
&alice_fpr.to_string(),
&String::from_utf8_lossy(bob_uid.value()),
],
120,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),
@ -2114,10 +2104,9 @@ fn path_multiple_userids_1() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&String::from_utf8_lossy(dave_uid.value()),
],
70,
None,
Some(&dave_uid),
None,
false,
&output_map(&human_output),
@ -2136,10 +2125,9 @@ fn path_multiple_userids_1() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&String::from_utf8_lossy(dave_uid.value()),
],
50,
None,
Some(&dave_uid),
None,
true,
&output_map(&human_output),
@ -2217,10 +2205,9 @@ fn path_multiple_users_2() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&frank_fpr.to_string(),
&String::from_utf8_lossy(frank_uid.value()),
],
70,
None,
Some(&frank_uid),
None,
true,
&output_map(&human_output),
@ -2241,10 +2228,9 @@ fn path_multiple_users_2() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
70,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2262,10 +2248,9 @@ fn path_multiple_users_2() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
50,
None,
Some(&carol_uid),
None,
true,
&output_map(&human_output),
@ -2288,10 +2273,9 @@ fn path_multiple_users_2() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&String::from_utf8_lossy(dave_uid.value()),
],
70,
None,
Some(&dave_uid),
None,
true,
&output_map(&human_output),
@ -2314,10 +2298,9 @@ fn path_multiple_users_2() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&ed_fpr.to_string(),
&String::from_utf8_lossy(ed_uid.value()),
],
70,
None,
Some(&ed_uid),
None,
false,
&output_map(&human_output),
@ -2377,10 +2360,9 @@ fn path_sha1() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
120,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2398,10 +2380,9 @@ fn path_sha1() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
60,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2423,10 +2404,9 @@ fn path_sha1() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
120,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2443,10 +2423,9 @@ fn path_sha1() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&String::from_utf8_lossy(carol_uid.value()),
],
60,
None,
Some(&carol_uid),
None,
true,
&output_map(&human_output),
@ -2828,10 +2807,9 @@ fn path_certification_network() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
120,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -2848,10 +2826,9 @@ fn path_certification_network() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&carol_uid.to_string(),
],
120,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2869,10 +2846,9 @@ fn path_certification_network() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&dave_uid.to_string(),
],
120,
None,
Some(&dave_uid),
None,
false,
&output_map(&human_output),
@ -2892,10 +2868,9 @@ fn path_certification_network() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
120,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -2912,10 +2887,9 @@ fn path_certification_network() -> Result<()> {
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&carol_uid.to_string(),
],
120,
None,
Some(&carol_uid),
None,
true,
&output_map(&human_output),
@ -2933,10 +2907,9 @@ fn path_certification_network() -> Result<()> {
&bob_fpr.to_string(),
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&dave_uid.to_string(),
],
120,
None,
Some(&dave_uid),
None,
true,
&output_map(&human_output),
@ -2953,10 +2926,9 @@ fn path_certification_network() -> Result<()> {
&[
&alice_fpr.to_string(),
&carol_fpr.to_string(),
&carol_uid.to_string(),
],
120,
None,
Some(&carol_uid),
None,
false,
&output_map(&human_output),
@ -2977,10 +2949,9 @@ fn path_certification_network() -> Result<()> {
&[
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&alice_uid.to_string(),
],
120,
None,
Some(&alice_uid),
None,
false,
&output_map(&human_output),
@ -2996,10 +2967,9 @@ fn path_certification_network() -> Result<()> {
&[
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&alice_uid.to_string(),
],
60,
None,
Some(&alice_uid),
None,
true,
&output_map(&human_output),
@ -3017,10 +2987,9 @@ fn path_certification_network() -> Result<()> {
&[
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&alice_uid.to_string(),
],
120,
None,
Some(&alice_uid),
None,
false,
&output_map(&human_output),
@ -3036,10 +3005,9 @@ fn path_certification_network() -> Result<()> {
&[
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&alice_uid.to_string(),
],
60,
None,
Some(&alice_uid),
None,
true,
&output_map(&human_output),
@ -3060,10 +3028,9 @@ fn path_certification_network() -> Result<()> {
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&alice_uid.to_string(),
],
60,
None,
Some(&alice_uid),
None,
false,
&output_map(&human_output),
@ -3083,10 +3050,9 @@ fn path_certification_network() -> Result<()> {
&carol_fpr.to_string(),
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&alice_uid.to_string(),
],
60,
None,
Some(&alice_uid),
None,
true,
&output_map(&human_output),
@ -3104,10 +3070,9 @@ fn path_certification_network() -> Result<()> {
&dave_fpr.to_string(),
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -3265,10 +3230,9 @@ fn target_cert_expired() -> Result<()> {
"20200214",
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -3304,10 +3268,9 @@ fn target_cert_expired() -> Result<()> {
"20200216",
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),
@ -3381,10 +3344,9 @@ fn target_cert_hard_revoked() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),
@ -3462,10 +3424,9 @@ fn target_cert_soft_revoked() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -3499,10 +3460,9 @@ fn target_cert_soft_revoked() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),
@ -3572,10 +3532,9 @@ fn target_userid_revoked() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
true,
&output_map(&human_output),
@ -3609,10 +3568,9 @@ fn target_userid_revoked() -> Result<()> {
&[
&alice_fpr.to_string(),
&bob_fpr.to_string(),
&bob_uid.to_string(),
],
60,
None,
Some(&bob_uid),
None,
false,
&output_map(&human_output),