Kong Gateway è una gateway API open source che assicura che solo le richieste corrette entrino, gestendo la sicurezza, il limite di velocità, il logging e altro. OPA (Open Policy Agent) è un motore di policy open source che prende il controllo delle decisioni sulla sicurezza e sull’accesso. Pensatelo come la mente che decoppola l’applicazione delle policy dal vostro app, in modo che i vostri servizi non debbano preoccuparsi dell’applicazione delle regole. Invece, OPA fa il lavoro con il suo linguaggio Rego, valutando le policy attraverso API, microservizi o anche Kubernetes. È flessibile e sicuro, e semplifica l’aggiornamento delle policy. OPA funziona valutando tre elementi chiave: input (dati in tempo reale come richieste), dati (informazioni esterne come i ruoli utente) e policy (la logica in Rego che decide se “consentire” o “nega”). Insieme, questi componenti permettono ad OPA di mantenere alta la vostra sicurezza mentre mantiene le cose semplici e coerenti.
Cosa cerchiamo di ottenere o risolvere?
Oftentimes, i dati in OPA sono come un vecchio amico costante — statici o in graduale cambiamento. Vengono utilizzati insieme ai dati di input in continuo cambiamento per prendere decisioni intelligenti. Ma immaginate un sistema con una fitta rete di microservizi, tonnellate di utenti e un database di massa come PostgreSQL. Questo sistema gestisce un alto volume di transazioni ogni secondo e necessita di mantenere la velocità e il throughput senza alcuno sforzo.
Il controllo dell’accesso a granularità fine in un sistema del genere è difficile, ma con OPA, è possibile scaricare il carico pesante dai vostri microservizi e gestirlo a livello di gateway. Insieme a Kong API Gateway e OPA, si ottengono sia un throughput di prim’ordine sia un preciso controllo dell’accesso.
Come mantenere dati utente accuratezze senza rallentare le cose? Colpire costantemente quel database PostgreSQL per recuperare milioni di record è sia costoso che lento. Ottenere sia accuratezza sia velocità solitamente richiede compromessi tra le due. Cerchiamo di trovare un equilibrio pratico sviluppando un plugin personalizzato (a livello di gateway) che carica frequentemente e memorizza in cache locale i dati per l’uso da parte di OPA nella valutazione delle sue politiche.
Demo
Fino ad ora l’ho configurato con dati di esempio in PostgreSQL, contenenti informazioni utente come nome, email e ruolo. Quando un utente tenta di accedere a un servizio attraverso un URL specifico, OPA valuta se la richiesta è permessa. La politica Rego controlla l’URL della richiesta (risorsa), il metodo e il ruolo dell’utente, quindi restituisce true o false in base alle regole. Se è true, la richiesta è autorizzata a passare; se è false, l’accesso è negato. Per ora, è una configurazione diretta. Facciamo un salto nel plugin personalizzato. Per una migliore comprensione della sua implementazione, si prega di fare riferimento al diagramma sottostante.
Quando una richiesta arriva attraverso il Proxy Kong, il plugin personalizzato Kong viene attivato. Il plugin recupererebbe i dati necessari e li passerebbe a OPA insieme all’input/alla query. Questo recupero dei dati ha due parti: una consiste nel cercare in Redis per trovare i valori necessari, e se trovati, li passa a OPA; altrimenti, eseguirebbe ulteriori query in Postgres e recupererebbe i dati, memorizzandoli in Redis prima di passarli a OPA. Possiamo rivedere questo processo quando eseguiamo i comandi nella prossima sezione e osserviamo i log. OPA prende una decisione (in base alla politica, all’input e ai dati) e se è permessa, Kong continuerà a inviare la richiesta all’API. Utilizzando questo approccio, il numero di query a Postgres è notevolmente ridotto, pur mantenendo i dati disponibili per OPA abbastanza precisi e la bassa latenza.
Per iniziare a costruire un plugin personalizzato, abbiamo bisogno di un handler.lua
in cui è implementata la logica principale del plugin e di un schema.lua
che, come indica il nome, definisce lo schema per la configurazione del plugin. Se state iniziando a imparare come scrivere plugin personalizzati per Kong, si prega di consultare questo link per maggiori informazioni. La documentazione spiega anche come impacchettare e installare il plugin. Procediamo e capiamo la logica di questo plugin.
Il primo passo della demo sarebbe installare OPA, Kong, Postgres e Redis sul vostro setup locale o su un qualsiasi setup cloud. Si prega di clonare questo repository.
Controllate il file yaml docker-compose che ha le configurazioni definite per deployare tutti e quattro i servizi sopra citati. Observate le variabili d’ambiente di Kong per vedere come viene caricato il plugin personalizzato.
Esegui i comandi di seguito per deployare i servizi:
docker-compose build
docker-compose up
Una volta verificato che i contenitori sono in esecuzione, Kong manager e OPA sono disponibili agli endpoint rispettivi https://localhost:8002 e https://localhost:8181 come mostrato di seguito:
Crea un servizio di prova, una route e aggiungi il nostro plugin personalizzato di Kong a questa route usando il comando seguente:
curl -X POST http://localhost:8001/config -F config=@config.yaml
La politica OPA, definita nel file authopa.rego, viene pubblicata e aggiornata al servizio OPA usando il comando seguente:
curl -X PUT http://localhost:8181/v1/policies/mypolicyId -H "Content-Type: application/json" --data-binary @authopa.rego
Questa politica di esempio concede l’accesso alle richieste utente solo se l’utente sta accedendo al percorso /demo con un metodo GET
e ha il ruolo di "Moderatore"
. Possono essere aggiunte regole aggiuntive secondo necessità per personalizzare il controllo dell’accesso in base a differenti criteri.
opa_policy = [
{
"path": "/demo",
"method": "GET",
"allowed_roles": ["Moderator"]
}
]
Ora la configurazione è pronta, ma prima di effettuare il test, ci serve qualche dato di prova da aggiungere in Postgres. Ho aggiunto alcuni dati di esempio (nome, email e ruolo) per alcuni impiegati come mostrato di seguito (fate riferimento a PostgresReadme).
Di seguito una richiesta di esempio fallita e una riuscita:
Ora, per testare la funzionalità principale di questo plugin personalizzato, facciamo due richieste consecutive e controlliamo i log per vedere come avviene il recupero dei dati.
Ecco i log:
2024/09/13 14:05:05 [error] 2535#0: *10309 [kong] redis.lua:19 [authopa] No data found in Redis for key: [email protected], client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "ebbb8b5b57ff4601ff194907e35a3002"
2024/09/13 14:05:05 [info] 2535#0: *10309 [kong] handler.lua:25 [authopa] Fetching roles from PostgreSQL for email: [email protected], client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "ebbb8b5b57ff4601ff194907e35a3002"
2024/09/13 14:05:05 [info] 2535#0: *10309 [kong] postgres.lua:43 [authopa] Fetched roles: Moderator, client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "ebbb8b5b57ff4601ff194907e35a3002"
2024/09/13 14:05:05 [info] 2535#0: *10309 [kong] handler.lua:29 [authopa] Caching user roles in Redis, client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "ebbb8b5b57ff4601ff194907e35a3002"
2024/09/13 14:05:05 [info] 2535#0: *10309 [kong] redis.lua:46 [authopa] Data successfully cached in Redis, client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "ebbb8b5b57ff4601ff194907e35a3002"
2024/09/13 14:05:05 [info] 2535#0: *10309 [kong] opa.lua:37 [authopa] Is Allowed by OPA: true, client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "ebbb8b5b57ff4601ff194907e35a3002"
2024/09/13 14:05:05 [info] 2535#0: *10309 client 192.168.96.1 closed keepalive connection
------------------------------------------------------------------------------------------------------------------------
2024/09/13 14:05:07 [info] 2535#0: *10320 [kong] redis.lua:23 [authopa] Redis result: {"roles":["Moderator"],"email":"[email protected]"}, client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "75bf7a4dbe686d0f95e14621b89aba12"
2024/09/13 14:05:07 [info] 2535#0: *10320 [kong] opa.lua:37 [authopa] Is Allowed by OPA: true, client: 192.168.96.1, server: kong, request: "GET /demo HTTP/1.1", host: "localhost:8000", request_id: "75bf7a4dbe686d0f95e14621b89aba12"
I log mostrano che per la prima richiesta, quando non ci sono dati in Redis, i dati vengono recuperati da Postgres e memorizzati nella cache di Redis prima di essere inoltrati a OPA per l’evaluazione. Nella successiva richiesta, siccome i dati sono disponibili in Redis, la risposta sarà molto più rapida.
Conclusione
In conclusione, combinando Kong Gateway con OPA e implementando il plugin personalizzato con il caching di Redis, bilanciamo efficacemente precisione e velocità per il controllo dell’accesso in ambienti ad alta trafico. Il plugin riduce al minimo il numero di costose query Postgres cachando i ruoli utente in Redis dopo la query iniziale. Nelle richieste successive, i dati vengono recuperati da Redis, riducendo significativamente la latenza mantenendo informazioni utente accurate e aggiornate per le valutazioni delle politiche OPA. Questo approccio assicura che il controllo dell’accesso a grano fine sia gestito efficientemente a livello di gateway senza sacrificare prestazioni o sicurezza, rendendolo una soluzione ideale per la scalabilità di microservizi mentre enforce precise politiche di accesso.
Source:
https://dzone.com/articles/enhanced-api-security-fine-grained-access-control