A Clínica A e a Clínica B compartilham uma base de código, dois subdomínios e uma mistura de visitantes do escritório e via VPN. As equipes de rede costumam configurar as duas entradas separadamente, e isso está bem, desde que a aplicação não o faça. As verificações abaixo pertencem à aplicação e devem se comportar de forma idêntica, independentemente da porta usada pela solicitação.

Primeiro: o nome do host apenas nomeia um inquilino

Resolva o nome do host solicitado contra um mapeamento mantido pelo administrador e rejeite qualquer coisa desconhecida. Use o valor de host validado pelo framework em vez do cabeçalho bruto, para que um Host forjado não possa injetar uma chave de consulta. Uma correspondência bem-sucedida diz ao código qual configuração de inquilino e qual marca carregar. Ela não diz nada sobre se o chamador pode ver os dados desse inquilino. Mantenha essa segunda pergunta em uma função separada com uma entrada separada.

Uma função auxiliar compartilhada que retorna tanto o contexto quanto a permissão a partir de uma única consulta de nome de host é o começo do defeito.

Segundo: a associação vem da sessão

Procure as associações ativas do usuário autenticado e compare-as com o inquilino da primeira verificação. Um usuário que pertence às duas clínicas pode alternar, mas a alternância deve ser uma ação explícita registrada no contexto da solicitação, não uma inferência da URL. Um usuário que pertence a uma clínica e solicita a outra é negado, inclusive para downloads e chamadas de API.

Teste o caso negativo editando um identificador de registro e um parâmetro de inquilino. Se qualquer uma das mudanças retornar dados, o escopo está sendo lido da solicitação e não da associação verificada.

O escopo dos cookies e o login único decidem onde uma conta pode ser apresentada. Eles não decidem o que essa conta pode ler.

Terceiro: a rede não prova nada sobre a pessoa

Um gateway VPN autentica um túnel, e uma lista de permissões pública autentica uma faixa de endereços. Nenhum dos dois identifica uma pessoa. O NAT agrupa muitos usuários em um único endereço de origem, e uma faixa de escritório faz o mesmo com todos no prédio. Trate ambos como fatos de transporte e mantenha a autorização na aplicação, ou em uma integração que afirme a identidade explicitamente e seja revisada como tal.

DNS é um terceiro fato de transporte. Uma resposta privada exige uma rota privada, e um front-end público exige um caminho de origem suportado. Nenhum deles carrega uma permissão.

Uma frase para a parede: a rede decide como uma solicitação chega, e a aplicação decide o que ela pode ler.

Quarto: execute a matriz nas duas entradas

Use contas controladas para exercitar A em A, B em B, A em B, um nome de host desconhecido e uma conta autenticada sem associações. A quarta e a quinta devem falhar fechadas e nunca recorrer a um inquilino padrão. Execute a mesma matriz também pela entrada VPN, com um pote de sessão por conta:

curl -s -o /dev/null -w '%{http_code}' -b jar.txt https://clinic-b.example.com/records/42
curl -s -o /dev/null -w '%{http_code}' -b jar.txt https://clinic-a.example.com/records/42

Depois altere uma entrada da lista de permissões e execute novamente. Um resultado que se move significa que um controle de rede está tomando uma decisão de autorização.

Repita a matriz após qualquer mudança no front-end, porque um segundo caminho de código que ignora a verificação é a forma mais comum de essa fronteira se erodir. O resultado esperado é entediante: cada entrada produz as mesmas respostas.

Artigos relacionados