Skip to content

Commit c492504

Browse files
committed
yhsm: Add command for dealing with the audit log.
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
1 parent 9d4e17d commit c492504

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

src/bin/yhsm.rs

+69-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use log::LevelFilter;
99
use std::{path::PathBuf, str::FromStr};
1010
use yubihsm::{
1111
object::{Id, Type},
12-
Client, Connector, Credentials, UsbConfig,
12+
AuditOption, Client, Connector, Credentials, UsbConfig,
1313
};
1414

1515
#[derive(Parser, Debug)]
@@ -29,8 +29,48 @@ struct Args {
2929
verbose: bool,
3030
}
3131

32+
#[derive(Subcommand, Clone, Debug, PartialEq)]
33+
enum LogCommand {
34+
/// dump log serialized to JSON
35+
Json,
36+
37+
/// Set the index of the last entry consumed from the HSM audit log.
38+
/// This causes entries with a lower index to be deleted.
39+
SetIndex {
40+
/// Last entry consumed.
41+
index: u16,
42+
},
43+
}
44+
45+
#[derive(Subcommand, Clone, Debug, PartialEq)]
46+
enum AuditCommand {
47+
/// Set the `force-audit` option to the disabled state.
48+
Disable,
49+
50+
/// Set the `force-audit` option to the enabled state.
51+
Enable,
52+
53+
/// Set the `force-audit` option to the locked state.
54+
Lock,
55+
56+
/// Query the state of the `force-audit` option.
57+
Query,
58+
59+
/// Manage the audit log.
60+
Log {
61+
#[command(subcommand)]
62+
command: Option<LogCommand>,
63+
},
64+
}
65+
3266
#[derive(Subcommand, Debug, PartialEq)]
3367
enum Command {
68+
/// Get / Set the state of the `force-audit` option.
69+
Audit {
70+
#[command(subcommand)]
71+
command: AuditCommand,
72+
},
73+
3474
/// Export an object identified under wrap.
3575
Backup {
3676
/// Object ID: https://developers.yubico.com/YubiHSM2/Concepts/Object_ID.html
@@ -98,6 +138,34 @@ fn main() -> Result<()> {
98138
let client = Client::open(connector, credentials, true)?;
99139

100140
match args.command {
141+
Command::Audit { command } => match command {
142+
AuditCommand::Disable => {
143+
Ok(client.set_force_audit_option(AuditOption::Off)?)
144+
}
145+
AuditCommand::Enable => {
146+
Ok(client.set_force_audit_option(AuditOption::On)?)
147+
}
148+
AuditCommand::Lock => Ok(oks::hsm::audit_lock(&client)?),
149+
AuditCommand::Query => {
150+
let state = client.get_force_audit_option()?;
151+
println!("{:?}", state);
152+
Ok(())
153+
}
154+
AuditCommand::Log { command } => match command {
155+
None | Some(LogCommand::Json) => {
156+
let entries = client.get_log_entries()?;
157+
if entries.entries.last().is_some() {
158+
println!("{}", serde_json::to_string_pretty(&entries)?);
159+
Ok(())
160+
} else {
161+
Err(anyhow::anyhow!("audit log contains no entries"))
162+
}
163+
}
164+
Some(LogCommand::SetIndex { index }) => {
165+
Ok(client.set_log_index(index)?)
166+
}
167+
},
168+
},
101169
Command::Backup { id, kind, file } => {
102170
// this is a bit weird but necessary because the Type type
103171
// returns () on error, not a type implementing std::Error

src/hsm.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use yubihsm::{
2424
authentication::{self, Key, DEFAULT_AUTHENTICATION_KEY_ID},
2525
object::{Id, Label, Type},
2626
wrap::{self, Message},
27-
Capability, Client, Connector, Credentials, Domain, HttpConfig, UsbConfig,
27+
AuditOption, Capability, Client, Connector, Credentials, Domain,
28+
HttpConfig, UsbConfig,
2829
};
2930
use zeroize::Zeroizing;
3031

@@ -699,6 +700,14 @@ pub fn reset(client: &Client) -> Result<()> {
699700
Ok(())
700701
}
701702

703+
pub fn audit_lock(client: &Client) -> Result<()> {
704+
if are_you_sure()? {
705+
Ok(client.set_force_audit_option(AuditOption::Fix)?)
706+
} else {
707+
Err(anyhow::anyhow!("command aborted"))
708+
}
709+
}
710+
702711
// consts for our authentication credential
703712
const AUTH_DOMAINS: Domain = Domain::all();
704713
const AUTH_CAPS: Capability = Capability::all();

0 commit comments

Comments
 (0)