開発者は、.NetコードからSQL Serverエージェントジョブを開始できる必要があります。 msdb..sp_start_jobを呼び出してそれを実行できることはわかっていますが、一般的なユーザーアカウントにジョブを実行するための直接アクセス権を付与したくありません。
私がやりたいのは、WITH EXECUTE AS句を使用してアプリケーションのデータベースにストアドプロシージャを作成し、プロキシアカウントを偽装することです。現在の手順は次のとおりです。
CREATE PROCEDURE dbo.StartAgentJob
WITH EXECUTE AS 'agentProxy'
AS
BEGIN
EXEC msdb.dbo.sp_start_job N'RunThisJob';
END
ただし、これを実行すると、次のメッセージが表示されます。
The EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.
何か案は?これはSQL2005でこれを行うための最良の方法ですか?
MsProデータベースにagentProxyログインを置き、sp_start_jobを実行する権限を与えましたか?そうでない場合は、msdbデータベースとユーザーデータベースのデータベース権限チェーンを有効にする必要があります。
ログインをmsdbデータベースに入れて、適切な権限を付与する方がよいでしょう。
これを解決してよかったですが、所有権の継承は推奨されるソリューションではありません。関係する権利のセキュリティと適切な細分性について正当に懸念しているように思われるので、この返信を遅らせながら、何が起こっているのか、およびこの問題を解決する方法への参照として追加します。
EXECUTE AS偽装スコープ
EXECUTE AS句には、EXECUTE AS LOGINとEXECUTE AS USERの2種類があります。 EXECUTE AS LOGINはサーバーによって認証され、SQLインスタンス全体(サーバースコープ)によって信頼される偽装コンテキストです。
EXECUTE AS LOGINステートメントを使用してプリンシパルを偽装する場合、またはEXECUTE AS句を使用してサーバースコープのモジュール内で偽装する場合、偽装のスコープはサーバー全体に及びます。これは、コンテキストの切り替え後、偽装ログインが権限を持っているサーバー内のすべてのリソースにアクセスできることを意味します。
EXECUTE AS USERはデータベースによって認証され、そのデータベースによってのみ信頼される偽装コンテキストです(データベーススコープ):
ただし、EXECUTE AS USERステートメントを使用してプリンシパルを偽装する場合、またはEXECUTE AS句を使用してデータベーススコープのモジュール内で偽装する場合、偽装のスコープはデフォルトでデータベースに制限されます。つまり、データベースのスコープ外のオブジェクトを参照すると、エラーが返されます。
EXECUTE AS句を含むストアドプロシージャは、データベーススコープの偽装コンテキストを作成します。そのため、msdb
にあるため、msdb.dbo.sp_start_job
を参照できないので、データベース外のオブジェクトを参照することはできません。 。サーバースコープDMVへのアクセスの試行、リンクサーバーの使用の試行、Service Brokerメッセージの別のデータベースへの配信の試行など、利用可能な他の多くの例があります。
データベーススコープの偽装を有効にして、通常は許可されないリソースにアクセスできるようにして、偽装コンテキストのauthenticatorを信頼する必要があります。データベーススコープの偽装の場合、オーセンティケーターはデータベースdboです。これは、次の2つの方法で実現できます。
これらの詳細はMSDNで説明されています: EXECUTE ASを使用したデータベース偽装の拡張 。
データベース間の所有権の連鎖を介して問題を解決すると、サーバーレベル全体でクロスDBの連鎖が有効になり、セキュリティリスクと見なされます。目的の結果を達成するための最も制御された細かい方法は、コード署名を使用することです。
dbo.StartAgentJob
に署名しますmsdb
にインポートしますmsdb
にインポートされた証明書から派生ユーザーを作成するmsdb
の派生ユーザーにAUTHENTICATE権限を付与しますこれらの手順により、dbo.StartAgentJob
プロシージャのEXECUTE ASコンテキストがmsdb
で信頼されるようになります。これは、コンテキストがmsdb
でAUTHENTICATE権限を持つプリンシパルによって署名されているためです。これでパズルの半分が解けます。残りの半分は、実際にmsdb.dbo.sp_start_job
に対するEXECUTE権限を、現在信頼されている偽装コンテキストに付与することです。これを行う方法はいくつかあります。
agentProxy
のユーザーをmsdb
にマッピングし、msdb.dbo.sp_start_job
に対する実行権限を付与しますmsdb
オーセンティケーター証明書から派生したユーザーに実行権限を付与するmsdb
でそのシグネチャのユーザーを派生させ、この派生ユーザーに実行権限を付与しますオプション1.は単純ですが、大きな欠点があります。agentProxy
ユーザーは自分の意志でmsdb.dbo.sp_start_job
を実行できるようになり、msdb
へのアクセスが本当に許可され、実行権限が付与されます。
オプション3は正解ですが、不必要にやりすぎだと思います。
したがって、私が優先するのは、オプション2:msdb
で作成された証明書から派生したユーザーにmsdb.dbo.sp_start_job
に対するEXECUTE権限を付与することです。
以下は対応するSQLです。
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
私のブログには、Service Brokerでアクティブ化されたプロシージャ(EXECUTE AS句が必要なため)のコンテキストで記述された、このトピックに関する記事がいくつかあります。
ところで、私のスクリプトをテストしようとしていて、東半球または英国の夏に住んでいる場合は、テストする前にリンクした最後の記事を必ず読んでください。
ネットワークSQLAgentOperatorRoleでランダムなSQLインスタンスを確認しても、sp_start_job権限は直接付与されず、SQLAgentUserRoleから継承されます。
を使用してそれを再確認してください:
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'
これをMSDBで実行し、明示的な拒否アクセスを継承していないことを再確認します。
hth。
SQL Serverエージェントを.NETコードから起動しようとしているので、これはStackOverflowのより良い質問ですか?
追加の権限を付与せずにこれを実現する1つの方法:ストアドプロシージャにジョブを直接開始させず、ストアドプロシージャが(アプリケーションデータベース内の)テーブルのビットを反転できるようにします。次に、ジョブを1分ごとに実行し、ビットが反転するかどうかを確認します。そうである場合は、作業を実行してビットを再度反転します。ジョブがビットが反転していないことを確認した場合、ジョブは終了します。
遅延(およびジョブが頻繁に実行される)を気にしない場合は、魅力のように機能します。