WL#3771: Pluggable Audit Interface
Affects: Server-5.5
—
Status: Complete
RATIONALE Make it possible to log server "events" (using a customizable plugin). "Events" include things like a) queries executed, b) query errors, c) summary of result set. SUMMARY Declare a new kind of plug-in to handle audit events. Audit plug-ins are able to specify a subset of classes of events that they wish to receive. The scope of this task is to: * Provide an abstract interface for audit plug-ins. * Provide the mysqld implementation of the interface. It is not expected that any audit plug-ins are to be created as a result of this worklog other than the minimum example required to demonstrate the proper functioning of the interface. As part of the mysqld implementation of the interface, it is expected that: * minimal intrusion within the existing code. * minimal runtime costs: Benchmark result differences should be indiscernible from noise. Further worklogs shall be created for optional log plug-ins as required.
There should be an interface where at any time, code within mysqld may call a function to notify that some significant auditable event has occurred. The server should examine if there are any installed audit plug-ins which are interested in the event and broadcast the event to them as required. At the time when the server is to wait upon the client, the server should ensure that all acquired resources are appropriately released. All auditable events are divided into event classes and each event class may have one or more event subtypes. For each event class, the parameters to the event shall be the same for every subtype. All audit plug-ins shall provide a bit-mask to indicate which event classes they require to be notified. Every audit plug-in will service all event subtypes for all event classes which they have indicated interest. An audit plug-in will not be notified for any event class of which they have not indicated interest. EVENT CLASSES: * Connection class: connect, login, logout, disconnect, etc. * Alter Privilege class: GRANT, REVOKE etc. * General Query class (additional classes to be declared as required based upon requirements) EXAMPLE PLUGIN: an example audit plugin will be created to demonstrate the proper functioning of the interface and to allow benchmarking. It'll listen for all events and will discard everything it receives (blackhole). COMMENT: from Brian Miezejewski We have storage engine partners that would like to use this interface to capture statements that do not normally make it to the storage engine such as GRANT, REVOKE, create VIEW, etc. They would like to get the parse tree so that they do not have to reparse the SQL to use it. They also need access to the thd->command value to help to quickly determine if the statement is of interest or not. Those storage engine partners can not use the GQ log for many reasons, primarily the security issues that it raises in what it writes to disk, the overhead of managing it and its impact on performance. It will be easy for us to create a plugin using the logging plugin API that does what they want. We have been sitting on this work for several months simply waiting to get this API implmented. They want to audit the following information below: - Login/Access Timestamp - Database username - Client IP/Hostname or terminal name - Client OS username - Client program name and process ID - Accessed table/view/other objects name and action - Full executed query string ADDITIONAL (potential) REQUIREMENTS: - Failed login/access information - The number of affected/retrieved rows - Values of prepared statement bind variables I suspect that logging OS username,program name and process ID is not worth implementation because it seems difficult to implement and easy-to-fake. ADDITIONAL COMMENT: From Brian M This looks to resolve the needs of the clients. The only potential issue is if some of the needed event classes are missing or if they might not be collected at the right point in time. As long as we can audit every auditable event everywhere it fails or succeeds we will be fine.
SERVER INTERFACE Within the mysqld server, the audit interface visible within the server is declared as: void mysql_audit_notify(THD *, event_class, event_subtype, error_code, ...); This may be encapsulated in a macro for conditional compialation for specific builds which have no need for auditing functionality - such as embedded builds. Macros and/or inline functions should be considered for each audit class to ensure correctness of parameters. The server code is free to call mysql_audit_notify() at any time during its execution as long as all arguments are valid. CREATED HOOKS we will create two hooks in this WL: - general query log, a hook where a general query logging happens, with the same set of parameters. - error/security log - in the my_message_sql. my_error* functions that call it (via error_handler_hook) will pass va_list args to my_message_sql. The latter will call mysql_audit_notify(). If the error is security related - unpacking the va_list into an appropriate structure (to help in the common case), otherwise sending va_list as is. PLUGIN INTERFACE struct audit_plugin_interface { uint64 *class_mask; void (*release_thd)(MYSQL_THD); void (*event_notify)(MYSQL_THD, struct mysql_event *); } class_mask uint64 bitmask of event classes release_thd() release any resources which may have been allocated for client thread. event_notify() Notify the plugin of an event for auditing. This function shall only be called when the class of the event is of interest to the plug-in by having its bit set to 1 in the class mask. There will be a set of struct mysql_event_xxx structures, where an xxx depends o n the event class. Any of these structures may be passed as the second argument to event_notify(). The structure is self-describing, its first field is event_class (same as in the class_mask). IMPLEMENTATION DETAILS When a Audit Plug-in is installed or uninstalled, a global mask is maintained which is the logical disjunction of all audit classes that all audit plug-ins have interest. The macro/notify function first checks if there are any interested parties of the audit class and returns quickly if there is no interest. The current thd is associated with the audit subsystem iff it has not already occurred. Association provides the thd with a list of active audit plug-ins which have no risk of 'going away' during execution. This list is iterated through and to notify when an audit class of interest has triggered. When an audit plug-in is to be notified for the first time in the current thd, the associate-thd function is first called. Success or failure is recorded and if failure has occurred, no further attempt to call that specific audit plug-in shall be made. At the end of statement execution before the current thd sleeps, all associated audit plug-ins are called to release before the list of audit plug-ins are unlocked. This strategy ensures that there is no more than 1 mutex contention event upon during typical execution of a statement.
Copyright (c) 2000, 2024, Oracle Corporation and/or its affiliates. All rights reserved.