O blog da AWS
Controle de acesso SaaS usando Amazon Verified Permissions com um armazenamento de políticas por tenant
Escrito por Manuel Heinkel, arquiteto de soluções na AWS e Alex Pulver, Principal Solutions Architect na AWS.
O controle de acesso é essencial para aplicações de software como serviço (SaaS) multitenant. Os desenvolvedores de SaaS devem gerenciar permissões, autorização refinada e isolamento.
Neste post, demonstramos como você pode usar o Amazon Verified Permissions para controle de acesso em um aplicativo SaaS de gerenciamento de documentos multitenant usando uma abordagem de armazenamento de políticas por tenant. Também descrevemos como impor o limite do tenant.
Geralmente, vemos as seguintes necessidades de controle de acesso em aplicativos SaaS multitenant:
- Os desenvolvedores da aplicaçãos precisam definir políticas que se apliquem a todos os tenants.
- Os usuários dos tenants precisam controlar quem pode acessar seus recursos.
- Os administradores de tenants precisam gerenciar todos os recursos de um tenant.
Além disso, fornecedores independentes de software (ISVs) implementam o isolamento de tenants para impedir que um tenant acesse os recursos de outro tenant. Impor limites aos tenants é fundamental para empresas de SaaS e é um dos tópicos fundamentais para provedores de SaaS.
O Amazon Verified Permissions é um serviço de autorização e gerenciamento de permissões escalável e refinado que ajuda você a criar e modernizar aplicativos sem precisar implementar a lógica de autorização no código do seu aplicativo.
As permissões são descritas em políticas na linguagem Cedar. Uma política Cedar é uma declaração que define quais principals estão explicitamente autorizadas, ou explicitamente proibidos, de realizar uma ação em um determinado recurso. O conjunto de políticas define as regras de autorização para sua aplicação. O Verified Permissions armazena as políticas em um repositório de políticas. Um repositório de políticas é um contêiner para políticas e templates. Você pode aprender mais sobre as políticas do Cedar na postagem Using Open Source Cedar to Write and Enforce Custom Authorization Policies.
Antes do Verified Permissions, você precisava implementar a lógica de autorização no código da sua aplicação. Agora, mostraremos como o Verified Permissions ajuda a remover esse trabalho em uma aplicação de exemplo.
Aplicação SaaS multitenant para gerenciamento de documentos
A aplicação permite adicionar, compartilhar, acessar e gerenciar documentos. Isso requer os seguintes controles de acesso:
- Desenvolvedores da aplicação podem definir políticas que se aplicam a todos os tenants.
- Usuários dos tenants podem controlar quem pode acessar seus documentos.
- Administradores de tenants podem gerenciar todos os documentos de um tenant.
Vamos começar descrevendo a arquitetura da aplicação e depois nos aprofundando nos detalhes do design.
Visão geral da arquitetura da aplicação
Há duas abordagens para o design de vários tenants no Verified Permissions: um único repositório de políticas compartilhado e um armazenamento de políticas por tenant. Você pode aprender mais sobre considerações, trade-offs e guias para essas abordagens no guia do usuário do Verified Permissions.
Para o exemplo de aplicação SaaS de gerenciamento de documentos, decidimos usar a abordagem de armazenamento de políticas por tenant pelos seguintes motivos:
- Isolamento de políticas de tenants com baixo esforço
- A capacidade de personalizar modelos e esquemas por tenant
- Off-boarding de tenants com baixo esforço
- Cotas de recursos de armazenamento de políticas por tenant
Decidimos aceitar os seguintes trade-offs:
- Grande esforço para implementar o gerenciamento global de políticas (porque o caso de uso da aplicação não exige mudanças frequentes nessas políticas)
- Esforço médio para implementar o fluxo de autorização (porque decidimos que, nesse contexto, os motivos acima superam a implementação de um mapeamento do ID do tenant para o ID do repositório de políticas)
A Figura 1 mostra a arquitetura da aplicação SaaS de gerenciamento de documentos. Para simplificar, omitimos o frontend e nos concentramos no back-end.
- Um usuário do tenant faz login em um provedor de identidade, como o Amazon Cognito. Ele recebe um JSON Web Token (JWT), que é utilizado para solicitações de API. O JWT contém declarações como o
user_id
, que identifica o usuário do tenant, e otenant_id
, que
define a qual tenant o usuário pertence. - O usuário do tenant faz solicitações de API com o JWT para a aplicação.
- O Amazon API Gateway verifica a validade do JWT com o provedor de identidade.
- Se o JWT for válido, o API Gateway encaminha a solicitação para processamento, neste caso a uma função do AWS Lambda, que executa a lógica de negócio.
- A função Lambda assume uma role do AWS Identity and Access Management (IAM) com uma política do IAM que permite acesso à tabela do Amazon DynamoDB que, por sua vez, fornece o mapeamento de tenant para o armazenamento das políticas. A política do IAM define o escopo do acesso de forma que a função Lambda só possa acessar dados do
tenant_id
atual. - A função Lambda pesquisa no Verified Permissions com o
policy_store_id
da solicitação atual. Para fazer isso, ele extrai otenant_id
do JWT. Em seguida, a função recupera opolicy_store_id
da tabela de mapeamento do tenant para o repositório de políticas. - A função Lambda assume outra role do IAM com uma política do IAM que permite acesso ao armazenamento de políticas do Verified Permissions, à tabela de metadados do documento e ao armazenamento de documentos. A política do IAM usa
tenant_id
epolicy_store_id
para granular o acesso. - A função Lambda obtém ou armazena metadados de documentos em uma tabela do DynamoDB. A função usa os metadados para solicitações de autorização de permissões verificadas.
- Usando as informações das etapas 5 e 6, a função Lambda chama o Verified Permissions para tomar uma decisão de autorização ou criar políticas Cedar.
- Se autorizado, a aplicação pode então acessar ou armazenar um documento.
Aprofundamento da arquitetura da aplicação
Agora que você conhece a arquitetura dos casos de uso, vamos analisá-los com mais detalhes e retroceder, desde a experiência do usuário até a parte relacionada da arquitetura da aplicação. A arquitetura se concentra no gerenciamento de permissões. Acessar e armazenar o documento real está fora do escopo.
Defina políticas que se apliquem a todos os tenants
O desenvolvedor da aplicação deve definir políticas globais que incluam um conjunto básico de permissões de acesso para todos os tenants. Usamos as políticas do Cedar para implementar essas permissões.
Como estamos usando uma abordagem de armazenamento de políticas por tenant, o processo de onboarding de tenants deve criar essas políticas para cada novo tenant. Atualmente, para atualizar as políticas, o pipeline de implantação deve aplicar as alterações em todos os repositórios de políticas.
As seções “Adicionar um documento” e “Gerenciar todos os documentos para um tenant” a seguir incluem exemplos de políticas globais.
Certifique-se de que um tenant não possa editar as políticas de outro tenant
A aplicação usa o IAM para isolar os recursos de um tenant do outro. Como estamos usando uma abordagem de armazenamento de políticas por tenant, podemos usar o IAM para isolar um armazenamento de políticas de tenant do outro.
Arquitetura
- Um usuário do tenant chama um endpoint de API usando um JWT válido.
- A função Lambda usa o AWS Security Token Service (AWS STS) para assumir uma role do IAM com uma política do IAM que permite acesso à tabela do DynamoDB de mapeamento do tenant para o armazenamento de políticas. A política do IAM só permite acesso à tabela e às entradas que pertencem ao tenant solicitante. Quando a função assume a role, ela usa o
tenant_id
para definir o escopo do acesso aos itens cuja chave de partição corresponde aotenant_id
. Consulte a postagem de blog Como implementar o isolamento de tenants de SaaS com o ABAC e o AWS IAM para ver exemplos dessas políticas. - A função Lambda usa o
tenant_id
do usuário para obter opolicy_store_id
a ser usado no Verified Permissions. - A função Lambda usa o mesmo mecanismo da etapa 2 para assumir uma role diferente do IAM usando
tenant_id
epolicy_store_id
, que só permitem acesso ao armazenamento de políticas do tenant. - A função Lambda acessa o repositório de políticas do tenant.
Adicionar um documento
Quando um usuário acessa a aplicação pela primeira vez, ele não possui nenhum documento. Para adicionar um documento, o frontend chama o endpoint POST /documents
e fornece um document_name
no corpo da solicitação.
Política Cedar
Essa política permite que qualquer principal adicione um documento. Como estamos usando uma abordagem de armazenamento de políticas por tenant, não há necessidade de definir o escopo do principal para um tenant.
Arquitetura
- Um usuário do tenant chama o endpoint
POST /documents
para adicionar um documento. - A função Lambda usa o
tenant_id
do usuário para obter opolicy_store_id
a ser usado no Verified Permissions. - A função Lambda chama o repositório de políticas do Verified Permissions para verificar se o usuário do tenant está autorizado a adicionar um documento.
- Após a autorização bem-sucedida, a função Lambda adiciona um novo documento ao banco de dados de metadados do documento e carrega o documento no armazenamento de documentos.
A estrutura do banco de dados é descrita na tabela a seguir:
tenant_id (chave de partição): String |
document_id (Chave de classificação): String |
document_name: String |
document_owner: String |
<TENANT_ID> | <DOCUMENT_ID> | <DOCUMENT_NAME> | <USER_ID> |
tenant_id
: Otenant_id
das declarações do JWT.document_id
: um identificador aleatório para o documento, criado pela aplicação.document_name
: o nome do documento fornecido com a solicitação da API.document_owner
: o usuário que criou o documento. O valor é ouser_id
das declarações do JWT.
Compartilhar um documento com outro usuário de um tenant
Depois que um usuário do tenant criar um ou mais documentos, talvez ele queira compartilhá-los com outros usuários do mesmo tenant. Para compartilhar um documento, o frontend chama o endpoint POST /shares
e fornece o document_id
do documento que o usuário deseja compartilhar e o user_id
do usuário receptor.
Política Cedar
Precisamos de uma política global do proprietário do documento que permita que o proprietário do documento gerencie o documento, incluindo o compartilhamento. O processo de onboarding do tenant cria essa política no repositório de políticas do tenant.
A política permite que os principals executem ações nos recursos disponíveis (o documento) quando o principal é o proprietário do documento. Essa política permite que a ação ShareDocument
, que descreveremos a seguir, compartilhe um documento.
Também precisamos de uma política de compartilhamento que permita que o usuário receptor acesse o documento. A aplicação cria essas políticas para cada ação de compartilhamento bem-sucedida. Recomendamos que você use templates de políticas para definir a política de compartilhamento. Os templates de política permitem que uma política seja definida uma vez e depois anexada a vários principals e recursos. As políticas que usam um template de política são chamadas de políticas vinculadas a templates. As atualizações do modelo de política são refletidas nos principals e recursos que usam o modelo. O processo de onboarding do tenant cria o template de política de compartilhamento no repositório de políticas do tenant.
Definimos o template de política de compartilhamento da seguinte forma:
Veja a seguir um exemplo de uma política vinculada a um template usando o template de política de compartilhamento:
A política inclui o user_id
do usuário receptor (principal) e o document_id
do documento (recurso).
Arquitetura
- Um usuário do tenant chama o endpoint
POST /shares
para compartilhar um documento. - A função Lambda usa o
tenant_id
do usuário para obter opolicy_store_id
a ser utilizado no Verified Permissions e os IDs do modelo de política para cada ação da tabela do DynamoDB que armazena o mapeamento do tenant no repositório de políticas. Nesse caso, a função precisa usar oshare_policy_template_id
. - A função consulta a tabela de metadados do documento do DynamoDB para recuperar o atributo
document_owner
do documento que o usuário deseja compartilhar. - A função Lambda chama o Verified Permissions para verificar se o usuário está autorizado a compartilhar o documento. O contexto da solicitação usa o
user_id
das declarações do JWT como entidade, shareDocument como ação edocument_id
como recurso. A entidade do documento inclui o atributodocument_owner
, que veio da tabela de metadados do documento do DynamoDB. - Se o usuário estiver autorizado a compartilhar o recurso, a função criará uma nova política de compartilhamento vinculada ao modelo no repositório de políticas do tenant. Essa política inclui o
user_id
do usuário receptor como entidade e odocument_id
como recurso.
Acesse um documento compartilhado
Depois que um documento é compartilhado, o usuário receptor deseja acessá-lo. Para acessar o documento, o frontend chama o endpoint GET /documents
e fornece o document_id
do documento que o usuário deseja acessar.
Política Cedar
Conforme mostrado na seção anterior, durante o processo de compartilhamento, a aplicação cria uma política de compartilhamento vinculada a um template que permite que o usuário receptor acesse o documento. O Verified Permissions avalia essa política quando o usuário tenta acessar o documento.
Arquitetura
- Um usuário do tenant chama o endpoint
GET /documents
para acessar o documento. - A função Lambda usa o
tenant_id
do usuário para obter opolicy_store_id
a ser usado no Verified Permissions. - A função Lambda chama o Verified Permissions para verificar se o usuário está autorizado a acessar o documento. O contexto da solicitação usa o
user_id
das declarações do JWT como principal, o AccessDocument como a ação e odocument_id
como o recurso.
Gerencie todos os documentos de um tenant
Quando um cliente realiza o onboarding em uma aplicação SaaS, a aplicação cria o usuário administrador do tenant. O administrador do tenant deve ter permissões para realizar todas as ações em todos os documentos do tenant.
Política Cedar
Precisamos de uma política global que permita que os administradores de tenants gerenciem todos os documentos. O processo de onboarding do tenant cria essa política no repositório de políticas do tenant.
Essa política permite que cada membro do grupo <admin_group_id>
execute qualquer ação em qualquer documento.
Arquitetura
- O administrador tenant chama o endpoint
POST /documents
para gerenciar um documento. - A função Lambda usa o
tenant_id
do usuário para obter opolicy_store_id
que será usado no Verified Permissions. - A função Lambda chama o Verified Permissions para verificar se o usuário está autorizado a gerenciar o documento.
Conclusão
Nesta postagem, mostramos como o Amazon Verified Permissions ajuda a implementar decisões de autorização refinadas em uma aplicação SaaS multitenant. Você viu como aplicar a abordagem de armazenamento de políticas por tenant à arquitetura da aplicação. Consulte o guia do usuário do Verified Permissions para saber como escolher entre usar um repositório de políticas por tenant ou um repositório de políticas compartilhado. Para saber mais, visite a documentação e o workshop do Amazon Verified Permissions.
Sobre os Autores
Manuel Heinkel é arquiteto de soluções na AWS e trabalha com empresas de software na Alemanha para criar aplicações inovadoras e seguros na nuvem. Ele apoia os clientes na solução de desafios de negócios e na obtenção do sucesso com a AWS. Manuel tem um histórico de aprofundamento em tópicos de segurança e SaaS. Fora do trabalho, ele gosta de passar tempo com sua família e explorar as montanhas. | |
Alex Pulver é um Principal Solutions Architect na AWS. Ele trabalha com clientes para ajudar a projetar processos e soluções para suas necessidades comerciais. Suas áreas de interesse atuais são engenharia de produto, experiência do desenvolvedor e estratégia de plataforma. Ele é o criador do Application Design Framework, que visa alinhar negócios e tecnologia, reduzir o retrabalho e permitir a arquitetura evolutiva. |
Este conteúdo foi traduzido para Português do blog original em inglês (link aqui).
Tradutor: Cesar Augusto Kuehl, arquiteto de soluções – AWS Brasil
Revisor: José Augusto Ferronato, arquiteto de soluções – AWS Brasil