Continuando nossa exploração sobre controle de acesso em interfaces de sistemas, esta segunda parte foca na autorização de APIs. Na primeira parte, abordamos a autorização de UI, e agora mergulharemos na arquitetura e no design de soluções para controle de atributos em cenários de complexidade variada, utilizando o método experimental de 'pós-análise de casos de uso' para o gerenciamento de tarefas em sistemas como o Сфера.Задачи.
Nosso rastreador de tarefas, operando no nível C2, é uma aplicação típica de microsserviços, composta por um front-end web, um serviço de tarefas e serviços adicionais, cada um com seu próprio banco de dados, com todas as requisições passando por um API Gateway. Para o escopo deste artigo, focaremos no serviço de tarefas e na API tasks com seus métodos POST, GET e PATCH. Utilizaremos os resultados da análise de casos de uso para construir um fluxo de trabalho alinhado ao ciclo de vida da tarefa. Este ciclo inclui a criação e arquivamento de tarefas pelo líder da equipe, a edição por qualquer membro da equipe, e a transição para o arquivamento após a conclusão. As requisições de criação utilizam POST, as de visualização (tabela ou quadro) utilizam GET, e as de edição utilizam PATCH. A autorização inicial para a versão 'as-is' do rastreador de tarefas é relativamente simples: verificar a função e a equipe do usuário para todas as requisições. Para requisições PATCH, é necessário verificar também o status da tarefa e se a requisição de arquivamento é válida. Para requisições GET de leitura em massa, a filtragem da resposta por equipes acessíveis é suficiente. A principal questão reside em onde implementar essa autorização. Se os dados de acesso do usuário residem no banco de dados do nosso serviço, a implementação mais desafiadora para a segurança é a requisição PATCH. Os componentes que lidam com requisições de API são o API Gateway e o API Service. Tradicionalmente, o API Service é responsável pela autorização. No entanto, questionamos se é possível realizar uma autorização completa de requisições PATCH no nível do API Gateway. Para isso, o API Gateway precisaria de atributos do sujeito e do objeto para a lógica de verificação. Uma solução óbvia seria usar o token JWT, mas isso introduz riscos de vazamento de informações e falsificação. Alternativamente, o API Gateway poderia obter esses atributos de um serviço separado ou do cliente web, via cabeçalhos. A primeira opção, embora forneça informações atualizadas, gera requisições de rede adicionais e impacta a performance. A segunda, com cabeçalhos customizados, pode resultar em perda de dados ou falsificação. Uma terceira via seria combinar ambas as abordagens: pré-solicitar e cachear permissões para dados do sujeito, com um tempo de invalidação definido pelos requisitos de segurança. Para os atributos do objeto, uma abordagem não convencional seria usar parâmetros de query obrigatórios como team e status, permitindo que o gateway tome decisões em caso de inconsistências. O serviço, por sua vez, seria responsável por detectar discrepâncias entre a informação real e a dos parâmetros de requisição. Assim, a autorização pode ocorrer antes mesmo da requisição atingir o serviço, no nível do API Gateway, que assume a responsabilidade pela segurança, enquanto o serviço principal se concentra na autorização para leitura em massa.
Na versão 'to-be' do rastreador de tarefas, o cenário se torna mais complexo: buscamos separar partes interessadas e conceder acesso para edição de dados. Os eventos registram que um membro da equipe precisa considerar o contexto da parte interessada para atualizar uma tarefa, pois alguns atributos podem ser editados, outros não, e dados confidenciais podem ser inacessíveis. A parte interessada só pode editar atributos se a tarefa estiver em seu contexto. Tarefas concluídas são arquivadas. As requisições seguem o mesmo padrão: POST para criação, PATCH para edição e GET para leitura. No entanto, os cenários de acesso com atributos são mais incertos: é necessário verificar não apenas a função e a equipe, mas também o contexto do objeto de forma contínua. Os requisitos de autorização para PATCH tornam-se significativamente mais complexos, exigindo pós-filtragem de dados por atributos para todas as respostas. Na versão desejada do planejador, as incertezas sobre o contexto necessário para a autorização e as limitações de leitura do cliente tornam o serviço o local mais adequado para a autorização das requisições. Para otimizar a performance, podemos cachear permissões na forma de uma ligação 'usuário-regra'. Antes de retornar qualquer resposta, os atributos inacessíveis dos objetos serão 'zerados'. A pós-análise de casos de uso para o design da autorização de API envolveu a definição do fluxo de trabalho e dos participantes, a identificação de eventos e condições de autorização, a análise de APIs e riscos de autorização no nível dos dados da requisição, e a comparação de abordagens 'antes' e 'depois' da lógica de negócio. Para condições de alta incerteza e dados insuficientes na requisição, a abordagem 'autorização na lógica de negócio' é preferível. O design da autorização contínua de API, com a abordagem 'antes da lógica de negócio' (no API Gateway), envolve o design de um endpoint para obter permissões e a lógica de acesso e cache de atributos do sujeito. Para cada funcionalidade, definimos a disponibilidade de requisições para funções ou permissões, considerando a entrega de atributos do objeto a serem autorizados no nível da requisição. Com uma ABAC verdadeiramente flexível, a abordagem 'na lógica de negócio', dentro do próprio serviço, é mais vantajosa. Aqui, definimos um Domain Specific Language (DSL) para as condições, juntamente com o princípio de filtragem e pós-filtragem. Para cada funcionalidade, mapeamos endpoints e ligações 'recurso-operação', fornecendo aos desenvolvedores exemplos de regras e resultados esperados da autorização de API em suas especificações.
Em conclusão, a implementação da autorização de UI requer a colaboração entre front-end e back-end. A distribuição da lógica pode variar: apenas no front-end (rápida, mas insegura), apenas no back-end (rápida e segura, mas com UX comprometido), paralela (clássica, segura, mas demorada) ou orientada ao back-end (mais complexa e demorada, cobrindo casos mais difíceis). Sistemas completos devem adotar um dos dois últimos ou uma abordagem híbrida. Para a autorização de API, a escolha recai entre: na borda do back-end (desenvolvimento rápido e relativamente simples, seguro para RBAC comum) ou dentro da lógica principal (desenvolvimento mais complexo e demorado, cobrindo casos de controle de atributos mais difíceis). Uma alternativa é a autorização externa, delegando verificações a um serviço separado, o que simplifica a implementação, mas pode comprometer o desempenho e a cobertura completa de ABAC. A 'pós-análise de casos de uso' é uma ferramenta valiosa para verificar a continuidade da autorização sob a ótica do Zero Trust. Ela auxilia analistas e engenheiros na discussão de problemas específicos e no design de interfaces. Em nosso caso, permitiu imergir em um novo sistema, estudar a solução existente e projetar uma nova em um mês, além de formar uma visão unificada sobre problemas e soluções entre desenvolvedores e partes interessadas. Isso resultou no desenvolvimento de um modelo de acesso flexível, que se tornou um diferencial chave em nosso sistema de gerenciamento de projetos Сфера.Задачи. É fundamental projetar a segurança sempre que se desenvolve UI e API, escolhendo a abordagem com base na interface e mapeando-a como caminhos de usuário, ciclo de vida de recursos ou fluxo de trabalho do sistema para analisar padrões e projetar novos designs.

