Extended Events Login audit - Reduce login noise
-
17-03-2021 - |
質問
We are looking for the optimal sql login audit solution, with usable filtering.
Thus far we have looked into Server Audits and profiler but have concluded that extended events look most promising, unless anyone can show us otherwise.
Question is, is there any good way to filter unnecessary login events? e.g. when I connect using SSMS, immediatly about 10 login events are added and continue to pile up if I leave SSMS connected to a instance. Why is that?
This is our current implementation:
USE master;
GO
-- Create the Event Session
IF EXISTS
(
SELECT
*
FROM sys.server_event_sessions
WHERE name = 'ServerLoginAudit'
)
DROP EVENT SESSION ServerLoginAudit ON SERVER;
GO
EXECUTE xp_create_subdir 'D:\audits\Sessions';
GO
CREATE EVENT SESSION ServerLoginAudit
ON SERVER
ADD EVENT sqlserver.login
(SET
collect_database_name = (1)
, collect_options_text = (1)
ACTION
(
sqlserver.sql_text
, sqlserver.nt_username
, sqlserver.server_principal_name
, sqlserver.client_hostname
, package0.collect_system_time
, package0.event_sequence
, sqlserver.database_id
, sqlserver.database_name
, sqlserver.username
, sqlserver.session_nt_username
, sqlserver.client_app_name
, sqlserver.session_id
, sqlserver.context_info
, sqlserver.client_connection_id
)
)
ADD TARGET package0.event_file
(SET filename = N'D:\audits\Sessions\ServerLoginAudit.xel', max_file_size = (20), max_rollover_files = (2))
WITH
(
STARTUP_STATE = OFF
, TRACK_CAUSALITY = ON
);
/* start the session */
ALTER EVENT SESSION ServerLoginAudit ON SERVER STATE = START;
GO
解決
Reason for the numerous connections
Those are connections caused by SSMS to provide you mainly the visual structure of object explorer. Also, When you're using SSMS, each new tab you open is a different session (and more connections - see The multiple connections of SSMS). IntelliSense also creates extra connections as you'll see if you remove the predicate on the query I suggested as a workaround.
try connecting with sqlcmd Utility like this on a CMD prompt:
sqlcmd -A
When I connected with SQLCMD only one log was reported on the Extended Event Session you provided.
Workaround
Instead of filtering the data you collect I suggest you filter the data you query afterwards, here's one way to do that:
WITH
event_data AS (
SELECT CAST(event_data AS XML) AS event_data_xml
FROM fn_xe_file_target_read_file('D:\audits\Sessions\ServerLoginAudit*.xel',NULL,NULL,NULL)
)
, event_data_fields AS (
SELECT
DATEADD(ms, -DATEPART(ms, event_data_xml.value('(/event/@timestamp)[1]', 'datetime')), event_data_xml.value('(/event/@timestamp)[1]', 'datetime')) AS interval
, event_data_xml.value('(/event/data[@name="database_name"]/value)[1]', 'varchar(250)') AS database_name
, event_data_xml.value('(/event/action[@name="client_app_name"]/value)[1]', 'nvarchar(250)') AS client_app_name
, event_data_xml.value('(/event/action[@name="client_hostname"]/value)[1]', 'nvarchar(250)') AS client_hostname
, event_data_xml.value('(/event/action[@name="server_principal_name"]/value)[1]', 'nvarchar(250)') AS server_principal_name
, event_data_xml.value('(/event/action[@name="nt_username"]/value)[1]', 'nvarchar(250)') AS nt_username
FROM event_data
)
SELECT
interval
, database_name
, client_app_name
, client_hostname
, server_principal_name
, nt_username
FROM event_data_fields
WHERE
client_app_name NOT IN ('SQLServerCEIP', 'Microsoft SQL Server Management Studio - Transact-SQL IntelliSense')
GROUP BY
interval
, database_name
, client_app_name
, client_hostname
, server_principal_name
, nt_username;
With that method, if you don't find the info you seek at first, you can reduce the predicates to show all data collected and have a more accurate report of all the connections that happened at the time. Also, if you filter the data you collect by the application name, it would leave a breach on your audit because one can Change the Application Name of SSMS and login to your server unnoticed.