Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ pub enum Error {
path: DisplayPath,
source: serde_yaml::Error,
},
#[snafu(display("key provided multiple times: `{key}`"))]
DuplicateKey {
backtrace: Option<Backtrace>,
key: PublicKey,
},
#[snafu(display("{count} mismatched file{}", if *count == 1 { "" } else { "s" }))]
EntryMismatch {
backtrace: Option<Backtrace>,
Expand Down
19 changes: 16 additions & 3 deletions src/subcommand/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ pub(crate) struct Verify {
fingerprint: Option<Hash>,
#[arg(help = "Ignore missing files", long)]
ignore_missing: bool,
#[arg(help = "Verify that manifest has been signed by <KEY>", long)]
key: Option<PublicKey>,
#[arg(
help = "Verify that manifest has been signed by <KEY>",
long = "key",
value_name = "KEY"
)]
keys: Vec<PublicKey>,
#[arg(
help = "Read manifest from <MANIFEST>, defaults to `<ROOT>/filepack.json`",
long
Expand Down Expand Up @@ -202,7 +206,16 @@ mismatched file: `{path}`
verified.signatures += 1;
}

if let Some(key) = self.key {
let mut keys = BTreeSet::new();

for key in &self.keys {
ensure! {
keys.insert(key.clone()),
error::DuplicateKey { key: key.clone() },
}
}

for key in self.keys {
ensure! {
manifest.signatures.contains_key(&key),
error::SignatureMissing { key },
Expand Down
78 changes: 78 additions & 0 deletions tests/verify.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
use super::*;

#[test]
fn duplicate_key() {
Test::new()
.args(["create"])
.success()
.args([
"verify",
"--key",
"7f1420cdc898f9370fd196b9e8e5606a7992fab5144fc1873d91b8c65ef5db6b",
"--key",
"7f1420cdc898f9370fd196b9e8e5606a7992fab5144fc1873d91b8c65ef5db6b",
])
.stderr(
"error: key provided multiple times: \
`7f1420cdc898f9370fd196b9e8e5606a7992fab5144fc1873d91b8c65ef5db6b`\n",
)
.failure();
}

#[test]
fn extra_fields_are_not_allowed() {
Test::new()
Expand Down Expand Up @@ -232,6 +251,65 @@ fn missing_signature_error() {
.failure();
}

#[test]
fn multiple_keys() {
let test = Test::new()
.data_dir("alice")
.args(["keygen"])
.success()
.data_dir("bob")
.args(["keygen"])
.success()
.touch("foo/bar")
.args(["create", "foo"])
.success()
.data_dir("alice")
.args(["sign", "foo"])
.success()
.data_dir("bob")
.args(["sign", "foo"])
.success();

let alice = test.read("alice/keys/master.public");
let bob = test.read("bob/keys/master.public");

test
.args(["verify", "foo", "--key", &alice, "--key", &bob])
.stderr("successfully verified 1 file totaling 0 bytes with 2 signatures\n")
.success();
}

#[test]
fn multiple_keys_one_missing() {
let test = Test::new()
.data_dir("alice")
.args(["keygen"])
.success()
.touch("foo/bar")
.args(["create", "foo"])
.success()
.data_dir("alice")
.args(["sign", "foo/filepack.json"])
.success();

let alice = test.read("alice/keys/master.public");

test
.args([
"verify",
"foo",
"--key",
&alice,
"--key",
"7f1420cdc898f9370fd196b9e8e5606a7992fab5144fc1873d91b8c65ef5db6b",
])
.stderr(
"error: no signature found for key \
7f1420cdc898f9370fd196b9e8e5606a7992fab5144fc1873d91b8c65ef5db6b\n",
)
.failure();
}

#[test]
fn multiple_mismatches() {
Test::new()
Expand Down