Question

I've read an article

http://www.sommarskog.se/grantperm.html#ownershipchaining

which has a very good information regarding ownership chaining in SQL Server.

So this is what i've done on my SQL Server 2008,

  1. Created 2 databases DatabaseA, DatabaseB with login sa
  2. Created a procedure 'TestProc' in DatabaseA which executes a procedure in DatabaseB
  3. Created a login 'testuser'
  4. Added this login as a user in DatabaseA and give rights to execute procedure 'TestProc'

As you can see my goal is to make 'testuser' execute a procedure in DatabaseB without adding this user in DatabaseB and without giving him direct execution rights on procedure in DatabaseB.

I did enable the Ownership Chaining on Server Level and on both Databases. I've restarted the SQL Server Service.

But still getting this error

Msg 916, Level 14, State 1, Procedure TestProc, Line 18 The server principal "testuser" is not able to access the database "DatabaseB" under the current security context.

Am I missing something here?

Was it helpful?

Solution

Ownership chaining works for objects inside a database. It does not allow you to enter the database itself. So you have to create a login in any database you read from, like:

use DatabaseB
exec sp_grantdbaccess 'testuser'

Ownership chaining does grant rights on the stored procedure. So the database login can be devoid of any permissions. It just has to exist.

Query that creates two test databases and calls a procedure in one:

use master
if exists (select * from sys.databases where name = 'TestDatabase1')
    drop database TestDatabase1
if exists (select * from sys.databases where name = 'TestDatabase2')
    drop database TestDatabase2
create database TestDatabase1
go
use TestDatabase1
exec sp_changedbowner 'sa'
go
create procedure dbo.sp1 as select 'hello world!'
go
create database TestDatabase2
go
use TestDatabase2
exec sp_changedbowner 'sa'
go
create procedure dbo.sp2 as exec TestDatabase1.dbo.sp1
go
use TestDatabase2
exec sp_grantdbaccess 'testuser'
grant execute on sp2 to testuser as dbo
use TestDatabase1
-- Either of the below lines would work
-- exec sp_grantdbaccess 'guest'
-- exec sp_grantdbaccess 'testuser'
use TestDatabase2
execute as login = 'testuser'
exec sp2
revert -- Revert back to original login

Query to display ownership for databases and procedures:

select  d.name
,       l.name
from    sys.databases d
join    sys.syslogins l
on      d.owner_sid = l.sid
where   d.name like '...your database...'

select  p.name
,       dp.name
from    TestDatabase.sys.procedures p
join    TestDatabase.sys.schemas s
on      s.schema_id = p.schema_id
join    TestDatabase.sys.database_principals dp
on      s.principal_id = dp.principal_id
where   p.name like '...your stored procedure...'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top