web-dev-qa-db-ja.com

ストアドプロシージャを実行する権限。ただし、基になるテーブルを直接読み取ることはできません。

多くの異なるテーブルからの多くの異なる列を含むストアドプロシージャがあります。 Excelを介してストアドプロシージャの結果に20人のユーザーがアクセスできるようにしたい.

ユーザーがストアドプロシージャにのみアクセスでき、基になるテーブルやビューにはアクセスできないようにすることはできますか?

7
DWD

もちろん、これらのユーザーに、基になるテーブルではなく、ストアドプロシージャへの権限を与えるだけです。

CREATE PROCEDURE dbo.test -- always use schema prefix!
AS
BEGIN
  SET NOCOUNT ON;

  SELECT t1.col1, t2.col2, ...
    FROM dbo.table1 AS t1
    INNER JOIN dbo.table2 AS t2
    ON ... ;
END
GO

GRANT EXEC ON dbo.test TO [user1], [user2], ...;

これは、テストできる完全に含まれた例です。最初に、データベースを作成します(うまくいけば、floobは既存のデータベースと競合しません)。

CREATE DATABASE floob;
GO

次に、2つのログインを作成します。

CREATE LOGIN floob1 WITH PASSWORD = 'foo', CHECK_POLICY = OFF;
CREATE LOGIN floob2 WITH PASSWORD = 'foo', CHECK_POLICY = OFF;
GO

そして、一緒に行くデータベースユーザーを作成します:

USE floob;
GO
CREATE USER floob1 FROM LOGIN floob1;
CREATE USER floob2 FROM LOGIN floob2;
GO

次に、デフォルトでアクセスできないテーブルと、それをクエリするストアドプロシージャを作成します。

CREATE TABLE dbo.whatwhat(id INT);
INSERT dbo.whatwhat(id) VALUES(1);
GO
CREATE PROCEDURE dbo.select_whatwhat
AS
BEGIN
  SET NOCOUNT ON;

  SELECT id FROM dbo.whatwhat;
END
GO

次に、floob1のみに実行権限を付与します。

GRANT EXEC ON dbo.select_whatwhat TO floob1;
GO

次に、プロシージャを実行して、テーブルからfloob1として選択します。

EXECUTE AS USER = 'floob1';
GO
EXEC dbo.select_whatwhat; -- works
GO
SELECT id FROM dbo.whatwhat; -- fails with error
GO
REVERT;

ストアドプロシージャを実行した結果、クエリは成功しますが、テーブルへのクエリを直接実行しようとすると、明示的にアクセスを許可されていないため、エラーメッセージが表示されます。

メッセージ229、レベル14、状態5
オブジェクト 'whatwhat'、データベース 'floob'、スキーマ 'dbo'に対するSELECT権限が拒否されました。

次に、ストアドプロシージャを実行するための明示的なアクセス権を付与されていないfloob2として試してください。

EXECUTE AS USER = 'floob2';
GO
EXEC dbo.select_whatwhat; -- fails with error
GO
SELECT id FROM dbo.whatwhat; -- fails with error
GO
REVERT;

今回はSELECTでも同じエラーが発生しますが、EXECでもこのエラーが発生します。

メッセージ229、レベル14、状態5、手順select_whatwhat
オブジェクト「select_whatwhat」、データベース「floob」、スキーマ「dbo」に対するEXECUTE権限が拒否されました。

クリーンアップすることを忘れないでください:

USE master;
GO
DROP DATABASE floob;
DROP LOGIN floob1;
DROP LOGIN floob2;
GO

あなたのコメントについて:

T-SQLコードを使用する代わりに、SQLサーバーでドロップアンドクリックを使用してユーザーを許可することはできますか?

それはそうですが、それは非常に良い考えのようには聞こえません。プロセスは次のとおりです。オブジェクトエクスプローラーでストアドプロシージャを右クリックし、[プロパティ]をクリックし、[アクセス許可]タブに移動して、[検索]をクリックし、ユーザー名を入力して[OK]をクリックし、左側のEXECUTEとGRANTが一致するチェックボックスをオンにします上部、[OK]をクリックします。すべてのストアドプロシージャについて繰り返し、20を掛けます(すべてのユーザー)。ええ、それはスクリプトを書くよりもずっと簡単に聞こえます。 GUIを介してインタラクティブにこれを行うために必要なポイントとクリックの数をだれが知っているかではなく、1つのコピー、貼り付け、実行で、必要なスクリプトを1つのステップで生成するより良い方法を次に示します。

DECLARE @xml NVARCHAR(MAX) = N'';

;WITH users AS 
(SELECT name = 'user1' UNION ALL SELECT 'user2' ... UNION ALL SELECT 'user20')
SELECT @xml += N'GRANT EXEC ON ' + QUOTENAME(s.name) + 
  '.' + QUOTENAME(p.name) + ' TO ' + QUOTENAME(u.name) + ';
'
FROM users AS u CROSS JOIN sys.procedures AS p
  INNER JOIN sys.schemas AS s ON s.[schema_id] = p.[schema_id];

PRINT @sql;
-- EXEC sp_executesql @sql;

sys.database_principalsをミックスに追加して、タイプミスのない適切なユーザーセットを確実に取得することもできます。

12
Aaron Bertrand