I have trust issues. No really, our trust between our domains was severed this morning.
Here is a script that will add logins to the servers, create users in all the user databases on the servers (under the datareader & datawriter roles, but configurable), and then grant view definition on all the procs, views & udf’s on the server.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null $Error.Clear() cls $servers = Get-Content c:\Test\Servers.txt $roles = @("db_datareader","db_datawriter") [string]$LoginName = "aaLogin"; [string]$Password = "BenderIsGreat!&"; foreach($server in $servers) { $srv = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $server #careful, if the login exists this will drop it if ($srv.Logins.Contains($LoginName)) { $srv.Logins[$LoginName].Drop(); } $login = New-Object ('Microsoft.SqlServer.Management.Smo.Login') $srv, $LoginName $login.LoginType = [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin; $login.Create($Password); # refresh login so it contains the SID $srv.Logins.Refresh(); $login = $srv.Logins[$LoginName] foreach($database in $srv.Databases) { if($database.IsSystemObject -eq $false -and $database.Name -ne "LiteSpeedLocal") { #careful, this will drop the user from the db if it exists if($database.Users.Contains($LoginName)) { $database.Users[$LoginName].Drop(); } $user = New-Object('Microsoft.SqlServer.Management.Smo.User') $database, $login.Name $user.Login = $login.Name $user.create(); foreach($role in $roles) { $role = $database.Roles[$role] $role.AddMember($user.Name) } foreach($proc in $database.StoredProcedures | where{$_.IsSystemObject -eq $false}) { $perm = New-Object('Microsoft.SqlServer.Management.Smo.ObjectPermissionSet') $perm.ViewDefinition = $true; $proc.grant($perm, $LoginName); } foreach($view in $database.Views | where{$_.IsSystemObject -eq $false}) { $perm = New-Object('Microsoft.SqlServer.Management.Smo.ObjectPermissionSet') $perm.ViewDefinition = $true; $view.grant($perm, $LoginName); } foreach($udf in $database.UserDefinedFunctions | where{$_.IsSystemObject -eq $false}) { $perm = New-Object('Microsoft.SqlServer.Management.Smo.ObjectPermissionSet') $perm.ViewDefinition = $true; $udf.grant($perm, $LoginName); } foreach($uda in $database.UserDefinedAggregates | where{$_.IsSystemObject -eq $false}) { $perm = New-Object('Microsoft.SqlServer.Management.Smo.ObjectPermissionSet') $perm.ViewDefinition = $true; $uda.grant($perm, $LoginName); } foreach($trigger in $database.Triggers | where{$_.IsSystemObject -eq $false}) { $perm = New-Object('Microsoft.SqlServer.Management.Smo.ObjectPermissionSet') $perm.ViewDefinition = $true; $trigger.grant($perm, $LoginName); } } } }
This script seems like it should work fairly well, but the permissions on SQL after you’re done seem like they might be sort of messy.
To simplify auditing of permissions, I would create a role, grant the permissions to the role and then add the users to that role. In this case I would create a role call db_definitionviewer, grant it permissions, then add users to it. In this example, I am granting permission at the database level instead of object level.
CREATE ROLE [db_definitionviewer]
GRANT VIEW DEFINITION TO [db_definitionviewer]
Hope this helps some.
Definitely a good suggestion. We’ve been granting permissions to objects directly to the users for quite some time now and are just now starting re-look at the way we implement it. We’ve not really noticed any issues with granting the permissions directly. But, assigning the users to a role with view definition definitely has advantages.