web-dev-qa-db-ja.com

トリガーの問題に対する権限

MS-SQL 2008 R2のデータベースを使用していて、問題が発生しています。

基本的なセットアップは次のとおりです。dbo.Assesmentsとaudit.Assesmentsの2つの対象テーブルがあります。 dbo.Assesmentsは作業データテーブルであり、変更のログでaudit.Assesmentsを更新するためのデータ変更(挿入、更新、削除)のトリガーがあります。私の知る限り、これは何年にもわたって機能しています。

私たちのL2サポートには、WinAuthで取得するSupportRoleと呼ばれるロールがあり、そのロールには、ストアドプロシージャに対するいくつかの選択権と実行権があります。これらのストアドプロシージャの1つは、dbo.Assesmentsを更新します。ここで問題が発生します。更新が行われ、ストアドプロシージャが起動して、audit.Assesmentsに監査行が挿入されます。その後、「挿入の拒否、挿入に対する不十分な権限」、トランザクションロールなどがすぐに返されます。

これは私にとって不可解です。トリガーはストアドプロシージャのようなものだと思っていました。トリガーが作成された場合、トリガーは何をする権利も持っているのですが、これは2度考えさせられます。監査テーブル/スキーマのサポートロールに挿入権限を与えたくありません。私は何をすべきか?

4
Kirbinator

トリガーは、デフォルトでは、トリガーを起動したプリンシパルのセキュリティコンテキストで実行されます。

この動作を変更するには、WITH EXECUTE AS OWNER句を使用してトリガーを作成する必要があります。

以下は、それがどのように機能するかを示す例です。 WITH EXECUTE AS OWNERを使用すると、テーブルを更新しているプリンシパルではなく、データベース所有者のセキュリティコンテキストでトリガーを実行できます。

まず、テストテーブルを作成します。

USE tempdb;
IF OBJECT_ID('dbo.t') IS NOT NULL
BEGIN
    DROP TRIGGER t_trig;
    DROP TABLE dbo.t;
END
GO
CREATE TABLE dbo.t
(
    ID INT NOT NULL
    , ID2 INT NULL
);
GO

これがEXECUTE AS OWNERを含むトリガーコードです。

CREATE TRIGGER t_trig ON dbo.t
WITH EXECUTE AS OWNER
AFTER INSERT
AS
BEGIN
    UPDATE dbo.t
    SET ID2 = ID
    WHERE EXISTS (SELECT 1 FROM inserted i WHERE i.ID = dbo.t.ID);
END
GO

ここで、低い特権でテストログインを作成し、EXECUTE AS OWNERが本来必要としない機能への特権不足のプリンシパルアクセスを許可するという仮説をテストするために使用できます。

CREATE LOGIN tLogin WITH PASSWORD = 'QWERFsdf23454%';
CREATE USER tLogin FROM LOGIN tLogin WITH DEFAULT_SCHEMA = dbo;

dbo.Tに行を挿入する機能を提供しますが、UPDATEステートメントを実行できないようにします。

GRANT INSERT ON dbo.t TO tLogin;
DENY UPDATE ON dbo.t TO tLogin;

ここでテストを行います:

EXECUTE AS USER = 'tLogin';
/*
    Output here shows we're running under the tLogin
    security context
*/
SELECT SUSER_SNAME();
/* 
    This will fail, with insufficient privileges
    since we've DENY'd the UPDATE privilege to tLogin.
*/
UPDATE dbo.t SET ID2 = ID; 
/*
    this will run the UPDATE since the trigger 
    has EXECUTE AS OWNER
*/
INSERT INTO dbo.t(ID) VALUES (1); 
/*
    This takes us out of the tLogin security context
*/
REVERT

ここで、dbo.Tの行にトリガーによって行われた変更があることがわかります。

SELECT *
FROM dbo.t;

そして、ここでは、低い特権のユーザーをクリーンアップします。

DROP USER tLogin;
DROP LOGIN tLogin;

上記を実行した場合の出力は次のとおりです。

enter image description here

7
Max Vernon