Skip to content

Commit

Permalink
yhsm: Add command for dealing with the audit log.
Browse files Browse the repository at this point in the history
YubiCo docs state that only 1-60 are valid index values. I've set this
value to well beyond 60 in testing. These docs don't say what happens
when the index (u16) rolls over.

https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#set-log-index-command
  • Loading branch information
flihp committed Oct 10, 2024
1 parent 9d4e17d commit dac5b48
Showing 1 changed file with 71 additions and 1 deletion.
72 changes: 71 additions & 1 deletion src/bin/yhsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use log::LevelFilter;
use std::{path::PathBuf, str::FromStr};
use yubihsm::{
object::{Id, Type},
Client, Connector, Credentials, UsbConfig,
AuditOption, Client, Connector, Credentials, UsbConfig,
};

#[derive(Parser, Debug)]
Expand All @@ -29,8 +29,48 @@ struct Args {
verbose: bool,
}

#[derive(Subcommand, Clone, Debug, PartialEq)]
enum LogCommand {
/// dump log serialized to JSON
Json,

/// Set the index of the last entry consumed from the HSM audit log.
/// This causes entries with a lower index to be deleted.
SetIndex {
/// Last entry consumed.
index: u16,
},
}

#[derive(Subcommand, Clone, Debug, PartialEq)]
enum AuditCommand {
/// Set the `force-audit` option to the disabled state.
Disable,

/// Set the `force-audit` option to the enabled state.
Enable,

/// Set the `force-audit` option to the locked state.
Lock,

/// Query the state of the `force-audit` option.
Query,

/// Manage the audit log.
Log {
#[command(subcommand)]
command: Option<LogCommand>,
},
}

#[derive(Subcommand, Debug, PartialEq)]
enum Command {
/// Get / Set the state of the `force-audit` option.
Audit {
#[command(subcommand)]
command: AuditCommand,
},

/// Export an object identified under wrap.
Backup {
/// Object ID: https://developers.yubico.com/YubiHSM2/Concepts/Object_ID.html
Expand Down Expand Up @@ -98,6 +138,36 @@ fn main() -> Result<()> {
let client = Client::open(connector, credentials, true)?;

match args.command {
Command::Audit { command } => match command {
AuditCommand::Disable => {
Ok(client.set_force_audit_option(AuditOption::Off)?)
}
AuditCommand::Enable => {
Ok(client.set_force_audit_option(AuditOption::On)?)
}
AuditCommand::Lock => {
todo!("implement Command::Audit::{:?}", command);
}
AuditCommand::Query => {
let state = client.get_force_audit_option()?;
println!("{:?}", state);
Ok(())
}
AuditCommand::Log { command } => match command {
None | Some(LogCommand::Json) => {
let entries = client.get_log_entries()?;
if entries.entries.last().is_some() {
println!("{}", serde_json::to_string_pretty(&entries)?);
Ok(())
} else {
Err(anyhow::anyhow!("audit log contains no entries"))
}
}
Some(LogCommand::SetIndex { index }) => {
Ok(client.set_log_index(index)?)
}
},
},
Command::Backup { id, kind, file } => {
// this is a bit weird but necessary because the Type type
// returns () on error, not a type implementing std::Error
Expand Down

0 comments on commit dac5b48

Please sign in to comment.