Como trabalhar com exibições seguras

Este tópico abrange conceitos e sintaxe para definir exibições e exibições materializadas como seguras.

Neste tópico:

Visão geral de exibições seguras

Por que devo usar exibições seguras?

  • Em uma exibição não segura, otimizações internas podem expor dados indiretamente.

    Algumas das otimizações internas para exibições requerem acesso aos dados subjacentes nas tabelas base da exibição. Esse acesso pode permitir que dados escondidos dos usuários da exibição sejam expostos através de código do usuário, tais como funções definidas pelo usuário, ou outros métodos programáticos. Exibições seguras não utilizam essas otimizações, garantindo que os usuários não tenham acesso aos dados subjacentes.

  • Para uma exibição não segura, a definição da exibição é visível para outros usuários.

    Por padrão, a expressão de consulta utilizada para criar uma exibição padrão, também conhecida como definição ou texto da exibição, é visível para os usuários em vários comandos e interfaces. Para obter mais detalhes, veja Como interagir com exibições seguras (neste tópico).

    Por razões de segurança ou privacidade, talvez você não queira expor as tabelas subjacentes ou detalhes estruturais internos para uma exibição. Com exibições seguras, a definição e os detalhes da exibição são visíveis apenas para usuários autorizados (ou seja, usuários que recebem a função que possui a exibição).

Quando devo usar uma exibição segura?

Exibições devem ser definidas como seguras quando são especificamente designadas para a privacidade dos dados (ou seja, para limitar o acesso a dados sensíveis que não devem ser expostos a todos os usuários da(s) tabela(s) subjacente(s)).

Exibições seguras não devem ser usadas para exibições que são definidas apenas para conveniência de consulta, tais como exibições criadas para simplificar consultas para as quais os usuários não precisam entender a representação dos dados subjacentes. Exibições seguras podem ser executadas mais lentamente do que exibições não seguras.

Dica

Para decidir se você deve usar uma exibição segura, você deve considerar a finalidade da exibição e pesar entre privacidade/segurança de dados e desempenho da consulta.

Como os dados podem ser expostos por uma exibição não segura?

Usando o seguinte exemplo de widgets, considere um usuário que somente tenha acesso aos widgets vermelhos. Suponha que o usuário se pergunte se existe algum widget roxo e faça a seguinte consulta:

SELECT *
    FROM widgets_view
    WHERE 1/iff(color = 'Purple', 0, 1) = 1;
Copy

Se algum widget roxo existir, a expressão IFF() retorna 0. A operação de divisão falhará devido a um erro de divisão por zero, o que permitirá ao usuário inferir que existe pelo menos um widget roxo.

Como criar exibições seguras

Exibições seguras são definidas usando a palavra-chave SECURE com o DDL padrão para exibições:

Como interagir com exibições seguras

Como ver a definição de exibições seguras

A definição de uma exibição segura é exposta apenas a usuários autorizados (ou seja, usuários a quem foi concedida a função que possui a exibição). Se um usuário não autorizado usar qualquer um dos seguintes comandos ou interfaces, a definição da exibição não será exibida:

No entanto, os usuários que receberam o privilégio IMPORTED PRIVILEGES no banco de dados SNOWFLAKE ou em outro banco de dados compartilhado têm acesso a definições de exibição seguras por meio da exibição VIEWS do Account Usage.

Os usuários aos quais foi concedida a função ACCOUNTADMIN ou a função de banco de dados SNOWFLAKE.OBJECT_VIEWER também podem ver definições de exibição segura por meio desta exibição. O meio de acesso preferencial e com menos privilégios é a função de banco de dados SNOWFLAKE.OBJECT_VIEWER.

Como determinar se uma exibição é segura

Para exibições não materializadas, a coluna IS_SECURE nas exibições Information Schema e Account Usage identifica se uma exibição é segura. Por exemplo, para uma exibição chamada MYVIEW no banco de dados mydb:

Information Schema:

select table_catalog, table_schema, table_name, is_secure
    from mydb.information_schema.views
    where table_name = 'MYVIEW';
Copy

Account Usage:

select table_catalog, table_schema, table_name, is_secure
    from snowflake.account_usage.views
    where table_name = 'MYVIEW';
Copy

(Para obter informações gerais sobre as diferenças entre as exibições INFORMATION_SCHEMA e ACCOUNT_USAGE, consulte Diferenças entre Account Usage e Information Schema).

Alternativamente, você pode usar o comando SHOW VIEWS para visualizar informações semelhantes (observe que o nome da exibição não diferencia maiúsculas de minúsculas):

SHOW VIEWS LIKE 'myview';
Copy

Para exibições materializadas, use o comando SHOW MATERIALIZED VIEWS para identificar se uma exibição é segura. Por exemplo:

SHOW MATERIALIZED VIEWS LIKE 'my_mv';
Copy

Visualização de detalhes de uma exibição segura no Perfil de Consulta

Os dados internos de uma exibição segura não são expostos no Perfil de Consulta (na interface da web). Esse é o caso até mesmo para o proprietário da exibição segura, pois não proprietários podem ter acesso ao Perfil de Consulta de um proprietário.

Como usar exibições seguras com o controle de acesso do Snowflake

A segurança das exibições pode ser integrada com usuários e funções do Snowflake usando as funções de contexto CURRENT_ROLE e CURRENT_USER. O exemplo a seguir ilustra o uso de funções para controlar o acesso às linhas de uma tabela. Além da tabela que contém os dados (widgets), o exemplo usa uma tabela de acesso (widget_access_rules) para monitorar quais funções têm acesso a quais linhas na tabela de dados:

CREATE TABLE widgets (
    id NUMBER(38,0) DEFAULT widget_id_sequence.nextval, 
    name VARCHAR,
    color VARCHAR,
    price NUMBER(38,0),
    created_on TIMESTAMP_LTZ(9));
CREATE TABLE widget_access_rules (
    widget_id NUMBER(38,0),
    role_name VARCHAR);
CREATE OR REPLACE SECURE VIEW widgets_view AS
    SELECT w.*
        FROM widgets AS w
        WHERE w.id IN (SELECT widget_id
                           FROM widget_access_rules AS a
                           WHERE upper(role_name) = CURRENT_ROLE()
                      )
    ;
Copy

A cláusula WHERE limita os widgets que cada função pode ver.

Suponha que um usuário que tenha acesso apenas a widgets vermelhos execute a consulta mostrada anteriormente:

SELECT *
    FROM widgets_view
    WHERE 1/iff(color = 'Purple', 0, 1) = 1;
Copy

A cláusula WHERE da exibição segura é executada antes de qualquer cláusula WHERE na consulta do usuário. Como os widgets roxos são excluídos pela exibição, a consulta do usuário nunca gera um erro de divisão por zero.

Se a exibição não fosse segura, o otimizador do Snowflake poderia reordenar os predicados nas cláusulas WHERE. Isso poderia permitir que o predicado na consulta do usuário fosse executado primeiro, o que permitiria a ocorrência do erro de divisão por zero.

Práticas recomendadas para a utilização de exibições seguras

Exibições seguras evitam que os usuários sejam possivelmente expostos a dados de linhas de tabelas que são filtradas pela exibição. Entretanto, ainda há maneiras de um proprietário de dados poder inadvertidamente expor informações sobre os dados subjacentes se as exibições não forem construídas com cuidado. Esta seção discute algumas armadilhas potenciais a serem evitadas.

Para ilustrar essas armadilhas, esta seção utiliza as tabelas de exemplo widgets e a exibição definida nos exemplos anteriores neste tópico.

Colunas geradas por sequências

Uma prática comum para gerar chaves alternativas é usar uma sequência ou coluna de incremento automático. Se essas chaves forem expostas a usuários que não têm acesso a todos os dados subjacentes, um usuário poderá conseguir adivinhar detalhes da distribuição dos dados subjacentes. Por exemplo, widgets_view expõe a coluna ID. Se a ID for gerada a partir de uma sequência, um usuário de widgets_view poderia deduzir o número total de widgets criados entre os carimbos de data/hora de criação de dois widgets aos quais o usuário tem acesso. Considere a seguinte consulta e resultado:

select * from widgets_view order by created_on;

------+-----------------------+-------+-------+-------------------------------+
  ID  |         NAME          | COLOR | PRICE |          CREATED_ON           |
------+-----------------------+-------+-------+-------------------------------+
...
 315  | Small round widget    | Red   | 1     | 2017-01-07 15:22:14.810 -0700 |
 1455 | Small cylinder widget | Blue  | 2     | 2017-01-15 03:00:12.106 -0700 |
...
Copy

Com base no resultado, o usuário pode suspeitar que 1139 widgets (1455 - 315) foram criados entre 7 e 15 de janeiro. Se essa informação for sensível demais para expor aos usuários de uma exibição, você pode usar qualquer uma das alternativas a seguir:

  • Não expor a coluna gerada por sequências como parte da exibição.

  • Usar identificadores aleatórios (por exemplo, gerados por UUID_STRING) em vez de valores gerados por sequência.

  • Ofuscar programaticamente os identificadores.

Tamanho dos dados verificados

Para consultas contendo exibições seguras, o Snowflake não expõe a quantidade de dados percorridos (seja em termos de bytes ou micropartições) ou a quantidade total de dados. Isso é feito para proteger as informações dos usuários que só têm acesso a um subconjunto dos dados. Entretanto, os usuários ainda podem conseguir fazer suposições sobre a quantidade de dados subjacentes com base nas características de desempenho das consultas. Por exemplo, uma consulta executada no dobro do tempo pode processar o dobro de dados. Embora tais observações sejam aproximadas no melhor dos casos, em alguns casos, pode ser indesejável que até mesmo esse nível de informação seja exposto.

Nesses casos, é melhor materializar os dados por usuário/função em vez de expor exibições dos dados de base aos usuários. No caso da tabela widgets, seria criada uma tabela para cada função que tivesse acesso aos widgets, contendo apenas os widgets acessíveis por essa função, e uma função teria acesso à tabela correspondente. Isso é muito mais trabalhoso do que usar uma única exibição, mas para situações de segurança extremamente alta, isso pode ser justificado.

Exibições seguras e compartilhamento de dados

Ao utilizar exibições seguras com Secure Data Sharing, use a função CURRENT_ACCOUNT para autorizar usuários de uma conta específica a acessar linhas em uma tabela base.

Nota

Ao usar as funções CURRENT_ROLE e CURRENT_USER com exibições seguras que serão compartilhadas com outras contas Snowflake, o Snowflake retorna um valor NULL para essas funções. A razão é que o proprietário dos dados que estão sendo compartilhados geralmente não controla os usuários ou funções na conta com a qual a exibição está sendo compartilhada.