SQL の セッション コンテキスト 機能を使用して、データ API ビルダーで行レベルのセキュリティを実装します。
Important
SQL Server 行レベルのセキュリティを使用したセッション コンテキストは、Data API Builder データベース ポリシーとは異なります。 データベース ポリシー (たとえば、 --policy-database "@item.owner eq @claims.user_id") はデータ API ビルダーによって WHERE 句に変換され、セッション コンテキストは SQL Server に要求を転送して、SQL ネイティブの行レベルのセキュリティがフィルター処理を処理できるようにします。
[前提条件]
- 既存の SQL サーバーとデータベース。
- データ API ビルダー CLI。 CLI をインストールする
注
セッション コンテキストは次でサポートされています。
- SQL Server 2016 以降
- Azure SQL Database
- Azure Synapse Analytics (専用 SQL プール)
- Azure Synapse Analytics (サーバーレス SQL プール) はサポートされていません
SQL テーブルとデータを作成する
この例のシナリオで使用する架空のデータを含むテーブルを作成します。
任意のクライアントまたはツールを使用して SQL データベースに接続します。
Revenues、id、category、およびrevenue列を含むaccessible_roleという名前のテーブルを作成します。DROP TABLE IF EXISTS dbo.Revenues; CREATE TABLE dbo.Revenues( id int PRIMARY KEY, category varchar(max) NOT NULL, revenue int, accessible_role varchar(max) NOT NULL ); GORevenuesテーブルに 4 つのサンプル行を挿入します。INSERT INTO dbo.Revenues VALUES (1, 'Book', 5000, 'Oscar'), (2, 'Comics', 10000, 'Oscar'), (3, 'Journals', 20000, 'Hannah'), (4, 'Series', 40000, 'Hannah') GOこの例では、
accessible_role列には、行にアクセスできるロール名が格納されています。
ヒント
一般的なセッション コンテキストのユース ケース:
- を使用したロールベースのフィルター処理 (ここに示す)
roles -
tenant_idを使用したマルチテナント分離 -
user_idを使用したユーザー固有のフィルタリング
単純な
SELECT *クエリを使用してデータをテストします。SELECT * FROM dbo.RevenuesRevenuesPredicateという名前の関数を作成します。 この関数は、現在のセッション コンテキストに基づいて結果をフィルター処理します。CREATE FUNCTION dbo.RevenuesPredicate(@accessible_role varchar(max)) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS fn_securitypredicate_result WHERE @accessible_role = CAST(SESSION_CONTEXT(N'roles') AS varchar(max));関数を使用して、
RevenuesSecurityPolicyという名前のセキュリティ ポリシーを作成します。CREATE SECURITY POLICY dbo.RevenuesSecurityPolicy ADD FILTER PREDICATE dbo.RevenuesPredicate(accessible_role) ON dbo.Revenues;
注
セキュリティ ポリシーで使用される関数には WITH SCHEMABINDING 句が必要であるため、基になるスキーマの変更によって述語が無効になりません。
(省略可能)ストアド プロシージャを作成する
このセクションでは、T-SQL でセッション コンテキスト値を直接使用するための単純な "hello world" パターンを示します。
rolesセッション コンテキスト値を読み取り、それを使用して結果をフィルター処理するストアド プロシージャを作成します。CREATE OR ALTER PROCEDURE dbo.GetRevenuesForCurrentRole AS BEGIN SET NOCOUNT ON; DECLARE @role varchar(max) = CAST(SESSION_CONTEXT(N'roles') AS varchar(max)); SELECT id, category, revenue, accessible_role FROM dbo.Revenues WHERE accessible_role = @role; END GO
ツールを実行
データ API ビルダー (DAB) ツールを実行して、構成ファイルと 1 つのエンティティを生成します。
--set-session-contextを true に設定しながら、新しい構成を作成します。dab init \ --database-type mssql \ --connection-string "<sql-connection-string>" \ --set-session-context true \ --auth.provider SimulatorSQL Server に対してセッション コンテキストが有効になっている場合、Data API ビルダーは、
sp_set_session_context(たとえば、roles) を呼び出して、認証済みのユーザー要求を SQL に送信します。 セッション コンテキストを有効にすると、そのデータ ソースの応答キャッシュも無効になります。
Warnung
set-session-contextが有効になっている場合、データ ソースの応答キャッシュは無効になります。 トラフィックの多いシナリオでは、パフォーマンスのテスト、述語列のインデックス作成、またはニーズに合ったデータ API ビルダー データベース ポリシーの使用を検討してください。
revenueテーブルのdbo.Revenuesという名前の新しいエンティティを追加します。dab add revenue \ --source "dbo.Revenues" \ --permissions "Authenticated:read"データ API ビルダー ツールを起動します。
dab start有効なロールを指定せずにエンドポイントにクエリを実行します。 次の理由から、データが返されていないことを確認します。
- 有効なロールは、自動的にデフォルト値
Authenticatedとなります。 -
accessible_role = 'Authenticated'を含む行はありません。 - セキュリティ ポリシーは、ロールが一致しない場合に結果をフィルター処理します。
curl http://localhost:5000/api/revenue- 有効なロールは、自動的にデフォルト値
有効なロールを
Oscarに設定しながら、エンドポイントにクエリを実行します。 フィルター処理された結果に、Oscar行のみが含まれているのを確認します。curl -H "X-MS-API-ROLE: Oscar" http://localhost:5000/api/revenueHannahロールを使用して繰り返します。curl -H "X-MS-API-ROLE: Hannah" http://localhost:5000/api/revenue
GraphQL を使用してテストする
セッション コンテキストは、GraphQL クエリでも機能します。
query {
revenues {
items {
id
category
revenue
accessible_role
}
}
}
ロール ヘッダを渡す。
curl -X POST http://localhost:5000/graphql \
-H "Content-Type: application/json" \
-H "X-MS-API-ROLE: Oscar" \
-d '{"query": "{ revenues { items { id category revenue accessible_role } } }"}'
データ API ビルダーが SQL Server に送信する内容
セッション コンテキストが有効になっている場合、データ API ビルダーは、クエリを実行する前にすべての要求にセッション コンテキスト値を設定します。
EXEC sp_set_session_context 'roles', 'Oscar', @read_only = 0;
-- Then executes your query
SELECT * FROM dbo.Revenues;
認証されたすべてのユーザー要求は、キーと値のペアとして送信されます。 一般的な要求には、 roles、 sub または oid、および ID プロバイダーからのカスタム要求が含まれます。
SQL でテストする
SQL でフィルターと述語を直接テストして、動作していることを確認します。
任意のクライアントまたはツールを使用して、SQL サーバーにもう一度接続します。
sp_set_session_contextを実行して、セッション コンテキストのrolesクレームを手動で静的な値Oscarに設定します。EXEC sp_set_session_context 'roles', 'Oscar';一般的な
SELECT *クエリを実行します。 述語を使用して結果が自動的にフィルター処理されることを確認します。SELECT * FROM dbo.Revenues;(省略可能)ストアド プロシージャを使用してテーブルのクエリを実行します。
EXEC dbo.GetRevenuesForCurrentRole;
リソースをクリーンアップする
サンプル オブジェクトを削除する場合は、次のコマンドを実行します。
DROP SECURITY POLICY IF EXISTS dbo.RevenuesSecurityPolicy;
DROP FUNCTION IF EXISTS dbo.RevenuesPredicate;
DROP PROCEDURE IF EXISTS dbo.GetRevenuesForCurrentRole;
DROP TABLE IF EXISTS dbo.Revenues;
トラブルシューティング
-
結果が返されない: セキュリティ ポリシーがアクティブ (
SELECT * FROM sys.security_policies) であることを確認し、セッション コンテキスト値 (SELECT SESSION_CONTEXT(N'roles')) を確認し、データ API ビルダー構成で--set-session-context trueが設定されていることを確認します。 -
返されるすべての行: セキュリティ ポリシーが無効になっていない (
WITH STATE = OFF) ことを確認し、述語が承認された行に対してのみ1返されることを確認します。 -
パフォーマンスの問題: 述語列 (
accessible_role) のインデックスを作成し、パフォーマンスへの影響を分離するためにポリシーを一時的に無効にすることを検討してください。