I need assistance executing a procedure inside one database to query another database on the same SQL Server 2019 instance. I can run the procedure fine as myself, but I can't use execute as in either of the three places I have tried (commented out below).
The error I get is:
Cannot execute as the server principal because the principal "Domain\ServiceAcctIn_GroupName" does not exist, this type of principal cannot be impersonated, or you do not have permission.
OR if I execute as Owner I get:
The server principal "saName" is not able to access the database "SourceDB" under the current security context.
My setup: I'm on a Windows AD domain, my service account is in a group that I have granted login to the SQL Server and created a database user for the group on both databases. I have also set DB_Chaining to ON on both databases.
I need to use my service account to query the data because I cannot add all users to the same group the service account is in. They will however be in a different domain group with a role to select and execute this procedure in the [WorkingDB].
Here is my sample code:
USE master;
ALTER DATABASE [WorkingDB] SET DB_CHAINING ON;
ALTER DATABASE [SourceDB] SET DB_CHAINING ON;
GO
IF (NOT EXISTS (SELECT 1 FROM sys.server_principals AS sp WHERE (sp.[name] = 'Domain\GroupName')))
CREATE LOGIN [Domain\GroupName] FROM WINDOWS;
GO
USE [SourceDB];
GO
EXEC sp_changedbowner 'saName';
IF (NOT EXISTS (SELECT 1 FROM sys.database_principals AS dp WHERE (dp.[name] = 'Domain\GroupName')))
CREATE USER [Domain\GroupName] FOR LOGIN [Domain\GroupName];
GRANT CONNECT TO [Domain\GroupName];
IF (DATABASE_PRINCIPAL_ID('SystemName_ReadOnlyRole') IS NULL)
CREATE ROLE SystemName_ReadOnlyRole AUTHORIZATION dbo;
GRANT EXECUTE TO SystemName_ReadOnlyRole;
ALTER ROLE db_datareader ADD MEMBER SystemName_ReadOnlyRole;
ALTER ROLE SystemName_ReadOnlyRole ADD MEMBER [Domain\GroupName];
GO
USE [WorkingDB];
GO
EXEC sp_changedbowner 'saName';
IF (NOT EXISTS (SELECT 1 FROM sys.database_principals AS dp WHERE (dp.[name] = 'Domain\GroupName')))
CREATE USER [Domain\GroupName] FOR LOGIN [Domain\GroupName];
ALTER ROLE db_owner ADD MEMBER [Domain\GroupName];
GO
CREATE OR ALTER PROCEDURE MySchema.GetDataFromSourceDB
--WITH EXECUTE AS N'Domain\UserInGroupName'
--WITH EXECUTE AS OWNER
AS
BEGIN
--EXECUTE AS LOGIN = N'Domain\ServiceAcctIn_GroupName';
--EXECUTE AS USER = N'Domain\ServiceAcctIn_GroupName';
--EXEC ('SELECT TOP(10) * FROM [SourceDB].[dbo].[TableName];');
SELECT TOP(10) * FROM [SourceDB].[dbo].[TableName];
END
GO
--EXECUTE AS LOGIN = N'Domain\ServiceAcctIn_GroupName';
EXEC MySchema.GetDataFromSourceDB;
--REVERT;
/*
Error:
Cannot execute as the server principal because the principal "Domain\ServiceAcctIn_GroupName" does not exist, this type of principal cannot be impersonated, or you do not have permission.
OR
The server principal "saName" is not able to access the database "FIMSynchronizationService" under the current security context.
*/
USEstatements, @PaulYoung ; you create the cert in both database, sign the procedure in its database (you can only do that in it's database), and create the certification user in the other database.publicrole, which will show the database, but does not show its content. If you want to just be able to view tables or views, you need a server role that is shared between your desired databases (similar topublicrole) with read permissions. then assign members to this role, and they will have access to those databases as well (depends on your permissions setup).