patternsqlMinor
Deny view definition at DB level and symmetric keys
Viewed 0 times
definitionsymmetriclevelviewdenykeysand
Problem
I don't want a restricted database role to be able to view table and stored procedure definitions and code.
So I do
It does appear though that this is not capable of being overridden.
seems to have no effect.
Worse
seems to have no effect. Basically if you deny view definition at the db level then symmetric keys are unusable by that role\user.
Am I missing something? Is there any way to grant rights to objects that override the rights of the db level deny?
So I do
deny view definition to some_db_roleIt does appear though that this is not capable of being overridden.
grant view definition on dbo.some_proc to some_db_roleseems to have no effect.
Worse
grant view definition, references on symmetric key::some_key to some_db_roleseems to have no effect. Basically if you deny view definition at the db level then symmetric keys are unusable by that role\user.
Am I missing something? Is there any way to grant rights to objects that override the rights of the db level deny?
Solution
From BOL:
any permission denial overrides all grants
The implication is that when you
Having said that, you don't need to explicitly deny "view definition" permissions on procedures and other code. If you don't grant
You can test this using the code below.
Create a test database:
Create a table, and a stored proc:
Create a test user, and a test role:
Grant
Impersonate the user so we can see the effect of the
Cleanup:
any permission denial overrides all grants
The implication is that when you
DENY permissions to an object those permissions override any GRANTed permissions applicable to that object.Having said that, you don't need to explicitly deny "view definition" permissions on procedures and other code. If you don't grant
VIEW DEFINITION the definitions are not visible, even if the code can be executed. Tables work slightly differently; you'll need to deny view definition to any tables the role has SELECT rights on.You can test this using the code below.
Create a test database:
USE master;
GO
IF EXISTS (SELECT 1 FROM master.sys.databases d WHERE d.name = 'TestPerms_20160921')
BEGIN
DROP DATABASE TestPerms_20160921;
END;
GO
CREATE DATABASE TestPerms_20160921;
GO
USE TestPerms_20160921;
GOCreate a table, and a stored proc:
IF OBJECT_ID('dbo.Test') IS NOT NULL
DROP TABLE dbo.Test;
CREATE TABLE dbo.Test
(
TestID INT NOT NULL
);
GO
IF OBJECT_ID('dbo.TestProc') IS NOT NULL
DROP PROCEDURE dbo.TestProc;
GO
CREATE PROCEDURE dbo.TestProc
AS
BEGIN
SELECT 1;
END
GOCreate a test user, and a test role:
IF EXISTS (
SELECT 1
FROM sys.database_principals dp
WHERE dp.name = 'TestU'
)
BEGIN
DROP USER TestU;
END
CREATE USER TestU WITHOUT LOGIN;
IF EXISTS (
SELECT *
FROM sys.database_principals dp
WHERE dp.name = 'dbtestrole'
)
BEGIN
DROP ROLE dbtestrole;
END
CREATE ROLE dbtestrole;
ALTER ROLE dbtestrole ADD MEMBER TestU;Grant
SELECT and EXECUTE to the test objects:GRANT SELECT ON dbo.Test TO dbtestrole;
GRANT EXECUTE ON dbo.TestProc TO dbtestrole;Impersonate the user so we can see the effect of the
GRANT statements above:EXECUTE AS USER = 'TestU';
/* column names and types **are** visible */
SELECT s.name
, t.name
, c.name
, ty.name
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types ty ON c.user_type_id = ty.user_type_id
WHERE s.name = 'dbo'
AND t.name = 'Test'
ORDER BY s.name
, t.name
, c.name;
/* access to view the definition is denied */
EXEC sys.sp_helptext @objname = 'dbo.TestProc', @columnname = NULL;
/* we can run the proc! */
EXEC dbo.TestProc;
REVERT;DENY VIEW DEFINITION on the table, and test again:DENY VIEW DEFINITION ON dbo.Test TO dbtestrole;
EXECUTE AS USER = 'TestU';
/* no rows returned as we can no longer view the table definition */
SELECT s.name
, t.name
, c.name
, ty.name
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types ty ON c.user_type_id = ty.user_type_id
WHERE s.name = 'dbo'
AND t.name = 'Test'
ORDER BY s.name
, t.name
, c.name;
/* we can still run the proc */
EXEC dbo.TestProc;
/* we can still see the content of the table */
SELECT *
FROM dbo.Test;
REVERT;Cleanup:
USE master;
GO
IF EXISTS (SELECT 1 FROM master.sys.databases d WHERE d.name = 'TestPerms_20160921')
DROP DATABASE TestPerms_20160921;Code Snippets
USE master;
GO
IF EXISTS (SELECT 1 FROM master.sys.databases d WHERE d.name = 'TestPerms_20160921')
BEGIN
DROP DATABASE TestPerms_20160921;
END;
GO
CREATE DATABASE TestPerms_20160921;
GO
USE TestPerms_20160921;
GOIF OBJECT_ID('dbo.Test') IS NOT NULL
DROP TABLE dbo.Test;
CREATE TABLE dbo.Test
(
TestID INT NOT NULL
);
GO
IF OBJECT_ID('dbo.TestProc') IS NOT NULL
DROP PROCEDURE dbo.TestProc;
GO
CREATE PROCEDURE dbo.TestProc
AS
BEGIN
SELECT 1;
END
GOIF EXISTS (
SELECT 1
FROM sys.database_principals dp
WHERE dp.name = 'TestU'
)
BEGIN
DROP USER TestU;
END
CREATE USER TestU WITHOUT LOGIN;
IF EXISTS (
SELECT *
FROM sys.database_principals dp
WHERE dp.name = 'dbtestrole'
)
BEGIN
DROP ROLE dbtestrole;
END
CREATE ROLE dbtestrole;
ALTER ROLE dbtestrole ADD MEMBER TestU;GRANT SELECT ON dbo.Test TO dbtestrole;
GRANT EXECUTE ON dbo.TestProc TO dbtestrole;EXECUTE AS USER = 'TestU';
/* column names and types **are** visible */
SELECT s.name
, t.name
, c.name
, ty.name
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types ty ON c.user_type_id = ty.user_type_id
WHERE s.name = 'dbo'
AND t.name = 'Test'
ORDER BY s.name
, t.name
, c.name;
/* access to view the definition is denied */
EXEC sys.sp_helptext @objname = 'dbo.TestProc', @columnname = NULL;
/* we can run the proc! */
EXEC dbo.TestProc;
REVERT;Context
StackExchange Database Administrators Q#14575, answer score: 2
Revisions (0)
No revisions yet.