First published on MSDN on Aug 11, 2016
Recently I was working with a customer who wanted to know all the users in their environment who had ssis_admin permissions within their Integration Services environment. In SQL Server 2008 R2, a new catalog view was introduced that allows us to bridge between database_roles and their associated members, under sys.database_role_members. With this simple bridge table, we can do some quick joins to the sys.database_principals catalog view and get a nice report of who has permissions under a specific database role. Here is a very straight forward SQL query that allows us to see all the users who have ssis_admin on our server:
SELECT dr.name [DatabaseRoleName] ,ISNULL(pr.Name, 'No Members Found!') [DatabaseUserName] FROM sys.database_role_members drm RIGHT JOIN sys.database_principals dr ON drm.role_principal_id = dr.principal_id LEFT JOIN sys.database_principals pr ON drm.member_principal_id = pr.principal_id WHERE dr.name = 'ssis_admin'
#list of servers to be check $servers = Invoke-Sqlcmd -ServerInstance sql2016a -Database PerformanceMonitor -Query "SELECT DISTINCT [ServerName] FROM Server WHERE HasIsCatalog = 1"
#function to retrieve database users and roles</pre> Function Get-DatabaseUsers ([string]$Servername) { $query = Invoke-Sqlcmd -ServerInstance $Servername -Database SSISDB -Query "SELECT @@SERVERNAME [ServerName] ,dr.name [DatabaseRoleName] ,ISNULL(pr.Name, 'No Members Found!') [DatabaseUserName] FROM sys.database_role_members drm RIGHT JOIN sys.database_principals dr ON drm.role_principal_id=dr.principal_id LEFT JOIN sys.database_principals pr ON drm.member_principal_id=pr.principal_id WHERE dr.name = 'ssis_admin'" #the below outputs the result of the above when the function is called $query }
Function out-DataTable { $dt = new-object Data.datatable $First = $true foreach ($item in $input){ $DR = $DT.NewRow() $Item.PsObject.get_properties() | foreach { if ($first) { $Col = new-object Data.DataColumn $Col.ColumnName = $_.Name.ToString() $DT.Columns.Add($Col) } if ($_.value -eq $null) { $DR.Item($_.Name) = "[empty]" } elseif ($_.IsArray) { $DR.Item($_.Name) =[string]::Join($_.value ,";") } else { $DR.Item($_.Name) = $_.value } } $DT.Rows.Add($DR) $First = $false } return @(,($dt)) }
#execute the functions foreach ($ServerName in $servers) { $dataTable = Get-DatabaseUsers $ServerName.ServerName | out-DataTable #$dataTable #you can use this to check the output
#initialize a sqlbulk copy object to write the data to the centralized table $connectionString = "Data Source=sql2016a; Integrated Security=True;Initial Catalog=PerformanceMonitor;" #open the connection $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $connectionString #set the destination table $bulkCopy.DestinationTableName = "DatabaseRolesList" #perform the column mappings $bulkCopy.ColumnMappings.Add("ServerName","ServerName") $bulkcopy.ColumnMappings.Add("DatabaseRoleName","DatabaseRoleName") $bulkcopy.ColumnMappings.Add("DatabaseUserName","DatabaseUserName") #write the data to the table $bulkCopy.WriteToServer($dataTable)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.