Contexte
Je rencontrais le même problème en connectant Phoenix/Ecto/Postgrex au serveur Azure Database pour PostgreSQL. Même après avoir défini ssl: true
dans ma configuration Repo, je n'étais toujours pas en mesure de me connecter à la base de données avec Postgrex même si je me connectais en utilisant psql "postgresql://...?sslmode=require" -U ...
sur la même machine a réussi. L'erreur renvoyée avec ssl: true
était :
[error] Postgrex.Protocol (#PID<0.1853.0>) failed to connect: **(DBConnection.ConnectionError) ssl connect: closed
** (DBConnection.ConnectionError) connection not available because of disconnection
(db_connection) lib/db_connection.ex:926: DBConnection.checkout/2
...
Après avoir fouillé dans le code source, j'ai découvert que l'appel défaillant était en fait le ssl.connect/3
appel depuis le module ssl d'Erlang
:
# deps/postgrex/lib/postgrex/protocol.ex:535
defp ssl_connect(%{sock: {:gen_tcp, sock}, timeout: timeout} = s, status) do
case :ssl.connect(sock, status.opts[:ssl_opts] || [], timeout) do
{:ok, ssl_sock} ->
startup(%{s | sock: {:ssl, ssl_sock}}, status)
{:error, reason} ->
disconnect(s, :ssl, "connect", reason)
end
end
En fouinant avec Wireshark, j'ai pu voir cela lors de la connexion avec psql
, je pouvais voir des paquets avec TLSV1.2
comme protocole, mais lorsque postgrex se connectait avec ssl: true
Je voyais des paquets avec SSL
comme protocole avant d'échouer à se connecter.
En regardant la docs sur les options Ecto.Adapters.Postgres
, vous verrez qu'il y a un ssl_opts
option de configuration qui finit par être transmise à :ssl.connect/3
dans lequel vous pouvez définir des versions
pour remplacer la ou les versions TLS utilisées pour se connecter.
Solution
J'ai pu me connecter à la base de données en ajoutant ce qui suit à ma configuration Repo :
ssl_opts: [
versions: [:"tlsv1.2"]
]
Ma configuration complète a fini par ressembler à ceci :
config :myapp, Myapp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "[email protected]",
password: "...",
database: "myapp_dev",
port: 5432,
hostname: "dev-db.postgres.database.azure.com",
pool_size: 10,
ssl: true,
ssl_opts: [
versions: [:"tlsv1.2"]
]
Je ne sais pas vraiment pourquoi la version TLS doit être définie explicitement, peut-être que quelqu'un avec plus d'expertise dans ce domaine peut nous éclairer à ce sujet.