Generate a security report on SQL Server instance - Security script
-- Srored Procedure to generate Security Audit report in HTML format:
CREATE PROC spAuditUsersPermissions
AS
SET NOCOUNT ON
DECLARE @sql VARCHAR(MAX)
DECLARE @strHTML VARCHAR(MAX)
DECLARE @i INT
DECLARE @rc INT
DECLARE @dbname VARCHAR(400)
-----------------Print header of the report--------------------
SELECT @strHTML = '<HTML><HEAD><TITLE> Security list for the auditor </TITLE><STYLE>TD.Sub{FONT-WEIGHT:bold;BORDER-BOTTOM: 0pt solid #000000;BORDER-LEFT: 1pt solid #000000;BORDER-RIGHT: 0pt solid #000000;BORDER-TOP: 0pt solid #000000; FONT-FAMILY: Tahoma;FONT-SIZE: 8pt} BODY{FONT-FAMILY: Tahoma;FONT-SIZE: 8pt} TABLE{BORDER-BOTTOM: 1pt solid #000000;BORDER-LEFT: 0pt solid #000000;BORDER-RIGHT: 1pt solid #000000;BORDER-TOP: 0pt solid #000000; FONT-FAMILY: Tahoma;FONT-SIZE: 8pt} TD{BORDER-BOTTOM: 0pt solid #000000;BORDER-LEFT: 1pt solid #000000;BORDER-RIGHT: 0pt solid #000000;BORDER-TOP: 1pt solid #000000; FONT-FAMILY: Tahoma;FONT-SIZE: 8pt} TD.Title{FONT-WEIGHT:bold;BORDER-BOTTOM: 0pt solid #000000;BORDER-LEFT: 1pt solid #000000;BORDER-RIGHT: 0pt solid #000000;BORDER-TOP: 1pt solid #000000; FONT-FAMILY: Tahoma;FONT-SIZE: 12pt} A.Index{FONT-WEIGHT:bold;FONT-SIZE:8pt;COLOR:#000099;FONT-FAMILY:Tahoma;TEXT-DECORATION:none} A.Index:HOVER{FONT-WEIGHT:bold;FONT-SIZE:8pt;COLOR:#990000;FONT-FAMILY:Tahoma;TEXT-DECORATION:none}</STYLE></HEAD><BODY><A NAME="_top"></A><BR>'
PRINT @strHTML
-----------------Login information-------------------------------------------------------------
SELECT ROW_NUMBER () OVER (ORDER BY name) AS RowNumber,
name, dbname,language,
CONVERT(CHAR(10),CASE denylogin WHEN 1 THEN 'X' ELSE '--' END) AS IsDenied,
CONVERT(CHAR(10),CASE isntname WHEN 1 THEN 'X' ELSE '--' END) AS IsWinAuTHENtication,
CONVERT(CHAR(10),CASE isntgroup WHEN 1 THEN 'X' ELSE '--' END) AS IsWinGroup,
createdate,UPDATEdate,
CONVERT(VARCHAR(2000),
CASE sysadmin WHEN 1 THEN 'sysadmin,' ELSE '' END +
CASE securityadmin WHEN 1 THEN 'securityadmin,' ELSE '' END +
CASE serveradmin WHEN 1 THEN 'serveradmin,' ELSE '' END +
CASE setupadmin WHEN 1 THEN 'setupadmin,' ELSE '' END +
CASE processadmin WHEN 1 THEN 'processadmin,' ELSE '' END +
CASE diskadmin WHEN 1 THEN 'diskadmin,' ELSE '' END +
CASE dbcreator WHEN 1 THEN 'dbcreator,' ELSE '' END +
CASE bulkadmin WHEN 1 THEN 'bulkadmin' ELSE '' END ) AS ServerRoles
INTO #syslogins
FROM master..syslogins WITH (nolock)
ORDER BY name
SET @rc = @@rowcount
SELECT @strHTML = '<BR><CENTER><FONT SIZE="5"><B> Server ' + @@servername + '</B></FONT></CENTER><BR>'
PRINT @strHTML
PRINT '<DIV ALIGN="center"><TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0" BORDERCOLOUR="003366" WIDTH="100%">'
-- Query the data only if there are rows:
IF @rc = 0
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="1" ALIGN="center"><B><A NAME="_LoginInfomration">Logins information</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>There are no logins on this server</B> </TD></TR>'
END
ELSE
BEGIN
UPDATE #syslogins
SET ServerRoles = SUBSTRING(ServerRoles,1,LEN(ServerRoles)-1)
WHERE SUBSTRING(ServerRoles,LEN(ServerRoles),1) = ','
UPDATE #syslogins SET ServerRoles = '--'
WHERE LTRIM(RTRIM(ServerRoles)) = ''
PRINT '<DIV ALIGN="center"><TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0" BORDERCOLOUR="003366" WIDTH="100%">'
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="9" ALIGN="center"><B><A NAME="_LoginInfomration">Logins information</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="50%"><B>Login Name</B> </TD><TD ALIGN="left" WIDTH="50%"><B>Default DB</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Language</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Denied acess?</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Windows Auth?</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Window group?</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Date created</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Date UPDATEd</B> </TD><TD AALIGN="left" WIDTH="770%"><B>Server roles</B> </TD></TR>'
SET @i = 1
WHILE @i <= @rc
BEGIN
SELECT @strHTML =
'<TR><TD><B>' + CONVERT(VARCHAR(50),name) + '</B> </TD>' +
'<TD>' + CONVERT(VARCHAR(50),CASE ISNULL(dbname,'--') WHEN '' THEN '--' ELSEISNULL(dbname,'--') END) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(language,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(10),ISNULL(IsDenied,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(10),ISNULL(IsWinAuTHENtication,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(10),ISNULL(IsWinGroup,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(30),ISNULL(createdate,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(30),ISNULL(UPDATEdate,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(100),ISNULL(ServerRoles,'--')) + ' </TD>' +
'</TR>'
FROM #syslogins
WHERE RowNumber = @i
PRINT @strHTML
SET @i = @i + 1
END
PRINT '</TABLE></DIV><BR><A CLASS="Index" HREF="#_top">Back To Top ^</A><BR><BR>'
PRINT'<BR><CENTER></CENTER><BR>'
END
DROP TABLE #syslogins
---------------Fetch data per database-------------------------------------------------
CREATE TABLE #LoginMap (LoginName VARCHAR(200), UserName VARCHAR(200) NULL)
CREATE TABLE #RoleUser (RoLEName VARCHAR(200), UserName VARCHAR(200) NULL)
CREATE TABLE #ObjectPerms (RowNumber INT IDENTITY, UserName VARCHAR(50), PerTypeVARCHAR(10),PermName VARCHAR(30), SchemaName VARCHAR(50),
ObjectName VARCHAR(100), ObjectType VARCHAR(20), ColName VARCHAR(50), IsGrantOption VARCHAR(10))
CREATE TABLE #DatabasePerms (RowNumber INT IDENTITY,UserName VARCHAR(50),PermTypeVARCHAR(20),PermName VARCHAR(50),IsGrantOption VARCHAR(5))
DECLARE dbs CURSOR FOR SELECT name FROM master..sysdatabases ORDER BY name
OPEN dbs
FETCH NEXT FROM dbs INTO @dbname
WHILE @@FETCH_STATUS = 0
BEGIN
TRUNCATE TABLE #LoginMap
TRUNCATE TABLE #RoleUser
TRUNCATE TABLE #ObjectPerms
TRUNCATE TABLE #DatabasePerms
SELECT @strHTML = '<BR><CENTER><FONT SIZE="5"><B> Database ' + @dbname + '</B></FONT></CENTER><BR>'
PRINT @strHTML
-----------------Mapping of logins to users------------------
EXEC('
INSERT INTO #LoginMap
SELECT login.loginname,users.name
FROM ['+ @dbname+'].dbo.sysusers users
INNER JOIN [master].[dbo].[syslogins] login
ON users.[sid] = login.[sid]
WHERE users.uid < 16382
and users.name not in (''public'',''dbo'',''guest'')
')
SET @strHTML = ''
PRINT '<DIV ALIGN="center"><TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0" BORDERCOLOUR="003366" WIDTH="60%">'
--Query the data only if there are rows
IF NOT EXISTS (SELECT 1 FROM #LoginMap)
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="1" ALIGN="center"><B><A NAME="_LoginMapping">Mapping of logins to users</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>There are no mappings in this database</B> </TD></TR>'
END
ELSE
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="2" ALIGN="center"><B><A NAME="_LoginMapping">Mapping of logins to users</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>Login Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>User Name</B> </TD></TR>'
SELECT @strHTML = @strHTML +
'<TR><TD><B>' + CONVERT(VARCHAR(50),LoginName) + '</B> </TD><TD>' +CONVERT(VARCHAR(50),ISNULL(UserName,'')) + ' </TD></TR>' + CHAR(10)
FROM #LoginMap
ORDER BY LoginName
PRINT @strHTML
END
PRINT '</TABLE></DIV><BR><A CLASS="Index" HREF="#_top">Back To Top ^</A><BR><BR>'
----------------SQL roles per user------------------
EXEC ('INSERT INTO #RoleUser
SELECT b.name AS Role_name, a.name AS User_name ' +
'FROM ['+ @dbname+']..sysusers a ' +
'INNER JOIN ['+ @dbname+ ']..sysmembers c on a.uid = c.memberuid ' +
'INNER JOIN ['+ @dbname+ ']..sysusers b ON c.groupuid = b.uid ' +
'WHERE a.name <> ''dbo'''
)
SET @strHTML = ''
PRINT '<DIV ALIGN="center"><TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0" BORDERCOLOUR="003366" WIDTH="60%">'
-- Query the data only if there are rows:
IF NOT EXISTS(SELECT 1 FROM #RoleUser)
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="1" ALIGN="center"><B><A NAME="_DBRoleMapping">Roles per user</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>There are no users mapped to roles in this database</B> </TD></TR>'
END
ELSE
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="2" ALIGN="center"><B><A NAME="_DBRoleMapping">Roles per user</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>Role Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>User Name</B> </TD></TR>'
SELECT @strHTML = @strHTML +
'<TR><TD><B>' + CONVERT(VARCHAR(50),RoLEName) + '</B> </TD><TD>' +CONVERT(VARCHAR(50),ISNULL(UserName,'')) + ' </TD></TR>' + CHAR(10)
FROM #RoleUser
ORDER BY RoLEName
PRINT @strHTML
END
PRINT '</TABLE></DIV><BR><A CLASS="Index" HREF="#_top">Back To Top ^</A><BR><BR>'
----------------Database level Permissions-------------------------
EXEC ('INSERT INTO #DatabasePerms
(UserName,PermType,PermName,IsGrantOption)
SELECT usr.name,
CASE WHEN perm.state <> ''W'' THEN perm.state_desc ELSE ''GRANT'' END,
perm.permission_name,
CASE WHEN perm.state != ''W'' THEN ''--'' ELSE ''X'' END AS IsGrantOption
FROM ['+@dbname+'].sys.database_permissions AS perm
INNER JOIN
['+@dbname+'].sys.database_principals AS usr
ON perm.grantee_principal_id = usr.principal_id
WHERE perm.major_id = 0
ORDER BY usr.name, perm.permission_name ASC, perm.state_desc ASC'
)
SET @rc = @@rowcount
PRINT '<DIV ALIGN="center"><TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0" BORDERCOLOUR="003366" WIDTH="60%">'
-- Query the data only if there are rows:
IF NOT EXISTS(SELECT 1 FROM #DatabasePerms)
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="1" ALIGN="center"><B><A NAME="_DBLvlPerms">Database level permissions</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>There are no specific permissions on the database level</B> </TD></TR>'
END
ELSE
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN=" 4" ALIGN="center"><B><A NAME="_DBPObjPerms">Database level permissions</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>User Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Permission type</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Permission Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Grant option?</B> </TD></TR>'
SET @i = 1
WHILE @i <= @rc
BEGIN
SELECT @strHTML =
'<TR><TD><B>' + CONVERT(VARCHAR(50),UserName) + '</B> </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(PermType,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(PermName,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(5),ISNULL(IsGrantOption,'--')) + ' </TD>'+
'</TR>'
FROM #DatabasePerms
WHERE Rownumber = @i
PRINT @strHTML
SET @i = @i + 1
END
END
PRINT '</TABLE></DIV><BR><A CLASS="Index" HREF="#_top">Back To Top ^</A><BR><BR>'
----------------Database object Permissions-------------------------
EXEC ('INSERT INTO #ObjectPerms
(UserName,PerType,PermName,SchemaName,ObjectName,ObjectType,ColName,IsGrantOption)
SELECT usr.name AS UserName,
CASE WHEN perm.state <> ''W'' THEN perm.state_desc ELSE ''GRANT'' END AS PerType,
perm.permission_name,USER_NAME(obj.schema_id) AS SchemaName, obj.name AS ObjectName,
CASE obj.Type
WHEN ''U'' THEN ''Table''
WHEN ''V'' THEN ''View''
WHEN ''P'' THEN ''Stored Proc''
WHEN ''FN'' THEN ''Function''
ELSE obj.Type END AS ObjectType,
CASE WHEN cl.column_id IS NULL THEN ''--'' ELSE cl.name END AS ColName,
CASE WHEN perm.state = ''W'' THEN ''X'' ELSE ''--'' END AS IsGrantOption
FROM ['+@dbname+'].sys.database_permissions AS perm
INNER JOIN
['+@dbname+'].sys.objects AS obj
ON perm.major_id = obj.[object_id]
INNER JOIN
['+@dbname+'].sys.database_principals AS usr
ON perm.grantee_principal_id = usr.principal_id
LEFT JOIN
['+@dbname+'].sys.columns AS cl
ON cl.column_id = perm.minor_id AND cl.[object_id] = perm.major_id
WHERE obj.Type <> ''S''
ORDER BY usr.name, perm.state_desc ASC, perm.permission_name ASC'
)
SET @rc = @@rowcount
PRINT '<DIV ALIGN="center"><TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0" BORDERCOLOUR="003366" WIDTH="60%">'
-- Query the data only if there are rows:
IF NOT EXISTS(SELECT 1 FROM #ObjectPerms)
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="1" ALIGN="center"><B><A NAME="_DBPObjPerms">Object permissions</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>There are no specific permissions to objects in this database</B> </TD></TR>'
END
ELSE
BEGIN
PRINT '<TR BGCOLOR="EEEEEE"><TD CLASS="Title" COLSPAN="8" ALIGN="center"><B><A NAME="_DBPObjPerms">Object permissions</A></B> </TD></TR>'
PRINT '<TR BGCOLOR="EEEEEE"><TD ALIGN="left" WIDTH="70%"><B>User Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Permission type</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Permission Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Schema Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Object Name</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Object type type</B> </TD><TD ALIGN="left" WIDTH="70%"><B>Column Name</B> </TD><TD ALIGN=" left" WIDTH="70%"><B>Grant option?</B> </TD></TR>'
SET @i = 1
WHILE @i <= @rc
BEGIN
SELECT @strHTML =
'<TR><TD><B>' + CONVERT(VARCHAR(50),UserName) + '</B> </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(PerType,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(PermName,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(SchemaName,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(ObjectName,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(30),ISNULL(ObjectType,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(50),ISNULL(ColName,'--')) + ' </TD>' +
'<TD>' + CONVERT(VARCHAR(5),ISNULL(IsGrantOption,'--')) + ' </TD></TR>'
FROM #ObjectPerms
WHERE Rownumber = @i
PRINT @strHTML
SET @i = @i + 1
END
END
PRINT '</TABLE></DIV><BR><A CLASS="Index" HREF="#_top">Back To Top ^</A><BR><BR>'
FETCH NEXT FROM dbs INTO @dbname
END
---------------Close cursor and drop all temporary objects-------------
CLOSE dbs
DEALLOCATE dbs
DROP TABLE #LoginMap
DROP TABLE #RoleUser
DROP TABLE #ObjectPerms
DROP TABLE #DatabasePerms
PRINT '</BODY></HTML>'
GO
|
---------------For the result- Execute the stored procedure -------------
USE [DbNAME]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[spAuditUsersPermissions]
SELECT 'Return Value' = @return_value
GO
|
Copy Output msg into notepad and save as "SQLSecurityReport.html".
Open SQLSecurityReport.html to view detaial.
SQLSecurityReport.html Output looks below:
Server AUZUR2K8DC6DQ\JIRA2PROD
Back To Top ^
Database Jiradb
Back To Top ^
Database tempdb
Back To Top ^
Back To Top ^
Back To Top ^
Back To Top ^
Open SQLSecurityReport.html to view detaial.
SQLSecurityReport.html Output looks below:
Logins information | ||||||||
Login Name | Default DB | Language | Denied acess? | Windows Auth? | Window group? | Date created | Date UPDATEd | Server roles |
##MS_AgentSigningCertificate## | master | us_english | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
##MS_PolicyEventProcessingLogin## | master | us_english | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
##MS_PolicySigningCertificate## | master | -- | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
##MS_PolicyTsqlExecutionLogin## | master | us_english | -- | -- | -- | Apr 2 2010 5:37PM | Feb 19 2014 5:13PM | -- |
##MS_SmoExtendedSigningCertificate## | master | -- | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
##MS_SQLAuthenticatorCertificate## | master | -- | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
##MS_SQLReplicationSigningCertificate## | master | -- | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
##MS_SQLResourceSigningCertificate## | master | -- | -- | -- | -- | Feb 19 2014 5:13PM | Feb 19 2014 5:13PM | -- |
AUZURMSD01\DepDBAmy | master | us_english | -- | X | X | Feb 12 2014 2:57PM | Feb 12 2014 2:57PM | sysadmin |
AUZURMSD01\hsrvjpsql | master | us_english | -- | X | -- | Feb 12 2014 2:16PM | Feb 12 2014 2:16PM | sysadmin |
Jirausr | master | us_english | -- | -- | -- | Feb 13 2014 2:14PM | Feb 13 2014 2:14PM | -- |
NT AUTHORITY\SYSTEM | master | us_english | -- | X | -- | Feb 12 2014 2:16PM | Feb 12 2014 2:16PM | sysadmin |
NT SERVICE\MSSQL$JIRA2PROD | master | us_english | -- | X | X | Feb 12 2014 2:16PM | Feb 12 2014 2:16PM | sysadmin |
NT SERVICE\SQLAgent$JIRA2PROD | master | us_english | -- | X | X | Feb 12 2014 2:16PM | Feb 12 2014 2:16PM | sysadmin |
sa | master | us_english | -- | -- | -- | Apr 8 2003 9:10AM | Feb 12 2014 2:16PM | sysadmin |
Back To Top ^
Mapping of logins to users | |
Login Name | User Name |
Jirausr | Jirausr |
Back To Top ^
Roles per user | |
Role Name | User Name |
db_owner | Jirausr |
Mapping of logins to users |
There are no mappings in this database |
Back To Top ^
Roles per user |
There are no users mapped to roles in this database |
Back To Top ^
Database level permissions | |||
User Name | Permission type | Permission Name | Grant option? |
dbo | GRANT | CONNECT | -- |
guest | GRANT | CONNECT | -- |
Back To Top ^
Object permissions |
There are no specific permissions to objects in this database |
Back To Top ^