web-dev-qa-db-ja.com

ストアドプロシージャが所有者として実行され、データベース接続が閉じない

ユーザーがQA環境ですべてのDb接続を閉じることができるようにするストアドプロシージャを作成しました。私はSAで、プロシージャを作成しました。

SPを変更すると、「所有者として実行」なしで実行すると結果が表示されます。「所有者として実行」を追加すると、結果が表示されません。

理由を理解しようとしています。

create procedure [dbo].[DatabaseConnectionClose]
    @DatabaseName varchar(255)
with execute as owner
as


DECLARE @kill varchar(8000) = '';  
SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'  
FROM sys.dm_exec_sessions
WHERE database_id  = db_id(@DatabaseName)

select @kill as CloseConnectionScript

EXEC(@kill);
2
user157965

EXECUTE ASステートメントのCREATE {module_type}句の使用は偽装ですが、データベースレベルでのみです。所有者は "dbo"(この場合は少なくとも)ですが、それは単なるユーザーです。データベースレベルのプリンシパル。 KILLコマンドには、インスタンスレベルの権限が必要です。デフォルトでは、データベースレベルの偽装(EXECUTE ASまたはEXECUTE AS USERステートメント))を使用すると、プロセスは現在のプロセスに隔離されます。データベース、そのユーザーが適切な権限を持つログイン(同じSIDを持つ)にマップされている場合でもこの制限のため、プロセスはインスタンスレベルまでのアクセス権をチェックするためにインスタンスに到達することはできません。

これを正しく行うには:

  1. EXECUTE ASを取り除く
  2. モジュール署名を使用してこれを実装します。

    誰にでも許可せずに安全かつ簡単に高レベルのアクセス許可を使用する:サーバーレベル (私のブログ投稿;外部ですが、より良い説明があります)

    SQL Serverエージェントサービスのステータスを確認できるように、ユーザーに最低限必要なアクセス許可を提供する必要がありますか? (私の回答の1つ。ここではDBA.SEにあります)

    証明書ベースのログインに付与する必要がある唯一の権限は、ALTER ANY CONNECTIONです(ドキュメントの [〜#〜] kill [〜#〜] のとおり)

モジュール署名の詳細については、次のWebサイトをご覧ください。 モジュール署名情報


また、質問に対するコメントでAaron Bertrandが述べた優れた点に加えて、SQL Serverエージェントなどの正当なプロセスのセッションを強制終了しないように注意する必要があります。少なくともprogram_namesys.dm_exec_sessionsの列。ただし、そうでない場合はlogin_name(および場合によってはその他)。

ただし、ALTER DATABASE [{db_name}] SET...が続行する方法になる場合は、次の投稿をガイドとして使用してください。その場合、インスタンスレベルの権限は関係ありません。

誰にも付与せずに安全かつ簡単に高レベルのアクセス許可を使用:データベースレベル

8
Solomon Rutzky