I have a SQL Server 2008 database where all access to the underlying tables is done through stored procedures. Some stored procedures simply SELECT records from the tables while others UPDATE, INSERT, and DELETE.
If a stored procedure UPDATES a table does the user executing the stored procedure also need UPDATE permissions to the affected tables or is the fact that they have EXECUTE permissions to the stored procedure enough?
Basically I am wondering if giving the user EXECUTE permissions to the stored procedures is enough or do I need to give them SELECT, UPDATE, DELETE, and INSERT permissions to the tables in order for the stored procedures to work. Thank you.
[EDIT] In most of my stored procedures it does indeed appear that EXECUTE is enough. However, I did find that in stored procedures where "Execute sp_Executesql" was used that EXECUTE was not enough. The tables involved needed to have permissions for the actions being performed within "sp_Executesql".
Permissions on tables are not checked (including DENY) if tables and proc have the same owner. They can be in different schemas too as long as the schemas have the same owner.
See Ownership chaining on MSDN
Edit, from a comment from a deleted answer.
The context is always the current login unless EXECUTE AS as been used: only referenced object DML permissions are not checked. Try OBJECT_ID(referencedtable) in a stored proc where no rights are assigned to referencedtable. It gives NULL. If executed by the owner of the stored proc then it would give a value because owener has rights on referencedtable
Execute permissions on the stored procedure is sufficient.
CREATE TABLE dbo.Temp(n int)
GO
DENY INSERT ON dbo.Temp TO <your role>
GO
CREATE PROCEDURE dbo.SPTemp(#Int int)
AS
INSERT dbo.Temp
SELECT #Int
GO
GRANT EXEC ON dbo.SPTemp TO <your role>
GO
Then the (non-db_owner) user will have the following rights:
EXEC dbo.SPTemp 10
GO
INSERT dbo.Temp --INSERT permission was denied on the object 'Temp'
SELECT 10
However, if there is dynamic SQL inside dbo.SPTemp that attempts to insert into dbo.Temp then that will fail. In this case direct permission on the table will need to be granted.
Maybe you can use
"with execute as owner"
when you create the stored procedure, such as below:
create procedure XXX
with execute as owner
as
begin
...
end
go
Then you only need to grant the user the EXECUTE permission for the stored procedure XXX.
Execute permission on a stored procedure that does an insert, update, or delete is sufficient. You do not need to grant those permissions at the table level. In fact, I would discourage that approach. Using a stored procedure gives you more control over how the change occurs. For instance, you may wish to do some checking prior to allowing the update. Using a stored procedure can also help prevent major accidents--like deleting all the rows in the table because someone forgot the WHERE clause!
THANK YOU SO MUCH! I had a similar problem. This lead me to the answer.
I was attempting to trunctate a table in a stored procedure that called other stored procedures that were nested in IF statements.
My error was
The server principal "domain\my_id" is not able to access the database "2nd_DB" under the current security context.
I had given the calling stored procedure rights to do the truncate (EXECUTE AS SELF), which then caused a problem because SELF didn't have rights to the 2nd DB. Our solution was to move the truncate to another SP, include the EXECUTE AS SELF. We now call the truncate SP, execute our data processing, make logic determination, and call the appropriate 3rd SP.
Related
I have a store procedure that have several selects for checking and balances in our order process, long story short, this store procedure reads (SELECT) about 20 tables with are spread in 3 databases.
CREATE USER [stageUsrOrder] FOR LOGIN [domain\[my user]]
GO
CREATE ROLE OrderSpecRole AUTHORIZATION [stageUsrOrder]
GO
GRANT EXECUTE on [orders].[ValidateOrderById] TO pmdSchedulerRole
GO
I thought that this statements would give me read access to all the tables inside the store procedure.
I have try
GRANT EXECUTE on [AVIS].[spReportValidationByLAN] TO pmdSchedulerRole WITH GRANT OPTION
GO
But it didn't work.
So, How do I grant execute access to the store procedure and SELECT to all the tables inside?
You don't. One of the value propositions of stored procedures is that you can restrict access to certain patterns. For example, if you want people to only search by ID, you give then a stored procedure that takes ID as a parameter.
But if you want to give them arbitrary select access to the underlying tables, you have to do that explicitly.
I have a stored procedure where I'd like to save the execution of an update statement for further down in the procedure, which I'm doing by putting the sql into a varchar variable.
My problem is that the EXECUTE() seems to use the original caller's permissions and then gives an error, as the caller does not (and should not) have UPDATE permissions for table1.
Why doesn't it use the permissions of the stored procedure's owner?
And more importantly: how can I make it use those permissions?
The stored procedure looks basically like this: (except #tsql_string is set dynamically)
create procedure dbo.woopwoop() as
BEGIN
DECLARE #tsql_string varchar(max)
SET #tsql_string = 'UPDATE table1 set c1 = 1'
EXECUTE(#tsql_string)
END
I'm on SQL Server 2008, and the owner (me) of the stored procedure is a Windows Authentication user with domain\user.
Anyone?
That's what the EXECUTE AS clause exists for - to allow you to control this:
By specifying the context in which the module is executed, you can control which user account the Database Engine uses to validate permissions on objects that are referenced by the module.
CALLER
Specifies the statements inside the module are executed in the context of the caller of the module. The user executing the module must have appropriate permissions not only on the module itself, but also on any database objects that are referenced by the module.
CALLER is the default for all modules except queues
You would be wanting to specify that the stored procedure executes as OWNER (or possibly SELF, read the above page and decide which makes most sense for you) instead.
create procedure dbo.woopwoop()
with execute as owner
as
....
From MSDN (This example grants EXECUTE permission on the stored procedure HumanResources.uspUpdateEmployeeHireInfo to an application role named Recruiting11):
USE AdventureWorks2012;
GRANT EXECUTE ON OBJECT::HumanResources.uspUpdateEmployeeHireInfo
TO Recruiting11;
GO
Source
Of course you should have permission to grant the permission.
Let's say that in a multi-schema db we have these 2 procs:
Create proc S1004.proc1
As
Exec proc2
GO
Create proc S1004.proc2
As
Select 1
Then, when I try to run proc1 from sa login, sql issues an error : Could not find stored procedure 'proc2'.
I know that if we add schema to proc2 in the body of proc1, then it can resolve the schema.
Is there any other solution for this problem.
If you can use your schema in the 'scope' of user (be aware that users and schemas are separated in SQL Server), you could get away with this:
CREATE USER S1004 FOR LOGIN S1004 WITH DEFAULT_SCHEMA = S1004;
GO
CREATE PROCEDURE S1004.proc1
WITH EXECUTE AS 'S1004'
AS
EXECUTE proc2
GO
CREATE PROCEDURE S1004.proc2
AS
SELECT 1
EXEC S1004.proc1
What happens here is that you create user S1004 with a default schema with the same name. That schema will be searched for object when object is not found immediately in the scope of current schema.
When you need to resolve your schema in a procedure, you run the procedure in the context of that user (see WITH EXECUTE AS 'S1004') and schema resolution will succeed.
However, pay attention that this changes execution scope to the another user. It's a workaround, but under the circumstances it's the best you can get.
I want to know what are the default permissions for sql server stored procedures.
For example, I created a user in database but no role or no permissions granted except execute permission like:
GRANT EXECUTE ON SCHEMA :: [dbo] TO [newUser]
later on me (as a sa login) created a stored procedure that makes just a select from a table like:
CREATE PROCEDURE dbo.selectX AS
BEGIN
SELECT ID, NAME FROM MyTable
END
and my user [newUser] can execute and see the result of select statement like:
EXEC dbo.selectX
up until now, I can assume that stored procedures have default permissions that my user don't have.
I tried other dmls like UPDATE, INSERT, DELETE and user managed to execute procedures successfully.
But! when I created a proceure with ddl as create table .. such as:
CREATE PROCEDURE dbo.crtNT AS
BEGIN
CREATE TABLE del(id int) --for test
END
and when the newUser executes this procedure error occurs like:
CREATE TABLE permission denied in database 'MyDb'
And here is my question: By default, do stored procedures have permission with DML(select, insert, update vs.) but not with DDL(create, drop table vs.)? Because I didn't see any explanation about this situation in Books Online or anywhere else.
Any comments will be welcomed.
You are correct in your assumption that DDL statements are treated differently.
The procedures with DML statements work through the mechanism of Ownership Chaining however as this quote from the EXECUTE AS documentation states
Remember that ownership chaining applies only to DML statements.
In my SQL Server 2005 database, a user belongs to a role and that role has been granted execute permission on all the stored procedures. One of the stored procedures inserts data into the table called tableA.
User has been explicit DENY permission on tableA. However, user can still execute stored procedure to insert new data.
Is there a way to prevent user to insert new data into the table (besides removing user from the role which has execute permission)
create table tableA
(id int identity(1,1), data varchar(20)
)
create proc uspInsertTableA
(#data varchar(20))
with execute as caller
as
begin
insert into tableA
values (#data)
end
DENY INSERT On tableA TO BrianG
GRANT EXECUTE on uspInsertTableA to BrianG
BrianG, can still insert data
exec uspInsertTableA 'yada'
There are two relevant factors:
"execute as" of the stored procedure.
Ownership chaining.
"EXECUTE as CALLER" is already the default (CREATE PROCEDURE ... WITH EXECUTE AS CALLER ...)
Additionally the stored procedure must have a different owner than TableA, to prevent ownership chaining. The owner of the stored procedure must not have the right to insert into the table.
Alternatively you could use the HAS_PERMS_BY_NAME function within the stored procedure to explicitly check whether the user has the permission.
if HAS_PERMS_BY_NAME('TableA','OBJECT','INSERT') = 0
raiserror ('User is not allowed to insert into TableA',16,1)
Could you change the database schema of the sproc? ie. change from dbo.Insert to protected.Insert?
Then you could deny exec against this schema?