@@ -9,7 +9,7 @@ use log::LevelFilter;
9
9
use std:: { path:: PathBuf , str:: FromStr } ;
10
10
use yubihsm:: {
11
11
object:: { Id , Type } ,
12
- Client , Connector , Credentials , UsbConfig ,
12
+ AuditOption , Client , Connector , Credentials , UsbConfig ,
13
13
} ;
14
14
15
15
#[ derive( Parser , Debug ) ]
@@ -29,8 +29,48 @@ struct Args {
29
29
verbose : bool ,
30
30
}
31
31
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
+
32
66
#[ derive( Subcommand , Debug , PartialEq ) ]
33
67
enum Command {
68
+ /// Get / Set the state of the `force-audit` option.
69
+ Audit {
70
+ #[ command( subcommand) ]
71
+ command : AuditCommand ,
72
+ } ,
73
+
34
74
/// Export an object identified under wrap.
35
75
Backup {
36
76
/// Object ID: https://developers.yubico.com/YubiHSM2/Concepts/Object_ID.html
@@ -98,6 +138,34 @@ fn main() -> Result<()> {
98
138
let client = Client :: open ( connector, credentials, true ) ?;
99
139
100
140
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
+ } ,
101
169
Command :: Backup { id, kind, file } => {
102
170
// this is a bit weird but necessary because the Type type
103
171
// returns () on error, not a type implementing std::Error
0 commit comments