florinpatrascu / bolt_sips

Neo4j driver for Elixir
Apache License 2.0
256 stars 49 forks source link

Connection difficulty -- Bolt.Sips.Internals.Error Port #Port<0.n> is closed #104

Closed mvellandi closed 2 years ago

mvellandi commented 2 years ago

Precheck

Environment

Current behavior

I'm following the docs N4D demo app instructions, but using a free instance of Neo4j Aura Cloud. On the neo4j discord, Michael Hunger advised I can use neo4j+s:// for the url protocol, since Aura has automatic certificates. Which by the sounds of it, I don't need a certificate via LetsEncrypt for example.

I've tried both starting Bolt.Sips in Application.ex and in iex using start_link -- both providing the same error trace. The elixir app tries to open multiple ports endlessly. I'm only showing two below. As a beginner, I can't think of anything else I could be missing.

Error Log / Stack Trace

Ensure I can connect to the cloud instance at 7687. It should hang.

> nc e0c2e18b.databases.neo4j.io 7687
^C

Starting Bolt connection manually

iex(2)> opts = Application.get_env(:bolt_sips, Bolt)
[
  url: 'neo4j+s://e0c2e18b.databases.neo4j.io:7687',
    basic_auth: [
    username: "neo4j",
    password: "pass"
  ]
]
iex(3)> {:ok, pid} = Bolt.Sips.start_link(opts)
{:ok, #PID<0.297.0>}
iex(4)>
19:52:39.827 [error] Bolt.Sips.Protocol (#PID<0.318.0>) failed to connect: ** (Bolt.Sips.Internals.Error) Port #Port<0.7> is closed

19:52:39.827 [error] Bolt.Sips.Protocol (#PID<0.308.0>) failed to connect: ** (Bolt.Sips.Internals.Error) Port #Port<0.17> is closed

This also happens with url protocol neo4j:// instead

iex(2)> {:ok, pid} = Bolt.Sips.start_link(opts)
{:ok, #PID<0.333.0>}
iex(3)>
20:21:44.837 [error] GenServer Bolt.Sips.Router terminating
** (Protocol.UndefinedError) protocol String.Chars not implemented for %Bolt.Sips.Internals.Error{code: nil, connection_id: 48, function: :handshake, message: "Port #Port<0.6> is closed", type: :connection_error} of type Bolt.Sips.Internals.Error (a struct). This protocol is implemented for the following type(s): Float, DateTime, Time, List, Version.Requirement, Atom, Integer, Version, Date, BitString, NaiveDateTime, URI
    (elixir 1.12.3) lib/string/chars.ex:3: String.Chars.impl_for!/1
    (elixir 1.12.3) lib/string/chars.ex:22: String.Chars.to_string/1
    (bolt_sips 2.0.11) lib/bolt_sips/router.ex:163: Bolt.Sips.Router._configure/1
    (bolt_sips 2.0.11) lib/bolt_sips/router.ex:144: Bolt.Sips.Router.handle_continue/2
    (stdlib 3.16.1) gen_server.erl:695: :gen_server.try_dispatch/4
    (stdlib 3.16.1) gen_server.erl:437: :gen_server.loop/7
    (stdlib 3.16.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:continue, :post_init}
State: [url: 'neo4j://e0c2e18b.databases.neo4j.io:7687', basic_auth: [username: "neo4j", password: "pass"]]

Expected behavior

When using a local DB instance with start_link

iex» {:ok, _neo} = Bolt.Sips.start_link(url: "bolt://neo4j:test@localhost")
{:ok, #PID<0.237.0>}

iex» conn = Bolt.Sips.conn()
#PID<0.242.0>
florinpatrascu commented 2 years ago

Hi there,

Did you try enabling ssl, as I suggested in reply to your DM on Twitter?

Please try adding ssl: true to your connection - one of the config options described in the docs and samples.

This for example, will work:


{:ok, _neo} = Sips.start_link(
    url: "bolt://xxxxxxxx.databases.neo4j.io", 
    ssl: true, 
    basic_auth: [username: "neo4j", password: "*********"])

{:ok, #PID<0.863.0>}

Sips.query!(conn, "UNWIND range(1, 10) AS n RETURN n")
%Bolt.Sips.Response{
  bookmark: "neo4j:bookmark:v1:tx27",
  fields: ["n"],
  notifications: [],
  plan: nil,
  profile: nil,
  records: [[1], [2], [3], [4], [5], [6], '\a', '\b', '\t', '\n'],
  results: [
    %{"n" => 1},
    %{"n" => 2},
    %{"n" => 3},
    %{"n" => 4},
    %{"n" => 5},
    %{"n" => 6},
    %{"n" => 7},
    %{"n" => 8},
    %{"n" => 9},
    %{"n" => 10}
  ],
  stats: [],
  type: "r"
}

(tested)

HTH

mvellandi commented 2 years ago

Yes I did. Here's the repo and the error with ssl set to true. I can post to the neo4j discord again with this error. Hmm. https://github.com/mvellandi/neo4j_bolt.sips_demo

Maybe neo4j auto certs don't work with this library? I'm not sure how I'd add my own cert with for example Let's Encrypt, because the various instructions available assume you're self-hosting neo4j or using one of their cloud VMs, not their managed Aura DB service.

 {:ok, pid} = Bolt.Sips.start_link(opts)
{:ok, #PID<0.341.0>}
iex(3)>
00:52:57.735 [warn]  Description: 'Authenticity is not established by certificate path validation'
     Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'
florinpatrascu commented 2 years ago

I also recommend using the latest bolt_sips version. Your demo is pointing to an old one, if I am not mistaken.

mvellandi commented 2 years ago

Okay, updated deps from: {:bolt_sips, "~> 2.0.0-rc"} to {:bolt_sips, "~> 2.0"} and ran mix deps.get but there weren't any updates:

> mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  bolt_sips 2.0.11
  calendar 0.17.6
  certifi 2.8.0
  connection 1.1.0
  db_connection 2.4.1
  hackney 1.18.0
  idna 6.1.1
  jason 1.2.2
  metrics 1.0.1
  mimerl 1.2.0
  parse_trans 3.3.1
  poison 3.1.0
  ssl_verify_fun 1.1.6
  telemetry 1.0.0
  tzdata 1.1.1
  unicode_util_compat 0.7.0
All dependencies are up to date
> iex -S mix
Erlang/OTP 24 [erts-12.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Compiling 2 files (.ex)
Generated n4d app
Interactive Elixir (1.12.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
11:59:11.554 [warn]  Description: 'Authenticity is not established by certificate path validation'
     Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'

Thank you for your help in debugging this!! :) Using a free managed DB is very helpful for someone like me very much in the dark on devops. I also checked out GrapheneDB but it seems they no longer have a free tier.

florinpatrascu commented 2 years ago

TBH it seems there's something iffy with your local env, around the certs?! But I don't know, sorry. Clearly the driver works with the hosted Aura service - tried myself last night on a fresh db (using their free tier) and had no issues at all.

Try making sure you can connect to other services requiring auth, not just Neo4j related. And if you see similar issues it may be a sign for you to needing to fresh install Erlang and Elixir. HTH

mvellandi commented 2 years ago

Well, looks like multiple versions of OTP 24 built with asdf on my macOS Big Sur either aren't properly compiled, ssl isn't properly configured or working, or something else. The demo app works with OTP 23 though.

conn = Bolt.Sips.conn() works now

Thank you so much for your help these last days!

florinpatrascu commented 2 years ago

Glad you found the culprit. Take care