Me alegro de que haya resuelto esto, pero el encadenamiento de propiedad no es la solución recomendada. Dado que parece estar válidamente preocupado por la seguridad y la granularidad adecuada de los derechos involucrados, agrego esta respuesta, aunque tarde, como referencia a lo que está sucediendo y cómo resolver estos problemas.
EJECUTAR COMO alcance de suplantación
Las cláusulas EJECUTAR COMO vienen en dos tipos: EJECUTAR COMO INICIAR SESIÓN y EJECUTAR COMO USUARIO. EJECUTAR COMO INICIAR SESIÓN está autenticado por el servidor y es un contexto de suplantación en el que confía toda la instancia de SQL (con ámbito de servidor):
Cuando se hace pasar por un principal utilizando la instrucción EXECUTE AS LOGIN, o dentro de un módulo con ámbito de servidor mediante la cláusula EXECUTE AS, el alcance de la suplantación abarca todo el servidor. Esto significa que después del cambio de contexto, se puede acceder a cualquier recurso dentro del servidor en el que el inicio de sesión suplantado tenga permisos.
EJECUTAR COMO USUARIO está autenticado por la base de datos y es un contexto de suplantación en el que solo confía esa base de datos (ámbito de base de datos):
Sin embargo, cuando se hace pasar por un principal utilizando la instrucción EXECUTE AS USER, o dentro de un módulo con ámbito de base de datos mediante la cláusula EXECUTE AS, el alcance de la suplantación se limita a la base de datos de forma predeterminada. Esto significa que las referencias a objetos fuera del alcance de la base de datos devolverán un error.
Un procedimiento almacenado que tiene una cláusula EXECUTE AS creará un contexto de suplantación de ámbito de base de datos y, como tal, no podrá hacer referencia a objetos fuera de la base de datos, en este caso, no podrá hacer referencia msdb.dbo.sp_start_job
porque está dentro msdb
. Hay muchos otros ejemplos disponibles, como intentar acceder al DMV de alcance de un servidor, intentar usar un servidor vinculado o intentar entregar un mensaje de Service Broker en otra base de datos.
Habilitar la suplantación de una base de datos para acceder a un recurso en el que normalmente no se permitiría confiar en el autenticador del contexto de suplantación. Para una suplantación de ámbito de base de datos, el autenticador es la base de datos dbo. Esto se puede lograr de dos maneras posibles:
- Al activar la propiedad TRUSTWORTHY en la base de datos que autenticó el contexto de suplantación (es decir, la base de datos donde se emitió la cláusula EXECUTE AS).
- Mediante el uso de firmas de código.
Estos detalles se describen en MSDN: Extensión de la suplantación de bases de datos mediante EXECUTE AS .
Cuando resolvió el problema mediante el encadenamiento de propiedad cruzada de la base de datos, habilitó el encadenamiento cruzado de base de datos en todo el nivel del servidor, lo que se considera un riesgo de seguridad. La forma más controlada y precisa para lograr el resultado deseado es usar la firma de código:
- En la base de datos de la aplicación, cree un certificado autofirmado
- firmar
dbo.StartAgentJob
con este certificado
- soltar la clave privada del certificado
- exportar el certificado al disco
- importar el certificado a
msdb
- crear un usuario derivado del certificado importado en
msdb
- conceder permiso AUTENTICADO al usuario derivado en
msdb
Estos pasos aseguran que dbo.StartAgentJob
ahora se confíe en msdb
el contexto EXECUTE AS del procedimiento , porque el contexto está firmado por un principal que tiene permiso AUTHENTICATE msdb
. Esto resuelve la mitad del rompecabezas. La otra mitad es otorgar el permiso EXECUTE msdb.dbo.sp_start_job
al contexto de suplantación ahora confiable. Hay varias formas de hacer esto:
- mapear el usuario suplantado
agentProxy
usuario en msdb
y le conceda permiso para ejecutarmsdb.dbo.sp_start_job
- conceder el permiso de ejecución al
msdb
usuario derivado del certificado de autenticación
- agregar una nueva firma al procedimiento, derivar un usuario para ello
msdb
y otorgar el permiso de ejecución a este usuario derivado
La opción 1. es simple, pero tiene una gran desventaja: el agentProxy
usuario ahora puede ejecutarla msdb.dbo.sp_start_job
por su propia voluntad, realmente se le otorga acceso msdb
y tiene el permiso de ejecución.
La opción 3 es muy correcta, pero creo que es una exageración innecesaria.
Por lo tanto, mi opción preferida es la 2: otorgar el permiso EXECUTE msdb.dbo.sp_start_job
al usuario derivado del certificado creado en msdb
.
Aquí está el SQL correspondiente:
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
Mi blog tiene algunos artículos que cubren este tema, escritos en el contexto de los procedimientos activados por Service Broker (ya que requieren una cláusula EXECUTE AS):
Por cierto, si estás tratando de probar mi guión y vives en el hemisferio oriental, o en el horario de verano del Reino Unido, definitivamente lee el último artículo que vinculé antes de probar.