Udostępnij za pośrednictwem


Implementowanie zabezpieczeń na poziomie wiersza z kontekstem sesji w Data API Builder

Użyj funkcji kontekstu sesji języka SQL, aby zaimplementować zabezpieczenia na poziomie wiersza w narzędziu Data API Builder.

Diagram przedstawiający sposób ustawiania kontekstu sesji SQL przez konstruktora interfejsu API danych w celu włączenia zabezpieczeń na poziomie wiersza.

Ważne

Kontekst sesji z zabezpieczeniami na poziomie wiersza programu SQL Server różni się od zasad bazy danych konstruktora interfejsu API danych. Zasady bazy danych (na przykład --policy-database "@item.owner eq @claims.user_id") są tłumaczone na klauzule WHERE przez Kompilator interfejsu API danych, podczas gdy kontekst sesji przekazuje oświadczenia do serwera SQL Server, aby natywne zabezpieczenia na poziomie wiersza obsługiwały filtrowanie.

Wskazówka

DAB 2.0, który jest obecnie w wersji zapoznawczej, obsługuje również uwierzytelnianie delegowane przez użytkownika On-Behalf-Of (OBO) dla SQL Server, które wymienia token użytkownika przychodzącego na token SQL, tak aby baza danych uwierzytelniała się jako faktyczny użytkownik wywołujący. OBO umożliwia zasady zabezpieczeń na poziomie wiersza, które zależą od rzeczywistej tożsamości użytkownika. Aby uzyskać więcej informacji, zobacz uwierzytelnianie delegowane przez użytkownika i co nowego.

Wymagania wstępne

  • Istniejący serwer SQL i baza danych.
  • Kreator interfejsu wiersza polecenia do API danych. Zainstaluj CLI

Uwaga / Notatka

Kontekst sesji jest obsługiwany w:

  • SQL Server 2016 i nowsze
  • Azure SQL Database
  • Azure Synapse Analytics (Dedykowana pula SQL)
  • Usługa Azure Synapse Analytics (bezserwerowa pula SQL) nie jest obsługiwana

Tworzenie tabeli i danych SQL

Utwórz tabelę z fikcyjnymi danymi do użycia w tym przykładowym scenariuszu.

  1. Nawiąż połączenie z bazą danych SQL przy użyciu preferowanego klienta lub narzędzia.

  2. Utwórz tabelę o nazwie Revenues z kolumnami id, category, revenuei 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. Wstaw cztery przykładowe wiersze do Revenues tabeli.

    INSERT INTO dbo.Revenues VALUES
        (1, 'Book', 5000, 'Oscar'),  
        (2, 'Comics', 10000, 'Oscar'),  
        (3, 'Journals', 20000, 'Hannah'),  
        (4, 'Series', 40000, 'Hannah')
    GO
    

    W tym przykładzie kolumna accessible_role przechowuje nazwę roli, która może uzyskać dostęp do wiersza.

Wskazówka

Typowe przypadki użycia kontekstu sesji:

  • Filtrowanie oparte na rolach (pokazane tutaj) przy użyciu roles
  • Izolacja w środowiskach wielodostępności przy użyciu tenant_id
  • Filtrowanie specyficzne dla użytkownika przy użyciu user_id
  1. Przetestuj dane przy użyciu prostego SELECT * zapytania.

    SELECT * FROM dbo.Revenues
    
  2. Utwórz funkcję o nazwie RevenuesPredicate. Ta funkcja filtruje wyniki na podstawie bieżącego kontekstu sesji.

    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. Utwórz zasady zabezpieczeń o nazwie RevenuesSecurityPolicy przy użyciu funkcji .

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

Uwaga / Notatka

Klauzula WITH SCHEMABINDING jest wymagana dla funkcji używanych w zasadach zabezpieczeń, aby podstawowe zmiany schematu nie powodowały unieważnienia predykatu.

(Opcjonalnie) Utwórz procedurę składowaną

W tej sekcji przedstawiono prosty wzorzec "hello world" umożliwiający używanie wartości kontekstu sesji bezpośrednio w języku T-SQL.

  1. Utwórz procedurę składowaną, która odczytuje roles wartość kontekstu sesji i używa jej do filtrowania wyników.

    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
    

Uruchamianie narzędzia

Uruchom narzędzie konstruktora interfejsu API danych (DAB), aby wygenerować plik konfiguracji i jedną jednostkę.

  1. Utwórz nową konfigurację przez ustawienie --set-session-context na prawdę.

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

    Gdy kontekst sesji jest włączony dla programu SQL Server, konstruktor interfejsu API danych wysyła uwierzytelnione oświadczenia użytkownika do bazy danych SQL przez wywołanie metody sp_set_session_context (na przykład roles). Włączenie kontekstu sesji powoduje również wyłączenie buforowania odpowiedzi dla tego źródła danych.

Ostrzeżenie

Po set-session-context włączeniu buforowanie odpowiedzi jest wyłączone dla źródła danych. W przypadku scenariuszy o dużym natężeniu ruchu rozważ przetestowanie wydajności, indeksowanie kolumny predykatu lub użycie zasad bazy danych Data API Builder, jeśli spełniają Twoje wymagania.

  1. Dodaj nową jednostkę o nazwie revenue dla dbo.Revenues tabeli.

    dab add revenue \
        --source "dbo.Revenues" \
        --permissions "Authenticated:read"
    
  2. Uruchom narzędzie konstruktora interfejsu API danych.

    dab start
    
  3. Wykonywanie zapytań względem punktu końcowego bez określania efektywnej roli. Zwróć uwagę, że żadne dane nie są zwracane, ponieważ:

    • Obowiązująca rola jest domyślnie ustawiona na Authenticated.
    • Nie ma wierszy z accessible_role = 'Authenticated'.
    • Polityka zabezpieczeń filtruje wyniki, gdy rola nie pasuje.
    curl http://localhost:5000/api/revenue
    
  4. Wykonaj zapytanie względem punktu końcowego, ustawiając obowiązującą rolę na Oscar. Zwróć uwagę, że przefiltrowane wyniki zawierają tylko Oscar wiersze.

    curl -H "X-MS-API-ROLE: Oscar" http://localhost:5000/api/revenue
    
  5. Powtarzaj, korzystając z roli Hannah.

    curl -H "X-MS-API-ROLE: Hannah" http://localhost:5000/api/revenue
    

Testowanie przy użyciu języka GraphQL

Kontekst sesji współdziała również z zapytaniami GraphQL.

query {
    revenues {
        items {
            id
            category
            revenue
            accessible_role
        }
    }
}

Przekaż nagłówek roli:

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 } } }"}'

Co konstruktor interfejsu API danych wysyła do programu SQL Server

Po włączeniu kontekstu sesji konstruktor interfejsu API danych ustawia wartości kontekstu sesji na każdym żądaniu przed wykonaniem zapytania.

EXEC sp_set_session_context 'roles', 'Oscar', @read_only = 0;
-- Then executes your query
SELECT * FROM dbo.Revenues;

Wszystkie oświadczenia uwierzytelnionych użytkowników są wysyłane jako pary klucz-wartość. Typowe oświadczenia obejmują roles, sub lub oid, a także wszelkie niestandardowe oświadczenia od dostawcy tożsamości.

Testowanie w programie SQL

Przetestuj filtr i predykat bezpośrednio w języku SQL, aby upewnić się, że działa.

  1. Połącz się ponownie z serwerem SQL przy użyciu preferowanego klienta lub narzędzia.

  2. Uruchom sp_set_session_context, aby ręcznie ustawić żądanie kontekstu sesji roles na statyczną wartość Oscar.

    EXEC sp_set_session_context 'roles', 'Oscar';
    
  3. Uruchom typowe SELECT * zapytanie. Zwróć uwagę, że wyniki są automatycznie filtrowane przy użyciu predykatu.

    SELECT * FROM dbo.Revenues;  
    
  4. (Opcjonalnie) Wykonaj zapytanie dla tabeli przy użyciu procedury składowanej.

    EXEC dbo.GetRevenuesForCurrentRole;
    

Uprzątnij zasoby

Jeśli chcesz usunąć przykładowe obiekty, uruchom polecenie:

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;

Rozwiązywanie problemów

  • Nie są zwracane żadne wyniki: Sprawdź, czy zasady zabezpieczeń są aktywne (SELECT * FROM sys.security_policies), sprawdź wartość kontekstu sesji (SELECT SESSION_CONTEXT(N'roles')) i potwierdź, że --set-session-context true ustawiono w konfiguracji konstruktora interfejsu API danych.
  • Zwrócone wszystkie wiersze: Upewnij się, że zasady zabezpieczeń nie są wyłączone (WITH STATE = OFF) i że predykat zwraca 1 tylko dla autoryzowanych wierszy.
  • Problemy z wydajnością: Zaindeksuj kolumnę predykatu (accessible_role) i rozważ tymczasowe wyłączenie polityki w celu odizolowania wpływu na wydajność.