次の方法で共有


データ API ビルダーでセッション コンテキストを使用して行レベルのセキュリティを実装する

SQL の セッション コンテキスト 機能を使用して、データ API ビルダーで行レベルのセキュリティを実装します。

データ API ビルダーで SQL セッション コンテキストを設定して行レベルのセキュリティを有効にする方法を示す図。

Important

SQL Server 行レベルのセキュリティを使用したセッション コンテキストは、Data API Builder データベース ポリシーとは異なります。 データベース ポリシー (たとえば、 --policy-database "@item.owner eq @claims.user_id") はデータ API ビルダーによって WHERE 句に変換され、セッション コンテキストは SQL Server に要求を転送して、SQL ネイティブの行レベルのセキュリティがフィルター処理を処理できるようにします。

[前提条件]

セッション コンテキストは次でサポートされています。

  • SQL Server 2016 以降
  • Azure SQL Database
  • Azure Synapse Analytics (専用 SQL プール)
  • Azure Synapse Analytics (サーバーレス SQL プール) はサポートされていません

SQL テーブルとデータを作成する

この例のシナリオで使用する架空のデータを含むテーブルを作成します。

  1. 任意のクライアントまたはツールを使用して SQL データベースに接続します。

  2. Revenuesidcategory、および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  
    );
    GO
    
  3. Revenues テーブルに 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 を使用したユーザー固有のフィルタリング
  1. 単純な SELECT * クエリを使用してデータをテストします。

    SELECT * FROM dbo.Revenues
    
  2. RevenuesPredicateという名前の関数を作成します。 この関数は、現在のセッション コンテキストに基づいて結果をフィルター処理します。

    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));
    
  3. 関数を使用して、 RevenuesSecurityPolicy という名前のセキュリティ ポリシーを作成します。

    CREATE SECURITY POLICY dbo.RevenuesSecurityPolicy
    ADD FILTER PREDICATE dbo.RevenuesPredicate(accessible_role)
    ON dbo.Revenues;
    

セキュリティ ポリシーで使用される関数には WITH SCHEMABINDING 句が必要であるため、基になるスキーマの変更によって述語が無効になりません。

(省略可能)ストアド プロシージャを作成する

このセクションでは、T-SQL でセッション コンテキスト値を直接使用するための単純な "hello world" パターンを示します。

  1. 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 つのエンティティを生成します。

  1. --set-session-contextを true に設定しながら、新しい構成を作成します。

    dab init \
        --database-type mssql \
        --connection-string "<sql-connection-string>" \
        --set-session-context true \
        --auth.provider Simulator
    

    SQL Server に対してセッション コンテキストが有効になっている場合、Data API ビルダーは、 sp_set_session_context (たとえば、 roles) を呼び出して、認証済みのユーザー要求を SQL に送信します。 セッション コンテキストを有効にすると、そのデータ ソースの応答キャッシュも無効になります。

Warnung

set-session-contextが有効になっている場合、データ ソースの応答キャッシュは無効になります。 トラフィックの多いシナリオでは、パフォーマンスのテスト、述語列のインデックス作成、またはニーズに合ったデータ API ビルダー データベース ポリシーの使用を検討してください。

  1. revenue テーブルのdbo.Revenuesという名前の新しいエンティティを追加します。

    dab add revenue \
        --source "dbo.Revenues" \
        --permissions "Authenticated:read"
    
  2. データ API ビルダー ツールを起動します。

    dab start
    
  3. 有効なロールを指定せずにエンドポイントにクエリを実行します。 次の理由から、データが返されていないことを確認します。

    • 有効なロールは、自動的にデフォルト値Authenticatedとなります。
    • accessible_role = 'Authenticated'を含む行はありません。
    • セキュリティ ポリシーは、ロールが一致しない場合に結果をフィルター処理します。
    curl http://localhost:5000/api/revenue
    
  4. 有効なロールを Oscarに設定しながら、エンドポイントにクエリを実行します。 フィルター処理された結果に、 Oscar 行のみが含まれているのを確認します。

    curl -H "X-MS-API-ROLE: Oscar" http://localhost:5000/api/revenue
    
  5. Hannah ロールを使用して繰り返します。

    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;

認証されたすべてのユーザー要求は、キーと値のペアとして送信されます。 一般的な要求には、 rolessub または oid、および ID プロバイダーからのカスタム要求が含まれます。

SQL でテストする

SQL でフィルターと述語を直接テストして、動作していることを確認します。

  1. 任意のクライアントまたはツールを使用して、SQL サーバーにもう一度接続します。

  2. sp_set_session_context を実行して、セッション コンテキストのroles クレームを手動で静的な値Oscarに設定します。

    EXEC sp_set_session_context 'roles', 'Oscar';
    
  3. 一般的な SELECT * クエリを実行します。 述語を使用して結果が自動的にフィルター処理されることを確認します。

    SELECT * FROM dbo.Revenues;  
    
  4. (省略可能)ストアド プロシージャを使用してテーブルのクエリを実行します。

    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) のインデックスを作成し、パフォーマンスへの影響を分離するためにポリシーを一時的に無効にすることを検討してください。