新しい行レベル セキュリティ機能: ブロック述語 (プレビュー)

このポストは、10 月 12 日に投稿された New Row-Level Security functionality: Block predicates (preview) の翻訳です。

 

Azure SQL Database の行レベル セキュリティ (RLS、英語) の機能強化として、ブロック述語のプレビューの提供が開始されました。ブロック述語は、セキュリティ ポリシーを適用し、それに違反する述語を含む行の挿入や更新、削除を禁止するもので、これまでにユーザーの皆様から寄せられた課題に対応しました。このブロック述語はすべての Azure SQL Database (V12) サーバーで使用できます。

以下は、ブロック述語の一般的な使用方法です。

  • マルチテナント データベースでのクロス テナントの挿入操作を禁止する
  • INSERT、UPDATE、DELETE の各操作で個別のアクセス ロジックが必要な場合に、ユーザーごとのデータへの書き込みアクセスの詳細な制御を強制適用する

ブロック述語はフィルター述語と同様に定義されているため、RLS の基本を理解している方はすぐにご利用いただけます。たとえば、RLS で表示行のフィルタリングを行う場合、この叙述関数をブロック述語で再利用して、表示行以外の挿入や更新を禁止することができます。

 CREATE SECURITY POLICY Security.userAccessPolicy
 ADD FILTER PREDICATE Security.userAccessPredicate(UserId) ON dbo.MyTable,
 ADD BLOCK PREDICATE Security.userAccessPredicate(UserId) ON dbo.MyTable

フィルター述語は読み込み操作に適用されますが、ブロック述語は書き込み操作に適用されます。

  • AFTER INSERT および AFTER UPDATE の各述語は、述語に対する新しい行の値をチェックします。
  • BEFORE UPDATE および BEFORE DELETE の各述語は、述語に対する既存の行の値をチェックします。

上記のように操作を指定しない場合、ブロック述語はすべての操作に適用されます。または、ブロック述語 1 つに対して 1 つの操作を指定することもできます。たとえば、BEFORE UPDATE および BEFORE DELETE にブロック述語を適用する場合、各操作に対してブロック述語を追加します。

次に示すのは、ブロック述語を使用してマルチテナントのデータベースでのクロス テナントの挿入操作を禁止する簡単なサンプルです。以前の記事で使用したサンプル (英語) と同様に、このアプリケーションでは CONTEXT_INFO を使用してテナントを識別します。

 --  各行に TenantId を持つサンプル テーブルを Create コマンドで作成
CREATE TABLE Sales (
 OrderId int,
 Qty int,
 Product varchar(10),
 TenantId int
)
 
INSERT INTO Sales VALUES 
 (1, 53, 'Valve', 1), 
 (2, 71, 'Bracket', 2), 
 (3, 60, 'Wheel', 2)
go
 
-- アプリケーションに接続する共有ユーザーを Create コマンドで作成
CREATE USER AppUser WITHOUT LOGIN
go
 
-- テナントでは読み込みと書き込みの両方が可能
GRANT SELECT, INSERT, UPDATE, DELETE ON Sales TO AppUser
DENY UPDATE ON Sales(TenantId) TO AppUser -- never allowed to change TenantId
go
 
-- RLS を有効化
CREATE SCHEMA Security
go
 
CREATE FUNCTION Security.tenantAccessPredicate(@TenantId int)
 RETURNS TABLE
 WITH SCHEMABINDING
AS
 RETURN SELECT 1 AS accessResult
 WHERE @TenantId = CONVERT(int, CONVERT(varbinary(4), CONTEXT_INFO()))
go
 
-- 注: BEFORE UPDATE および BEFORE DELETE の行には既にフィルターが 
-- 適用されており、また AFTER UPDATE は列のアクセス許可により 
-- 不要であるため、必要なブロック述語は AFTER INSERT のみです。
CREATE SECURITY POLICY Security.tenantPolicy
 ADD FILTER PREDICATE Security.tenantAccessPredicate(TenantId) ON dbo.Sales,
 ADD BLOCK PREDICATE Security.tenantAccessPredicate(TenantId) ON dbo.Sales AFTER INSERT
go
 
-- AppUser が TenantId = 2 に接続された場合のクエリをシミュレートしてテスト
EXECUTE AS USER = 'AppUser'
SET CONTEXT_INFO 2
go
 
SELECT * FROM Sales -- 現在のテナント行のみが表示される
go
 
INSERT INTO Sales VALUES (4, 1000, 'Wheel', 1) -- 誤ったテナントへの挿入がブロックされた
go
 
REVERT
go

 

ブロック述語は皆様から寄せられたフィードバックを反映して完成した機能であるため、必ず皆様のお役に立つはずです。ぜひお試しのうえ、ページ下部のコメント欄にご意見をお寄せいただけますと幸いです。

詳細については MSDN の行レベル セキュリティのドキュメントをお読みください。