Práticas recomendadas de RLS para fontes de dados e pastas de trabalho
A segurança em nível de linha (RLS) no Tableau restringe as linhas de dados que determinado usuário pode ver em uma pasta de trabalho. É diferente das permissões do Tableau, que controlam o acesso ao conteúdo e à funcionalidade dos recursos. Por exemplo, as permissões controlam se um usuário pode comentar ou editar uma pasta de trabalho, enquanto a segurança em nível de linha permite que dois usuários visualizem o mesmo painel para ver apenas os dados que cada usuário tem permissão.
Há várias maneiras de implementar a RLS no Tableau. Por exemplo, você pode definir a RLS no nível da fonte de dados ou da pasta de trabalho ou pode definir a RLS no nível da conexão usando uma conexão virtual com uma política de dados (requer Data Management). Consulte a Visão geral das opções de segurança em nível de linha no Tableau para obter detalhes sobre alternativas.
Observação: este tópico se concentra nas práticas recomendadas de RLS para fontes de dados e pastas de trabalho. Para obter exemplos mais detalhados dos conceitos descritos neste tópico, consulte o whitepaper Práticas recomendadas para segurança em nível de linha(O link abre em nova janela) ou Como configurar o banco de dados para segurança em nível de linha no Tableau(O link abre em nova janela) no blog Tableau and Behold.
Fluxo de trabalho de RLS
Para conexões em tempo real e extrações de várias tabelas, o fluxo de trabalho básico de RLS é o seguinte:
- O usuário é identificado ao fazer logon no Tableau Server ou no Tableau Cloud
- Isso requer um nome de usuário diferente por usuário e um logon único (SSO) seguro
- A REST API do Active Directory, LDAP ou Tableau Server pode ser usada para sincronizar os nomes de usuário e estabelecer as permissões
- O conjunto de direitos de dados do usuário é recuperado em todos os direitos de dados possíveis
- Isso requer uma estrutura de dados que possa vincular os direitos ao nome de usuário do Tableau
- Os dados são filtrados pelos direitos desse usuário
- Geralmente, isso exige o uso das funções de usuário em um campo calculado
- Os dados publicados e filtrados são usados para criar conteúdo
- O uso de uma fonte de dados publicada (em vez de inserida) com um filtro de fonte de dados garante que o RLS não possa ser modificado ao baixar ou editar a pasta de trabalho
A forma como as uniões de colunas, campos calculados e filtros são configurados depende da estrutura dos dados e da forma como os usuários são gerenciados.
Tabelas de direitos
Qualquer combinação única de atributos em que os dados possam ser filtrados constitui um direito. Mais comumente, existem tabelas separadas para especificar os direitos em si e mapear esses direitos para os usuários ou funções de usuário. A desnormalização é recomendada do ponto de vista do desempenho, pois as uniões de colunas são operações caras.
A exibição de direitos, que consiste nos direitos mapeados para os usuários ou as funções, é unida com os dados. Um filtro de fonte de dados baseado no usuário é aplicado, atuando como uma cláusula WHERE que traz apenas os direitos e - portanto, as linhas de dados apropriadas - para o usuário relevante. (A otimização de consultas deve garantir que a filtragem ocorra antes da união de colunas quando a consulta é processada para minimizar a duplicação de dados. Para obter mais informações, consulte a Ordem de operações de desempenho e processamento.)
Modelos de tabela de direitos
Geralmente, existem dois modelos para representar direitos:
Mapeamento completo até o nível de granularidade mais profunda
- Os direitos são definidos integralmente para cada coluna.
- Há uma linha na tabela de mapeamento para todos os direitos possíveis que o usuário tem.
- Esse modelo requer menos cláusulas de união.
Direitos esparsos
- Os direitos são definidos para todos os níveis de hierarquia e NULL é usado para representar um estado de “todos”.
- Há uma única linha na tabela de mapeamento para determinado nível na hierarquia de direitos, o que reduz consideravelmente o número de linhas de direitos para usuários em níveis elevados em uma hierarquia.
- Esse modelo requer uniões de colunas e filtros mais complexos.
Usuários e funções
As combinações de direitos são comumente representadas como funções, que são vinculadas aos usuários em uma tabela de mapeamento de muitos para muitos. Isso permite alterar ou remover facilmente um usuário da função e, ao mesmo tempo, manter um registro da função e seus direitos.
Como alternativa, uma tabela de mapeamento de muitos para muitos pode ser criada que, em vez disso, atribui os usuários diretamente aos direitos e não passa pela união de colunas em uma tabela de funções. Isso requer o gerenciamento de valores mais direto na tabela, mas elimina uma união de colunas.
Observação: os valores do usuário associados a uma função ou direito precisam corresponder ao nome de usuário ou nome completo no site do Tableau para aproveitar as funções de usuário no Tableau Desktop.
Uniões de colunas
Independentemente do modelo usado para representar os direitos, é aconselhável unir colunas em todos os direitos e tabelas de mapeamento para uma única exibição de direitos desnormalizados. Embora a princípio isso cause uma versão “explosiva” (altamente duplicativa) dos direitos, o filtro de fonte de dados no usuário o reduzirá novamente. Você também vai querer essa exibição se planejar usar uma extração.
O método de granularidade mais profunda pode ter um benefício de desempenho quando tudo é hierárquico - basta fazer uma única união de colunas no nível mais profundo da hierarquia. Isso só funciona se todos os atributos no nível mais baixo forem distintos. Se houver uma chance de duplicação (por exemplo, uma sub-região Central em mais de uma região), você precisará unir todas as colunas para alcançar o efeito de um valor-chave distinto.
Os detalhes reais e suas características de desempenho dependem do sistema de dados e exigem testes. Por exemplo, usar uma única chave pode melhorar potencialmente o desempenho, pois a união de colunas está sendo executada apenas em uma coluna, mas a indexação correta de todas as colunas pode resultar no mesmo desempenho quando outros fatores são levados em consideração.
Implementar a segurança em nível de linha
Granularidade mais profunda
Após criada a exibição desnormalizada dos direitos mapeados, uma união de colunas interna é configurada entre a exibição e os dados na caixa de diálogo de conexão de dados do Tableau. Os dados podem permanecer em um esquema de estrela tradicional. Como alternativa, as tabelas de dimensões e fatos podem ser materializadas juntas em duas exibições. As extrações de várias tabelas criarão tabelas de extração para corresponder às uniões de colunas, portanto, a criação de duas exibições simplificará a extração resultante. O SQL seguirá este padrão básico:
SELECT * FROM data d INNER JOIN entitlements e ON d.attribute_a = e.attribute_a AND d.attribute_b = e.attribute_b AND ... WHERE e.username = USERNAME()
Direitos esparsos
Se os direitos são mais semelhantes ao modelo de direitos esparsos, o SQL personalizado para unir colunas de dados aos direitos seria um pouco mais complexo devido aos valores NULL. Conceitualmente, seria parecido com o seguinte:
SELECT * FROM data d INNER JOIN entitlements e ON (e.region_id = d.region_id OR ISNULL(e.region_id) AND (e.sub_region_id = d.sub_region_id OR ISNULL(e.sub_region_id) AND (e.country_id = d.country_id OR ISNULL(e.country_id)
Sem o uso de SQL personalizado, isso pode ser realizado com uma união de colunas cruzada e filtros adicionais no Tableau Desktop. Crie um cálculo de união de colunas nos dois lados da caixa de diálogo da união de colunas, que consiste simplesmente no número inteiro 1, e defina-os como iguais. Essa ação une colunas de todas as linhas da tabela de dados a todas as linhas da tabela de direitos.
Então é necessário um cálculo (ou cálculos individuais) para explicar os níveis na hierarquia. Por exemplo, você pode ter vários cálculos que seguem este formato: [region_id] = [region_id (Entitlements View)] OR ISNULL([region_id (Entitlements View)]
Ou você pode ter um cálculo combinado para todos os níveis em um:
([region_id] = [region_id (Entitlements View)] OR ISNULL([region_id (Entitlements View)]) AND ([sub_region_id] = [sub_region_id (Entitlements View)] OR ISNULL([sub_region_id (Entitlements View)]) AND ([country_id] = [country_id (Entitlements View)] OR ISNULL([country_id (Entitlements View)])
A função ISNULL corresponde a qualquer coluna de direitos para todos os itens da outra coluna. Como sempre ocorre com a RLS, esses cálculos devem ser adicionados como filtros de fonte de dados.
Filtros de fonte de dados
Para ambas as abordagens, depois que as colunas de direitos e dados foram unidas corretamente, um filtro precisa ser configurado para limitar os dados para um usuário específico. Um campo calculado deve ser criado com uma função de usuário. Por exemplo, uma comparação booliana simples para ver se o usuário listado no campo Nome de usuário é o mesmo Nome de usuário da pessoa conectada no site do Tableau: [Username] = USERNAME()
Esse cálculo deve ser usado como filtro de fonte de dados (onde TRUE é selecionado).
Se a fonte de dados for inserida e um usuário tiver permissões para editar na Web ou baixar a pasta de trabalho, a RLS não existe pois os filtros que a impõem podem ser facilmente removidos. A fonte de dados do Tableau deve ser publicada separadamente, em vez de ser inserida na pasta de trabalho.
Acesso integral com granularidade mais profunda
Há também um cenário comum em que existem dois níveis de acesso dentro da organização: pessoas que podem ver tudo (“acesso integral”) ou pessoas com algum subconjunto de direitos consideravelmente definível. Isso é observado mais comumente para aplicativos inseridos - a organização que hospeda os dados pode ver tudo, mas cada cliente só pode ver seus próprios dados. Nesse caso, você precisa de uma maneira de devolver os dados completos para os usuários com “acesso integral”, mantendo as uniões de colunas de granularidade mais profunda para todos os outros usuários.
Para essa técnica, você usará os grupos do Tableau para criar uma substituição, usando um cálculo na condição de união.
- Crie um grupo para usuários que devem ver todos os dados (aqui chamado de Acesso integral)
- Na exibição de fatos, crie uma união esquerda com duas condições de união
- A primeira condição de união deve estar na coluna que representa o nível de granularidade mais profunda
- A segunda condição de união deve ter dois cálculos:
- No lado esquerdo (a exibição de fatos), para o cálculo, digite
True
- No lado direito (a exibição de direitos), o cálculo deve ser:
IF ISMEMBEROF('All Access') THEN False ELSE True END
- No lado esquerdo (a exibição de fatos), para o cálculo, digite
- Em uma planilha, crie um cálculo estruturado como:
[Username] = USERNAME() OR ISMEMBEROF(['All Access'] ([Entitlements View)])
- Crie um filtro de fonte de dados no cálculo do nome de usuário
Se um usuário for membro do grupo de Acesso integral, a união de colunas se torna uma união esquerda em True = False
. Isso significa que não há correspondências na exibição de direitos, portanto, toda a exibição de fatos é devolvida com NULLs para as colunas da exibição de direitos (duplicação zero). No caso em que o usuário não faz parte do grupo de Acesso integral, a condição de união True = True
não muda nada e a união de colunas funcionará como esperado.
O cálculo do usuário usado como filtro de fonte de dados é true para todas as linhas, quando a substituição de grupo está funcionando, ou filtrará apenas a granularidade mais profunda do usuário na hierarquia.
Ordem de operações de desempenho e processamento
Quando uma visualização é feita no Tableau Desktop, Tableau Server ou Tableau Cloud, o Tableau envia uma consulta otimizada para o RDBMS, que processa a consulta e devolve os resultados ao Tableau, para renderizar a visualização com os dados resultantes. A ordem de operações de quando as uniões de colunas, cálculos e filtros são realizados depende do otimizador de consultas e de como a consulta é executada.
Conexões em tempo real
Ao usar uma conexão em tempo real com uma fonte de dados no Tableau, o desempenho da execução de consultas depende do otimizador de consultas que traduz o SQL de entrada em um plano eficiente para recuperar os dados.
Há duas maneiras de processar a consulta:
- Filtrar as linhas de direitos para o usuário e depois unir colunas para a tabela de fatos
- Unir colunas de direitos para a tabela de fatos e depois filtrar para as linhas do usuário
Em uma situação ideal, o otimizador de consultas garantirá que o banco de dados processe a consulta filtrando e depois unindo colunas. Se um usuário tiver direito a tudo, isso significa que o número máximo de linhas processadas será o número de linhas na tabela de dados.
Se o banco de dados processar a consulta unindo colunas e depois filtrando, pode haver duplicação de dados. O número máximo de linhas processadas será o número de usuários autorizados a ver essa linha específica vezes cada linha na tabela de dados.
Ficará claro se esse segundo cenário acontecer: as consultas levam muito tempo para terminar, você recebe erros ou há uma indicação de problemas de desempenho no banco de dados. O volume total de dados aumentará exponencialmente, o que pode causar uma sobrecarga excessiva no sistema no back-end.
Extrações
Quando a fonte de dados no Tableau é uma conexão em tempo real, o Tableau envia todas as consultas necessárias para renderizar uma visualização ou painel específico para o RDBMS. Quando a fonte de dados é uma extração, o processo de consulta de dados da fonte de dados subjacente só acontece na criação e atualização de extração. Todas as consultas individuais para visualizações são respondidas pelo mecanismo de extração do arquivo de extração.
O mesmo problema da ordem de operações está presente na criação de extrações de tabela única. No entanto, a “explosão” acontecerá na fonte de dados subjacente e dentro da própria extração resultante.
Considerações sobre extrações
A partir da versão 2018.3, o processador de dados pode criar uma extração de várias tabelas e a RLS pode ser implementada conforme descrito acima. O uso de extrações de várias tabela reduz o tempo necessário para gerar uma extração com relações de muitos para muitos, não materializando a união de colunas.
A extração deve ser criada com um objeto de dados e um objeto de direitos. Este é o armazenamento mais simples na extração e resulta no melhor desempenho.
- O objeto de dados é a tabela, exibição ou consulta de SQL personalizado que representa a combinação desnormalizada das tabelas de fatos e dimensões necessárias
- O objeto de direitos é uma tabela, exibição ou consulta de SQL personalizado desnormalizada de quaisquer direitos necessários para filtrar os dados no nível mais granular, o que requer:
- Uma coluna para o nome de usuário que corresponda aos nomes de usuário exatos no Tableau Server ou no Tableau Cloud
- Uma linha para cada um dos direitos mais granulares para o objeto de dados
Esse formato é apresentado no método de granularidade mais profunda acima. As extrações de várias tabelas usam o mesmo método, com a ressalva de que as colunas de apenas dois objetos de dados estão sendo unidas e qualquer filtragem específica de campo já é aplicada no objeto.
Como os filtros das extrações de várias tabelas são desativados, você pode filtrar as extrações ou tabelas conectadas na fonte de dados ou definir os filtros nos objetos de SQL personalizado na caixa de diálogo de conexão de dados do Tableau.
Observação: como ocorre com as conexões em tempo real, se a fonte de dados for inserida e um usuário tiver permissões para editar na Web ou baixar a pasta de trabalho, a RLS não existe pois os filtros que a impõem podem ser facilmente removidos. A extração deve ser publicada separadamente, em vez de ser inserida na pasta de trabalho.
Extrações de tabela única
O seguinte método é recomendado somente ao usar uma versão do Tableau anterior a 2018.3 - as extrações de várias tabelas são preferenciais, se disponíveis.
As extrações de tabela única materializam as uniões de colunas criadas ao construir a fonte de dados do Tableau e armazena tudo como uma tabela única por meio de uma consulta e os resultados são transformados em uma tabela única no arquivo de extração. Essa desnormalização acarreta o risco de causar uma enorme duplicação de dados, já que cada linha que foi alocada para mais de um direito ou usuário seria duplicada como resultado da relação de muitos para muitos.
Para evitar essa duplicação:
- Crie um Campo de usuários de segurança que contenha os nomes de usuário para esse direito
- por exemplo, um valor pode ser “bhowell|mosterheld|rdugger”
- Use a função CONTAINS() no Tableau para identificar usuários individuais corretamente
- Por exemplo,
CONTAINS([Security Users Field], USERNAME())
- Por exemplo,
Obviamente, esse método tem algumas ressalvas. Ele exige que você acesse seus direitos nas linhas para uma única coluna separada corretamente usando SQL e essa coluna só pode conter tantos caracteres. Correspondências parciais podem se tornar problemas e você precisa usar separadores que nunca serão válidos nas IDs em si. Embora tenha um bom desempenho no Processador de dados do Tableau, como cálculo de cadeia de caracteres, será muito lento para a maioria dos bancos de dados. Isso limita a capacidade de voltar a uma conexão em tempo real.
Como alternativa, você pode usar diferentes extrações por “função” ou nível de direito, para que apenas os dados apropriados para essa pessoa ou nível estejam incluídos na extração, mas isso exigirá processos de permissão adequados e aproveitará a publicação de modelos no Tableau Server, geralmente por meio de APIs.
Usar segurança em nível de linha integrada em um banco de dados
Muitos bancos de dados têm mecanismos para RLS integrada. Se sua organização já criou a segurança em nível de linha em uma fonte de dados, você poderá tirar proveito da RLS existente. Não é necessariamente mais fácil ou melhor implementar um modelo de RLS integrada, em comparação a criá-la tendo em mente o Tableau. Geralmente, essas técnicas são utilizadas quando uma organização já investiu nessas tecnologias e querem aproveitar o investimento. O principal benefício de usar a RLS integrada é que os administradores podem implementar e controlar a respectiva política de segurança de dados em um local: nos respectivos bancos de dados. Para obter mais informações, consulte Segurança em nível de linha no banco de dados.