Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « Performance Impacts of Unicode, Equals vs LIKE, and Partially Filled Fixed WidthSQL Advent 2011: What is coming in SQL Server 2012? »
    comments

    Continuing onwards with the SQL Server auditing feature, let's start off by creating a simple audit that will capture some database level events.

    Previously we looked at how to create a Server Audit Specification and creating a Database Specification follows the same steps. The main difference is the location, as well as the objects to capture. In the following example we will look at capturing delete statements on a database.

    It is also important to note, that you cannot audit across databases, you will need to set up a Database Specification and its corresponding Audit per database.

    Creating the Audit

    We follow the same steps as previously by creating the Audit file:

    Expand your instance >> Security >> Right-Click the audit folder >> Select New Audit

    This should bring up a new window similar to this:

    Creating the Specification

    To Create a Database Specification you can find it under:

    Database >> Security >> Database Audit Specification

    The first configuration I have for the Database Specification, I am capturing on a database level, only deletes, and only when executed by user belonging to the db_datawriter role.

    I executed the following query on my account which is sysadmin:

    1. USE testdb;
    2. GO
    3.  
    4. DELETE FROM tab1 WHERE id BETWEEN 9990 AND 10000;
    5. GO
    6. DELETE FROM tab2 WHERE id BETWEEN 5000 AND 5100;
    7. GO
    8. DELETE FROM tab3 WHERE id BETWEEN 2000 AND 2002;
    9. GO

    This resulted in no deletes being captured:

    When executed as test_writer, which belongs to the db_datawriter role and I execute the following:

    1. USE testdb;
    2. GO
    3.  
    4. DELETE FROM tab1 WHERE id BETWEEN 9900 AND 9990;
    5. GO
    6. DELETE FROM tab2 WHERE id BETWEEN 4500 AND 4990;
    7. GO
    8. DELETE FROM tab3 WHERE id BETWEEN 2500 AND 2560;
    9. GO

    I receive the following results:

    One thing to note on the output is under "audit_file_offset". All three values are 6144, which indicates that the three statements where executed in the same query.

    As with the Server Audits, use the following query to retrieve the audit information as it is displayed above:

    1. SELECT  event_time ,
    2.         action_id ,
    3.         succeeded ,
    4.         session_id ,
    5.         server_principal_name ,
    6.         server_instance_name ,
    7.         database_name ,
    8.         [statement] ,
    9.         audit_file_offset
    10. FROM    fn_get_audit_file('E:\SQLAuditing\DBAudit*.sqlaudit',
    11.                           DEFAULT, DEFAULT)

    The second example is just to audit a specific table:

    Note the areas in the red squares, it changes to audit objects, then a specific table, and lastly to which principle it should be bound and again in this case it will be db_datawriter.

    Again, I execute a delete statement:

    1. USE testdb;
    2. GO
    3.  
    4. DELETE FROM tab1 WHERE id BETWEEN 1 AND 100;
    5. GO
    6. DELETE FROM tab2 WHERE id BETWEEN 400 AND 6000;
    7. GO
    8. DELETE FROM tab3 WHERE id BETWEEN 7000 AND 7050;
    9. GO

    Inspecting the statement column, we can see that it only captured the delete statement that was executed against tab1:

    To create the users, database, and populate it with the data I used - run the following:

    1. /*Creates the database and the logins*/
    2.  
    3. USE [master]
    4. GO
    5.  
    6. IF EXISTS(SELECT NAME FROM master.sys.server_principals WHERE name = 'testuser')
    7. DROP LOGIN testuser;
    8. IF EXISTS(SELECT NAME FROM master.sys.server_principals WHERE name = 'test_writer')
    9. DROP LOGIN test_writer;
    10. IF EXISTS(SELECT NAME FROM master.sys.databases WHERE name = 'testdb')
    11. DROP DATABASE testdb;
    12. GO
    13.  
    14. CREATE LOGIN [testuser] WITH PASSWORD=N'password', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english],
    15. CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
    16. GO
    17.  
    18. ALTER LOGIN [testuser] ENABLE
    19. GO
    20.  
    21. CREATE LOGIN [test_writer] WITH PASSWORD=N'password', DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english],
    22. CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
    23. GO
    24.  
    25. ALTER LOGIN [test_writer] ENABLE
    26. GO
    27.  
    28. CREATE DATABASE [testdb] ;
    29. GO
    30.  
    31. /* Grants the access for the logins */
    32. USE [testdb] ;
    33. GO
    34.  
    35. CREATE USER [testuser] FOR LOGIN [testuser] WITH DEFAULT_SCHEMA=[dbo]
    36. GO
    37. CREATE USER [test_writer] FOR LOGIN [test_writer] WITH DEFAULT_SCHEMA=[dbo]
    38. GO
    39. EXEC sp_addrolemember N'db_owner', N'testuser' ;
    40. EXEC sp_addrolemember N'db_datawriter', N'test_writer' ;
    41. GO
    42.  
    43. /*Creates the test tables */
    44.  
    45. CREATE TABLE [dbo].[tab1]
    46.     (
    47.       [id] [int] IDENTITY(1, 1)
    48.                  NOT NULL ,
    49.       [comment] [varchar](10) NULL ,
    50.       [tabdate] [date] NULL
    51.     )
    52. ON  [PRIMARY]
    53.  
    54. GO
    55. CREATE TABLE [dbo].[tab2]
    56.     (
    57.       [id] [int] IDENTITY(1, 1)
    58.                  NOT NULL ,
    59.       [comment] [varchar](10) NULL ,
    60.       [tabdate] [date] NULL
    61.     )
    62. ON  [PRIMARY]
    63.  
    64. GO
    65. CREATE TABLE [dbo].[tab3]
    66.     (
    67.       [id] [int] IDENTITY(1, 1)
    68.                  NOT NULL ,
    69.       [comment] [varchar](10) NULL ,
    70.       [tabdate] [date] NULL
    71.     )
    72. ON  [PRIMARY]
    73. GO
    74.  
    75. USE [master]
    76. GO
    77. ALTER DATABASE [testdb] SET  READ_WRITE
    78. GO
    79.  
    80.  
    81. /* Random test data */
    82. USE testdb ;
    83. GO
    84.  
    85. INSERT  INTO tab1
    86.         ( comment, tabdate )
    87. VALUES  ( 'abcdefg', GETDATE() )
    88.  
    89. GO 10000
    90.  
    91. INSERT  INTO tab2
    92.         SELECT  comment ,
    93.                 tabdate
    94.         FROM    TAB1 ;
    95. GO
    96.  
    97. INSERT  INTO tab3
    98.         SELECT  comment ,
    99.                 tabdate
    100.         FROM    TAB1 ;
    101. GO

    Final Thoughts

    Just based on auditing for delete statements on database can prove to be very dynamic when using the auditing feature. It doesn't even stop here, as this was only a demo, there are a lot more you can audit like stored procedures, functions, views, etc. This is a powerful feature especially for monitoring critical and highly sensitive databases.

    To see what else you can audit with the Database Specifications go here and skip down to Database-Level Audit Action Groups.

    About the Author

    Stephan specializes in MS SQL Server technology stack with the main focus on the database engine component as well as high availability, automation, troubleshooting and optimization. Currently he holds a position at Microsoft South Africa (EMEA) as a Premier Field Engineer for MS SQL Server.
    Social SitingsTwitterLinkedInLTD RSS Feed
    415 views
    Instapaper

    No feedback yet

    Leave a comment


    Your email address will not be revealed on this site.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)