Uso de políticas de acesso a linhas

Este tópico fornece uma introdução à implementação de políticas de acesso a linhas.

Neste tópico:

Implementação de políticas de acesso a linhas

As subseções a seguir fornecem exemplos sobre como implementar políticas de acesso a linhas:

  • Use uma política típica de acesso a linhas com uma busca na tabela de mapeamento.

  • Substitua as subconsultas existentes da política de acesso a linhas por funções memoizáveis para aumentar o desempenho da consulta.

  • Faça referência a uma tabela de mapeamento protegida por uma política de acesso a linhas em uma política de acesso a linhas diferente.

Exemplo: pesquisa da tabela de mapeamento

As etapas seguintes são um guia representativo para configurar privilégios de políticas de acesso a linhas e adicionar políticas de acesso a linhas a tabelas e exibições.

Estas etapas fazem as seguintes suposições:

  • A abordagem de gerenciamento é centralizada.

    Se o caso de uso da política de acesso a linhas incluir uma abordagem de gerenciamento híbrida ou descentralizada, consulte Gerenciamento de políticas de acesso a linhas para uma distribuição representativa de funções e privilégios.

  • É necessária uma tabela de mapeamento, semelhante a Caso de uso representativo: uso de uma tabela de mapeamento para filtrar o resultado da consulta.

    As etapas seguintes usam a função de contexto CURRENT_ROLE para determinar se os usuários veem linhas em um resultado de consulta, enquanto o caso de uso representativo se concentra no nome do usuário (ou seja, CURRENT_USER).

    Se a ativação e a hierarquia de funções forem importantes, Snowflake recomenda que as condições da política utilizem a função de contexto IS_ROLE_IN_SESSION. Para exemplos de políticas, consulte a seção Exemplos na função IS_ROLE_IN_SESSION.

    O processo geral para implementar uma política de acesso a linhas com tabelas de mapeamento permanece o mesmo, embora as funções de contexto sejam diferentes.

  • A função SECURITYADMIN do sistema concede privilégios a funções personalizadas para gerenciar e implementar políticas de acesso a linhas.

    Se você não quiser usar funções mais privilegiadas (ou seja, SECURITYADMIN ou ACCOUNTADMIN) em um ambiente de produção em vez de funções personalizadas menos privilegiadas (por exemplo, database_admin, finance_admin), verifique se as funções menos privilegiadas têm os privilégios necessários para gerenciar e implementar políticas de acesso a linhas.

    Para obter mais informações, consulte Privilégios da política de acesso a linhas e Resumo de comandos DDL, operações e privilégios.

  • Há etapas separadas para criar uma tabela a ser protegida por uma política de acesso a linhas (etapa 1) e adicionar a política de acesso a linhas à tabela (etapa 5). É possível adicionar uma política de acesso a linhas à tabela quando a tabela é criada, assumindo que já exista uma política de acesso a linhas. Para obter mais informações sobre a sintaxe, consulte CREATE TABLE.

Por exemplo:

  1. Crie uma tabela para os dados de vendas:

    CREATE TABLE sales (
      customer   varchar,
      product    varchar,
      spend      decimal(20, 2),
      sale_date  date,
      region     varchar
    );
    
    Copy
  2. No esquema security, crie uma tabela de mapeamento como mostrado no exemplo representativo. Esta tabela define quais linhas na tabela sales podem ser vistas pelos gerentes de vendas:

    CREATE TABLE security.salesmanagerregions (
      sales_manager varchar,
      region        varchar
    );
    
    Copy
  3. Em seguida, um administrador de segurança cria a função mapping_role personalizada e concede o privilégio SELECT à função personalizada. Esta concessão permite aos usuários com a função personalizada consultar a tabela de mapeamento:

    USE ROLE SECURITYADMIN;
    
    CREATE ROLE mapping_role;
    
    GRANT SELECT ON TABLE security.salesmanagerregions TO ROLE mapping_role;
    
    Copy
  4. Usando a função de proprietário do esquema, crie uma política de acesso a linhas com as duas condições a seguir:

    • Os usuários com a função sales_executive_role personalizada podem visualizar todas as linhas.

    • Os usuários com a função sales_manager personalizada podem visualizar linhas com base na tabela de mapeamento salesmanagerregions.

    Observe que a função de proprietário do esquema recebe automaticamente o privilégio CREATE ROW ACCESS POLICY. Se outras funções devem ser capazes de criar políticas de acesso a linhas, a função do proprietário do esquema pode conceder o privilégio da política CREATE ROW ACCESS a outras funções.

    USE ROLE schema_owner_role;
    
    CREATE OR REPLACE ROW ACCESS POLICY security.sales_policy
    AS (sales_region varchar) RETURNS BOOLEAN ->
      'sales_executive_role' = CURRENT_ROLE()
        OR EXISTS (
          SELECT 1 FROM salesmanagerregions
            WHERE sales_manager = CURRENT_ROLE()
            AND region = sales_region
        )
    ;
    
    Copy

    Onde:

    security.sales_policy

    O nome da política de acesso a linhas no esquema security.

    AS (sales_region varchar)

    A assinatura da política de acesso a linhas.

    Uma assinatura especifica o atributo da tabela de mapeamento e o tipo de dados. O valor retornado determina se o usuário tem acesso a uma determinada linha na tabela ou exibição à qual a política de acesso a linhas é adicionada.

    'sales_executive_role' = CURRENT_ROLE()

    O início de body na política de acesso a linhas.

    A primeira condição da expressão da política de acesso a linhas que permite aos usuários com a função sales_executive_role personalizada visualizar dados.

    OR EXISTS (select 1 from salesmanagerregions WHERE sales_manager = CURRENT_ROLE() AND region = sales_region)

    A segunda condição da expressão da política de acesso a linhas que utiliza uma subconsulta.

    A subconsulta requer que CURRENT_ROLE seja a função sales_manager personalizada com a consulta executada nos dados para especificar uma região listada na tabela de mapeamento {salesmanagerregions}.

    Dica

    Para aumentar o desempenho da consulta na tabela protegida por política, substitua a subconsulta de pesquisa da tabela de mapeamento na cláusula EXISTS por uma função memoizável.

    Para obter mais detalhes, consulte o exemplo de função memoizável (neste tópico).

  5. Usando a função SECURITYADMIN do sistema, execute as duas instruções a seguir:

    GRANT OWNERSHIP ON ROW ACCESS POLICY security.sales_policy TO mapping_role;
    
    GRANT APPLY ON ROW ACCESS POLICY security.sales_policy TO ROLE sales_analyst_role;
    
    Copy

    Estas duas instruções GRANT <privilégios> têm os seguintes efeitos:

    • A propriedade da política não recai sobre a função do sistema SECURITYADMIN. No tempo de execução da consulta, o Snowflake usa os privilégios concedidos à função personalizada porque as políticas são executadas com os direitos do proprietário, não com a função de sistema SECURITYADMIN mais privilegiada. Esta abordagem suporta o princípio de privilégio mínimo.

    • A função personalizada sales_analyst_role pode adicionar ou descartar a política de acesso a linhas a partir de uma tabela conforme necessário.

  6. Adicione (vincule) a política de acesso a linhas à coluna da região na tabela de dados sales:

    USE ROLE SECURITYADMIN;
    
    ALTER TABLE sales ADD ROW ACCESS POLICY security.sales_policy ON (region);
    
    Copy
  7. Conceda o privilégio SELECT para os dados protegidos de sales à função personalizada sales_manager_role:

    GRANT SELECT ON TABLE sales TO ROLE sales_manager_role;
    
    Copy
  8. Depois que os dados de vendas preencherem os dados de sales, teste a política de acesso a linhas:

    USE ROLE sales_manager_role;
    SELECT product, SUM(spend)
    FROM sales
    WHERE YEAR(sale_date) = 2020
    GROUP BY product;
    
    Copy

Exemplo: substitua as subconsultas de política por uma função memoizável

As etapas neste exemplo criam uma função memoizável para cada pesquisa de tabela de mapeamento nas condições da política de acesso a linhas. A subconsulta em cada cláusula EXISTS especifica a pesquisa da tabela de mapeamento, onde as tabelas são nomeadas regions, customers e products, respectivamente:

CREATE OR REPLACE ROW ACCESS POLICY rap_NO_memoizable_function
  AS (region_id number, customer_id number, product_id number)
  RETURNS BOOLEAN ->
    EXISTS(SELECT 1 FROM regions WHERE id = region_id) OR
    EXISTS(SELECT 1 FROM customers WHERE id = customer_id) OR
    EXISTS(SELECT 1 FROM products WHERE id = product_id)
  ;
Copy

Para as etapas seguintes, assumir que a função rap_admin personalizada pode criar políticas de acesso a linhas (ou seja, tem o privilégio CREATE ROW ACCESS POLICY no SCHEMA).

Complete as seguintes etapas para substituir cada uma das pesquisas da tabela de mapeamento de políticas de acesso a linhas por uma função memoizável:

  1. Criar uma função personalizada chamada functions_admin para gerenciar a função memoizável:

    USE ROLE USERADMIN;
    
    CREATE ROLE functions_admin;
    
    Copy
  2. Conceder os seguintes privilégios à função functions_admin para permitir a criação da função memoizável em um esquema existente chamado governance.functions:

    USE ROLE SECURITYADMIN;
    
    GRANT USAGE ON DATABASE governance TO ROLE functions_admin;
    
    GRANT USAGE ON SCHEMA governance.functions TO ROLE functions_admin;
    
    GRANT CREATE FUNCTION ON SCHEMA governance.functions TO ROLE functions_admin;
    
    Copy
  3. Crie uma função memoizável para cada uma das cláusulas EXISTS de subconsulta na política de acesso a linhas. Cada definição de função memoizável assume a mesma forma. Para maior brevidade, apenas um exemplo de função é mostrado:

    USE ROLE functions_admin;
    
    USE SCHEMA governance.functions;
    
    CREATE OR REPLACE function allowed_regions()
      RETURNS array
      memoizable
      AS 'SELECT ARRAY_AGG(id) FROM regions';
    
    Copy
  4. Use uma instrução CREATE ROW ACCESS POLICY para definir uma nova política de acesso a linhas que substitui as subconsultas por funções memoizáveis:

    A nova política de acesso a linhas permite o teste em consultas em uma tabela protegida, quando a política usa ou não as funções memoizáveis, para quantificar o impacto de desempenho do uso de funções memoizáveis nas condições da política:

    USE ROLE rap_admin;
    
    CREATE OR REPLACE ROW ACCESS POLICY rap_with_memoizable_function
      AS (region_id number, customer_id number, product_id number)
      RETURNS BOOLEAN ->
        ARRAY_CONTAINS(region_id, allowed_regions()) OR
        ARRAY_CONTAINS(customer_id, allowed_customers()) OR
        ARRAY_CONTAINS(product_id, allowed_products())
      ;
    
    Copy

Exemplo: proteja a tabela de mapeamento com uma política de acesso a linhas

Este exemplo mostra como fazer referência a uma tabela de mapeamento protegida por uma política de acesso a linhas em uma política de acesso a linhas diferente. A política de acesso a linhas que protege a tabela de mapeamento chama a função de contexto IS_ROLE_IN_SESSION para dar conta da hierarquia de funções. Uma política de acesso a linhas diferente protege a tabela que o usuário consulta. Esta política de acesso a linhas usa uma subconsulta para realizar uma pesquisa na tabela de mapeamento. Por exemplo:

  1. Crie uma tabela de mapeamento para definir funções permitidas com base em regiões geográficas de vendas e insira dados na tabela:

    CREATE OR REPLACE TABLE sales.tables.regional_managers (
      allowed_regions varchar
      allowed_roles varchar
    );
    
    Copy
    INSERT INTO sales.tables.regional_managers
    (allowed_regions, allowed_roles)
    VALUES
    ('na', 'NA_MANAGER'),
    ('eu', 'EU_MANAGER'),
    ('apac', 'APAC_MANAGER');
    
    Copy
  2. Crie uma política de acesso a linhas para especificar a coluna ALLOWED_ROLES na tabela de mapeamento:

    CREATE OR REPLACE ROW ACCESS POLICY governance.policies.rap_map_exempt
    AS (allowed_roles varchar) RETURNS BOOLEAN ->
    IS_ROLE_IN_SESSION(allowed_roles);
    
    Copy
  3. Adicione a política de acesso a linhas na tabela de mapeamento usando uma instrução ALTER TABLE:

    ALTER TABLE sales.tables.regional_managers
      ADD ROW ACCESS POLICY governance.policies.rap_map_exempt
      ON (allowed_roles);
    
    Copy
  4. Crie uma nova política de acesso a linhas que especifique a pesquisa da tabela de mapeamento na tabela de mapeamento protegida:

     CREATE OR REPLACE ROW ACCESS POLICY governance.policies.rap_map_lookup
     AS (allowed_regions varchar) RETURNS BOOLEAN ->
     EXISTS (
       SELECT * FROM sales.tables.regional_managers
       WHERE
         REGION = allowed_regions
    );
    
    Copy
  5. Adicione a política de acesso a linhas denominada governance.policies.rap_map_lookup na tabela denominada sales.tables.data usando uma instrução ALTER TABLE:

    ALTER TABLE sales.tables.data
      ADD ROW ACCESS POLICY governance.policies.rap_map_lookup
      ON (allowed_regions);
    
    Copy
  6. Conceda privilégios às funções na tabela de mapeamento para permitir que usuários com essas funções consultem os dados protegidos. Por exemplo, estas concessões são para a função personalizada na_manager:

    USE ROLE SECURITYADMIN;
    GRANT USAGE ON DATABASE sales TO ROLE na_manager;
    GRANT USAGE ON SCHEMA sales.tables TO ROLE na_manager;
    GRANT SELECT ON TABLE sales.tables.regional_managers TO ROLE na_manager;
    GRANT SELECT ON TABLE sales.tables.data TO ROLE na_manager;
    
    Copy

    Conforme necessário, repita os comandos desta etapa para cada função na tabela de mapeamento.