I created a user in SQL Server 2012 database and revoked all permissions given by the public
role.
Then I granted EXECUTE
permission on a stored procedure.
The user can execute the procedure but cannot get the data it returns.
The procedure is in schema1
, and the tables from which it selects are in schema2
.
If I add the user to the db_datareader
role it can read all data from all the tables in the database. I tried using WITH EXECUTE AS OWNER
but it didn't work.
How can I grant only the access to the given procedure and nothing else?
Best Answer
No, you do not want (or need)
WITH EXECUTE AS OWNER
.The problem is simply that your two schemas —
Schema1
wit the stored procedure, andSchema2
with the tables — have different owners. If you execute the following query, you will see who owns which schemas:Ownership chaining, the default security mechanism, assumes DML and EXECUTE permissions on objects referenced by the object being accessed, IF the owner is the same. If no owner has been explicitly assigned to an object (default =
NULL
), then the "owner" is considered to be the owner of the schema in which the object exists.So, technically your schemas could have the same owner and it's just that the tables have a different owner due to being given one explicitly (via
ALTER AUTHORIZATION
), but it's much more likely that the schemas have different owners.Fortunately, this situation is easy to solve using Module Signing.
The concept is to create a certificate in the database containing these schemas and objects, which will then be used to sign the stored procedure that exists in
Schema1
but selects from tables inSchema2
.A user is created from the certificate, and is then assigned whatever permission(s) are needed in order for the stored procedure to complete successfully.
No permissions are being granted to anyone that will be executing the stored procedure. The permissions are granted only to the certificate-based user. The connection between the stored procedure and the certificate-based user is (effectively) the public key of the certificate. And that public key is only loaded into the session's security context when a module that has been signed with that certificate is being executed. And that signature requires the certificate's password (in the
ADD SIGNATURE
statement), and is dropped if anyone changes even a single byte of the stored procedure (or the owner of it). Hence, very secure.The following illustrates this concept:
Main Setup
Test Same Schema Owners
Reproduce Current Situation
Test Current Situation (no extra permissions)
Module Signing Setup
Test with Module Signing