PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie verbinde ich mich von Phoenix Web App über SSL mit PostgreSQL?

Hintergrund

Ich hatte das gleiche Problem beim Verbinden von Phoenix/Ecto/Postgrex mit Azure Database for PostgreSQL-Server. Auch nach dem Setzen von ssl: true In meiner Repo-Konfiguration konnte ich immer noch keine Verbindung zur Datenbank mit Postgrex herstellen, obwohl die Verbindung mit psql "postgresql://...?sslmode=require" -U ... hergestellt wurde auf der gleichen Maschine erfolgreich. Der mit ssl: true zurückgegebene Fehler war:

[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
    ...

Nachdem ich den Quellcode durchsucht hatte, entdeckte ich, dass der fehlgeschlagene Aufruf tatsächlich ssl.connect/3 war Aufruf von dem Erlang-SSL-Modul :

# 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

Als ich etwas mit Wireshark schnüffelte, konnte ich das sehen, als ich erfolgreich eine Verbindung mit psql herstellte , konnte ich Pakete mit TLSV1.2 sehen als Protokoll, aber wenn Postgrex eine Verbindung mit ssl: true herstellte Ich habe Pakete mit SSL gesehen als Protokoll, bevor die Verbindung fehlschlägt.

Schauen Sie sich die Ecto.Adapters.Postgres-Optionsdokumentation an , sehen Sie, dass es einen ssl_opts gibt Konfigurationsoption, die schließlich an :ssl.connect/3 übergeben wird in dem Sie versions einstellen können um die für die Verbindung verwendete(n) TLS-Version(en) zu überschreiben.

Lösung

Ich konnte eine Verbindung zur Datenbank herstellen, indem ich Folgendes zu meiner Repo-Konfiguration hinzufügte:

ssl_opts: [
  versions: [:"tlsv1.2"]
]

Meine vollständige Konfiguration sah am Ende so aus:

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"]
  ]

Ich bin mir nicht wirklich sicher, warum die TLS-Version explizit festgelegt werden muss, vielleicht kann jemand mit mehr Erfahrung auf diesem Gebiet etwas Licht ins Dunkel bringen.