florinpatrascu / bolt_sips

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

Unable to connect when using authentication #85

Closed willricketts closed 4 years ago

willricketts commented 4 years ago

Environment

Current behavior

Background: The application in which I'm using Bolt.Sips is an umbrella in which a single sub-app handles a connection with Neo4j.

I've never been able to connect to a running instance of Neo4j locally or remotely when providing authentication. When doing local development, I have to disable authentication on Neo4j and omit any auth data in my local configuration. This problem is also occurring in my Kubernetes cluster. I'm using GrapheneDB for Neo hosting and am able to connect by any other means, be it Neo4j Desktop, etc. However, whenever Bolt.Sips tries to connect with the same information, it's unable to, though I'm 100% sure that all environment variables have been set correctly.

Below is my Bolt.Sips configuration:

prod.exs:

use Mix.Config

config :db, DB.Repo,
  username: System.fetch_env!("DB_USERNAME"),
  password: System.fetch_env!("DB_PASSWORD"),
  database: System.fetch_env!("DB_NAME"),
  socket_dir: System.fetch_env!("DB_SOCKET"),
  pool_size: 15

config :galaxy_map, Bolt,
  url: System.fetch_env!("BOLT_URL"),
  basic_auth: [username: System.fetch_env!("BOLT_USERNAME"), password: System.fetch_env!("BOLT_PASSWORD")],
  ssl: true,
  pool_size: 10

releases.exs:

import Config

config :db, DB.Repo,
  username: System.fetch_env!("DB_USERNAME"),
  password: System.fetch_env!("DB_PASSWORD"),
  database: System.fetch_env!("DB_NAME"),
  socket_dir: System.fetch_env!("DB_SOCKET"),
  pool_size: 15

config :galaxy_map, Bolt,
  url: System.fetch_env!("BOLT_URL"),
  basic_auth: [username: System.fetch_env!("BOLT_USERNAME"), password: System.fetch_env!("BOLT_PASSWORD")],
  ssl: true,
  pool_size: 10

config :api, Api.Endpoint,
  load_from_system_env: true,
  http: [port: {:system, "PORT"}],
  check_origin: false,
  server: true,
  root: ".",
  cache_static_manifest: "priv/static/cache_manifest.json",
  secret_key_base: System.fetch_env!("SECRET_KEY_BASE")

I would very much appreciate any advice I could get!

florinpatrascu commented 4 years ago

Hi @willricketts - could you please try config :bolt_sips, Bolt.Sips, rather than config :galaxy_map, Bolt? Unless you’re explicitly initializing the driver in a specific way?!

willricketts commented 4 years ago

Sadly this change produces the same effect.

florinpatrascu commented 4 years ago

That’s weird, can you please post how you start the driver, as a short code snippet?! Also, did you try to specify the username and password in the url?! I’ll troubleshoot this as soon as I get near a computer. Sorry for the delay.

willricketts commented 4 years ago

No problem man! All open source is a gift and you owe me absolutely nothing <3

This is how I'm starting Bolt.Sips within application.ex:

def start(_type, _args) do
    children = [
      {Bolt.Sips, Application.get_env(:bolt_sips, Bolt)}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: GalaxyMap.Supervisor]
    Supervisor.start_link(children, opts)
  end

I haven't tried interpolating the auth into the URL, but I'll try that now.

willricketts commented 4 years ago

I just tried interpolating basic auth into the url -> bolt://{username}:{password}@{url}:{port} with the same result.

One thing I just want to make sure that's clear is that I'm utilizing Bolt.Sips inside an umbrella in a sub-app.

kristofka commented 4 years ago

Does the connection fail if you pass the configuration as a keyword list in the second element of the child Bolt.Sips eg : chlidren = [ {Bolt.Sips, [url: url, basic_auth: [ username: uname, password: pword], ssl: true]} ] I've created an account on graphene and was successfully able to connect to the database through bolt sips with ssl enabled.

florinpatrascu commented 4 years ago

Maybe there’s a issue with how the app is configured?! @willricketts is specifying it is an umbrella app. I wonder: are the params available, when the driver starts?!

willricketts commented 4 years ago

@kristofka I tried this as well with the same result. I've also verified that all environment variables are set correctly at runtime.

@florinpatrascu That's honestly what I'm leaning toward being the case, however I had the same problem with a Phoenix app and a plain old elixir app as well.

The funny thing is that this project being an umbrella app has introduced a lot of complexity around other aspects of it as well, and I'm starting to think that approach isn't worth it. I'm going to try starting up a blank Phoenix app and seeing if I can get it to connect to my Graphene instance. Until then, here are a few more details about how my codebase is structured:

config/config.exs:

use Mix.Config

config :api,
  ecto_repos: [DB.Repo],
  generators: [context_app: false]

import_config "#{Mix.env}.exs"

config :phoenix, json_library: Jason

Structure:

apps/
  api/
  db/
  galaxy_map/        # <--- this is where the Neo4j connection lives
  main /

Umbrella dependencies:

defp deps do
    [
      {:credo, "~> 1.1.0", only: [:dev, :test], runtime: false},
      {:benchee, "~> 1.0", only: :dev}
    ]
  end

^ Note that none of the sub apps are required as dependencies here. I don't think that matters, but it seemed worth noting.

willricketts commented 4 years ago

I just created an empty Phoenix app and was able to connect to Graphene via iex by calling start_link on Bolt.Sips and passing the url with basicauth interpolated as well as setting ssl to true.

I was also able to connect by configuring Bolt within dev.exs. Somehow, this same pattern breaks within an umbrella.

Another important point is that I'm connecting to a few other external services (postgres, etc) within the same config and they're able to connect without issue.

florinpatrascu commented 4 years ago

I too just verified that the auth mechanism works; as expected. Maybe it is indeed something specific to your configuration, but I am not sure what.

@willricketts - if you are able to start the bolt driver, then you can connect to the running app and check what is the state of the driver. This can be easily done by calling this: Bolt.Sips.info, from your remote session. You'll see something like this:

iex(......)» Bolt.Sips.info()

%{
  default: %{
    connections: %{
      direct: %{".....npailel.dbs.graphenedb.com:24787" => 0},
      routing_query: nil
    },
    user_options: [
      socket: :ssl,
      basic_auth: [
        username: "****",
        password: "*****"
      ],
      port: 24787,
      routing_context: %{},
      schema: "bolt",
      hostname: ".....npailel.dbs.graphenedb.com",
      pool_size: 15,
      max_overflow: 0,
      timeout: 15000,
      with_etls: false,
      prefix: :default,
      url: "bolt://*****:******@.....npailel.dbs.graphenedb.com:24787",
      ssl: true
    ]
  }
}

maybe this will help you troubleshooting the connectivity a bit further?!

willricketts commented 4 years ago

This is something I've wanted to do since I deployed to a Gcloud Kubernetes cluster, but I'm not too sure of how I can get to an IEx session within one of those instances.

I've been reading as many articles and how-tos on umbrella configuration as I can find this morning, and it honestly seems like everything is properly in place.

This is an issue I've experienced in two umbrella projects, and I've simply hit a wall in terms of being able to reason about the problem with the resources I have. I'm getting to the point where I'm considering refactoring the entire application to be a standalone elixir app, or possibly rebuild as a standalone. I'm not too far into it, but it still seems silly to abandon an architecture with sound reasoning behind it just to get around a weird configuration issue that I can't seem to figure out.

florinpatrascu commented 4 years ago

@willricketts - is this issue something you believe our team could help you with? I can't find any problems with how the authentication works today. Can this issue be closed?

willricketts commented 4 years ago

I guess this can be closed. I've tried every possible configuration and can't get Bolt.Sips to work inside an umbrella. I was forced to rebuild as a standalone app.

florinpatrascu commented 4 years ago

sorry to hear that, @willricketts I'll try to build a simple umbrella app, one of these days, and see if I stumble upon similar issues.