Modify the sq key revoke tests to test the cert store integration.

- Modify the `sq key revoke` tests to also test the cert store and
    key store integration.

  - Somehow this wasn't added to
    cca564356c958ca90e4a7d3fdbe627ff16de1b46.
This commit is contained in:
Neal H. Walfield 2024-05-28 15:04:48 +02:00
parent ab0e2a446c
commit 3debf8b584
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3

View File

@ -1,13 +1,13 @@
use assert_cmd::Command;
use tempfile::TempDir;
use chrono::Duration;
use openpgp::parse::Parse;
use openpgp::types::ReasonForRevocation;
use openpgp::types::RevocationStatus;
use openpgp::types::SignatureType;
use openpgp::Cert;
use openpgp::Packet;
use openpgp::PacketPile;
use openpgp::Result;
use sequoia_openpgp as openpgp;
@ -18,9 +18,10 @@ use common::STANDARD_POLICY;
#[test]
fn sq_key_revoke() -> Result<()> {
let (tmpdir, path, time) = sq_key_generate(None)?;
let (tmpdir, cert_path, time) = sq_key_generate(None)?;
let cert_path = cert_path.display().to_string();
let cert = Cert::from_file(&path)?;
let cert = Cert::from_file(&cert_path)?;
let valid_cert = cert.with_policy(STANDARD_POLICY, Some(time.into()))?;
let fingerprint = &valid_cert.clone().fingerprint();
@ -49,12 +50,6 @@ fn sq_key_revoke() -> Result<()> {
None,
),
(ReasonForRevocation::KeyRetired, "retired", None, None),
(
ReasonForRevocation::KeyRetired,
"retired",
None,
Some(time + Duration::hours(1)),
),
(
ReasonForRevocation::KeyRetired,
"retired",
@ -62,12 +57,6 @@ fn sq_key_revoke() -> Result<()> {
None,
),
(ReasonForRevocation::KeySuperseded, "superseded", None, None),
(
ReasonForRevocation::KeySuperseded,
"superseded",
None,
Some(time + Duration::hours(1)),
),
(
ReasonForRevocation::KeySuperseded,
"superseded",
@ -88,7 +77,18 @@ fn sq_key_revoke() -> Result<()> {
None,
),
] {
let revocation = &path.parent().unwrap().join(format!(
eprintln!("==========================");
eprintln!("reason: {}, message: {}, notations: {:?}, time: {:?}",
reason, reason_str, notations, revocation_time);
for keystore in [false, true].into_iter() {
eprintln!("--------------------------");
eprintln!("keystore: {}", keystore);
let home = TempDir::new().unwrap();
let home = home.path().display().to_string();
let revocation = &tmpdir.path().join(format!(
"revocation_{}_{}_{}.rev",
reason_str,
if notations.is_some() {
@ -103,19 +103,46 @@ fn sq_key_revoke() -> Result<()> {
}
));
if keystore {
// When using the keystore, we need to import the key.
let mut cmd = Command::cargo_bin("sq")?;
cmd.args([
"--no-cert-store",
"--no-key-store",
"--home", &home,
"key",
"import",
&cert_path,
]);
let output = cmd.output()?;
if !output.status.success() {
panic!(
"sq exited with non-zero status code: {}",
String::from_utf8(output.stderr)?
);
}
}
let mut cmd = Command::cargo_bin("sq")?;
cmd.args([
"--home", &home,
"key",
"revoke",
"--output",
&revocation.to_string_lossy(),
"--cert-file",
&path.to_string_lossy(),
reason_str,
message,
]);
if keystore {
cmd.args([
"--cert", &cert.fingerprint().to_string(),
]);
} else {
cmd.args([
"--output",
&revocation.to_string_lossy(),
"--cert-file",
&cert_path,
]);
}
if let Some(notations) = notations {
for (k, v) in notations {
cmd.args(["--notation", k, v]);
@ -135,24 +162,43 @@ fn sq_key_revoke() -> Result<()> {
);
}
// We should get the primary key and the revocation signature.
let packet_pile = PacketPile::from_file(&revocation)?;
if keystore {
// When using the keystore, we need to export the
// revoked certificate.
assert_eq!(
packet_pile.children().count(),
2,
"expected the primary key and the revocation signature"
let mut cmd = Command::cargo_bin("sq")?;
cmd.args([
"--home", &home,
"cert",
"export",
"--cert", &cert.fingerprint().to_string(),
]);
let output = cmd.output()?;
if !output.status.success() {
panic!(
"sq exited with non-zero status code: {}",
String::from_utf8(output.stderr)?
);
}
std::fs::write(&revocation, &output.stdout)
.expect(&format!("Writing {}", &revocation.display()));
}
let updated = Cert::from_file(&revocation).expect("valid cert");
if let RevocationStatus::Revoked(sigs)
= updated.revocation_status(STANDARD_POLICY, None)
{
assert_eq!(sigs.len(), 1);
let sig = sigs.into_iter().next().unwrap();
if let Some(Packet::Signature(sig)) = packet_pile.path_ref(&[1]) {
// the issuer is the certificate owner
assert_eq!(
sig.get_issuers().into_iter().next(),
Some(fingerprint.into())
);
let cert = Cert::from_file(&path)?;
let revoked_cert = cert.insert_packets(sig.clone()).unwrap();
let revoked_cert = cert.clone().insert_packets(sig.clone()).unwrap();
let status = revoked_cert
.with_policy(STANDARD_POLICY, revocation_time.map(Into::into))
.unwrap()
@ -176,7 +222,8 @@ fn sq_key_revoke() -> Result<()> {
// we passed in
compare_notations(sig, notations)?;
} else {
panic!("Expected a signature, got: {:?}", packet_pile);
panic!("Not revoked");
}
}
}
@ -187,11 +234,13 @@ fn sq_key_revoke() -> Result<()> {
#[test]
fn sq_key_revoke_thirdparty() -> Result<()> {
let (tmpdir, path, _) = sq_key_generate(None)?;
let cert = Cert::from_file(&path)?;
let (tmpdir, cert_path, _) = sq_key_generate(None)?;
let cert_path = cert_path.display().to_string();
let cert = Cert::from_file(&cert_path)?;
let (thirdparty_tmpdir, thirdparty_path, thirdparty_time) =
sq_key_generate(Some(&["bob <bob@example.org>"]))?;
let thirdparty_path = thirdparty_path.display().to_string();
let thirdparty_cert = Cert::from_file(&thirdparty_path)?;
let thirdparty_valid_cert = thirdparty_cert
.with_policy(STANDARD_POLICY, Some(thirdparty_time.into()))?;
@ -261,7 +310,11 @@ fn sq_key_revoke_thirdparty() -> Result<()> {
None,
),
] {
let revocation = &path.parent().unwrap().join(format!(
for keystore in [false, true].into_iter() {
let home = TempDir::new().unwrap();
let home = home.path().display().to_string();
let revocation = &tmpdir.path().join(format!(
"revocation_{}_{}_{}.rev",
reason_str,
if notations.is_some() {
@ -276,21 +329,52 @@ fn sq_key_revoke_thirdparty() -> Result<()> {
}
));
if keystore {
// When using the keystore, we need to import the key.
for path in &[ &cert_path, &thirdparty_path ] {
let mut cmd = Command::cargo_bin("sq")?;
cmd.args([
"--no-cert-store",
"--no-key-store",
"--home", &home,
"key",
"import",
&path,
]);
let output = cmd.output()?;
if !output.status.success() {
panic!(
"sq exited with non-zero status code: {}",
String::from_utf8(output.stderr)?
);
}
}
}
let mut cmd = Command::cargo_bin("sq")?;
cmd.args([
"--home", &home,
"key",
"revoke",
"--output",
&revocation.to_string_lossy(),
"--cert-file",
&path.to_string_lossy(),
"--revoker-file",
&thirdparty_path.to_string_lossy(),
reason_str,
message,
]);
if keystore {
cmd.args([
"--cert", &cert.fingerprint().to_string(),
"--revoker", &thirdparty_cert.fingerprint().to_string(),
]);
} else {
cmd.args([
"--output",
&revocation.to_string_lossy(),
"--cert-file",
&cert_path,
"--revoker-file",
&thirdparty_path,
]);
}
if let Some(notations) = notations {
for (k, v) in notations {
cmd.args(["--notation", k, v]);
@ -310,6 +394,28 @@ fn sq_key_revoke_thirdparty() -> Result<()> {
);
}
if keystore {
// When using the keystore, we need to export the
// revoked certificate.
let mut cmd = Command::cargo_bin("sq")?;
cmd.args([
"--home", &home,
"cert",
"export",
"--cert", &cert.fingerprint().to_string(),
]);
let output = cmd.output()?;
if !output.status.success() {
panic!(
"sq exited with non-zero status code: {}",
String::from_utf8(output.stderr)?
);
}
std::fs::write(&revocation, &output.stdout)
.expect(&format!("Writing {}", &revocation.display()));
}
// read revocation cert
let revocation_cert = Cert::from_file(&revocation)?;
assert!(! revocation_cert.is_tsk());
@ -356,6 +462,7 @@ fn sq_key_revoke_thirdparty() -> Result<()> {
panic!("there are no signatures in {:?}", status);
}
}
}
tmpdir.close()?;
thirdparty_tmpdir.close()?;