diff --git a/NEWS b/NEWS index 9058676a..b0022210 100644 --- a/NEWS +++ b/NEWS @@ -72,6 +72,9 @@ - Add the `--domain` argument to `sq pki authorize` so the user doesn't have to manually convert a domain to a regular expression. + - `sq pki link add`'s positional argument for specifying the + certificate to link must now be specified using a named + argument, `--cert`. * Changes in 0.38.0 ** Notable changes diff --git a/src/cli/encrypt.rs b/src/cli/encrypt.rs index 39d8e886..47e4b330 100644 --- a/src/cli/encrypt.rs +++ b/src/cli/encrypt.rs @@ -27,7 +27,7 @@ const ENCRYPT_EXAMPLES: Actions = Actions { Action::Setup(Setup { command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email", "alice@example.org", ], }), diff --git a/src/cli/key/approvals.rs b/src/cli/key/approvals.rs index cf66096c..29e3897b 100644 --- a/src/cli/key/approvals.rs +++ b/src/cli/key/approvals.rs @@ -148,7 +148,7 @@ const UPDATE_EXAMPLES: Actions = Actions { Action::Setup(Setup { command: &[ "sq", "pki", "link", "add", - "511257EBBF077B7AEDAE5D093F68CB84CE537C9A", + "--cert", "511257EBBF077B7AEDAE5D093F68CB84CE537C9A", "--email", "bob@example.org", ], }), diff --git a/src/cli/pki.rs b/src/cli/pki.rs index 45ea88b6..9dbde193 100644 --- a/src/cli/pki.rs +++ b/src/cli/pki.rs @@ -68,7 +68,8 @@ const AUTHENTICATE_EXAMPLES: Actions = Actions { Action::Setup(Setup { command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--all", ], }), Action::Example(Example { @@ -143,7 +144,8 @@ const LOOKUP_EXAMPLES: Actions = Actions { Action::Setup(Setup { command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--all", ], }), Action::Example(Example { @@ -208,7 +210,8 @@ const IDENTIFY_EXAMPLES: Actions = Actions { Action::Setup(Setup { command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--all", ], }), Action::Example(Example { @@ -270,7 +273,8 @@ const LIST_EXAMPLES: Actions = Actions { Action::Setup(Setup { command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--all", ], }), Action::Example(Example { diff --git a/src/cli/pki/link.rs b/src/cli/pki/link.rs index cbf0d6ca..d5c4ffd3 100644 --- a/src/cli/pki/link.rs +++ b/src/cli/pki/link.rs @@ -6,6 +6,8 @@ use sequoia_openpgp as openpgp; use openpgp::KeyHandle; use crate::cli::examples::*; +use crate::cli::types::CertDesignators; +use crate::cli::types::cert_designator; use crate::cli::types::Expiration; use crate::cli::types::TrustAmount; @@ -68,7 +70,7 @@ Link the certificate EB28F26E2739A4870ECC47726F0073F60FD0CBF0 \ with the email address alice@example.org.", command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email=alice@example.org", ], }), @@ -81,7 +83,7 @@ user IDs for a week.", command: &[ "sq", "pki", "link", "add", "--expiration=1w", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -95,7 +97,7 @@ certificate is considered a trusted introducer for example.org.", command: &[ "sq", "pki", "link", "add", "--ca=example.org", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -275,12 +277,12 @@ to force the signature to be re-created anyway.", The special keyword `never` sets an unlimited expiry.", )] pub expiration: Expiration, - #[clap( - value_name = "FINGERPRINT|KEYID", - required = true, - help = "The certificate to accept.", - )] - pub certificate: KeyHandle, + + #[command(flatten)] + pub cert: CertDesignators< + cert_designator::CertArg, + cert_designator::CertPrefix, + cert_designator::OneValue>, #[clap( long = "all", @@ -351,7 +353,7 @@ Link the certificate EB28F26E2739A4870ECC47726F0073F60FD0CBF0 \ with the email address alice@example.org.", command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email=alice@example.org", ], }), @@ -373,7 +375,7 @@ user IDs for a week.", command: &[ "sq", "pki", "link", "add", "--expiration=1w", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -385,7 +387,7 @@ EB28F26E2739A4870ECC47726F0073F60FD0CBF0 with all of its self-signed \ user IDs.", command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -398,7 +400,7 @@ authority. That is, the certificate is considered a trust root.", command: &[ "sq", "pki", "link", "add", "--ca=*", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -412,7 +414,7 @@ certificate is considered a trusted introducer for example.org.", command: &[ "sq", "pki", "link", "add", "--ca=example.org", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -426,7 +428,7 @@ certification authority.", "sq", "pki", "link", "add", "--ca=*", "--amount=60", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--all", ], }), @@ -531,7 +533,7 @@ Link the certificate EB28F26E2739A4870ECC47726F0073F60FD0CBF0 \ with the email address alice@example.org.", command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email=alice@example.org", ], }), @@ -591,7 +593,7 @@ Link the certificate EB28F26E2739A4870ECC47726F0073F60FD0CBF0 \ with the email address alice@example.org.", command: &[ "sq", "pki", "link", "add", - "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", + "--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0", "--email=alice@example.org", ], }), diff --git a/src/cli/verify.rs b/src/cli/verify.rs index 45d0327c..e78b852d 100644 --- a/src/cli/verify.rs +++ b/src/cli/verify.rs @@ -25,7 +25,7 @@ const VERIFY_EXAMPLES: Actions = Actions { command: &[ "sq", "--time", "2024-06-19", "pki", "link", "add", - "7A58B15E3B9459483D9FFA8D40E299AC5F2B0872", + "--cert", "7A58B15E3B9459483D9FFA8D40E299AC5F2B0872", "--email", "juliet@example.org", ], }), diff --git a/src/commands.rs b/src/commands.rs index 2aa4239a..41542a19 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -497,7 +497,7 @@ impl<'c, 'store, 'rstore> VHelper<'c, 'store, 'rstore> { you can authenticate the binding using:", cert_fpr, signer_userid)) .sq().arg("pki").arg("link").arg("add") - .arg(cert_fpr) + .arg("--cert").arg(cert_fpr) .arg(signer_userid) .done(); } @@ -512,7 +512,7 @@ impl<'c, 'store, 'rstore> VHelper<'c, 'store, 'rstore> { you can authenticate the binding using:", cert_fpr, signer_userid)) .sq().arg("pki").arg("link").arg("add") - .arg(cert_fpr) + .arg("--cert").arg(cert_fpr) .arg(signer_userid) .done(); } diff --git a/src/commands/key/generate.rs b/src/commands/key/generate.rs index 0a62fd24..febebf25 100644 --- a/src/commands/key/generate.rs +++ b/src/commands/key/generate.rs @@ -258,13 +258,13 @@ pub fn generate( fully trusted introducer:")) .sq().arg("pki").arg("link").arg("add") .arg_value("--ca", "*") - .arg(cert.fingerprint()) + .arg("--cert").arg(cert.fingerprint()) .arg("--all") .done(); sq.hint(format_args!("Otherwise, you should mark it as authenticated:")) .sq().arg("pki").arg("link").arg("add") - .arg(cert.fingerprint()) + .arg("--cert").arg(cert.fingerprint()) .arg("--all") .done(); diff --git a/src/commands/network.rs b/src/commands/network.rs index 7890e332..b2b5231e 100644 --- a/src/commands/network.rs +++ b/src/commands/network.rs @@ -143,7 +143,7 @@ pub fn import_certs(sq: &Sq, certs: Vec) -> Result<()> { { hint = hint .sq().arg("pki").arg("link").arg("add") - .arg(vcert.fingerprint()) + .arg("--cert").arg(vcert.fingerprint()) .arg_value("--userid", uid) .done(); @@ -155,7 +155,7 @@ pub fn import_certs(sq: &Sq, certs: Vec) -> Result<()> { "Alternatively, all user IDs can be marked as authenticated \ using:")) .sq().arg("pki").arg("link").arg("add") - .arg(vcert.fingerprint()) + .arg("--cert").arg(vcert.fingerprint()) .arg("--all") .done(); } diff --git a/src/commands/pki/link.rs b/src/commands/pki/link.rs index b2c9c2bc..38569be2 100644 --- a/src/commands/pki/link.rs +++ b/src/commands/pki/link.rs @@ -211,7 +211,8 @@ pub fn add(sq: Sq, c: link::AddCommand) let trust_root = sq.local_trust_root()?; let trust_root = trust_root.to_cert()?; - let cert = sq.lookup_one(&c.certificate, None, true)?; + let (cert, _from_file) + = sq.resolve_cert(&c.cert, sequoia_wot::FULLY_TRUSTED)?; let mut userids = check_userids(&sq, &cert, true, &c.userid, &c.email, &c.pattern) diff --git a/tests/integration/common.rs b/tests/integration/common.rs index 4cdd562a..e8d82063 100644 --- a/tests/integration/common.rs +++ b/tests/integration/common.rs @@ -1498,7 +1498,7 @@ impl Sq { for arg in extra_args { cmd.arg(arg); } - cmd.arg(&cert.to_string()); + cmd.arg("--cert").arg(cert.to_string()); cmd.arg(userid); let output = self.run(cmd, None); diff --git a/tests/integration/sq_key_approvals_update.rs b/tests/integration/sq_key_approvals_update.rs index 218551e2..961ef663 100644 --- a/tests/integration/sq_key_approvals_update.rs +++ b/tests/integration/sq_key_approvals_update.rs @@ -219,7 +219,7 @@ fn update_authenticated() -> Result<()> { // Link Bob's cert to his user ID. let mut link = sq.command(); - link.args(&["pki", "link", "add", &bob_fp, BOB_USERID]); + link.args(&["pki", "link", "add", "--cert", &bob_fp, BOB_USERID]); sq.run(link, true); // Attest Bob's certification. diff --git a/tests/integration/sq_pki_link.rs b/tests/integration/sq_pki_link.rs index 67eff658..fe4f310b 100644 --- a/tests/integration/sq_pki_link.rs +++ b/tests/integration/sq_pki_link.rs @@ -93,7 +93,8 @@ fn sq_link(sq: &Sq, -> (ExitStatus, String, String) { let mut cmd = sq.command(); - cmd.args(&["pki", "link", "add", "--time", &tick(), cert]); + cmd.args(&["pki", "link", "add", "--time", &tick()]); + cmd.arg("--cert").arg(cert); cmd.args(userids); cmd.args(more_args); let output = sq.run(cmd, None);