Ir para o conteúdo

Blogue ·

Painéis white-label: o que o cliente vê

Pôr o seu nome num painel de revenda é a metade fácil. A difícil é decidir que ecrãs sequer existem para o seu cliente, e depois impor essa decisão.

Por Provibr

Quem revende VPS ou alojamento acaba por ter clientes que querem um painel. Querem reiniciar a própria máquina às duas da manhã em vez de abrirem um pedido de assistência, e o revendedor quer exatamente o mesmo.

Daí saem duas perguntas que parecem uma só e não são. Quem tem o nome no painel, e que partes do painel sequer existem para essa pessoa. A primeira é marca, e é sobretudo apresentação. A segunda é uma fronteira, e é ao errá-la que um cliente seu acaba a ler a fatura do seu fornecedor.

A marca acaba onde começam os documentos

Mudar a marca de um painel significa mudar a moldura: o logótipo na barra lateral, o título da página, o ícone do separador, o nome no bloco da conta. Já é bastante, e é onde a maioria das funcionalidades white-label para.

A parte interessante é a lista das coisas que nunca podem levar o nome do revendedor.

EcrãQue nome levaPorquê
Moldura do painel, títulos, íconeO revendedorA relação em que o cliente está
Declaração de privacidadeA plataformaUm aviso de tratamento descreve quem trata de facto
Termos e condiçõesA plataformaÉ o contrato da plataforma, não o do revendedor
Contrato de tratamento de dadosA plataformaO mesmo, e nomeia subcontratantes
Faturas e documentos proformaA plataformaÉ o registo financeiro de uma transação real
A linha num extrato bancárioA plataformaUm registo permanente que ninguém pode anotar depois

O raciocínio cabe numa frase: um cliente do seu cliente nunca pode passar a acreditar que tem um contrato com alguém que não seja a parte com quem o tem de facto. Tudo o que tenha caráter jurídico ou financeiro leva o nome da contraparte desse documento, e isso não é uma preferência de desenho.

Mais importante do que a regra é o sítio onde ela vive. No nosso código é uma lista de caminhos de ficheiros, e um teste percorre a árvore de importações transitiva a partir de cada um deles, falhando no momento em que um consiga sequer chegar ao módulo da marca. Em largura primeiro, para que o erro nomeie a cadeia mais curta, que é a que se deve cortar.

Uma verificação de importação direta é fácil de contornar: põe-se a consulta da marca num auxiliar, importa-se o auxiliar, pronto. E a salvaguarda testa-se a si própria nos dois sentidos. Um caminho listado que desapareça é um erro em vez de uma passagem silenciosa, e o teste afirma separadamente que a moldura do painel chega de facto ao módulo da marca, porque um resolvedor que em silêncio não resolvesse nada marcaria todos os ficheiros a verde.

O início de sessão do próprio revendedor nunca muda de marca

Existe uma segunda regra menos óbvia, e que teríamos errado sem a enunciar: a marca aplica-se apenas no domínio do próprio cliente.

Quando o revendedor inicia sessão no anfitrião da própria plataforma, vê a plataforma e não a sua própria marca. É aí que vivem as faturas, a subscrição e a relação connosco. A consulta da marca recorre ao aspeto simples no momento em que um pedido não está associado a um domínio de conta, pelo que há exatamente um sítio que decide e nenhum ecrã tem de se lembrar.

O ecrã de gestão da marca mostra uma pré-visualização da moldura que o cliente vê, em vez de mudar de marca a si próprio. Isso parece pedante até se pensar no que a alternativa ensina: um revendedor que vê o seu próprio logótipo por cima da sua própria fatura conclui, com razão, que os seus clientes veem algo semelhante.

Um logótipo branco numa barra lateral branca

O fundo do nosso painel é branco, pelo que um logótipo com fundo transparente e tinta branca é invisível, e quem o carrega não vai descobrir: está a olhar para ele numa ferramenta de desenho, sobre uma prancha cinzenta.

Medimos em vez de adivinhar, compondo cada logótipo sobre a cor real da superfície num navegador sem interface:

LogótipoContraste com a superfície do painel
Tinta escura, fundo transparente16,46:1
Tinta branca, fundo transparente1,00:1
Tinta branca sobre a sua própria placa opaca17,74:1
Tinta cinzenta-clara1,24:1

A linha de 1,00:1 não é «difícil de ler». Todos os pixéis são idênticos ao fundo. O logótipo é desenhado e não há nada para ver.

Daí saíram duas decisões. Não há deliberadamente nenhuma placa por baixo do logótipo, porque isso voltaria a desenhar a marca do cliente e daria uma moldura a todos os logótipos normais para salvar uma exceção. E o ecrã de carregamento avisa em vez de recusar, porque uma marca tem o direito de ser cinzenta-clara.

A medição conta a tinta, não a sobreposição. Um logótipo com uma grande margem transparente coincide com o fundo na maior parte da sua área e é perfeitamente visível; o que importa é que parte dele é desenhada e a que distância essa tinta está da cor da superfície.

A ausência não é uma permissão

Agora a metade mais difícil. Que ecrãs devem existir para um cliente de um revendedor?

O instinto é modelar isto como permissões: dar um papel ao subcliente, assinalar menos caixas. É a forma errada, por uma razão que só aparece nos extremos. As permissões respondem a «pode este membro fazer isto». A pergunta aqui é «existe este ecrã neste domínio», e as duas separam-se no momento em que o titular de uma conta inicia sessão para ver o seu próprio painel de cliente. É o titular. Todas as verificações de permissões o deixam passar.

Por isso, o modelo é uma inversão em vez de um direito. Uma lista fixa diz que superfícies estão ausentes num domínio de conta: faturação, definições da conta, pedidos de assistência, agentes, integrações, o registo de atividade da conta, a vista de topologia, a área de administração da plataforma, e as páginas de registo e de recuperação de palavra-passe. Ausentes para toda a gente, incluindo o titular.

Três dessas precisam de justificação, porque a razão não é a óbvia.

Os pedidos de assistência estão ausentes porque um cliente de um revendedor tem uma relação de assistência com o revendedor, e não connosco. Se esse ecrã existisse, leria uma resposta que nomeia uma empresa que, segundo o seu próprio painel, não existe.

O registo de atividade está ausente porque é o registo da conta, e não de quem o lê. O resultado honesto não é um registo filtrado mas «este ecrã não existe aqui». O separador de atividade por servidor mantém-se, porque esse está mesmo delimitado a uma máquina que essa pessoa tem.

A vista de topologia prova o modelo. Corre sobre o módulo de servidores, e o módulo de servidores é precisamente a única coisa que um subcliente tem. Uma barreira de permissões não filtraria absolutamente nada.

Três fechos, porque uma página não é uma fronteira

Uma verificação não chega, e cada um dos três apanha aquilo que os outros não conseguem.

O primeiro está na própria função de permissões, onde a ordem de duas linhas é a questão toda:

  1. Existe este módulo nesta superfície? Se não, recusar.
  2. Este papel tem acesso total? Se sim, permitir.

Pôr o teste da superfície primeiro é o que faz «não existe» ganhar a «pode tudo», e é o que faz a inversão valer em todo o lado em vez de valer apenas nos ecrãs de que alguém se lembrou.

O segundo é uma guarda em todas as páginas sob esses caminhos, que produz um 404 normal. Não recebe deliberadamente nenhum argumento: uma chamada que nomeasse o seu próprio ecrã deixaria uma gralha tornar-se uma porta aberta em silêncio.

O terceiro está no proxy inverso, porque uma página não consegue apanhar um pedido que nunca chega a uma página. Um POST para um caminho ausente é recusado antes de correr qualquer código de página. As navegações passam, para que o 404 da própria aplicação apareça em vez de um erro seco do proxy.

Esta é a descoberta que vale a pena levar daqui, mesmo para quem não construa nada do que está acima.

Os nossos cookies de sessão são exclusivos do anfitrião. Sem atributo Domain, pelo que uma sessão num domínio de cliente não é enviada para outro, nem para o anfitrião da plataforma. Isso está correto e está testado, incluindo o caso negativo em que ativar cookies entre subdomínios faz aparecer um Domain.

Também não é uma fronteira. O subcliente tem na mão o seu próprio token de sessão e pode enviá-lo para onde quiser com um cliente HTTP de linha de comandos. Só um navegador é que teria recusado.

Medimos o que isso permitia, e era pior do que o esperado: um subcliente conseguia criar uma organização completamente nova, com ele próprio como titular, com direito a subscrição de avaliação, por dois caminhos de código independentes alcançáveis a partir de quatro pontos de entrada diferentes. Quatro organizações, contadas na base de dados no fim. No seu próprio domínio, o mesmo pedido era recusado pelo proxy, pelo que a porta estava fechada de um lado e aberta do outro.

A reparação não foi acrescentar verificações a esses dois caminhos. Foi pôr a fronteira no ponto único por onde passa todo o pedido autenticado, e a invariante «um subcliente nunca se torna titular de uma organização» na única função que todos os caminhos de criação partilham.

A mesma ronda encontrou noutro sítio a versão geral do problema. Uma chave de API transporta um papel, mas não uma superfície. Isso não era explorável, porque o separador onde uma chave é criada não existe num domínio de conta. Mas isso é um botão escondido, não uma fronteira, e a diferença conta no dia em que alguém acrescentar uma segunda forma de criar chaves. A correção recusa o principal em vez de etiquetar a chave.

Nenhuma coluna diz «isto é um subcliente»

Uma última nota de desenho, porque é o tipo de decisão que compensa em silêncio.

Um subcliente é uma linha de utilizador comum com um endereço de correio reservado da forma username@<organisation-id>.invalid, mais uma linha de adesão comum com um perfil de permissões estreito. Não há nenhuma coluna booleana a assinalá-lo, de propósito: uma segunda fonte de verdade pode afastar-se do endereço, e depois duas partes do sistema discordam sobre quem alguém é.

Como o identificador da organização está dentro do endereço, a unicidade vem de graça do índice que já lá estava, e o mesmo nome de utilizador pode existir sob dois revendedores. O formulário de início de sessão pede um nome de utilizador e retira o identificador da organização do anfitrião em vez do formulário, pelo que ninguém entra numa conta diferente por adivinhar um identificador.

E o endereço nunca é marcado como verificado, porque ninguém o consegue verificar. Essa coluna significa «este endereço pertence comprovadamente a esta pessoa», e pô-la a verdadeiro para um endereço que não chega a caixa nenhuma mudaria a mentira para um sítio menos visível.

O que isto não faz

Mudar a marca cobre a moldura. O texto da interface continua a ler-se como o nosso produto na língua que o visitante usar, e fingir o contrário significaria traduzir o vocabulário de um revendedor para nove línguas em nome dele. A lista de superfícies ausentes é uma decisão sobre a forma do produto, e não um modelo de segurança por si só: funciona porque os três fechos por trás dela funcionam.

É assim que funcionam os domínios de conta no Provibr, onde o agente corre no seu próprio hardware e só se liga para fora.

Comece com um host e um agente

Crie uma conta, instale o agente com um único comando e ligue o seu primeiro host Proxmox. O período experimental dura 14 dias e não pede quaisquer dados de pagamento.