Controle de acesso e roles
O modelo de controle de acesso do Mondrian permite dividir seu schema em roles. Uma role é um conjunto nomeado de grants e denials que cobre todo o schema — de quais cubos são visíveis até quais membros individuais um usuário tem permissão de ver. Você define roles diretamente no arquivo de schema, e o Saiku Cloud as aplica quando estabelece uma conexão em nome de um usuário.
Definir uma role
Elementos <Role> são filhos diretos de <Schema>, colocados após o último <Cube>. Aqui está um exemplo completo:
- name: "California manager" schema_grant: access: "none" cubes: - cube: "Sales" access: "all" dimensions: - dimension: "[Measures]" access: "all" hierarchies: - hierarchy: "[Store]" access: "custom" top_level: "[Store].[Store Country]" members: - member: "[Store].[USA].[CA]" access: "all" - member: "[Store].[USA].[CA].[Los Angeles]" access: "none" - hierarchy: "[Customers]" access: "custom" top_level: "[Customers].[State Province]" bottom_level: "[Customers].[City]" members: - member: "[Customers].[USA].[CA]" access: "all" - member: "[Customers].[USA].[CA].[Los Angeles]" access: "none" - hierarchy: "[Gender]" access: "none"<Role name="California manager"> <SchemaGrant access="none"> <CubeGrant cube="Sales" access="all"> <DimensionGrant dimension="[Measures]" access="all"/>
<HierarchyGrant hierarchy="[Store]" access="custom" topLevel="[Store].[Store Country]"> <MemberGrant member="[Store].[USA].[CA]" access="all"/> <MemberGrant member="[Store].[USA].[CA].[Los Angeles]" access="none"/> </HierarchyGrant>
<HierarchyGrant hierarchy="[Customers]" access="custom" topLevel="[Customers].[State Province]" bottomLevel="[Customers].[City]"> <MemberGrant member="[Customers].[USA].[CA]" access="all"/> <MemberGrant member="[Customers].[USA].[CA].[Los Angeles]" access="none"/> </HierarchyGrant>
<HierarchyGrant hierarchy="[Gender]" access="none"/> </CubeGrant> </SchemaGrant></Role>As seções abaixo explicam cada elemento em detalhe.
<SchemaGrant>
<SchemaGrant> define o acesso default ao schema inteiro. Seu atributo access pode ser:
| Valor | Significado |
|---|---|
all | A role pode ver cada cubo e dimensão no schema. |
all_dimensions | A role pode ver todas as dimensões, mas ainda precisa de entradas <CubeGrant> explícitas para acessar os dados de qualquer cubo. |
none | A role não pode ver nada a menos que seja explicitamente concedido. |
No exemplo acima, access="none" significa que o usuário pode navegar somente pelo cubo “Sales”, porque é o único explicitamente concedido.
<CubeGrant>
<CubeGrant> controla acesso a um cubo específico. Seu atributo access pode ser:
| Valor | Significado |
|---|---|
all | Acesso completo ao cubo e a todas as suas dimensões e hierarquias. |
custom | O acesso é definido pelos elementos filhos <DimensionGrant> e <HierarchyGrant>. |
none | O cubo é escondido da role. |
<DimensionGrant>
<DimensionGrant> controla acesso a uma dimensão inteira dentro de um cubo. Seu atributo access pode ser:
| Valor | Significado |
|---|---|
all | Todas as hierarquias filhas desta dimensão são acessíveis. |
custom | Sem acesso inerente às hierarquias filhas — cada hierarquia deve ser concedida separadamente usando <HierarchyGrant>. |
none | A dimensão é escondida. |
O atributo dimension recebe o nome único MDX da dimensão (por exemplo "[Measures]" ou "[Store]").
<HierarchyGrant>
<HierarchyGrant> controla acesso a uma hierarquia, opcionalmente restringindo os levels e membros visíveis.
| Atributo | Obrigatório | Descrição |
|---|---|---|
hierarchy | sim | Nome único MDX da hierarquia, ex. "[Store]". |
access | sim | "all", "custom" ou "none". |
topLevel | não | Nome único MDX do level mais alto visível. Membros acima deste level são escondidos. |
bottomLevel | não | Nome único MDX do level mais baixo visível. Membros abaixo deste level são escondidos. |
rollupPolicy | não | Como calcular totais quando alguns filhos estão escondidos. Veja Política de rollup. |
Valores de access
| Valor | Significado |
|---|---|
all | Cada membro é visível. |
none | A hierarquia é escondida da role. |
custom | A visibilidade é controlada por topLevel, bottomLevel e/ou filhos <MemberGrant>. |
<MemberGrant>
<MemberGrant> concede ou nega acesso a um membro específico e todos os seus filhos. Você só pode usar <MemberGrant> quando o <HierarchyGrant> que o envolve tem access="custom".
| Atributo | Obrigatório | Descrição |
|---|---|---|
member | sim | Nome único MDX do membro, ex. "[Store].[USA].[CA]". |
access | sim | "all" ou "none". |
Regras para member grants
Member grants interagem de uma forma específica quando múltiplos grants se aplicam à mesma hierarquia:
- Membros herdam acesso dos seus pais. Negar acesso à Califórnia automaticamente nega acesso a San Francisco.
- Grants dependem da ordem. Se você conceder acesso aos EUA e depois negar Oregon, Oregon fica escondido. Se você negar Oregon primeiro e depois conceder EUA, tudo fica visível. Ordem importa.
- Um membro é visível se algum dos filhos for visível. Se você negar EUA mas conceder Califórnia, verá EUA e Califórnia — mas nenhum outro estado. Nota: totais para EUA sob a política de rollup
fullainda refletem todos os estados (veja Política de rollup). Se umtopLevelfor definido, só pais nesse level ou abaixo são mostrados. - Member grants não sobrescrevem
topLevelebottomLevel. SetopLevel="[Store].[Store State]"está definido e você concede Califórnia, ainda não pode ver o level EUA.
Walkthrough do exemplo
Com a role “California manager” do exemplo de abertura, o usuário pode:
- Ver Califórnia e todas as cidades na Califórnia exceto Los Angeles.
- Ver EUA (porque Califórnia, um filho visível, torna o pai visível), mas nenhum outro país.
- Não ver “All Stores” porque fica acima do
topLevelde Store Country. - Não ver clientes fora da faixa State Province até City, e não Los Angeles.
- Não ver a hierarquia Gender de jeito nenhum.
Row security baseada em predicado (<PredicateGrant>)
Member grants restringem quais membros de dimensão uma role pode ver. Às vezes você precisa restringir as próprias linhas de fato por um valor de coluna que rastreia o usuário solicitante — row-level security multi-tenant clássica ou o access_filter do Looker. Para isso, o Saiku adiciona um <PredicateGrant> (uma extensão do Saiku ao Mondrian 4, issue #106): ele vincula uma role a um filtro em uma coluna real de fato, com valor vindo do parâmetro de consulta da conexão.
<Role name="Regional"> <SchemaGrant access="all"/> <PredicateGrant measureGroup="Sales" column="region" operator="eq" parameter="region"/></Role>O backend Calcite injeta o predicado como um filtro WHERE em cada carregamento de segmento do measure group nomeado, pré-agregação, para que totais — não só linhas folha — sejam corretamente restritos, e o resultado por role seja isolado no cache de segmento. Um parâmetro não vinculado falha fechado (zero linhas), nunca irrestrito. operator é eq (igualdade) ou in (membership).
Política de rollup
Uma política de rollup determina qual valor o Mondrian mostra para um membro pai quando a role atual não pode ver todos os seus filhos.
| Política | Significado |
|---|---|
full | O total do pai inclui todos os filhos, visíveis ou não. Este é o default. |
partial | O total do pai inclui apenas os filhos acessíveis. |
hidden | Se algum filho for inacessível, o total do pai é suprimido. |
Exemplo: efeito de cada política
Suponha que uma role pode ver [USA].[CA] e [USA].[OR] mas não [USA].[WA] e roda:
SELECT {[Measures].[Unit Sales]} ON COLUMNS, {[Store].[USA], [Store].[USA].Children} ON ROWSFROM [Sales]Full (default) — o total de [USA] inclui as 124.366 unidades de Washington:
| Membro | Unit Sales |
|---|---|
[USA] | 266,773 |
[USA].[CA] | 74,748 |
[USA].[OR] | 67,659 |
Partial — o total de [USA] reflete apenas CA e OR:
| Membro | Unit Sales |
|---|---|
[USA] | 142,407 |
[USA].[CA] | 74,748 |
[USA].[OR] | 67,659 |
Hidden — o total de [USA] é suprimido porque ao menos um filho é inacessível:
| Membro | Unit Sales |
|---|---|
[USA] | — |
[USA].[CA] | 74,748 |
[USA].[OR] | 67,659 |
Especificar a política de rollup
O atributo rollupPolicy fica em <HierarchyGrant>. Você pode aplicar políticas diferentes a hierarquias diferentes na mesma role:
- name: "South Pacific manager" schema_grant: access: "none" cubes: - cube: "Sales" access: "all" hierarchies: - hierarchy: "[Store]" access: "custom" top_level: "[Store].[Store Country]" rollup_policy: "partial" members: - member: "[Store].[USA].[CA]" access: "all" - member: "[Store].[USA].[CA].[Los Angeles]" access: "none" - hierarchy: "[Customers]" access: "custom" top_level: "[Customers].[State Province]" bottom_level: "[Customers].[City]" rollup_policy: "full" members: - member: "[Customers].[USA].[CA]" access: "all" - member: "[Customers].[USA].[CA].[Los Angeles]" access: "none" - hierarchy: "[Gender]" access: "none"<Role name="South Pacific manager"> <SchemaGrant access="none"> <CubeGrant cube="Sales" access="all"> <HierarchyGrant hierarchy="[Store]" access="custom" rollupPolicy="partial" topLevel="[Store].[Store Country]"> <MemberGrant member="[Store].[USA].[CA]" access="all"/> <MemberGrant member="[Store].[USA].[CA].[Los Angeles]" access="none"/> </HierarchyGrant>
<HierarchyGrant hierarchy="[Customers]" access="custom" rollupPolicy="full" topLevel="[Customers].[State Province]" bottomLevel="[Customers].[City]"> <MemberGrant member="[Customers].[USA].[CA]" access="all"/> <MemberGrant member="[Customers].[USA].[CA].[Los Angeles]" access="none"/> </HierarchyGrant>
<HierarchyGrant hierarchy="[Gender]" access="none"/> </CubeGrant> </SchemaGrant></Role>Union roles
Uma union role combina os privilégios de duas ou mais roles existentes. O resultado tem o acesso menos restritivo entre todas as suas roles constituintes: a union role pode ver qualquer objeto do schema que pelo menos uma role constituinte possa ver, e sua política de rollup para uma dada hierarquia é a política menos restritiva entre todas as constituintes.
<Role name="Coastal manager"> <Union> <RoleUsage roleName="California manager"/> <RoleUsage roleName="Eastern sales manager"/> </Union></Role>As roles constituintes devem ser declaradas antes no arquivo de schema. Elas podem ser roles regulares, outras union roles ou roles custom baseadas em classe. A union role “Coastal manager” pode ver qualquer membro acessível por qualquer constituinte, e também pode ver células na intersecção de membros que só uma role pode ver.
Definir a role de uma conexão
Uma role entra em vigor quando é associada a uma conexão. Por default, conexões têm uma role irrestrita que pode ver cada cubo no schema. Há duas formas de ativar uma role específica:
Na connect string
Inclua a palavra-chave Role na string de conexão do Mondrian. O Saiku Cloud define isso em nome dos seus usuários com base na configuração do seu tenant:
Provider=mondrian; Role="California manager";Jdbc=jdbc:postgresql://host/db; JdbcUser=user; JdbcPassword=pw;Catalog=/WEB-INF/MySchema.mondrian.xmlPara ativar múltiplas roles de uma vez (criando uma union ad-hoc), separe os nomes com vírgulas. Se um nome de role em si contém uma vírgula, escape-a com uma vírgula dupla.
Programaticamente
Se você está embutindo o Mondrian diretamente, chame Connection.setRole(Role) após abrir uma conexão, ou consulte uma role nomeada com Schema.lookupRole(String).
Role default
Você pode marcar uma role como o default no seu schema usando o atributo defaultRole em <Schema>. Qualquer conexão que não especifique explicitamente uma role usará este default:
<Schema name="FoodMart" defaultRole="California manager"> ...</Schema>Roles em schemas YAML
Se você escreve seu schema em formato YAML, roles são declaradas sob a chave top-level roles. Cada entrada mapeia para um elemento <Role>. Veja a referência de schemas YAML para a sintaxe completa de roles, incluindo chaves schema_grant, cubes, hierarchies, members, rollup_policy, top_level e bottom_level.
Um exemplo rápido:
roles: - name: "California manager" schema_grant: access: "none" cubes: - cube: "Sales" access: "all" hierarchies: - hierarchy: "[Store].[Stores]" access: "custom" top_level: "[Store].[Stores].[Store Country]" members: - member: "[Store].[Stores].[USA].[CA]" access: "all" - member: "[Store].[Stores].[USA].[CA].[Los Angeles]" access: "none"
- name: "No HR Cube" schema_grant: access: "all" cubes: - cube: "HR" access: "none"Adaptado do guia de schema do projeto Mondrian (EPL v1.0).