SQL Server project - how to publish stored procedure permissions - sql-server

In my .NET WinForms application (in a Visual Studio solution), I have the tables and stored procedures in a SQL Server project within the solution so I can easily keep my schema under version control, and I can successfully use the 'Publish' feature to deploy schema changes to the development database.
I'm getting ready to deploy my application and have asked a user to trial the application on their PC against the development database prior to rolling out the new application and database schema changes to production company wide.
What I'm finding is that the application is throwing SqlException. I've managed to track this down to permissions on the new stored procedures (obviously, I don't have this issue as the owner of the stored procedures).
I can manually correct this by granting permissions on the stored procedure(s), as follows
GRANT EXECUTE ON [dbo].[<tablename(s)>] TO DatabaseUsers
...but what I'd ideally like to do is include this within the definition of the stored procedure(s) in the SQL Server project that's under version control.
I've tried adding the above statement to the end of the stored procedure definition (below) in the SQL Server project, the output from the deployment script seems to show the command being executed, however whilst it updates the stored procedure, it won't touch the permissions.
-- Snipped 50 lines above for brevity
OR c.name LIKE #search
OR CAST(it.id AS VARCHAR) LIKE #search
OR ig.name LIKE #search
ORDER BY it.id
END
GRANT EXECUTE ON [dbo].[search_items_allfields] TO DatabaseUsers
GO
I've also tried adding an additional GO before the GRANT statement in the above definition, but then I'm unable to use the publish script, as it refuses to run due to not being able to resolve the group 'DatabaseUsers' (without the GO, it's still unable to resolve it, but is happy enough to run it).

In addition to the GO before the GRANT (so it's not part of the procedure), you need to add a script for the role to your project to resolve the reference:
CREATE ROLE DatabaseUsers;
GO
Of course, you'll need to add role members too. I suggest you manage role memberships separately rather than part of the SSDT project since those will vary by environment and many organizations have separate process for managing database access security.

Related

DACPAC SQL Server dropping schema permissions

I am trying to use a DACPAC database project in Azure Data Studio.
So far, it works fine except for the "publishing" of the project to the actual DB.
When I generate the delta script, I see that all permissions on all schemas are being dropped.
I know that I could exclude certain objects:
SQL Server DACPAC Deployment Dropping Users/Roles/Permissions
However, I would prefer to have also the permissions of DB roles on a schema in the DB project.
Here, of course, the order is important. (Create schema, create user, create DB role, add user to DB role, grant permission for DB role on schema)
How (and to which file) can I add the schema permissions to the project and how can it be ensured that the TSQL statements that are generated are executed in the correct oder?
Thx.
At the linked QA have a look at the XML: there are separate parameters
DropPermissionsNotInSource
DropRoleMembersNotInSource
represented in sqlproj/publish.xml in a reversed way
<DoNotDropRoleMembership>True</DoNotDropRoleMembership>
<DoNotDropPermissions>True</DoNotDropPermissions>
By switching them to "do not drop" state you can avoid excluding permissions from deployment. Thus new permissions (defined in project but missing on target server) would be created but old ones (existing on target server but missing in the project) will not be dropped. Same goes for role membership.
Valid command order in publish script is guaranteed by the SSDT engine.
Still, permissions on target server can be lost if publishing requires object recreation. For example if you alter table-type then referencing procs will be dropped and recreated after type recreation.

SQL Server Grant Remote access to execute Stored Procedures within a given Schema

I am a developer for a hospital which uses software provided by a 3rd party vendor which hosts Sql Server for us. We have a local instance of Sql Server 2012 which has a linked server to their Sql Server instance. Within our instance of Sql Server we can see all of the Views and Tables that have been assigned to us but none of the stored procedures.
However, I have been given a Citrix connection which allows me to access Sql Server on their network. From here, I can create, alter and execute stored procedures in the [CUSTOMER] schema they created for this purposes (we can only execute procs in dbo, but not alter or create).
The vendor is now trying to give me access to execute stored procedures we created in [CUSTOMER] through our linked server. However, it's not working. They say they have given permission to my user as well as the user listed under the Security tab of Linked Server Properties in "Be made using this security context".
Properties for RPC and RPC Out are set to true.
No Sp's show up under the linked server node (no "programmability" node at all). And when I try to execute my proc like this: [remoteserver.ip.address].[remoteDbInstance].[Customer].[extr_myProc], I get the following error:
"Cannot find the object "extr_myProc" because it does not exist or you do not have permissions."
I suspect there's an issue on their side but our contact at the vendor says they've done everything. Is there something else I should be doing on my side though?
I suspect that there's more than one measure a vendor can take to lock down stored procs over a linked server and all their support staff did was to make sure [CUSTOMER] was executable for our users, but another setting is blocking it specifically for linked servers.
Is there something I can suggest to their support staff to look at for us that can hide stored procs from a user, but only over a linked server?
Thanks!

XP_DirTree in SQL Server

Variations to this have been asked. I have no problem searching a local directory with the below piece of code.
EXEC MASTER.sys.xp_dirtree 'C:\', 1, 1
When I switch the path to a network location the results are empty.
EXEC MASTER.sys.xp_dirtree '\\Server\Folder', 1, 1
I first thought maybe it was something to do with permissions. I added the SQL Server Service to the ACL list on the shared volume as well as the security group.
Any help or direction to point me in is greatly appreciated or even another way to get a list of files in a directory and sub directories.
[Edited]
The two things to look out for are:
Make certain that the Log On account for the SQL Server service (the service typically listed as "SQL Server (MSSQLSERVER)" in the Services list) has rights to that network share.
UPDATE
The problem ended up being that the O.P. was running the SQL Server service as a local system account. So, the O.P. created a domain account for SQL Server, assigned that new domain account as the Log On As account for the SQL Server service, and granted that domain account the proper NTFS permissions.
Please note that this might have also been fixable while keeping the SQL Service running as a local system account by adding the server itself that SQL Server is running on to the NTFS permissions. This should usually be possible by specifying the server name followed by a dollar sign ($). For example: MySqlServer01$. Of course, this then gives that NTFS permission to all services on that server that are running as a local system account, and this might not be desirable. Hence, it is still preferable to create a domain account for the SQL Server service to run as (which is a good practice in any case!).
It sounds like this has been done, so it should be tested by logging onto windows directly as that account and attempting to go to that specific network path.
Make sure that the Login in SQL Server that is executing xp_dirtree has "sysadmin" rights:
This can be done directly by adding the account to the sysadmin server role, or
Sign a stored procedure that runs xp_dirtree:
Create a certificate in [master]
Create a login based on that certificate
Add the certificate-based login to the sysadmin server role
Backup the certificate
Restore the certificate into whatever database has, or will have, the stored procedure that runs xp_dirtree
Sign the stored procedure that runs xp_dirtree, using ADD SIGNATURE and the certificate that was just restored
GRANT EXECUTE on that stored procedure to the user(s) and/or role(s) that should be executing this.
Just to have it stated, another option is to do away with xp_dirtree altogether and instead use SQLCLR. There is probably sample C# code on various blogs. There are also a few CodePlex projects that have file system functions and might also provide a pre-compiled assembly for those that don't want to deal with compiling. And, there is also the SQL# library that has several filesystem functions including File_GetDirectoryListing which is a TVF (meaning: you can use it in a SELECT statement with a WHERE condition rather than needing to dump all columns and all rows into a temp table first). It is also fully-streamed which means it is very fast, even for 100k or more files. Please note that the FILE_* functions are only in the Full version (i.e. not free) and I am the creator of SQL#, but it does handle this situation quite nicely.

Grant permissions to a SQL database role remotely

I'm working on a short-term disaster recovery planning effort at my company, and we're planning on using replicated reporting servers as warm spares in case our primary transaction server dies.
Our web application can to write to that transaction server, but with only certain rights given by a SQL role. (webapplication) I want to give us a way of updating this role that also updates the same role as it exists on other servers. This way, if we fail over to another server, our webapplication role is reasonably close to the same, if not exactly the same. (I'm not really worried about someone updating it directly)
So, I have a MakeWebWriteable procedure that should generate and execute some code like what is below. Except, what's below clearly won't work. I'm at a loss for how to reference the role and update it on a remote server. I thought about using exec (#sql) at [reporting\server], but I'm not sure how I would reference a certain database's role object within that.
grant insert, update, delete on dbo.TableName to webapplication
grant insert, update, delete on [reporting\server].DBName.dbo.TableName to [reporting\server].DBName.dbo.webapplication
How might I do this, or are there any better ideas? (i.e. replication)
edit 1: We generally write migrations as SQL scripts, commit those to SVN, and have our databases updated with a syncing script - sort of like what the process in RoR is, only without a model->SQL translation. Ideally, we would just put a line at the end of a migration in which we added a table like so, if we want the table to be web-writeable.
-- Code to create NewTable...
if object_id('SetWebWriteable') is not null
exec SetWebWriteable #tableName = 'NewTable'
This way, nothing happens on our developer machines, but in our test and production environments, the correct actions occur. If the role can be replicated automatically, then naturally we wouldn't need to do this.
From what You are describing, You need SQLCMD utility. Connect to any server using the credentials it accepts (I usually use -E which represents windows authentication) and execute whatever scripts YOu need. If You are not trusted there, create an account with sufficient credentials.
The question is: What is the trigger of this script to execute? Do YOu execute it manually, or should it fire up automatically. In this case You are bound to write some code to achieve that (not very difficult though).
And You can leverage powershell built into SQL Server 2008 which can operate on objects on ANY server You can connect to (with your credentials). Look into that. It has a cmdlet Invoke-Sqlcmd which helps a TON.
luke

Cannot Find Stored Procedure Error

I recently did an import of database from a sql server 2000 database to a sql server 2005 database. I've gone through and setup what I thought were the same login credentials and owner permissions that I had previously setup in my old database.
All of the code base I'm working has stored procedures listed simply by stored procedure name.
In order to make sure I have the proper logins created, I am logging into the SQL Server Management studio with the connection information my application is using (i.e. using the username "licensemgr" and it's associated password). I can see all the tables, stored procedures, etc... in my database when I log in with combination. When I try to run a stored procedure, Sql Server Management Studio uses the following syntax to execute it:
EXEC: #return_value = [licensemgr].[Stored_Procedure_Name]
and it executes without error.
If I try to remove the [licensemgr]. from before the [Stored_Procedure_Name], however I get the error "Cannot find stored procedure: Stored_Procedure_Name". This is the same error I get when running my application off this database. I changed one stored procedure call in my application to have "licensemgr." in front of the stored procedure name and that seemed to correct the problem, however, I don't want to do that for each and every stored procedure call in my application. I am therefore wondering what type of setup / permissions type issue I might be missing in my SQL Server instance so that even when I'm logged into the database as licensemgr, I cannot see the stored procedure which is in the schema "licensemgr".
In SQL server 2000 the [licensemgr] referred to the owner of the table. So when you are logged in as [licensemgr] you do not need the prefix.
In SQL Server 2005 this has been changed to the schema, therefore it must be specified. See:
http://msdn.microsoft.com/en-us/library/ms190387.aspx
EDIT
There are two things that you need to watch out for:
If the user is in the sysadmin role, he will always default to the dbo schema, therefore you need to prefix
If your user needs to run code that is in different schemas you will need to prefix
If none of the two above it should work by setting the default schema for the user
When you created your user, did you specify DEFAULT_SCHEMA?
CREATE USER ... WITH DEFAULT_SCHEMA = "licensemgr"
If not, you may need to use ALTER USER to fix this for your user in the new system.

Resources