Sono contento che tu l'abbia risolto, ma il concatenamento della proprietà non è la soluzione consigliata. Dal momento che sembri validamente preoccupato per la sicurezza e la corretta granularità dei diritti coinvolti, sto aggiungendo questa risposta, anche se in ritardo, come riferimento a ciò che sta accadendo e come risolvere questi problemi.
ESEGUIRE come ambito di rappresentazione
Le clausole EXECUTE AS sono disponibili in due versioni: EXECUTE AS LOGIN ed EXECUTE AS USER. EXECUTE AS LOGIN è autenticato dal server ed è un contesto di rappresentazione attendibile dall'intera istanza SQL (con ambito server):
Quando si impersona un'entità utilizzando l'istruzione EXECUTE AS LOGIN o all'interno di un modulo con ambito server utilizzando la clausola EXECUTE AS, l'ambito della rappresentazione è a livello di server. Ciò significa che, dopo il cambio di contesto, è possibile accedere a qualsiasi risorsa all'interno del server per la quale il login rappresentato è autorizzato.
EXECUTE AS USER è autenticato dal database ed è un contesto di rappresentazione attendibile solo da quel database (con ambito database):
Tuttavia, quando si impersona un'entità utilizzando l'istruzione EXECUTE AS USER o all'interno di un modulo con ambito database utilizzando la clausola EXECUTE AS, l'ambito di rappresentazione è limitato al database per impostazione predefinita. Ciò significa che i riferimenti ad oggetti al di fuori dell'ambito del database restituiranno un errore.
Una procedura memorizzata che ha una clausola EXECUTE AS creerà un contesto di rappresentazione con ambito database e come tale non sarà in grado di fare riferimento a oggetti al di fuori del database, nel caso in cui non sarà possibile fare riferimento msdb.dbo.sp_start_job
perché è attivo msdb
. Sono disponibili molti altri esempi, come il tentativo di accedere a un DMV di ambito server, il tentativo di utilizzare un server collegato o il tentativo di recapitare un messaggio di Service Broker in un altro database.
L'abilitazione di una rappresentazione con ambito database per accedere a una risorsa che non sarebbe normalmente consentita all'autenticatore del contesto di rappresentazione deve essere considerata attendibile. Per una rappresentazione con ambito database, l'autenticatore è il database dbo. Ciò può essere ottenuto con due possibili mezzi:
- Attivando la proprietà TRUSTWORTHY sul database che ha autenticato il contesto di rappresentazione (ovvero il database in cui è stata emessa la clausola EXECUTE AS).
- Usando le firme di codice.
Questi dettagli sono descritti in MSDN: Estensione della rappresentazione del database mediante EXECUTE AS .
Quando il problema è stato risolto tramite il concatenamento della proprietà tra database, è stato abilitato il concatenamento tra database a livello dell'intero server, che è considerato un rischio per la sicurezza. Il modo più controllato, a grana fine per ottenere il risultato desiderato è usare la firma del codice:
- Nel database dell'applicazione creare un certificato autofirmato
- firmare
dbo.StartAgentJob
con questo certificato
- rilascia la chiave privata del certificato
- esportare il certificato su disco
- importare il certificato in
msdb
- crea un utente derivato dal certificato importato in
msdb
- concedere l'autorizzazione AUTENTICATA all'utente derivato in
msdb
Questi passaggi assicurano che il contesto EXECUTE AS della dbo.StartAgentJob
procedura sia ora attendibile msdb
, poiché il contesto è firmato da un'entità con l'autorizzazione AUTHENTICATE in msdb
. Questo risolve metà del puzzle. L'altra metà è concedere effettivamente l'autorizzazione EXECUTE msdb.dbo.sp_start_job
al contesto di rappresentazione ormai attendibile. Esistono diversi modi per farlo:
- mappare l'utente rappresentato
agentProxy
utente msdb
e concedergli il permesso di esecuzione sumsdb.dbo.sp_start_job
- concedere l'autorizzazione di esecuzione
msdb
all'utente derivato dal certificato dell'autenticatore
- aggiungere una nuova firma alla procedura, derivarne un utente
msdb
e concedere l'autorizzazione di esecuzione a questo utente derivato
L'opzione 1. è semplice, ma presenta un grosso svantaggio: l' agentProxy
utente può ora eseguire la msdb.dbo.sp_start_job
propria volontà, gli è veramente concesso l'accesso msdb
e ha il permesso di esecuzione.
L'opzione 3 è decisamente corretta, ma ritengo che sia eccessivo inutile.
Quindi il mio preffered è l'opzione 2: concedere l'autorizzazione EXECUTE msdb.dbo.sp_start_job
all'utente derivato dal certificato creato in msdb
.
Ecco l'SQL corrispondente:
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
Il mio blog contiene alcuni articoli che trattano questo argomento, scritti nel contesto delle procedure attivate da Service Broker (poiché richiedono una clausola EXECUTE AS):
A proposito, se stai provando a testare la mia sceneggiatura e vivi nell'emisfero orientale, o nell'ora legale del Regno Unito, leggi sicuramente l'ultimo articolo che ho collegato prima del test.