Microservizi - 1
Introduzione
In questo post descrivo come creare una architettura a microservizi con JHipster.
Architettura
Microservizio
Il microservizio che andremo a creare deve avere totale autonomia ed essere auto-consistente. Questo dice la letteratura. In effetti il microservizio deve svolgere un servizio "completo" a livello di modulo di business logic. Ad esempio in un sistema complesso la gestione delle mail integrata. Quindi deve fornire servizi come l'elenco delle mail di uno specifico utente, crearne, cancellarne, inviarne di nuove.
Per fare questo userà il database per accedere alla lista della mail dello specifico utente (che qui ipotizziamo stiano su un db).
Questo quello che deve fare. Quello che NON deve fare è autenticare l'utente che gli invia le richieste. Quindi di questa fase se ne occuperà un altro modulo. L'autenticazione, in questo prototipo, avverrà mediante token JWT. Creaiamo il microservizio.
Creato con il wizard di JHipster selezionando il tipo di applicazione come "microservizio", l'autenticazione come "JWT" e come servizio di discovery "JHipster Registry".
Importato lo schema dati jdl:
$ jhipster import-jdl test.jh
Dopo ho impostato l'ip del docker del registry, per fare in modo che avvenga il discover del servizio, nei seguenti file (il punto di intervento è reso evidente dalla presenza della porta :8761 che è quella di default del registry):
- /src/main/resources/config/application-dev.yml
- /src/main/resources/config/application-prod.yml
- /src/main/resources/config/bootstrap-prod.yml
- /src/main/resources/config/bootstrap.yml
Per configurare il docker dal quale generare il registry:
- /src/main/docker/central-server-config/docker-config/application.yml
- /src/main/docker/central-server-config/localhost-config/application.yml
- /src/main/docker/app.yml
ATTENZIONE: l'esecuzione dell'applicazione che segue è stata lanciata solo dopo aver configurato il registry come al passo successivo, altrimenti non partirà mai.
L'esecuzione dell'applicazione l'ho lanciata con il "Run As/Java Application" di Eclipse:
Registry
Questa componente ha le seguenti mansioni:
- Implementa un Eureka server che fa il discovery per le applicazioni. Così JHipster gestisce il routing e il load balancing per la scalabilità delle applicazioni.
- Fa da Spring Cloud Config Server e fornisce la configurazione a run-time a tutte le applicazioni.
- Fa anche da server per l'amministrazione e il monitoraggio di tutte le applicazioni.
Il servizio di discovering, basato su "Netflix Eureka server", consiste nel censire tutte le applicazioni che fanno parte della soluzione Eureka > Instances :
E' così che nelle architetture a microservizi il gateway sa quali microservizi sono disponibili, e con quali istanze sono in esecuzione, e per le applicazioni monolitiche è così che la cache distribuita di Hazelcast può scalare.
Dal registry è possibile anche gestire la configurazione centralmente dal menu: Configuration > Cloud Config:
E vedere la configurazione di ogni singola applicazione registrata dal menu: Administration > Configuration. Questa la configurazione del mio microservizio:
Le applicazioni quando vengono lanciate la prima cosa che fanno è collegarsi al JHipster Registry per ottenerne la configurazione ed essere "registrate". Questo vale sia per i microservizi che per i gateway (vedi nel paragrafo "Microservizio" dove configurare la chiave con l'ip e la porta del Registry).
Nota: tutte le applicazioni create con il wizard di JHipster avranno il client Eureka (del servizio di discovering) incluso, anche il Registry, solo che questo sarà caratterizzato dalla variabile eureka.client.fetchRegistry=false. Cosa verificabile mediante il servizio del Registry che ci mostra le configurazioni delle componenti (Gateway, microservizi e Registry stesso).
Un'altra funzione utilissima demandata al Registry è quella per la gestione dei parametri criptati. E' necessario aver installato Java Cryptography Extension (JCE). Per fare in modo che, ad esempio, la password per l'accesso al database non venga messa in chiaro nei file .yml basterà configurare una password per la chiave simmetrica in "encrypt.key" nel bootstrap.yml del Registry oppure come variabile di ambiente "ENCRYPT_KEY" come ho fatto io nel file jhipster-registry.yml del docker del Registry. Anche la gui web del Registry fornisce una pagina apposita per usare questa funzione Configuration > Encryption:
Per usarla praticamente nei file .yml di configurazione in maniera criptata:
password= '{cipher}myciphertextafterencryotion'
Il servizio è accessibile mediante:
IPDELREGISTRY:8761/config/encrypt -d mypassword
Servizio da usare ogni volta che si deve mandare un parametro di configurazione sensibile ad un utilizzatore.
Utilizzo
Andando nel menu Administration > API e selezionando la app di interesse dal menu a tendina in alto a destra avremo accesso ai servizi:
E possiamo provare le chiamate REST/API ai servizi:
Installazione
Per la soluzione ho usato l'immagine docker del registry (jhipster-registry),ottenendola mediante docker compose, e usando la configurazione presente nella dir del progetto a microservizi, creato al passo precedente, e lanciando il comando:
$ docker-compose -f src/main/docker/jhipster-registry.yml up
Dopo il lancio va fermato il servizio per gestirlo da Eclipse come specificato in seguito.
Prima di crearla potrebbe essere utile modificare il file /src/main/docker/jhipster-registry.yml che verrà usato per la configurazione. Ad esempio io ho inserito la variabile di ambiente: ENCRYPT_KEY=chiaveCript necessaria al crypt/decrypt descritto prima.
Ho usato il plugin per Eclipse Docker Tooling che prima ho installato, sotto Windows, DockerToolbox.exe. Con questo lancio e fermo lo specifico container docker.
Il Gateway ed il Microservizio in esecuzione su due istanze viste dal registry:
Verrà creato un container docker con le specifiche del file puntanto dal comando precedente (jhipster-registry.yml) e verrà lanciato. Se si dispone del plugin per Eclipse di docker conviene fermarlo e gestirne lo start/stop dal plugin (consigliato).
Il compose prende un file di ocnfigurazione che è presente in /src/main/docker/central-server-config/ e che è comune a tutte le applicazioni create con JHipster impostate per l'uso di JHipster-Registry.
Gateway
Creata con il wizard dal sito.
Per il lancio del progetto anche qui con "Run As/Java Application" di Eclipse:
Ogni applicazione a microservizi registrata sul Registry è raggiungibile mediante questo, qui la chiamata del microservizio "mailms" passando dal gateway:
Che chiaramente dice che non siamo autorizzati.
Ogni applicazione, microservizi e gateway, devono registrarsi al Registry (vedi nel paragrafo "Microservizio" dove configurare la chiave con l'ip e la porta del Registry).
Sicurezza
Per questo scenario, nella realizzazione del progetto mediante wizard dal sito, ho scelto l'autenticazione "JWT".
JWT (JSON Web Token) è un metodo per rendere sicure le applicazioni in una architettura a microservizi.
JHipster usa la libreria JJWT , fornita da Okta, per implementare JWT.
Questa tecnologia si basa sull'uso di un token che viene generato dal gateway ed inviato ai microservizi sottostanti con i quali si condivide una chiave segreta, in modo che il microservizio possa validare il token e autenticare l'utente che sta usando il token.
I token sono auto-sufficienti perché contengono le informazioni relative sia all'autenticazione che alle autorizzazioni dell'utente. Quindi il microservizio non ha bisogno di accedere a database esterni (fondamentale per garantire la scalabilità).
JWT è un sistema di sicurezza "stateless", cioè senza memoria di stato. Questa è una ottima scelta se si vuole scalare la propria applicazione su più server.Questa soluzione prevede un token che contiene il nome utente e le sue autorizzazioni. Il token è firmato e non può essere alterato dall'utente.
Impostazioni
JHipster usa una chiave segreta configurata in due proprietà di Spring Boot:
jhipster.security.authentication.jwt.secret
jhipster.security.authentication.jwt.base64-secret
La seconda, come si capisce dal nome, consiste in una chiave codificata in base64 e quindi vine considerata più sicura. Se entrambe sono configurate verrà usata la "secret" meno sicura per retro-compatibilità ma un warning verrà mostrato all'avvio della applicazione.
Entrambe devono essere lunghe almeno 512 bits e vengono inserite nei file "application-*.yml":
Si consiglia di tenere al sicuro quella di produzione e fare in modo che, tale file, venga inviato con una connessione SCP da un sysadmin nella stessa directory del WAR della nostra applicazione.
Si suggerisce anche di cambiare la password di "admin" e di "user" dall'apposito menu "Account>Password" nel momento in cui si va in produzione.
Quest'opera è distribuita con Licenza Creative Commons Attribuzione 4.0 Internazionale (CC BY 4.0) - Condividi allo stesso modo
Commenti
Posta un commento