Salta al contenuto

Blog ·

Pannelli white-label: che cosa vede il cliente

Mettere il proprio nome su un pannello per rivenditori è la metà facile. La difficile è decidere quali schermate esistano per il cliente, e farlo rispettare.

Di Provibr

Se rivende VPS o hosting, prima o poi i suoi clienti vorranno un pannello. Vogliono riavviare la propria macchina alle due di notte invece di aprire un ticket, e lei vuole che lo facciano.

Questo si trasforma in due domande che sembrano una sola e non lo sono. Di chi è il nome sul pannello, e quali parti del pannello esistano per quella persona. La prima è il marchio, ed è per lo più presentazione. La seconda è un confine, e sbagliarla è il modo in cui un suo cliente finisce per leggere la fattura del suo fornitore.

Il marchio si ferma dove inizia la carta bollata

Rimarchiare un pannello significa cambiare la cornice: il logotipo nella barra laterale, il titolo della pagina, la favicon, il nome nel blocco dell’account. È una quantità utile di cose, ed è il punto in cui la maggior parte delle funzioni white-label si ferma.

La parte interessante è l’elenco delle cose che non devono mai portare il nome del rivenditore.

SchermataDi chi è il nome che portaPerché
Cornice del pannello, titoli, faviconIl rivenditoreLa relazione in cui si trova il cliente
Informativa sulla privacyLa piattaformaUn’informativa sul trattamento descrive chi tratta davvero
Condizioni di servizioLa piattaformaÈ l’accordo della piattaforma, non del rivenditore
Accordo sul trattamento dei datiLa piattaformaLo stesso, e nomina i sub-responsabili
Fatture e documenti proformaLa piattaformaÈ la registrazione finanziaria di una transazione reale
La riga su un estratto contoLa piattaformaUna traccia permanente che nessuno può annotare in seguito

Il ragionamento sta in una frase: un cliente del suo cliente non deve mai arrivare a credere di avere un contratto con qualcuno diverso dalla parte con cui lo ha davvero. Tutto ciò che ha carattere legale o finanziario porta il nome della controparte di quel documento, e questa non è una preferenza di design.

Ciò che conta più della regola è dove essa vive. Nella nostra base di codice è un elenco di percorsi di file, e un test percorre l’albero transitivo degli import a partire da ciascuno di essi, fallendo nell’istante in cui uno di essi riesce a raggiungere il modulo del marchio. In ampiezza, così l’errore nomina la catena più corta, che è quella da tagliare.

Un controllo sugli import diretti è troppo facile da aggirare: metta la ricerca del marchio in un helper, importi l’helper, fatto. E il presidio verifica sé stesso in entrambe le direzioni. Un percorso elencato che scompare è un errore anziché un salto silenzioso, e separatamente il test afferma che il layout del pannello raggiunge davvero il modulo del marchio, perché un risolutore che in silenzio non risolve nulla segnerebbe ogni file come verde.

Il login del rivenditore non viene mai rimarchiato

C’è una seconda regola, meno ovvia, che avremmo sbagliato se non l’avessimo enunciata: il marchio si applica soltanto sul dominio del cliente.

Quando il rivenditore accede sull’host della piattaforma, vede la piattaforma, non il proprio marchio. È lì che vivono le fatture, l’abbonamento e la relazione con noi. La ricerca del marchio ripiega sulla versione neutra nell’istante in cui una richiesta non è legata a un dominio di account, quindi decide esattamente un posto solo e nessuna schermata deve ricordarsene.

La schermata di gestione del marchio mostra un’anteprima della cornice rivolta al cliente anziché essere rimarchiata a sua volta. Sembra pedanteria, finché non si considera che cosa insegna l’alternativa: un rivenditore che vede il proprio logo sopra la propria fattura concluderà ragionevolmente che i suoi clienti vedano qualcosa di simile.

Un logo bianco su una barra laterale bianca

Lo sfondo del nostro pannello è bianco, quindi un logo con sfondo trasparente e inchiostro bianco è invisibile, e chi lo carica non lo scoprirà: lo sta guardando in uno strumento di design su una tavola grigia.

Abbiamo misurato anziché indovinare, componendo ciascun logo sul colore reale della superficie in un browser headless:

LogoContrasto rispetto alla superficie del pannello
Inchiostro scuro, sfondo trasparente16,46:1
Inchiostro bianco, sfondo trasparente1,00:1
Inchiostro bianco su una propria targa opaca17,74:1
Inchiostro grigio chiaro1,24:1

La riga a 1,00:1 non significa «difficile da leggere». Ogni pixel è identico allo sfondo. Il logo viene disegnato e non c’è nulla da vedere.

Ne sono uscite due decisioni. Non c’è deliberatamente alcuna targa sotto il logo, perché ridisegnerebbe il marchio del cliente e darebbe una cornice a ogni logo normale per salvare un’unica eccezione. E la schermata di caricamento avvisa anziché rifiutare, perché a un marchio è consentito essere grigio chiaro.

La misurazione conta l’inchiostro, non la sovrapposizione. Un logo con un ampio margine trasparente coincide con lo sfondo su gran parte della sua area ed è perfettamente visibile; ciò che conta è quanta parte di esso venga disegnata e quanto quell’inchiostro disti dal colore della superficie.

L’assenza non è un permesso

Ora la metà più difficile. Quali schermate dovrebbero esistere per il cliente di un rivenditore?

L’istinto è modellare la cosa come permessi: si dà un ruolo al sotto-cliente e si spuntano meno caselle. È la forma sbagliata, per una ragione che emerge soltanto ai margini. I permessi rispondono a «questo membro può fare questo». La domanda qui è «questa schermata esiste su questo dominio», e le due si separano nell’istante in cui il titolare di un account accede per guardare il proprio pannello cliente. Lui è il titolare. Ogni controllo dei permessi lo lascia passare.

Perciò il modello è un’inversione anziché un diritto. Un elenco fisso dice quali superfici siano assenti su un dominio di account: la fatturazione, le impostazioni dell’account, i ticket, gli agenti, le integrazioni, il registro attività dell’account, la vista della topologia, l’area di amministrazione della piattaforma e le pagine di registrazione e di password dimenticata. Assenti per tutti, titolare incluso.

Tre di queste richiedono una giustificazione, perché la ragione non è quella ovvia.

I ticket sono assenti perché il cliente di un rivenditore ha una relazione di assistenza con il rivenditore, non con noi. Se quella schermata esistesse, leggerebbe una risposta che nomina un’azienda la quale, secondo il suo stesso pannello, non esiste.

Il registro attività è assente perché è il registro dell’account, non di chi lo legge. L’esito onesto non è un registro filtrato ma «questa schermata qui non esiste». La scheda attività per singolo server resta, perché quella è davvero delimitata a una macchina che possiede.

La vista della topologia dimostra il modello. Gira sul modulo dei server, e il modulo dei server è precisamente l’unica cosa che un sotto-cliente ha. Un cancello sui permessi non filtrerebbe proprio nulla.

Tre chiusure, perché una pagina non è un confine

Un solo controllo non basta, e ciascuna delle tre intercetta ciò che le altre non possono.

La prima sta nella funzione dei permessi stessa, dove l’ordine di due righe è tutto il punto:

  1. Questo modulo esiste su questa superficie? In caso contrario, rifiutare.
  2. Questo ruolo ha accesso completo? In tal caso, consentire.

Mettere per primo il test sulla superficie è ciò che fa vincere «non esiste» su «può tutto», ed è ciò che fa reggere l’inversione ovunque anziché soltanto nelle schermate che qualcuno si è ricordato.

La seconda è un presidio in ogni pagina sotto quei percorsi, che produce un normale 404. Deliberatamente non accetta argomenti: una chiamata che nominasse la propria schermata lascerebbe che un errore di battitura diventi una porta silenziosamente aperta.

La terza sta nel reverse proxy, perché una pagina non può intercettare una richiesta che non arriva mai a una pagina. Un POST verso un percorso assente viene rifiutato prima che venga eseguito qualunque codice di pagina. Le navigazioni vengono lasciate passare, così viene reso il 404 dell’applicazione invece di un nudo errore del proxy.

Questa è la scoperta che vale la pena portarsi via anche se non costruisce nulla di quanto sopra.

I nostri cookie di sessione sono host-only. Nessun attributo Domain, quindi una sessione su un dominio cliente non viene inviata a un altro, e nemmeno all’host della piattaforma. È corretto ed è verificato, compreso il caso negativo in cui abilitare i cookie fra sottodomini fa comparire un Domain.

E non è nemmeno un confine. Il sotto-cliente detiene il proprio token di sessione e può inviarlo dove vuole con un client HTTP da riga di comando. Solo un browser avrebbe rifiutato.

Abbiamo misurato che cosa questo consentisse, ed era peggio del previsto: un sotto-cliente poteva creare un’organizzazione nuova di zecca con sé stesso come titolare, completa di abbonamento di prova, lungo due percorsi di codice indipendenti raggiungibili da quattro punti di ingresso diversi. Quattro organizzazioni, contate nel database a posteriori. Sul proprio dominio la stessa richiesta veniva rifiutata dal proxy, quindi la porta era chiusa da un lato e aperta dall’altro.

La riparazione non è stata aggiungere controlli a quei due percorsi. È stata mettere il confine nell’unico punto attraversato da ogni richiesta autenticata, e l’invariante «un sotto-cliente non diventa mai il titolare di un’organizzazione» nell’unica funzione condivisa da tutti i percorsi di creazione.

Lo stesso giro ha trovato altrove la versione generale del problema. Una chiave API porta un ruolo ma non una superficie. Non era sfruttabile, perché la scheda in cui si crea una chiave non esiste su un dominio di account. Ma quello è un pulsante nascosto, non un confine, e la differenza conta il giorno in cui qualcuno aggiunge un secondo modo di creare chiavi. La correzione rifiuta il soggetto autenticato anziché etichettare la chiave.

Nessuna colonna dice «questo è un sotto-cliente»

Un’ultima nota di progettazione, perché è il tipo di decisione che ripaga in silenzio.

Un sotto-cliente è una comune riga utente con un indirizzo e-mail riservato nella forma username@<organisation-id>.invalid, più una comune riga di appartenenza con un profilo di permessi ristretto. Non c’è alcuna colonna booleana che li contrassegni, di proposito: una seconda fonte di verità può disallinearsi rispetto all’indirizzo, e allora due parti del sistema non concordano su chi sia qualcuno.

Poiché l’ID dell’organizzazione sta dentro l’indirizzo, l’unicità arriva gratis dall’indice che c’era già, e lo stesso nome utente può esistere sotto due rivenditori. Il modulo di accesso chiede un nome utente e prende l’ID dell’organizzazione dall’host anziché dai campi compilati, quindi nessuno accede a un account diverso indovinando un identificatore.

E il loro indirizzo non viene mai contrassegnato come verificato, perché nessuno può verificarlo. Quella colonna significa «questo indirizzo appartiene dimostrabilmente a questa persona», e impostarla a vero per un indirizzo che non raggiunge alcuna casella sposterebbe la menzogna in un punto meno visibile.

Che cosa non fa

Il rimarchio copre la cornice. I testi dell’interfaccia si leggono comunque come il nostro prodotto nella lingua che il visitatore usa, e fingere il contrario significherebbe tradurre il vocabolario di un rivenditore in nove lingue per suo conto. L’elenco delle superfici assenti è una decisione sulla forma del prodotto, non un modello di sicurezza a sé stante: funziona perché funzionano le tre chiusure che ha dietro.

Ecco come funzionano i domini di account in Provibr, dove l’agente gira sul suo hardware e si connette solo verso l’esterno.

Inizi con un host e un agente

Crei un account, installi l’agente con un solo comando e colleghi il suo primo host Proxmox. Il periodo di prova dura 14 giorni e non chiede alcun dato di pagamento.