aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2020-09-09 21:37:19 +0200
committerRobin Krahl <robin.krahl@ireas.org>2020-09-11 11:03:32 +0200
commitef7b6b03355b82621d16f4f02a5a1a4558ae64cc (patch)
tree97b505e2e74a4b9e8aacb6c530fd23d7244a37c2
parent70b9a1f0287f2aeda9677110106f43d1048306f3 (diff)
downloadnitrocli-ef7b6b03355b82621d16f4f02a5a1a4558ae64cc.tar.gz
nitrocli-ef7b6b03355b82621d16f4f02a5a1a4558ae64cc.tar.bz2
List all matching devices in status commmand
Previously, the status command would fail if more than one Nitrokey device is connected. With this patch, we list all attached devices that match the specified filter (model, serial number, USB path). This also casues some changes in the test cases: Previously, we assumed that status fails for multiple attached devices. We now use the lock command to produce this behavior.
-rw-r--r--CHANGELOG.md2
-rw-r--r--doc/nitrocli.110
-rw-r--r--doc/nitrocli.1.pdfbin42203 -> 42810 bytes
-rw-r--r--src/commands.rs31
-rw-r--r--src/tests/run.rs16
-rw-r--r--src/tests/status.rs20
6 files changed, 60 insertions, 19 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83fc8d9..248069e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,8 @@ Unreleased
device to connect to
- Added `--usb-path` option that restricts the USB path of the device to
connect to
+ - Changed the `status` command to print the status for all attached Nitrokey
+ devices that match the specified filter.
- Bumped `structopt` dependency to `0.3.17`
diff --git a/doc/nitrocli.1 b/doc/nitrocli.1
index 6fb1fd9..87b52b4 100644
--- a/doc/nitrocli.1
+++ b/doc/nitrocli.1
@@ -67,10 +67,12 @@ To omit the serial number of Nitrokey Storage devices instead of connecting to
them, set the \fB\-\-no-connect\fR option.
.TP
.B nitrocli status
-Print the status of the connected Nitrokey device, including the stick serial
-number, the firmware version, and the PIN retry count. If the device is a
-Nitrokey Storage, also print storage related information including the SD card
-serial number, the encryption status, and the status of the volumes.
+Print the status of the attached Nitrokey devices that match the filter
+options (see the Device selection section), including the stick serial number,
+the firmware version, and the PIN retry count.
+For Nitrokey Storage devices, also print storage related information including
+the SD card serial number, the encryption status, and the status of the
+volumes.
.TP
.B nitrocli lock
Lock the Nitrokey.
diff --git a/doc/nitrocli.1.pdf b/doc/nitrocli.1.pdf
index d98ab41..d040b6b 100644
--- a/doc/nitrocli.1.pdf
+++ b/doc/nitrocli.1.pdf
Binary files differ
diff --git a/src/commands.rs b/src/commands.rs
index 597fcd8..a4e805e 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -363,19 +363,24 @@ fn print_storage_status(
}
/// Query and pretty print the status that is common to all Nitrokey devices.
-fn print_status(ctx: &mut Context<'_>, device: &nitrokey::DeviceWrapper<'_>) -> anyhow::Result<()> {
+fn print_status(
+ ctx: &mut Context<'_>,
+ idx: usize,
+ device: &nitrokey::DeviceWrapper<'_>,
+) -> anyhow::Result<()> {
let serial_number = device
.get_serial_number()
.context("Could not query the serial number")?;
println!(
ctx,
- r#"Status:
+ r#"Device #{idx}:
model: {model}
serial number: {id}
firmware version: {fwv}
user retry count: {urc}
admin retry count: {arc}"#,
+ idx = idx,
model = args::DeviceModel::from(device.get_model()).as_user_facing_str(),
id = serial_number,
fwv = device
@@ -402,7 +407,27 @@ fn print_status(ctx: &mut Context<'_>, device: &nitrokey::DeviceWrapper<'_>) ->
/// Inquire the status of the nitrokey.
pub fn status(ctx: &mut Context<'_>) -> anyhow::Result<()> {
- with_device(ctx, |ctx, device| print_status(ctx, &device))
+ let device_infos = find_devices(&ctx.config)?;
+ anyhow::ensure!(
+ !device_infos.is_empty(),
+ "Nitrokey device not found{}",
+ format_filter(&ctx.config)
+ );
+
+ let mut manager =
+ nitrokey::take().context("Failed to acquire access to Nitrokey device manager")?;
+ for (idx, device_info) in device_infos.iter().enumerate() {
+ let device = manager
+ .connect_path(device_info.path.deref())
+ .with_context(|| {
+ format!(
+ "Failed to connect to Nitrokey device at path {}",
+ device_info.path
+ )
+ })?;
+ print_status(ctx, idx, &device)?;
+ }
+ Ok(())
}
/// List the attached Nitrokey devices.
diff --git a/src/tests/run.rs b/src/tests/run.rs
index b39b1da..3dd4c98 100644
--- a/src/tests/run.rs
+++ b/src/tests/run.rs
@@ -113,7 +113,7 @@ fn config_file() {
fn connect_multiple(_model: nitrokey::Model) -> anyhow::Result<()> {
let devices = nitrokey::list_devices()?;
if devices.len() > 1 {
- let res = Nitrocli::new().handle(&["status"]);
+ let res = Nitrocli::new().handle(&["lock"]);
let err = res.unwrap_err().to_string();
assert_eq!(
err,
@@ -190,16 +190,12 @@ fn connect_model(_model: nitrokey::Model) -> anyhow::Result<()> {
model.to_lowercase()
)
);
- } else if count == 1 {
- assert!(res?.contains(&format!("model: {}\n", model)));
} else {
- let err = res.unwrap_err().to_string();
assert_eq!(
- err,
- format!(
- "Multiple Nitrokey devices found (filter: model={}). ",
- model.to_lowercase()
- ) + "Use the --model, --serial-number, and --usb-path options to select one"
+ count,
+ res?
+ .matches(&format!("model: {}\n", model))
+ .count()
);
}
}
@@ -213,7 +209,7 @@ fn connect_usb_path_model_serial(_model: nitrokey::Model) -> anyhow::Result<()>
for device in devices {
let mut args = Vec::new();
args.push("status".to_owned());
- args.push(format!("--usb-path={}", device.path));
+ args.push(format!("--usb-path={}", &device.path));
if let Some(model) = device.model {
args.push(format!("--model={}", model.to_string().to_lowercase()));
}
diff --git a/src/tests/status.rs b/src/tests/status.rs
index fe69d78..1f5bbf7 100644
--- a/src/tests/status.rs
+++ b/src/tests/status.rs
@@ -24,7 +24,7 @@ fn not_found() {
#[test_device(pro)]
fn output_pro(model: nitrokey::Model) -> anyhow::Result<()> {
let re = regex::Regex::new(
- r#"^Status:
+ r#"^Device #0:
model: Pro
serial number: 0x[[:xdigit:]]{8}
firmware version: v\d+\.\d+
@@ -42,7 +42,7 @@ $"#,
#[test_device(storage)]
fn output_storage(model: nitrokey::Model) -> anyhow::Result<()> {
let re = regex::Regex::new(
- r#"^Status:
+ r#"^Device #0:
model: Storage
serial number: 0x[[:xdigit:]]{8}
firmware version: v\d+\.\d+
@@ -64,3 +64,19 @@ $"#,
assert!(re.is_match(&out), out);
Ok(())
}
+
+#[test_device]
+fn output_multiple(_model: nitrokey::Model) -> anyhow::Result<()> {
+ let devices = nitrokey::list_devices()?;
+ let out = Nitrocli::new().handle(&["status"])?;
+ for (idx, device) in devices.iter().enumerate() {
+ assert!(out.contains(&format!("Device #{}:\n", idx)), out);
+ if let Some(model) = device.model {
+ assert!(out.contains(&format!("model: {}\n", model)), out);
+ }
+ if let Some(sn) = device.serial_number {
+ assert!(out.contains(&format!("serial number: {}\n", sn)), out);
+ }
+ }
+ Ok(())
+}