Layer 1 DETImótica logo DETImótica

Introdução

Relativamente à API, esta surge no sistema como a interface da camada de sensores, possuindo então um conjunto de endpoints desenvolvidos com recurso à framework Flask, que permitem que os programadores e utilizadores finais acedam aos dados dos mesmos, e ainda que possam interagir com esta, por exemplo, criando novas salas, atribuindo sensores a espaços ou alargando o número de ações que dados utilizadores podem realizar .

Todos os endpoints são autenticados, isto é, apenas utilizadores que pertencem à Universidade de Aveiro são capazes de usufruir do sistema. Para isso, foi feita uma integração de um servidor de autorização, implementando por cima desta serviços de cache de identificação do utilizador e validação das sessões, que permitem também a autenticação do sujeito que concedeu a autorização.

Para além disso, a API está diretamente integrada com o módulo de controlo de acessos, que serve para a gestão das permissões dos utilizadores, por forma a que o acesso aos recursos da API, como Salas e Sensores, possa ser personalizado para cada um por criação de políticas.

A API conecta-se também a uma Base de Dados auxiliar para garantir a persistência da meta-informação associada aos dados do sistema, e ainda guardar as relações entre os mesmos .

Por fim, a API é configurada por ficheiros para o efeito, e é executada a partir de um Web Server Gateway Interface (WSGI), que a expõe e intermedia todos os pedidos a esta assincronamente, garantindo uma performance significativamente maior do que se fosse executada diretamente. A configuração do WSGI garante, ainda, segurança nas comunicações ao nível dos pedidos.

Desenho da API

Especificando os endpoints desta solução, durante a sua definição adotou-se o estilo de desenho de APIs REST: para tal, mapeou-se cada um dos principais recursos e as suas operações num conjunto de endpoints que tem sempre como Base o nome do recurso (Ex: /).

Posteriormente, fez-se uso das opções de ação nativas nos requests do protocolo HTTP/HTTPS para diferenciar, num mesmo endpoint, o resultado que é esperado da sua execução, deixando deste modo a API simples e intuitiva de utilizar. Resumo nas Tabelas abaixo.

Recurso Endpoint Base Path
Salas /room
Sensores /sensor
Tipos de Sensores /type
Utilizadores /user
Políticas de Acesso /accessPolicy

Resumo dos recursos na API

Ação Resultado Esperado
GET devolva valores de um recurso
POST modificação (alteração dos campos do recurso)
DELETE apague um dado recurso

Resumo das ações na API


Exemplos:

[POST] /sensor - criar um novo sensor

[POST] /sensor/”id” - modificar um sensor com o id “id” já existente

Além disto cada recurso pode ainda possuir Opções ou Recursos Internos: nestes dois casos, decidiu-se que deve ser também indicada a opção, após a escolha do recurso ( [ / recurso_base ] [ / opção/recurso_secundário ] ).

Exemplos:

[GET] /sensor/”id”/measure/”tipo_medição” - obter os valores de um sensor “id” segundo a forma especificada dentro da opção “tipo_medição”

[GET] /room/”id”/sensors - obter os sensores existentes na sala “id”

Para terminar ainda se implementou alguns endpoints diretos, que participam na autenticação dos utilizadores na API. Estes são descritos mais abaixo.

Autorização e autenticação

Todos os pedidos de acesso a recursos pelos endpoints da API são autenticados.

Para isto, é necessária a definição de endpoints especiais de sessão que consigam realizar um mecanismo capaz de autenticar o utilizador final. Adicionalmente, a definição de uma API com controlo de acessos por atributos requer que exista recolha de atributos relacionados com o utilizador que, depois, sejam utilizados para definir políticas que controlem finamente os recursos existentes.

Com isto, foi utilizado o Identity@UA, que é um servidor OAuth (Open Authorization), versão 1.0a, que integra a autenticação dos utilizadores associados à Universidade de Aveiro pelo IdP (Identity Provider). Isto permite que a API tenha, a partir de um token de acesso, permissão por parte do end-user para recolher atributos de identidade.

Por si só, este método não faz qualquer autenticação - para o efeito, uma sessão é criada (a partir de uma cookie de sessão), internamente mapeada para um token de acesso, que fica em cache, e validada sempre que o utilizador fizer um pedido à API.

Para mais informação acerca da implementação do servidor OAuth, por favor, ver a página do Identity@UA e a documentação do serviço de OAuth.

Processo de autenticação na API

O utilizador inicia a sessão chamando o endpoint associado para o efeito (/login). A API faz um pré-processamento para averiguar se o utilizador já está autenticado com sucesso no sistema. No caso de estar, então o processo é finalizado diretamente com a resposta de redirecionamento ou de sucesso final.

Nota: Dependendo com que propósito foi chamado, o seu URL poderá ter parâmetros app (ID de aplicação) e redirect_url (página de redirecionamento após autenticação bem sucedida). Se estes existirem, o primeiro passo consiste em incluí-los na cookie de sessão. Esta fase aplica-se à autenticação dentro da plataforma de gestão e do serviço de dashboards, que diferem do passo final.

Neste ponto, a API começa o processo OAuth, pede o token de pedido e a chave correspondente, e redireciona o utilizador para o IdP da Universidade.

De seguida, o utilizador introduz as suas credenciais, valida-as e responde ao consentimento para permissão de utilização de dados pela API, enviado pelo servidor de OAuth.

Este, seguidamente, comunica à API pelo endpoint de callback, configurado aquando do registo inicial da API no servidor (/auth_callback).

No processo deste endpoint, é verificado se o utilizador consentiu os dados.

Com este token, de seguida, é feito um pedido de todos os atributos do utilizador, seleciona-se e processa-se os que são relevantes para a definição do conjunto de atributos para efeitos de controlo de acesso do utilizador, e guarda-se o resultado em cache de dados local.

Os atributos básicos que identificam o utilizador são guardados na cookie da sessão, e internamente mapeados com estas (access token e chave) noutra cache local da sessão.

Ainda falta persistir dados básicos de utilizador na base de dados relacional de atributos para haver um registo de utilizadores que, no passado, utilizaram a plataforma, e conseguir admitir administradores do sistema.

Assim sendo, se o utilizador ainda não existir na base de dados, este é inserido com as informações básicas (email e ID), sem o papel de administrador.

Por fim, para concluir o processo de login com sucesso, é necessário responder de acordo com o início do processo:

login_flow

Processo de desautenticação

O processo de logout inicia quando o utilizador final chama o endpoint /logout. Primeiro, é verificado se este não se encontra autenticado.

No caso de não estar autenticado, então o processo de desautenticação começa:

logout_flow

Integração de controlo de acessos

A API combina regras internas pré-definidas de acesso administrativo a endpoints e a utilização um submódulo de controlo de acessos baseado em atributos (ABAC), desenvolvido em Python.

Este utiliza uma framework denominada Vakt, que define um conjunto de funcionalidades capazes de fornecer uma solução de controlo de acesso por políticas baseada em dicionários Python e estruturas do tipo JSON, que unifica o desenvolvimento da API no que toca às mensagens transmitidas em todo o fluxo de dados com as componentes de frontend.

Mais informação pode ser consultada aqui

Regras internas de acesso

A especificação de endpoints da API reúne um conjunto de pressupostos que são internos e que definem, à partida, o acesso que deve ser dado em endpoints.

Algumas considerações

Em termos de endpoints na API, averiguou-se algumas considerações:

Por isto, é necessário coordenar a classe PDP do módulo de controlo de acessos com implementações dos endpoints na API para que a análise de políticas na consulta faça corresponder estas regras:

Resumo das Funcionalidades

Nesta seção, é sucintamente descrito o que cada endpoint é esperado que faça. Para efeitos de simplificação, não se indica que ação do protocolo http/https deve ser usada, nem quais são os parâmetros necessários no corpo do pedido, nem quais são as possíveis formas de erros e seus códigos. Caso seja necessário e precise de procurar saber mais acerca destes detalhes, é possível recorrer à especificação em Swagger (Documentação da API).

Rooms

Sensors

Types

Users

Access Policies