Sample Header Ad - 728x90

Permissions in triggers when using cross database certificates

12 votes
1 answer
3222 views
I use cross database certificates (as explained by Erland Sommarskog ) to control access to a certain database in my environment ( SQL Server 2008 R2 ). I have stored procedures in database A that update tables in database B. This has always worked for a variety of stored procedures in db A and tables in db B until now. I am trying to update a table in db B, but the table has a trigger on it. This trigger is inserting additional data in another table in db B. I am getting the error: > Msg 916, Level 14, State 1, Procedure table_trigger, Line 11 The server > principal "sql\login" is not able to access the database > "B" under the current security context. I tried granting insert permissions for database B user that is tied to the certificate to insert into that other table, but it did not resolve the error. Do I have any options other than changing the trigger so it uses WITH EXECUTE AS OWNER? Here is DDL to replicate the issue: CREATE LOGIN [GuggTest] WITH PASSWORD=N'abcd', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF CREATE DATABASE A; CREATE DATABASE B; USE A; CREATE TABLE dbo.SPtoUpdate ( ID INT , ILoveFishing VARCHAR(255) ); INSERT INTO dbo.SPtoUpdate ( ID , ILoveFishing ) VALUES ( 1,'Musky'),( 2,'Pike'),( 3,'Yellow Perch'); CREATE TABLE dbo.TriggerToInsert ( ID INT , ILoveFishing VARCHAR(255) , ChangeDate DATETIME2 ); GO CREATE TRIGGER dbo.SPtoUpdateTrigger ON dbo.SPtoUpdate FOR UPDATE AS DECLARE @datetime DATETIME2; SELECT @datetime = GETDATE() INSERT INTO dbo.TriggerToInsert ( ID , ILoveFishing , ChangeDate ) VALUES ( 1 , 'Yes' , @datetime ); GO CREATE CERTIFICATE BExecutor ENCRYPTION BY PASSWORD = 'Obfuscated' WITH SUBJECT = 'Execute sp from B to A', START_DATE = '20140101', EXPIRY_DATE = '20300101' GO BACKUP CERTIFICATE BExecutor TO FILE = 'C:\temp\crossdbcert.cer' WITH PRIVATE KEY (FILE = 'C:\temp\crossdbcert.pvk' , ENCRYPTION BY PASSWORD = 'Obfuscated', DECRYPTION BY PASSWORD = 'Obfuscated') GO CREATE USER BExecutor FROM CERTIFICATE BExecutor GRANT UPDATE ON dbo.SPtoUpdate TO BExecutor GRANT SELECT ON dbo.SPtoUpdate TO BExecutor --Also give insert on dbo.TriggerToInsert GRANT INSERT ON dbo.TriggerToInsert TO BExecutor USE B GO CREATE USER [GuggTest] FOR LOGIN [GuggTest]; EXEC sp_addrolemember N'db_owner', N'GuggTest' GO CREATE PROCEDURE dbo.UpdateTableInA AS BEGIN UPDATE A.dbo.SPtoUpdate SET ILoveFishing = 'Walleye' WHERE ID = 2; END GO CREATE CERTIFICATE BExecutor FROM FILE = 'C:\temp\crossdbcert.cer' WITH PRIVATE KEY (FILE = 'C:\temp\crossdbcert.pvk' , ENCRYPTION BY PASSWORD = 'Obfuscated', DECRYPTION BY PASSWORD = 'Obfuscated') GO EXEC master..xp_cmdshell 'DEL C:\temp\crossdbcert.*', 'no_output' GO ADD SIGNATURE TO dbo.UpdateTableInA BY CERTIFICATE BExecutor WITH PASSWORD = 'Obfuscated' GO --Log In or Change execution context to GuggTest, then EXEC dbo.UpdateTableInA
Asked by Dave.Gugg (331 rep)
Jan 13, 2017, 10:39 PM
Last activity: Mar 6, 2017, 11:19 PM