Estou feliz que você tenha resolvido isso, mas o encadeamento de propriedade não é a solução recomendada. Como você parece validamente preocupado com a segurança e a granularidade adequada dos direitos envolvidos, estou adicionando esta resposta, embora atrasada, como uma referência ao que está acontecendo e como resolver esses problemas.
EXECUTAR COMO escopo de representação
As cláusulas EXECUTE AS têm dois tipos: EXECUTE AS LOGIN e EXECUTE AS USUÁRIO. O EXECUTE AS LOGIN é autenticado pelo servidor e é um contexto de representação confiável para toda a instância SQL (com escopo no servidor):
Ao representar uma entidade usando a instrução EXECUTE AS LOGIN ou dentro de um módulo com escopo do servidor usando a cláusula EXECUTE AS, o escopo da representação é de todo o servidor. Isso significa que, após a alternância de contexto, qualquer recurso no servidor em que o logon representado tenha permissões pode ser acessado.
EXECUTE AS USER é autenticado pelo banco de dados e é um contexto de representação confiável apenas por esse banco de dados (com escopo no banco de dados):
No entanto, ao representar um principal usando a instrução EXECUTE AS USER, ou dentro de um módulo com escopo de banco de dados usando a cláusula EXECUTE AS, o escopo da representação é restrito ao banco de dados por padrão. Isso significa que as referências a objetos fora do escopo do banco de dados retornarão um erro.
Um procedimento armazenado que possui uma cláusula EXECUTE AS criará um contexto de representação no escopo do banco de dados e, como tal, não poderá fazer referência a objetos fora do banco de dados, caso em que você não poderá fazer referência msdb.dbo.sp_start_job
porque está dentro msdb
. Existem muitos outros exemplos disponíveis, como tentar acessar uma DMV do escopo do servidor, tentar usar um servidor vinculado ou tentar entregar uma mensagem do Service Broker em outro banco de dados.
A habilitação de uma representação no escopo do banco de dados para acessar um recurso que normalmente não seria permitido no qual o autenticador do contexto de representação deve ser confiável. Para uma representação no escopo do banco de dados, o autenticador é o dbo do banco de dados. Isso pode ser alcançado por dois meios possíveis:
- Ativando a propriedade TRUSTWORTHY no banco de dados que autenticou o contexto de representação (ou seja, o banco de dados em que a cláusula EXECUTE AS foi emitida).
- Usando assinaturas de código.
Esses detalhes são descritos no MSDN: Estendendo a representação de banco de dados usando o EXECUTE AS .
Quando você resolveu o problema por meio do encadeamento de propriedade entre bancos de dados, ativou o encadeamento entre bancos de dados em todo o nível do servidor, o que é considerado um risco de segurança. A maneira mais controlada e refinada de obter o resultado desejado é usar a assinatura de código:
- No banco de dados do aplicativo, crie um certificado autoassinado
- assine o
dbo.StartAgentJob
com este certificado
- solte a chave privada do certificado
- exportar o certificado para o disco
- importar o certificado para
msdb
- crie um usuário derivado do certificado importado em
msdb
- conceda permissão AUTHENTICATE ao usuário derivado em
msdb
Essas etapas garantem que o contexto EXECUTE AS do dbo.StartAgentJob
procedimento agora seja confiável msdb
, porque o contexto é assinado por uma entidade com permissão AUTHENTICATE msdb
. Isso resolve metade do quebra-cabeça. A outra metade é realmente conceder a permissão EXECUTE msdb.dbo.sp_start_job
para o contexto de representação agora confiável. Existem várias maneiras de como isso pode ser feito:
- mapear o usuário
agentProxy
usuário representado msdb
e conceder a ele permissão de execução emmsdb.dbo.sp_start_job
- conceda a permissão de execução ao
msdb
usuário derivado do certificado de autenticador
- adicione uma nova assinatura ao procedimento, obtenha um usuário para ele
msdb
e conceda a permissão de execução a esse usuário derivado
A opção 1. é simples, mas tem uma grande desvantagem: o agentProxy
usuário agora pode executar o que msdb.dbo.sp_start_job
quiser, ele realmente tem acesso msdb
e permissão de execução.
A opção 3 está positivamente correta, mas acho que é um exagero desnecessário.
Portanto, minha preferida é a Opção 2: conceda a permissão EXECUTE msdb.dbo.sp_start_job
ao usuário derivado do certificado criado em msdb
.
Aqui está o SQL correspondente:
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
Meu blog possui alguns artigos que abordam esse tópico, escritos no contexto dos procedimentos ativados pelo Service Broker (uma vez que exigem uma cláusula EXECUTE AS):
BTW, se você está tentando testar meu roteiro e mora no hemisfério leste ou no horário de verão do Reino Unido, leia definitivamente o último artigo que vinculei antes de testar.