Chiamare sp_start_job da una procedura memorizzata


8

I nostri sviluppatori devono essere in grado di avviare un processo di SQL Server Agent dal loro codice .Net. So che posso chiamare msdb..sp_start_job per fare proprio questo, ma non voglio dare agli account degli utenti generali l'accesso diretto per eseguire i lavori.

Quello che mi piacerebbe fare è creare una procedura memorizzata nel database dell'applicazione usando la clausola WITH EXECUTE AS per impersonare un account proxy. La procedura così come è è:

CREATE PROCEDURE dbo.StartAgentJob 
    WITH EXECUTE AS 'agentProxy'
AS
BEGIN
    EXEC msdb.dbo.sp_start_job N'RunThisJob';
END

Quando eseguiamo questo, però, riceviamo il seguente messaggio:

The EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.

Qualche idea? È questo il modo migliore per farlo in SQL2005?


1
Risolto. La soluzione conteneva tre elementi: il concatenamento della proprietà deve essere abilitato sul server; l'utente utilizzato nell'istruzione EXECUTE AS deve essere sa o un utente con autorizzazioni simili per eseguire i lavori xp_sqlagent_ *; e il lavoro deve essere di proprietà dello stesso utente elencato nell'istruzione EXECUTE AS.
Ed Leighton-Dick,

Un po 'più di sperimentazione ha mostrato una variazione a questa soluzione. Se si desidera utilizzare un utente proxy non SA per eseguire il processo, è possibile concedere all'utente proxy le autorizzazioni EXECUTE sulle procedure xp_sqlagent_ * nel database master. (Gli altri due requisiti - proprietà tra database e proprietà del lavoro - si applicano ancora.)
Ed Leighton-Dick,

Risposte:


5

Hai inserito il login agentProxy nel database msdb e gli hai concesso i diritti per eseguire sp_start_job? Altrimenti dovrai abilitare il concatenamento delle autorizzazioni per il database msdb e il database utente.

Probabilmente stai meglio inserendo il login nel database msdb e concedendogli i diritti corretti.


Sì, ho iniziato aggiungendolo al ruolo SQLAgentOperator e quindi ho provato le autorizzazioni EXECUTE dirette su sp_start_job stesso. Nessuno dei due ha aiutato. Sembra lanciare questo errore a prescindere dalle autorizzazioni del proxy - anche un account di livello sysadmin ha esito negativo.
Ed Leighton-Dick,

Utilizzare SQL Profiler e vedere quale account sta effettivamente effettuando la chiamata. Ora che ci penso di più, Execute As sta usando un utente di database, che probabilmente non sta traducendo correttamente nell'altro database. Prova ad attivare il concatenamento del database e vedi se funziona.
mrdenny,

Il concatenamento della proprietà è stato una parte importante della soluzione, quindi sto assegnando i punti qui. Si scopre anche che ci sono altri due pezzi in questo; Prenderò nota di quelli sopra.
Ed Leighton-Dick,

8

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_jobperché è 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.StartAgentJobcon 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.StartAgentJobprocedura 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_jobal contesto di rappresentazione ormai attendibile. Esistono diversi modi per farlo:

  1. mappare l'utente rappresentato agentProxyutente msdbe concedergli il permesso di esecuzione sumsdb.dbo.sp_start_job
  2. concedere l'autorizzazione di esecuzione msdball'utente derivato dal certificato dell'autenticatore
  3. aggiungere una nuova firma alla procedura, derivarne un utente msdbe concedere l'autorizzazione di esecuzione a questo utente derivato

L'opzione 1. è semplice, ma presenta un grosso svantaggio: l' agentProxyutente può ora eseguire la msdb.dbo.sp_start_jobpropria volontà, gli è veramente concesso l'accesso msdbe 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_joball'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.


0

Dal momento che stai provando ad avviare SQL Server Agent dal codice .NET, questa potrebbe essere una domanda migliore per StackOverflow?

http://www.stackoverflow.com


1
Penso che questo sia probabilmente un problema di sicurezza del database, ma proverò StackOverflow se non riusciamo a trovare una risposta qui.
Ed Leighton-Dick,

0

Il controllo di un'istanza SQL casuale sulla rete SQLAgentOperatorRole non fornisce direttamente i privilegi di sp_start_job, ma li eredita da SQLAgentUserRole.

Ricontrolla usando:

select dp.NAME AS principal_name,
                 dp.type_desc AS principal_type_desc,
                 o.NAME AS object_name,
                 p.permission_name,
                 p.state_desc AS permission_state_desc 
    from    sys.database_permissions p
    left    OUTER JOIN sys.all_objects o on p.major_id = o.OBJECT_ID
    inner   JOIN sys.database_principals dp on p.grantee_principal_id = dp.principal_id
    where o.name = 'sp_start_job'

Esegui questo in MSDB e ricontrolla di non aver ereditato alcun accesso di rifiuto esplicito.

hth.


L'utente è esplicitamente membro di SQLAgentOperatorRole e SQLAgentUserRole.
Ed Leighton-Dick,

0

Un modo per raggiungere questo obiettivo senza concedere autorizzazioni aggiuntive: non consentire al proc memorizzato di avviare direttamente il processo, ma consenti semplicemente al proc memorizzato di capovolgere un po 'in una tabella (nel database dell'applicazione); quindi, lascia che il lavoro venga eseguito ogni minuto circa, controlla se il bit è invertito e, in tal caso, esegui il lavoro e riavvolgi nuovamente il bit. Se il lavoro vede che il bit non è invertito, il lavoro verrà semplicemente chiuso.

Funziona come un incantesimo, se non ti dispiace il ritardo (e il lavoro viene eseguito molto spesso).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.