Я рад, что вы решили это, но цепочка владения не является рекомендуемым решением. Поскольку вы, кажется, действительно обеспокоены безопасностью и надлежащим уровнем детализации соответствующих прав, я добавляю этот ответ, хотя и поздно, в качестве ссылки на то, что происходит и как решить эти проблемы.
ВЫПОЛНИТЬ КАК сфера олицетворения
Предложения EXECUTE AS представлены в двух вариантах: EXECUTE AS LOGIN и EXECUTE AS USER. EXECUTE AS LOGIN аутентифицируется сервером и является контекстом олицетворения, которому доверяет весь экземпляр SQL (в области сервера):
При олицетворении принципала с помощью оператора EXECUTE AS LOGIN или в модуле с серверной областью с помощью предложения EXECUTE AS область действия олицетворения распространяется на весь сервер. Это означает, что после переключения контекста можно получить доступ к любому ресурсу на сервере, на который у олицетворенного входа есть разрешения.
EXECUTE AS USER аутентифицируется базой данных и является контекстом олицетворения, которому доверяет только эта база данных (в области баз данных):
Однако при олицетворении принципала с помощью оператора EXECUTE AS USER или в модуле с областью базы данных с помощью предложения EXECUTE AS область олицетворения по умолчанию ограничивается базой данных. Это означает, что ссылки на объекты вне области базы данных будут возвращать ошибку.
Хранимая процедура с предложением EXECUTE AS создаст контекст олицетворения в области базы данных, и, таким образом, не сможет ссылаться на объекты вне базы данных, в данном случае вы не сможете ссылаться, msdb.dbo.sp_start_job
потому что она находится в msdb
. Есть много других доступных примеров, таких как попытка доступа к DMV области сервера, попытка использовать связанный сервер или попытка доставить сообщение компонента Service Broker в другую базу данных.
Разрешить олицетворению в области базы данных доступ к ресурсу, который обычно не разрешается, следует доверять аутентификатору контекста олицетворения. Для олицетворения в области базы данных аутентификатором является база данных dbo. Это может быть достигнуто двумя возможными способами:
- Включив свойство TRUSTWORTHY в базе данных, которая аутентифицировала контекст олицетворения (т. Е. В базе данных, в которой было выдано предложение EXECUTE AS).
- Используя кодовые подписи.
Эти подробности описаны в MSDN: Расширение олицетворения базы данных с помощью EXECUTE AS .
Когда вы решили проблему с помощью цепочки владения несколькими базами данных, вы включили цепочку между базами данных на всем уровне сервера, что считается угрозой безопасности. Наиболее контролируемый, тонко детализированный способ достижения желаемого результата - это использование подписи кода:
- В базе данных приложения создайте самозаверяющий сертификат
- подписать
dbo.StartAgentJob
с этим сертификатом
- сбросить закрытый ключ сертификата
- экспортировать сертификат на диск
- импортировать сертификат в
msdb
- создать производного пользователя из импортированного сертификата в
msdb
- предоставить разрешение AUTHENTICATE производному пользователю в
msdb
Эти шаги гарантируют, что контексту EXECUTE AS dbo.StartAgentJob
процедуры теперь доверяют msdb
, потому что контекст подписан участником, имеющим разрешение AUTHENTICATE msdb
. Это решает половину головоломки. Другая половина - фактически предоставить разрешение EXECUTE msdb.dbo.sp_start_job
для доверенного контекста олицетворения. Есть несколько способов, как это можно сделать:
- карта олицетворяемых пользователя
agentProxy
пользователя в msdb
и предоставить ему разрешение на выполнениеmsdb.dbo.sp_start_job
- предоставить разрешение на выполнение
msdb
производному пользователю сертификата аутентификатора
- добавьте новую сигнатуру в процедуру, создайте для нее пользователя
msdb
и предоставьте разрешение на выполнение этому производному пользователю
Вариант 1. прост, но имеет большой недостаток: agentProxy
пользователь теперь может выполнить msdb.dbo.sp_start_job
его по собственному желанию, он действительно имеет доступ msdb
и имеет разрешение на выполнение.
Вариант 3, безусловно, правильный, но я чувствую, что это излишнее излишество.
Поэтому я предпочитаю вариант 2: предоставить разрешение EXECUTE для получателя msdb.dbo.sp_start_job
сертификата, созданного в msdb
.
Вот соответствующий SQL:
use [<appdb>];
go
create certificate agentProxy
ENCRYPTION BY PASSWORD = 'pGFD4bb925DGvbd2439587y'
with subject = 'agentProxy'
, start_date='01/01/2009';
go
ADD SIGNATURE TO OBJECT::[StartAgentJob]
BY CERTIFICATE [agentProxy]
WITH PASSWORD = 'pGFD4bb925DGvbd2439587y';
go
alter certificate [agentProxy]
remove private key;
go
backup certificate [agentProxy]
to file='c:\temp\agentProxy.cer';
go
use msdb
go
create certificate [agentProxy]
from file='c:\temp\agentProxy.cer';
go
create user [agentProxyAuthenticator]
from certificate [agentProxy];
go
grant authenticate to [agentProxyAuthenticator];
grant execute on msdb.dbo.sp_start_job to [agentProxyAuthenticator];
go
use [<appdb>];
go
exec dbo.StartAgentJob;
go
В моем блоге есть несколько статей на эту тему, написанных в контексте активированных процедур Service Broker (поскольку для них требуется условие EXECUTE AS):
Кстати, если вы пытаетесь проверить мой сценарий и живете в восточном полушарии или в летнее время в Великобритании, обязательно прочитайте последнюю статью, которую я связал, перед тестированием.