What database user permissions are needed? - sql-server

FYI: SQL Server 2005
I have a database user account (user_web) that has the ability to connect to and run queries and stored procedures in my database. Specifically, I have given the user the db_datareader and db_datawriter roles as well as granted them execute permission on the specific stored procedures it needs to be able to run.
In one of the stored procedures, I need to disable a trigger then re-enable it after some specific edits are done. When I attempt to run that stored procedure with the user I get the following error:
Cannot find the object "TableName" because it does not exist or you do not have permissions.
TableName is the table where I am attempting to disable and enable the trigger. My question is what is the least amount of permissions I can give to my user account that will allow it to successfully run the stored procedure.

The user will "at a minimum" require ALTER permissions on the table in question. See: http://technet.microsoft.com/en-us/library/ms182706.aspx

Rather than grant the user ALTER permissions on the table, which could be a security issue, I'd have that particular stored procedure run as a different user that does have those permissions. Use the EXECUTE AS syntax to accomplish this.
http://msdn.microsoft.com/en-us/library/ms188354.aspx

Related

How to create a login that ONLY has access to run stored procedures?

I have a C# Winform application that interacts with an SQL Server DB via stored procedures. In SSMS, how do I create a login that ONLY has permissions to run stored procedures? That login wouldn't be able to view/edit/create table definitions, etc. It would also only have access to a single specified DB.
The reason I want to create such a login is because I store the SQL Server credentials used by my Winform application in its App.config file. Since the app.config can easily be read, anyone with malicious intent can easily perform unwanted operations on the database if the given login had any other permissions than just stored procedures.
A neat trick in this scenario is to create a separate (custom) SQL Server role that can only execute stored procedures:
CREATE ROLE db_executor;
GRANT EXECUTE TO db_executor;
This role now has the permission to execute any stored procedure in the database in which it's been created - and in addition: that permission will also extend to any future stored procedures you might create later on in this database.
Now create a user in your database and give it only this database role - this user will only be able to execute stored procedures - any and all of them in your database.
If you user should be allowed to execute any and all stored procedures - this is a very convenient way to allow this (and you don't have to constantly update the permissions when new stored procedures are created).
You can use the following query in order to allow stored procedure execute permision to your user
USE [DB]
GRANT EXECUTE ON dbo.procname TO username;
However, in my humble opinion , you should secure the connection string in the app.config.
Maybe , this How to store login details securely in the application config file link can be helped to you.
The access to a specific database is done through creating a user on the database that you want him to operate on. You can find more infos about users here.
If the user is created you can Grant, With Grant and Deny actions for every single item on the database.
The user will then be granted/denied those rights by a grantor, which is the dbo by default.
You can use this to also deny him access to every item on your database that isn't your stored procedure, which is what you're looking for if I understand you correctly.
Try folloiwng approach (grant execute should be repeated for every SP). Note that MyStoredProcedure has to be in MyDatabase :)
-- create login to server
create login test_user with password = 'test';
-- create user mapped to a database
use MyDatabase
go
create user test_user for login test_user;
-- grant permission to execute SP
grant execute on MyStoredProcedure to test_user

How to give permission to rename a database sql-server

I have a user who needs to rename a database. I could give dbcreator privileges, but this would allow the user to rename any database, and even create new ones.
So I tried to create a stored procedure that the user would call to do the job.
CREATE PROCEDURE SPMyRenameDB
WITH EXECUTE AS 'MySuperUser' -- MySuperUser is a SQL user with dbcreator permission
AS
ALTER DATABASE A MODIFY NAME = B
GO
I get an error :
The server principal "MySuperUser" is not able to access the database "A" under the current security context.
I tried with sp_renamedb, I get : User does not have permission to perform this action.
Even a simple SELECT statement to a table in database A is not allowed : The server principal "MySuperUser" is not able to access the database "A" under the current security context.
When I connect as MySuperUser and query the database A, it works as expected. (MySuperUser is a SQL user with dbCreator and sysAdmin privileges on the server).
I suspect that the "WITH EXECUTE AS" statement has some security restrictions that do not allow to use it outside of the current database.
The Stored Procedure is in a database (other than A and B) where the user has db_owner permissions.
Any suggestions ? I do not need to stick with my "WITH EXECUTE AS" approach. Anything that would do the trick is welcome.
Thanks,
Yves
Check ALTER DATABASE in MSDN -> Permissions
Requires ALTER permission on the database.
So just query as following
USE A
GO
GRANT ALTER TO 'someuser'
GO
User must be member of dbcreator server role. (MSDN documentation is wrong!).

stored procedure permissions and execute

I have a SQL user that I gave explicit Execute permission for a specific stored procedure. This stored procedure contains a truncate statement. The user is unable to execute that procedure and receives the error:
Cannot find the object TableName because it does not exist or you do not have permissions.
If I alter the stored procedure to use Delete instead of truncate the user can execute the procedure.
What do I need to do to allow the user to execute this stored procedure, without giving the user more access than necessary?
From MSDN:
http://msdn.microsoft.com/en-us/library/ms177570.aspx
"The minimum permission required is ALTER on table_name. TRUNCATE TABLE permissions default to the table owner, members of the sysadmin fixed server role, and the db_owner and db_ddladmin fixed database roles, and are not transferable. However, you can incorporate the TRUNCATE TABLE statement within a module, such as a stored procedure, and grant appropriate permissions to the module using the EXECUTE AS clause. For more information, see Using EXECUTE AS to Create Custom Permission Sets."
You can try this:
create procedure SpName
with execute as owner
as
truncate table TableName
go
Then assign permission to user
grant execute on TruncTable to User
truncate table Setting permission on objects like stored procedures can be accomplished with:
GRANT EXECUTE ON <schema>.<object> to <user>;
However, you may also want to grant security rights at both the login and user level. You will want to determine and grant ONLY the necessary rights for the objects that require access (such as execution). Consider use of the EXECUTE AS capability which enables impersonation of another user to validate permissions that are required to execute the code WITHOUT having to grant all of the necessary rights to all of the underlying objects (e.g. tables). EXECUTE AS can be added to stored procedures, functions, triggers, etc.
Add to the code as follows right within the Stored Procedure:
CREATE PROCEDURE dbo.MyProcedure WITH EXECUTE AS OWNER
In this case you are impersonating the owner of the module being called. You can also impersonate SELF, OR the user creating or altering the module OR... imperonate CALLER , which will enable to module to take on the permissionsof the current user, OR... impersonate OWNER, which will take on the permission of the owner of the procedure being called OR... impersonate 'user_name', which will impersonate a specific user OR... impersonate 'login_name' with will impersonate a specific login.
MOST of the time, you will only need to grant EXECUTE rights to stored procs and then rights are granted to all objects referenced within the stored proc.
In this way, you DO NO need to give implicit rights (example: to update data or call additional procs). Ownership chaining handles this for you. This is especially helpful for dynamic sql or if you need to create elevated security tasks such as CREATE TABLE. EXECUTE AS is a handy tool to consider for these.
This example may help clarify all of this:
Create a user called NoPrivUser with public access to a database (e.g. dbadb):
USE [master];
GO
CREATE LOGIN [NoPrivUser] WITH PASSWORD=N'ABC5%', DEFAULT_DATABASE=[dbadb],
CHECK_EXPIRATION=ON, CHECK_POLICY=ON;
GO
USE [DBAdb];
GO
CREATE USER [NoPrivUser] FOR LOGIN [NoPrivUser];
GO
NOTE: CREATOR OR OWNER OF THIS PROCEDURE WILL REQUIRE CREATE TABLE RIGHTS within the target database.
use DBAdb
go
CREATE PROCEDURE dbo.MyProcedure
WITH EXECUTE AS OWNER
truncate table MyTable
GO
GRANT EXEC ON dbo.MyProcedure TO NoPrivUser;
GO
-- Now log into your database server as NoPrivUser and run the following.
With the EXECUTE AS clause the stored procedure is run under the context of the object owner. This code successfully creates dbo.MyTable and rows are inserted successfully. In this example, the user NoPrivUser has absolutey no granted rights to modify the table, or read or modify any of the data in this table.
It only takes on the rights needed to complete this specific task coded WITHIN the context of this procedure.
This method of creating stored procedures that can perform tasks that require elevated security rights without permanently assigning those rights come be very useful.

Question on schemas and security

I need to set some users up to be able to create stored procedures with READ access only. Also, in production they cannot have SELECT, only EXECUTE on the procs they created. In development they would have SELECT so they could create their procedures.
I've set up a schema called Reports. The owner of that schema is a login - Report_Admin. That user has select access to tables. I then gave alter and execute on the Reports schema to my report writer account. Dbo owns the table - so it works if dbo also owns the Reporting schema - but then a delete will also work in the procedure!
We are using reporting services and would like to have all the SQL in the database for maintainability.
Thanks!
You're not going to succeed using ownership chaining, as you already discovered. A solution would be like this: report_writer must create its reports with an EXECUTE AS SELF clause so they get executed under the report_writer priviledges. Then the report_reader group will be able to leverage the EXECUTE permission on reports schema to execute said reports, and the reports will be able to read the data because of the execute as clause.
You can assign permissions to roles and users, no need for separate schema's. So I'd only use one schema: "dbo" (the default)
Create a database role for the users. Grant data_reader to that role on development. On both development and production, grant execute rights on the stored procedures. As far as I know, you'll have to grant the execute right for each stored procedure.

How to grant permissions to developers to grant permissions to users?

Is there a way I can give developers permission to grant a user permissions over objects without giving them the option to create users or functions?
I'm trying to limit developers permissions, I recently found out that developers had db_owner permissions in dev and prod environments! So I'm doing my best to stop this madness.
Any good article about this matter?
You can make them members of the "db_securityadmin" database role
As said, if someone could hand out permissions, they could hand out permissions to themselves (or a dummy account). I'm not sure if there is a trick in SQL Server to provide "give user permissions less then me".
The way I would do it is with stored procedures.
Create a stored procedure that gives a specified user a specific right or set of rights (those rights are the ones that regular users are allowed to have). Then give the developers execute access to this stored procedure. In effect you use stored procedures to create a limited version of GRANT, while keeping the full GRANT command to yourself.
If someone can give someone else permissions, he can also give himself the permission to do what he wants. So what is this good for? Probably I don't understand your situation.
Owners of objects can grant permissions on those objects. Provided your developers don't need to grant things like CREATE TABLE rights, you might be able to give them ownership of the objects that you want them to grant permission on.
As Stefan said, giving them grant permissions would effectively give them all permissions, since if they want to do something all they have to do is grant themselves the permissions to do it.
Rather than considering the developers the enemy, though, you may want to consider giving the developers a second user account that's used to administer the database. It's pretty common not to give developers ANY permissions to production, at least on their development account.
Setting permission on objects like stored procedures can be accomplished with "GRANT EXECUTE ON . to ;
However, you may also want to grant security rights at both the login and user level. You will want to determine and grant ONLY the necessary rights for the objects that require access (such as execution). Consider use of the "EXECUTE AS" capability which enables impersonation of another user to validate permissions that are required to execute the code WITHOUT having to grant all of the necessary rights to all of the underlying objects (e.g. tables). The EXECUTE AS can be added to stored procs, functions, triggers, etc.
Add to the code as follows right within the Stored Procedure: CREATE PROCEDURE dbo.MyProcedure WITH EXECUTE AS OWNER
In this case you are impersonating the owner of the module being called. You can also impersonate SELF, OR the user creating or altering the module OR... imperonate CALLER , which will enable to module to take on the permissionsof the current user, OR... impersonate OWNER, which will take on the permission of the owner of the procedure being called OR... impersonate 'user_name', which will impersonate a specific user OR... impersonate 'login_name' with will impersonate a specific login.
MOST of the time, you will only need to grant EXECUTE rights to stored procs and then rights are granted to all objects referenced within the stored proc.
In this way, you DO NO need to give implicit rights (example: to update data or call additional procs). Ownership chaining handles this for you. This is especially helpful for dynamic sql or if you need to create elevated security tasks such as CREATE TABLE. EXECUTE AS is a handy tool to consider for these.
This example may help clarify all of this:
Create a user called NoPrivUser with public access to a database (e.g. dbadb)
USE [master] GO CREATE LOGIN [NoPrivUser] WITH PASSWORD=N'ABC5%', DEFAULT_DATABASE=[dbadb], CHECK_EXPIRATION=ON, CHECK_POLICY=ON GO USE [DBAdb] GO CREATE USER [NoPrivUser] FOR LOGIN [NoPrivUser] GO
NOTE: CREATOR OR OWNER OF THIS PROCEDURE WILL REQUIRE CREATE TABLE RIGHTS within the target database.
use DBAdb go CREATE PROCEDURE dbo.MyProcedure WITH EXECUTE AS OWNER AS IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].MyTable') AND type in (N'U')) CREATE TABLE MyTable (PKid int, column1 char(10)) INSERT INTO MyTable VALUES (1,'ABCDEF')
GO
GRANT EXEC ON dbo.MyProcedure TO NoPrivUser; GO
-- Now log into your database server as NoPrivUser and run the following.
use dbadb go
EXEC dbo.MyProcedure
(1 row(s) affected)
Now try to select from the new table while logged on as NoPrivuser.
You will get the following:
select * from MyTable go
Msg 229, Level 14, State 5, Line 1 The SELECT permission was denied on the object 'MyTable', database 'DBAdb', schema 'dbo'.
That is expected since you only ran the procedure under the security context of Owner while logged on as NoPrivUser.
NoPrivUser as no rights to actually read the table. Just to execute the procedure which creates and inserts the rows.
With the EXECUTE AS clause the stored procedure is run under the context of the object owner. This code successfully creates dbo.MyTable and rows are inserted successfully. In this example, the user "NoPrivUser" has absolutey no granted rights to modify the table, or read or modify any of the data in this table.
It only takes on the rights needed to complete this specific task coded WITHIN the context of this procedure.
This method of creating stored procedures that can perform tasks that require elevated security rights without permanently assigning those rights come be very useful.
I've found that the most dangerous aspect of the db_owner role is that if you issue a deny on a permissions, then the members of the role can grant it back to themselves. I've just started reading about this and I'm testing this
Create role db_ControlDatabase
grant control to db_ControlDatabase
deny backup database to db_ControleDatabase
alter role db_ControlDatabase add member TestUser
So far, I've found that the subject TestUser has permissions without being able to add or remove members of the fixed database roles. You should be able to deny whatever you need at this point like backup certificate, backup master key, etc.
Here is a list of permissions that can be denied or granted:

Resources