@@ -9,7 +9,7 @@ use log::LevelFilter;
99use std:: { path:: PathBuf , str:: FromStr } ;
1010use 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 ) ]
3367enum 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
0 commit comments