diff --git a/src/audit.rs b/src/audit.rs index 5d9019fb9fc565e004153554c82efdcf6ac61958..92b6277d410a3cfc8c6407a3d1b6bd22512a323c 100644 --- a/src/audit.rs +++ b/src/audit.rs @@ -280,9 +280,29 @@ pub fn root() -> Option<&'static slog::Logger> { } } +// A helper macro which rewrites audit field syntax to the one used by slog. +#[doc(hidden)] +#[macro_export] +macro_rules! audit_kv( + // Format using Display. Example: `key: %value`. + ($key:ident : %$value:expr, $($rest:tt)*) => { + (slog::slog_kv!(stringify!($key) => %$value), $crate::audit_kv!($($rest)*)) + }; + // Format using Debug. Example: `key: ?value`. + ($key:ident : ?$value:expr, $($rest:tt)*) => { + (slog::slog_kv!(stringify!($key) => ?$value), $crate::audit_kv!($($rest)*)) + }; + // Substitute as is. Example: `key: value`. + ($key:ident : $value:expr, $($rest:tt)*) => { + (slog::slog_kv!(stringify!($key) => $value), $crate::audit_kv!($($rest)*)) + }; + () => { () }; +); + /// This is the main API for adding new entries to the audit log. /// The required fields are `message`, `title` and `severity`, -/// the rest is up to the caller. +/// the rest is up to the caller. Auxiliary values may be prefixed +/// with `%` or `?` to format them using `Display` or `Debug`. /// /// Example: /// ``` @@ -293,13 +313,13 @@ pub fn root() -> Option<&'static slog::Logger> { /// severity: Low, /// ); /// ``` -#[macro_export] +#[macro_export(local_inner_macros)] macro_rules! audit( ( message: $message:expr, title: $title:expr, severity: $severity:ident, - $($key:ident: $value:expr),* $(,)? + $($aux_fields:tt)* ) => { if let Some(root) = $crate::audit::root() { slog::slog_log!( @@ -307,11 +327,12 @@ macro_rules! audit( root, slog::Level::Info, "", // The message itself. $message; - // Mandatory fields. - "title" => $title, - "severity" => $crate::audit::Severity::$severity.as_str(), - // Arbitrary fields. - $(stringify!($key) => $value,)* + // Additional fields. + audit_kv!( + title: $title, + severity: $crate::audit::Severity::$severity.as_str(), + $($aux_fields)* + ) ); } }; diff --git a/src/storage.rs b/src/storage.rs index 1e9c57e248f7db26c0e93532aa5377b399aacbd0..26c738937a27b59d9fd6665e209450cccc802320 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -2669,6 +2669,7 @@ pub mod acl { title: "create_user", severity: High, auth_type: user_def.auth.method.as_str(), + user: user, ); Ok(()) @@ -2689,6 +2690,7 @@ pub mod acl { title: "change_password", severity: High, auth_type: auth.method.as_str(), + user: user, ); Ok(()) @@ -2706,6 +2708,7 @@ pub mod acl { message: "dropped user `{user}`", title: "drop_user", severity: Medium, + user: user, ); Ok(()) @@ -2720,6 +2723,7 @@ pub mod acl { message: "created role `{role}`", title: "create_role", severity: High, + role: role, ); Ok(()) @@ -2742,6 +2746,7 @@ pub mod acl { message: "dropped role `{role}`", title: "drop_role", severity: Medium, + role: role, ); } @@ -2765,6 +2770,9 @@ pub mod acl { message: "granted role `{object}` to {grantee_type} `{grantee}`", title: "grant_role", severity: High, + role: object, + grantee: &grantee, + grantee_type: grantee_type, ); } _ => { @@ -2773,6 +2781,11 @@ pub mod acl { to {grantee_type} `{grantee}`", title: "grant_privilege", severity: High, + privilege: privilege, + object: object, + object_type: object_type, + grantee: &grantee, + grantee_type: grantee_type, ); } } @@ -2803,6 +2816,9 @@ pub mod acl { message: "revoke role `{object}` from {grantee_type} `{grantee}`", title: "revoke_role", severity: High, + role: object, + grantee: &grantee, + grantee_type: grantee_type, ); } _ => { @@ -2811,6 +2827,11 @@ pub mod acl { from {grantee_type} `{grantee}`", title: "revoke_privilege", severity: High, + privilege: privilege, + object: object, + object_type: object_type, + grantee: &grantee, + grantee_type: grantee_type, ); } } diff --git a/src/traft/node.rs b/src/traft/node.rs index dff31a071b11e381b4e516dedd82985ffbbf301e..502a4b48ed968bad9920208fa55d99597cd3e5f9 100644 --- a/src/traft/node.rs +++ b/src/traft/node.rs @@ -680,9 +680,11 @@ impl NodeImpl { if prev.as_ref().map(|x| x.raft_id) != Some(new.raft_id) { let instance_id = &new.instance_id; crate::audit!( - message: "added a new instance `{instance_id}` to the cluster", - title: "create_database", + message: "a new instance `{instance_id}` joined the cluster", + title: "join_instance", severity: Low, + instance_id: %instance_id, + raft_id: %new.raft_id, ); } @@ -693,6 +695,8 @@ impl NodeImpl { message: "current grade of instance `{instance_id}` changed to {grade}", title: "change_current_grade", severity: Medium, + instance_id: %instance_id, + new_grade: %grade, ); } @@ -703,6 +707,8 @@ impl NodeImpl { message: "target grade of instance `{instance_id}` changed to {grade}", title: "change_target_grade", severity: Low, + instance_id: %instance_id, + raft_id: %new.raft_id, ); } @@ -790,6 +796,7 @@ impl NodeImpl { message: "created table `{name}`", title: "create_table", severity: Medium, + name: &name, ); } @@ -803,6 +810,7 @@ impl NodeImpl { message: "dropped table `{name}`", title: "drop_table", severity: Medium, + name: &name, ); }