[PD2] Relatorio final

Co-authored-by: tsousa111 <tiagao2001@hotmail.com>
This commit is contained in:
Afonso Franco 2024-05-31 23:56:59 +01:00
parent a8a1c21e8e
commit 9951c4b9da
Signed by: afonso
SSH key fingerprint: SHA256:PQTRDHPH3yALEGtHXnXBp3Orfcn21pK20t0tS1kHg54
5 changed files with 51 additions and 38 deletions

View file

@ -2,21 +2,21 @@
## Introdução
Neste segundo projeto de desenvolvimento (PD2), realizamos várias alterações em relação ao PD1, visando melhorar a estrutura e a segurança do sistema de mensagens seguro e autenticado. A principal mudança foi a introdução de uma API Gateway entre o cliente e o servidor, responsável pela autenticação dos utilizadores e pelo encaminhamento dos pedidos para o servidor. Este relatório detalha as modificações implementadas e os benefícios alcançados com essas mudanças.
Após o sucesso do projeto inicial de partilha de mensagens, a empresa decidiu ampliar o sistema para atender a todas as empresas do grupo, melhorando a robustez e a segurança da aplicação. Este novo desenvolvimento, denominado PD2, concentra-se na criação de uma arquitetura mais segura e eficiente, integrando uma API Gateway para reforçar a autenticação e a segurança das comunicações.
Falar do gin
A API Gateway introduzida desempenha um papel crucial ao atuar como intermediária entre clientes e servidores, gerindo a autenticação, encaminhamento de pedidos e garantindo canais de comunicação seguros através de TLS. Este componente centraliza a autenticação dos utilizadores, a gestão dos tokens JWT e a proteção das trocas de mensagens, garantindo a integridade e confidencialidade dos dados.
## Mudanças Implementadas
Optámos por utilizar a framework **Gin** para o desenvolvimento da REST API devido à nossa experiência prévia com esta tecnologia, o que facilitou a sua adoção e implementação. Gin é uma framework web em Go reconhecida pela sua alta performance e simplicidade, permitindo lidar eficientemente com um grande número de pedidos simultaneos. Oferece funcionalidades essenciais como routing flexível, middleware para gestão de autenticação e autorização, e uma documentação robusta.
### Microsserviços
## Microsserviços
![Arquitetura](report_content/microservices-pd2.png)
#### Gateway
### Gateway
A principal alteração na arquitetura foi a introdução de uma API Gateway, que atua como intermediária entre o cliente e o servidor. A API Gateway é responsável pela autenticação dos utilizadores, criação de um canal seguro, e encaminhamento dos pedidos ao servidor.
##### Funções da Gateway
#### Funções da Gateway
1. **Autenticação de Utilizadores**: A API Gateway lida com os processos de login e registo dos utilizadores, armazenando o ID do utilizador e uma hash da palavra-passe, e validando o certificado do utilizador.
@ -24,7 +24,7 @@ A principal alteração na arquitetura foi a introdução de uma API Gateway, qu
1. **Criação de Canal Seguro**: A comunicação entre o cliente e a API Gateway, assim como entre a API Gateway e o servidor, é protegida utilizando o protocolo TLS, garantindo a segurança dos dados transmitidos.
##### Endpoints da Gateway
#### Endpoints da Gateway
Foram adicionados novos endpoints à API Gateway para lidar com a autenticação e as operações de mensagens:
@ -40,10 +40,18 @@ Foram adicionados novos endpoints à API Gateway para lidar com a autenticação
- `GET /cert/:user`: Obtém o certificado de outro utilizador.
- `POST /message`: Envia uma mensagem para um destinatário.
#### Token de Autenticação JWT
Ao fazer login, a API Gateway gera um token JWT para o utilizador autenticado. Esse token é enviado ao cliente, que deve incluí-lo no campo "Token" do header de cada request subsequente.
#### Base de Dados da API Gateway
A API Gateway utiliza uma base de dados SQLite3 para armazenar os utilizadores e as hashes das suas palavra-passes.
### Servidor
O servidor foi ajustado para trabalhar em conjunto com a API Gateway.
Aceita conexões apenas provenientes da API Gateway, verificando isso através do certificado enviado pela gateway no início da conexão TLS.
Aceita conexões apenas provenientes da API Gateway, verificando isso através do certificado enviado pela mesma no início da conexão TLS.
O servidor confia plenamente na Gateway, enviando qualquer informação que seja pedida.
#### Endpoints do Servidor
@ -56,34 +64,26 @@ Foram mantidos e ajustados os seguintes endpoints no servidor para corresponder
- `POST /message/:user`: Armazena uma mensagem para um utilizador.
- `POST /cert/:user`: Armazena o certificado de um utilizador.
### Token de Autenticação JWT
Ao fazer login, a API Gateway gera um token JWT para o utilizador autenticado. Esse token é enviado ao cliente, que deve incluí-lo no campo "Token" do header de cada request subsequente.
### Base de Dados da API Gateway
A API Gateway utiliza uma base de dados SQLite3 para armazenar os utilizadores e as hashes das suas palavra-passes.
## Criptografia
O mecanismo de cifra das mensagens manteve-se, com a exceção de uma pequena alteração na assinatura do conteúdo. Decidimos colocar o id do recetor na assinatura digital, visando garantir que este tenha a certeza de que a mensagem é para ele.
O mecanismo de cifra das mensagens manteve-se, com a exceção de uma pequena alteração na assinatura do conteúdo. Decidimos colocar o id do recetor na assinatura digital, visando garantir que este tenha a certeza de que a mensagem é dirigida a si.
![Digital Envelope](report_content/digital_envelope.jpeg)
![Digital Envelope](report_content/digital-envelope-diagram.jpg)
## Execução
### Gateway
A gateway utiliza o valor da variável de ambiente "SECRET_KEY" para criar os tokens JWT.
A gateway utiliza o valor da variável de ambiente "SECRET_KEY" para criar e validar os tokens JWT.
Esta variável pode ser inicializada desta forma
```bash
SECRET_KEY=thisisasecretkey go run ./cmd/gateway/gateway.go
> SECRET_KEY=thisisasecretkey go run ./cmd/gateway/gateway.go
```
### Servidor
O servidor pode ser corrido da seguinte forma.
```bash
go run ./cmd/server/server.go
> go run ./cmd/server/server.go
```
### Cliente
@ -91,7 +91,18 @@ go run ./cmd/server/server.go
O cliente pode ser corrido da seguinte forma.
```bash
go run ./cmd/client/client.go -user ./certs/client2/client2.p12 COMANDO_AQUI
> go run ./cmd/client/client.go help
```
```
Comandos da aplicação cliente:
-user <FNAME>: Especifica o ficheiro com dados do utilizador. Por omissão, será assumido que esse ficheiro é userdata.p12.
send <UID> <SUBJECT>: Envia uma mensagem com assunto <SUBJECT> destinada ao utilizador com identificador <UID>. O conteúdo da mensagem será lido do stdin, e o tamanho deve ser limitado a 1000 bytes.
askqueue: Solicita ao servidor que lhe envie a lista de mensagens não lidas da queue do utilizador.
getmsg <NUM>: Solicita ao servidor o envio da mensagem da sua queue com número <NUM>.
register: Solicita ao servidor o registo do utilizador.
login: Solicita ao servidor o login do utilizador.
logout: Elimina o token de acesso do utilizador.
help: Imprime instruções de uso do programa.
```
## Conclusão

View file

@ -30,6 +30,11 @@ func Run() {
if flag.NArg() == 0 {
log.Fatalln("No command provided. Use 'help' for instructions.")
}
command := flag.Arg(0)
if command == "help"{
showHelp()
return
}
//Get user KeyStore
password := readStdin("Insert keystore passphrase")
clientKeyStore, err := cryptoUtils.LoadKeyStore(userFile, password)
@ -43,7 +48,6 @@ func Run() {
printError("no pseudonym field on my certificate")
os.Exit(1)
}
command := flag.Arg(0)
// Check if token is in memory
var token string
if command != "login" && command != "register" {
@ -142,7 +146,7 @@ func Run() {
printError(err.Error())
os.Exit(1)
}
printInfo("Registered successfully")
printInfo("Registered successfully")
case "login":
if flag.NArg() != 1 {
printError("MSG SERVICE: command error!")
@ -172,16 +176,14 @@ func Run() {
printError(err.Error())
os.Exit(1)
}
printInfo("Login was successful")
printInfo("Login was successful")
case "logout":
err := os.Remove(tokenFolder + myUID)
if err != nil {
printError(err.Error())
}
printInfo("Logout was successful")
case "help":
showHelp()
case "logout":
err := os.Remove(tokenFolder + myUID)
if err != nil {
printError(err.Error())
}
printInfo("Logout was successful")
default:
printError("MSG SERVICE: command error!")
@ -494,10 +496,10 @@ func getUnreadMessagesInfo(keyStore cryptoUtils.KeyStore, page int, pageSize int
}
parsedURL = parsedURL.JoinPath("queue")
query := parsedURL.Query()
query.Set("page", fmt.Sprint(page))
query.Set("pagesize", fmt.Sprint(pageSize))
parsedURL.RawQuery = query.Encode()
query := parsedURL.Query()
query.Set("page", fmt.Sprint(page))
query.Set("pagesize", fmt.Sprint(pageSize))
parsedURL.RawQuery = query.Encode()
req, err := http.NewRequest("GET", parsedURL.String(), nil)
if err != nil {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View file

@ -1 +1 @@
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcyNzg4OTMsInN1YiI6IkNMMiJ9.v8_aRomq2oYTMBKwr0yWyJj808t3ju7mmLG1gD7ZuRY
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcyODA0MjIsInN1YiI6IkNMMiJ9.ZetiLnLMExXVhE5mf8VUR22hCjE5odT4sqU934Ed5T4