Mi sono imbattuto in un comportamento piuttosto curioso utilizzando DBeaver con un server MySQL locale.
All’avvio di DBeaver, il tentativo di connessione falliva con il messaggio:
Public Key Retrieval is not allowed
La cosa sorprendente era che bastava aprire un terminale ed eseguire:
mysql -u root -p -h 127.0.0.1
Una volta autenticato con il client a riga di comando, tornando in DBeaver la connessione funzionava perfettamente.
Il contesto
La configurazione del server era la seguente:
- MySQL locale su Ubuntu;
- utente
rootconfigurato con il plugin di autenticazionecaching_sha2_password; - DBeaver collegato inizialmente all’host
localhost.
Verificando il server:
SELECT user, host, plugin FROM mysql.user;
ottenevo:
root | % | caching_sha2_password
e:
SHOW VARIABLES LIKE 'default_authentication_plugin';
restituiva:
+-------------------------------+-----------------------+ | Variable_name | Value | +-------------------------------+-----------------------+ | default_authentication_plugin | caching_sha2_password | +-------------------------------+-----------------------+
Flusso delle informazioni
Per capire quello che succede dobbiamo studiare come avviene l’autentiazione di un clinet (sia esso mysql o DBeaver) con il server. Questo schema illustra come viene gestita l’autenticazione
Server
|
Client | tabella mysql.user
| | root -> hash della password H1
| |
| digito password = pippo123 |
| |
|---- chiede la chiave pubblica RSA -->|
| |
|<----------- chiave pubblica ---------|
| |
| cifra "pippo123" con la chiave |
| pubblica -> "x76f78avhh!6" |
| |
|------ password cifrata ------------->|
| |
| | decifra "x76f78avhh!6" con la chiave privata
| |
| | ottiene "pippo123"
| |
| | calcola l'hash della password -> H2
| |
| | confronta con l'hash memorizzato H1
| |
|<-------------------------------------| se H1==H2 OK
|
Client autenticato
A questo punto sorge spontanea una domanda: se il server mette a disposizione la propria chiave pubblica, perché DBeaver non la richiede automaticamente?
Il motivo è di sicurezza. Se un aggressore riuscisse a frapporsi tra client e server (attacco Man-in-the-Middle), potrebbe sostituire la chiave pubblica del server con una propria. Il client cifrerebbe la password usando la chiave dell’aggressore, che potrebbe quindi decifrarla e inoltrarla successivamente al vero server senza che nessuna delle due parti se ne accorga.
Per questo motivo il driver JDBC, per impostazione predefinita, rifiuta di recuperare automaticamente la chiave pubblica del server. L’opzione allowPublicKeyRetrieval=true comunica invece al driver che, nello specifico contesto, questa operazione è considerata sicura.
La soluzione
Nel mio caso è stato sufficiente modificare la configurazione della connessione in DBeaver.
- Utilizzare come host:
127.0.0.1
invece di:
localhost
- Nelle proprietà del driver abilitare:
allowPublicKeyRetrieval = true
- Trattandosi di una macchina di sviluppo locale, potrei anche mantenere disabilitato SSL:
useSSL = false
oppure, nelle versioni più recenti del driver:
sslMode = DISABLED
Dopo queste modifiche (le ultime due non sono necessarie) la connessione funziona regolarmente fin dal primo tentativo, senza dover eseguire preventivamente il client mysql.
Prova del 9
Ho rimesso l’impostazione allowPublicKeyRetrieval=false da Dbeaver e sono uscito dal programma.
Poi ho riavviato il container con mysql
marcob@bombelli$ docker restart 6d36d6599ad3
6d36d6599ad3
marcob@bombelli$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d36d6599ad3 mysql:8.0 "docker-entrypoint.s…" 15 months ago Up 1 second 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp mio-mysql
A questo punto, riavviato il servizio, anche la cache viene cancellata.
Ora riavvio DBeaver.
Public Key Retrieval is not allowed
Il comportamento è quello atteso, ho riprodotto l’errore iniziale in modo controllato, infatti la cache è stata cancellata dal riavvio del container e DBeaver non l’ha trovata. La sua politica di non consentire l’acquisizione della chiave pubblica del server gli impedisce di innescare tutto il flusso della figura sopra.
Invece il client mysql (il programma /usr/bin/mysql, per intenderci) va direttamente a chiedere la chiave pubblica: anche questo lo potrei gestire diversamente ma in un contesto locale non ha senso porsi più problemi del necessario, ad un certo punto ben venga il rasoio di Occam: stiamo contattando un servizio sulla stessa macchina quindi non usciamo neanche dal localhost (sì: usiamo TCP/IP perché mysql è in un container Docker e non esiste il socket Unix come spiegato qui).
Dunque ho due modi per uscire da questo problema:
- o consento a DBeaver di andare a chiedere la chiave pubblica del server
- oppure, con un accesso da terminale, faccio in modo che la password finisca nella cache, così che DBeaver poi possa trovarla.









Commenti recenti