OpenMED - Identity e Access Management

@mj8284 che ne pensi?

Ciao @massimo.scattarella!

Innanzitutto grazie mille, mi sembra tutto davvero molto interessante! E se ti sei divertito…ancora meglio! :slight_smile:

Scusa la latitanza ma stiamo ultimando la prima versione della GUI, che verrà rilasciata nei prossimi giorni.

Proviamo ad integrare il lavoro che hai fatto con l’installazione su AWS, in modo da concludere il PoC: sicuramente ci saranno domande per te :smiley:

In questa fase penso possa essere utile avere anche la GUI, pertanto proverei ad installare anche Konga: ho aggiunto una issue in modo da tenere traccia del task.

Sulle customizzazione dei template di Keycloak come sei messo (anche su questo c’è un task)? Hai già avuto modo di lavorarci? Abbiamo provato a creare un template “openmed” estendendo “keycloak”, quello fornito, ma viene su una mezza schifezza. Puoi darci una mano anche su quello? :wink:

Scusa ti ho risposto solo ora perché non ho moltissimo tempo. Per la custom del template keycloak non dovrebbe essere difficile, basta copiare la cartella di keycloak e modificare html e css con i vostri template/requisiti. Es ho trovato questa guida https://www.baeldung.com/spring-keycloak-custom-themes.
Per il resto kong siete riusciti a farlo andare?

@massimo.scattarella figurati capisco benissimo :slight_smile:

Si nel frattempo abbiamo inserito nel progetto di frontend una cartella con la prima versione del template: non fa praticamente nulla, cambia solo il background, ma era giusto per avere il primo mattoncino :wink:

Per Kong abbiamo iniziato a lavorarci certo, sembra davvero promettente.

L’obiettivo dei prossimi giorni è quello di creare un ambiente di sviluppo dockerizzato che abbia anche keycloak + kong + konga: qualcosa di molto simile a questo più ovviamente le nostre componenti applicative.

Che ti sembra?

Si, sembra molto simile a quello che faccio io con Ansible. L’unica cosa e che non vedo il db di konga, ma magari quell’immagine lo fa internamente. Nel mio caso configuro anche service e route su kong direttamente con ansible, ma niente di difficile, e’ un ruolo che fa curl semplicissime. Nel tuo caso potresti anche usare la GUI di konga inizialmente.

1 Mi Piace

Ciao @mj8284 ho provato a farti una demo con docker-compose, nel readme troverai i run dei service perche’ per fare bene le dipendenze per lo start al momento giusto ci vuole un po di piu’ di tempo, e per un poc non ne vale la pena. Butta un occhio a https://github.com/MassimoScattarella/demo-openmed/tree/develop , puo’ essere un inizio a sistemae anche le idee, sicuramente si potrebbe completare e sistemare meglio il readme con le variabili e i path corretti. Io propongo di iniziare a buttargli un occhio. Se funziona potremmo usarlo per altri casi con @msciab e @imoas83 che sta lavorando a una roba simile.

Fammi sapere.

1 Mi Piace

Ciao @massimo.scattarella grazie mille!! Appena riusciamo ci ritagliamo un momento per integrare questa parte nei componenti di sviluppo!

Ci aggiorniamo appena possibile, nel frattempo grazie ancora per i tuoi contributi e buone feste! :slight_smile:

Ciao @massimo.scattarella,
sto provando anch’io ad integrare Kong e Konga nel flusso di autenticazione delle API, e credo di essere ad un buon punto, però son bloccato su un problema di CORS sul quale magari mi sai dare qualche dritta.

Ti spiego cosa ho fatto fino ad ora:

  • sono riuscito a configurare correttamente kong e keycloak (purtroppo non ho avuto occasione di usare il tuo docker-compose perchè è un lavoro che avevo già fatto prima che lo pubblicassi!)
  • ho configurato un service + route su Kong, che punta ad uno degli endpoint OpenWhisk
  • disabilitando il plugin Keycloak su Kong, ho verificato la raggiungibilità (senza autenticazione) dell’endpoint tramite Kong
  • riabilitando il plugin ho verificato che Kong restituisse correttamente 401 Unauthorized sulla stessa chiamata all’endpoint
  • ho configurato il frontend React in modo da passare come header ‘Authorization’ della richiesta il bearer token ottenuto da keycloak

A questo punto riscontro un problema: l’aggiunta dell’header induce axios (la libreria usata dal frontend) ad usare il CORS mandando una pre-flight request, ma a questo tipo di richieste Kong mi restituisce un 404. Ti allego un’immagine della chiamata:

Ho provato ad installare e configurare il plugin CORS, ma il problema rimane…sai darmi qualche consiglio su come procedere?

Grazie in anticipo per l’aiuto! :slight_smile:

Ciao @P3nt4 hai provato a mettere dichiarare sulla rotta tutti i methods , GET, POST …e OPTIONS? non sono sicuro ma fai una prova, nel tuo caso specifico dovrebbe essere GET,OPTIONS

Si ho provato GET e OPTIONS, che sono i due metodi che usa la chiamata, ma non è cambiato niente

@P3nt4 ho provato in locale, e ho messo il plugin cors sul servizio che riceve la chiamata (come nel tuo caso per facility) ma visto che il plugin oidc gira tutto sul servizio di keycloak, ho messo anche su quest’ultimo il plugin cors e tutto mi funziona. Senza il plugin cors sul servizio keycloak mi dava un errore simile al tuo.
Ti do un esempio di come ho configurato cors (ho messo di tutto per fare piu’ veloce, te togli tutto quello che non serve):

curl -i -X POST http://localhost:8001/services/keycloak-svc/plugins \
    --data "name=cors"  \
    --data "config.origins=http://localhost:3000" \
    --data "config.origins=https://server.massimoscattarella.com" \
    --data "config.origins=*" \
    --data "config.methods=GET" \
    --data "config.methods=POST" \
    --data "config.methods=PUT" \
    --data "config.methods=PATCH" \
    --data "config.methods=DELETE" \
    --data "config.methods=OPTIONS" \
    --data "config.headers=Accept" \
    --data "config.headers=Accept-Version" \
    --data "config.headers=Content-Length" \
    --data "config.headers=Content-MD5" \
    --data "config.headers=Content-Type" \
    --data "config.headers=Date" \
    --data "config.headers=X-Auth-Token" \
    --data "config.headers=X-Requested-With" \
    --data "config.headers=Access-Control-Allow-Origin" \
    --data "config.headers=Access-Control-Allow-Headers" \
    --data "config.headers=User-Agent" \
    --data "config.headers=Origin" \
    --data "config.headers=Authorization" \
    --data "config.headers=Referer" \
    --data "config.exposed_headers=Accept" \
    --data "config.exposed_headers=Accept-Version" \
    --data "config.exposed_headers=Content-Length" \
    --data "config.exposed_headers=Content-MD5" \
    --data "config.exposed_headers=Content-Type" \
    --data "config.exposed_headers=Date" \
    --data "config.exposed_headers=X-Auth-Token" \
    --data "config.exposed_headers=X-Requested-With" \
    --data "config.exposed_headers=Access-Control-Allow-Origin" \
    --data "config.exposed_headers=Access-Control-Allow-Headers" \
    --data "config.exposed_headers=User-Agent" \
    --data "config.exposed_headers=Origin" \
    --data "config.exposed_headers=Authorization" \
    --data "config.exposed_headers=Referer" \
    --data "config.credentials=true" \
    --data "config.max_age=3600"

Per provare il caso piu’ simile al tuo ho fatto un hook reactjs con axios:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function MyComponent() {
    const [error, setError] = useState(null);
    const [isLoaded, setIsLoaded] = useState(false);
    const [items, setItems] = useState([]);
    
  
    // Note: the empty deps array [] means
    // this useEffect will run once
    // similar to componentDidMount()

    useEffect(() => {
      const fetchData = async () => {
        try {
          const result = await axios(
            'https://server.massimoscattarella.com/guestbook/entries'
            );
          setIsLoaded(true);
          setItems(result.data.entries);
        } catch (error) {
          if (error.response) {
            console.log(error.response.data);
            console.log(error.response.status);
            console.log(error.response.headers);
          } else {
            console.log('no error.response');
          }
          setIsLoaded(true);
          setError(error);
        }
      };
  
      fetchData();
    }, []);

  
  
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <ul>
          {items.map((item,index) => (
            <li key={index}>
              {item.createdAt} {item.name} {item.comment}
            </li>
          ))}
        </ul>
      );
    }
  }


export default MyComponent;

Ovviamente essendo tutto ajax ho messo sul client keyclaok Access-Type: bearer-only , altrimenti prova a fare redirect in automatico. Una volta recuperato il 403 farai te redirect a mano.

Fammi sapere se e’ bastato altrimenti indago ancora un po.

Ciao @massimo.scattarella,
ho provato a seguire quello che dici ma forse mi manca un pezzo: su Kong io ho configurato un solo servizio, quello delle facility, su cui ho abilitato il plugin oidc per interagire con Keycloak. Quello che ho provato a fare è stato abilitare anche il plugin cors sullo stesso servizio (usando tutti i parametri come nel tuo esempio), ma il risultato non cambia.

Questa parte non mi è chiara: tu parli di configurare il plugin cors anche sul servizio keycloak, questo significa che hai creato due servizi su kong? O c’è qualche configurazione da abilitare sul server Keycloak?

P.S. ho provato a seguire la tua procedura dockerizzata e sto lavorando su quella, molto efficace! Ho solo un paio di piccole segnalazioni:

  • Nella documentazione il login di Konga è sbagliato, probabilmente a causa di un copia incolla, infatti nel punto 2 fai riferimento a Keycloak invece che a Konga
  • Ho avuto problemi con il container di Kong, mi dava questo errore: “error loading plugin schemas: on plugin ‘oidc’: oidc plugin is enabled but not installed”. Ho risolto cancellando la riga 83 nel docker compose (image: kong:latest)
  • Per installare il plugin cors ho dovuto aggiungerlo alla riga 102 del docker compose (KONG_PLUGINS: “oidc,cors”)

Ciao @massimo.scattarella, ce l’abbiamo fatta!
Dopo il confronto che abbiamo avuto ieri son riuscito a far funzionare la comunicazione dal client react al backend passando per kong + keycloak.

Ho usato il plugin kong che abbiamo trovato ieri, jwt-keycloak, e l’unica accortezza in più è stata configurare come indirizzo keycloak lo stesso sia nel frontend che nel plugin jwt di kong, configurando un ip statico per keycloak nel docker compose.

@mj8284 sta integrando questa parte nel branch develop del progetto, partendo dal tuo repository e allineando le configurazioni.

1 Mi Piace

Buonasera a tutti,
Io ho provato ad impostare tutto l’ambiente e sono arrivato al punto che riesco a loggarmi con il client React, ma non riesco a chiamare le API impostate su ibmcloud perché ho errori di CORS.
La soluzione potrebbe risolvere anche il mio problema?

Ho modificato un paio di punti della documentazione (es. nelle api, credo non siano corretti la definizione delle url e delle funzioni), se volete provo a fare una PR, ma non credo di avere i permessi per farlo.

Grandissimi e bravissimi, sia @P3nt4 che @mj8284 , io e’ la prima volta che provo a contribuire e pensavo andasse peggio :rofl: . Bene dai appena finite di integrare fatemelo sapere che provo ad usarla.

1 Mi Piace

Ciao @stuzzo,
si l’ultimo commit che ho fatto sul progetto ha avuto come effetto secondario quello di attivare l’uso del CORS da parte dell’app React, e molto probabilmente questo crea problemi con IBMCloud.
Sono abbastanza sicuro che la soluzione che include Kong nel giro risolva il tuo problema.

Come già detto @mj8284 sta approntando un rilascio che integri il contributo di Massimo, quindi entro un paio di giorni al max puoi testare il giro completo. Se invece nel frattempo vuoi testare il giro senza Kong, puoi provare cancellando il codice nel commit che ti ho indicato!

Riguardo alla PR: se vuoi prova pure a farla, che io sappia non ci sono problemi di permessi, comunque considera che la documentazione varierà un po’ con l’introduzione di Kong, quindi forse conviene farla dopo? Valuta tu su questo

Buongiorno @P3nt4,
grazie della risposta.

Da quanto mi dici, conviene che aspetti il rilascio delle ultime modifiche così da verificare il problema delle CORS ed eventualmente la proposta di modifica al Readme.

A presto.

Ciao a tutti!!

Finalmente siamo riusciti a rilasciare la versione aggiornata con l’API Gateway, la trovate nel repository ufficiale.

Grazie al fondamentale contributo di @massimo.scattarella e @P3nt4 abbiamo integrato Keycloak + Kong + Konga in un unico ambiente dockerizzato. Manca ancora un passaggio, ma dovrebbe essere solo di configurazione (autenticare le API lato IBMCloud, mentre il client è completamente integrato).

@stuzzo questa è la versione che dovrebbe risolvere il problema CORS: se dovessi avere altri problemi facci sapere :wink:

@massimo.scattarella abbiamo rilasciato tutto il template di keycloak anche se probabilmente si poteva sfoltire…vabbè, lo facciamo con calma nei prossimi giorni :wink:

Provatelo e fateci sapere!

Ciao a tutti!
@mj8284 ho appena provato ad aggiornare il codice e seguire la nuova guida, ma ora ho un problema credo con Kong.

Ho configurato le url in questa maniera:
--data "config.origins=http://localhost:3000" mentre al posto di **API_SERVER** ho inserito il dominio che mi è stato assegnato da IBM cloud. Ora l’errore che ricevo è

no Route matched with those values su questa url http://localhost:8000/auth/realms/OpenMED/protocol/openid-connect/auth?client_id=openmed-app&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F%23%2F&state=755c89c6-7aef-4a29-81e3-f7f1138d83ac&response_mode=fragment&response_type=code&scope=openid&nonce=5d74808f-e905-4f2e-9dc9-d36a25dd812d. Probabilmente mi sto perdendo in qualche passaggio, se qualcuno è disponibile, potremmo anche sentirci una decina di minuti in modo da vedere insieme le configurazioni.

Grazie.

Ciao @stuzzo,
ho l’impressione che hai un problema di configurazione nelle variabili d’ambiente dell’app.
Controlla di aver configurato la variabile REACT_APP_KEYCLOAK a https://172.33.0.100:8443/auth/, perchè dall’errore che hai postato mi sembra che al momento ce l’hai settata su localhost:8000.
Se il problema non è quello scrivimi in privato così ci organizziamo per sentirci!