Reputation: 143
I have two tables in different schemas, one owned by dbo, the other not. I have a third schema where I'm trying to create a view that reads from those two tables. My understanding is that if dbo is the owner of the view, because it has grant options to all objects in the database, users with only access to the view should be able to query it. But that isn't working, even when I explicitly grant dbo SELECT WITH GRANT to the underlying table in the schema it doesn't own.
I've read a few other posts, but don't see an answer that works: https://stackoverflow.com/a/4134892/1499015, Ownership Chaining and Tutorial: Ownership Chains and Context Switching
I assume I'm doing something wrong with permission chaining, but I can't figure out what the problem is.
--use master
--GO
--create login testuser with password='******************'
-- principal3 will own schema3
--create login principal3 with password='*****************'
--use testingDB
--GO
create user testuser for login testuser
create user principal3 for login principal3
GO
-- testrole that will only have select permissions on schema2
CREATE ROLE testrole
exec sp_addrolemember 'testrole', 'testuser'
GO
-- the first schema is owned by dbo
CREATE SCHEMA schema1 authorization dbo
GO
-- the schema where the view will live, also owned by dbo
create schema schema2 authorization dbo
GO
-- schema3 owned by principal3
create schema schema3 authorization principal3
go
-- tables in schema1 and schema3
CREATE TABLE schema1.testtable1 (
id int
, testvalue sysname
)
GO
CREATE TABLE schema3.testtable3 (
id int
, testvalue sysname
)
GO
-- some base data
INSERT schema1.testtable1
SELECT 1, 'a'
UNION SELECT 2, 'b'
UNION SELECT 3, 'c'
INSERT schema3.testtable3
SELECT 1, 'hot dogs rule'
UNION SELECT 2, 'pizza sucks'
UNION SELECT 3, 'haw just kidding that''s obviously backwards'
GO
-- view in schema2 that queries tables in schema1 and schema3, owned by dbo
CREATE VIEW schema2.testview
AS
SELECT t1.testvalue as v1
, t3.testvalue as v3
FROM schema1.testtable1 t1
INNER JOIN schema3.testtable3 t3 ON t1.id = t3.id
GO
GRANT SELECT ON schema::schema1 TO dbo WITH GRANT OPTION
GRANT SELECT ON schema::schema3 TO dbo WITH GRANT OPTION
ALTER AUTHORIZATION ON schema2.testview TO dbo
-- give testrole permission to query the view
GRANT SELECT ON schema2.testview to testrole
GO
EXECUTE AS USER = 'testuser';
SELECT USER_NAME();
BEGIN TRY
select top 100 * from schema2.testview
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
REVERT;
SELECT USER_NAME();
When I run this code, I get
The SELECT permission was denied on the object 'testtable3', database 'testingDb', schema 'schema3'.
I've also tried to create a schema owner user for the schema that the view lives in, and granting that user select with grant to the underlying tables, but it's still not working.
Any ideas what I'm doing wrong? Thanks!
Upvotes: 1
Views: 2713
Reputation: 5694
The documentation says:
When an object is accessed through a chain, SQL Server first compares the object's owner to the owner of the calling object (the previous link in the chain). If both objects have the same owner, permissions on the referenced object are not checked. Whenever an object accesses another object that has a different owner, the ownership chain is broken and SQL Server must check the caller's security context.
In this case, when the object testtable3
is accessed, SQL Server first compares testtable3
owner to the owner of the testview
. If both objects have the same owner, permissions on the referenced object are not checked. It does not matter if you GRANT dbo rights on testtable3
, even WITH GRANT (he this right anyway). It matters that the owner of testtable3
is the same as the owner of the testview
.
For example, try:
ALTER AUTHORIZATION ON SCHEMA::schema3 TO dbo
And it will work.
If the owners are different, the ownership chain is broken and SQL Server must check the caller's security context. In this case: does testuser
have rights to select from testtable3
?.
Therefore, if the owners are different you need to do this to make it work:
GRANT SELECT ON schema3.testtable3 TO testuser
Upvotes: 1