Je suis heureux que vous ayez résolu ce problème, mais le chaînage de la propriété n'est pas la solution recommandée. Puisque vous semblez valablement préoccupé par la sécurité et la bonne granularité des droits impliqués, j'ajoute cette réponse, bien que tardive, comme référence à ce qui se passe et comment résoudre ces problèmes.
EXECUTE AS portée d'emprunt d'identité
Les clauses EXECUTE AS sont disponibles en deux versions: EXECUTE AS LOGIN et EXECUTE AS USER. EXECUTE AS LOGIN est authentifié par le serveur et est un contexte d'emprunt d'identité approuvé par l'ensemble de l'instance SQL (portée serveur):
Lors de l'emprunt d'identité d'un principal à l'aide de l'instruction EXECUTE AS LOGIN, ou dans un module à portée de serveur à l'aide de la clause EXECUTE AS, la portée de l'emprunt d'identité est à l'échelle du serveur. Cela signifie qu'après le changement de contexte, toutes les ressources du serveur sur lesquelles la connexion empruntée a des autorisations sont accessibles.
EXECUTE AS USER est authentifié par la base de données et est un contexte d'emprunt d'identité approuvé uniquement par cette base de données (portée de la base de données):
Toutefois, lors de l'emprunt d'identité d'un principal à l'aide de l'instruction EXECUTE AS USER, ou dans un module de portée de base de données à l'aide de la clause EXECUTE AS, la portée de l'emprunt d'identité est limitée à la base de données par défaut. Cela signifie que les références à des objets hors de la portée de la base de données renverront une erreur.
Une procédure stockée qui a une clause EXECUTE AS créera un contexte d'emprunt d'identité de portée de base de données et, en tant que tel, ne pourra pas référencer des objets en dehors de la base de données, au cas où vous ne pourrez pas faire référence msdb.dbo.sp_start_job
car se trouve dans msdb
. Il existe de nombreux autres exemples disponibles, comme essayer d'accéder à un DMV de portée de serveur, essayer d'utiliser un serveur lié ou essayer de remettre un message Service Broker dans une autre base de données.
Activer l'emprunt d'identité de portée de base de données pour accéder à une ressource qui ne serait normalement pas autorisée authentificateur du contexte d'emprunt d'identité doit être approuvé. Pour une usurpation d'identité à base de données, l'authentificateur est le dbo de base de données. Cela peut être réalisé par deux moyens possibles:
- En activant la propriété TRUSTWORTHY sur la base de données qui a authentifié le contexte d'emprunt d'identité (c'est-à-dire la base de données dans laquelle la clause EXECUTE AS a été émise).
- En utilisant des signatures de code.
Ces détails sont décrits dans MSDN: Extension de l'emprunt d'identité de base de données en utilisant EXECUTE AS .
Lorsque vous avez résolu le problème via le chaînage de propriété de base de données croisée, vous avez activé le chaînage cross-db au niveau du serveur entier, ce qui est considéré comme un risque pour la sécurité. La façon la plus contrôlée et la plus fine d'obtenir le résultat souhaité est d'utiliser la signature de code:
- Dans la base de données d'application, créez un certificat auto-signé
- signer le
dbo.StartAgentJob
avec ce certificat
- déposez la clé privée du certificat
- exporter le certificat sur le disque
- importer le certificat dans
msdb
- créer un utilisateur dérivé du certificat importé dans
msdb
- accorder l'autorisation AUTHENTICATE à l'utilisateur dérivé dans
msdb
Ces étapes garantissent que le contexte EXECUTE AS de la dbo.StartAgentJob
procédure est désormais approuvé msdb
, car le contexte est signé par un principal disposant de l'autorisation AUTHENTICATE dans msdb
. Cela résout la moitié du puzzle. L'autre moitié consiste à accorder réellement l'autorisation EXECUTE msdb.dbo.sp_start_job
au contexte d'emprunt d'identité désormais fiable. Il existe plusieurs façons de procéder:
- carte l'utilisateur personnifié
agentProxy
utilisateur msdb
et lui accorder l' autorisation d' exécution surmsdb.dbo.sp_start_job
- accorder l'autorisation d'exécution à l'
msdb
utilisateur dérivé du certificat d'authentificateur
- ajouter une nouvelle signature à la procédure, en dériver un utilisateur
msdb
et accorder l'autorisation d'exécution à cet utilisateur dérivé
L'option 1. est simple, mais présente un gros inconvénient: l' agentProxy
utilisateur peut désormais exécutermsdb.dbo.sp_start_job
à sa guise, il a vraiment accès à msdb
et a la permission d'exécution.
L'option 3 est tout à fait correcte, mais je pense que c'est une surpuissance inutile.
Donc, je préfère l'option 2: accorder l'autorisation EXECUTE msdb.dbo.sp_start_job
à l'utilisateur dérivé du certificat créé dansmsdb
.
Voici le SQL correspondant:
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
Mon blog contient des articles couvrant ce sujet, écrits dans le contexte des procédures activées par Service Broker (car elles nécessitent une clause EXECUTE AS):
BTW, si vous essayez de tester mon script et que vous vivez dans l'hémisphère oriental ou à l'heure d'été du Royaume-Uni, lisez certainement le dernier article que j'ai lié avant de tester.