From de53ed087392d4529eca7152b27a4597382ba618 Mon Sep 17 00:00:00 2001 From: Ygor Castor Date: Mon, 30 May 2022 22:00:42 +0200 Subject: [PATCH 1/4] Fixing the CAStore certificates (#13) --- lib/connection/connection_state_manager.ex | 2 +- lib/connection/executor/request_executor.ex | 14 +++++++++++--- lib/connection/models/server_node.ex | 11 ++++++++--- mix.exs | 1 + mix.lock | 1 + 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/connection/connection_state_manager.ex b/lib/connection/connection_state_manager.ex index 54adc8a..fbf2e12 100644 --- a/lib/connection/connection_state_manager.ex +++ b/lib/connection/connection_state_manager.ex @@ -139,7 +139,7 @@ defmodule Ravix.Connection.State.Manager do defp register_nodes(%ConnectionState{} = state) do registered_nodes = state.urls - |> Enum.map(fn url -> ServerNode.from_url(url, state.database, state.certificate) end) + |> Enum.map(fn url -> ServerNode.from_url(url, state) end) |> Enum.map(fn node -> RequestExecutor.Supervisor.register_node_executor(state.store, node) end) diff --git a/lib/connection/executor/request_executor.ex b/lib/connection/executor/request_executor.ex index d334b40..ce3d68e 100644 --- a/lib/connection/executor/request_executor.ex +++ b/lib/connection/executor/request_executor.ex @@ -32,15 +32,23 @@ defmodule Ravix.Connection.RequestExecutor do def init(%ServerNode{} = node) do {:ok, conn_params} = build_params(node.certificate, node.protocol) - Logger.info("[RAVIX] Connecting to node '#{node}' for store '#{inspect(node.store)}'") + Logger.info( + "[RAVIX] Connecting to node '#{inspect(node)}' for store '#{inspect(node.store)}'" + ) case Mint.HTTP.connect(node.protocol, node.url, node.port, conn_params) do {:ok, conn} -> - Logger.info("[RAVIX] Connected to node '#{node}' for store '#{inspect(node.store)}'") + Logger.info( + "[RAVIX] Connected to node '#{inspect(node)}' for store '#{inspect(node.store)}'" + ) {:ok, %ServerNode{node | conn: conn}} {:error, reason} -> + Logger.error( + "[RAVIX] Unable to register the node '#{inspect(node)} for store '#{inspect(node.store)}', cause: #{inspect(reason)}'" + ) + {:stop, reason} end end @@ -50,7 +58,7 @@ defmodule Ravix.Connection.RequestExecutor do GenServer.start_link( __MODULE__, node, - name: executor_id(node.database, node.url) + name: executor_id(node.url, node.database) ) end diff --git a/lib/connection/models/server_node.ex b/lib/connection/models/server_node.ex index 7b16902..8b8adc2 100644 --- a/lib/connection/models/server_node.ex +++ b/lib/connection/models/server_node.ex @@ -25,6 +25,7 @@ defmodule Ravix.Connection.ServerNode do opts: [] alias Ravix.Connection.ServerNode + alias Ravix.Connection.State, as: ConnectionState @type t :: %ServerNode{ store: atom(), @@ -42,15 +43,19 @@ defmodule Ravix.Connection.ServerNode do @doc """ Creates a new node state from the url, database name and ssl certificate """ - @spec from_url(binary | URI.t(), any, any) :: ServerNode.t() - def from_url(url, database, certificate) do + @spec from_url(binary | URI.t(), ConnectionState.t()) :: ServerNode.t() + def from_url(url, %ConnectionState{ + certificate: certificate, + certificate_file: certificate_file, + database: database + }) do parsed_url = URI.new!(url) %ServerNode{ url: parsed_url.host, port: parsed_url.port, protocol: String.to_atom(parsed_url.scheme), - certificate: certificate, + certificate: %{certificate: certificate, certificate_file: certificate_file}, database: database } end diff --git a/mix.exs b/mix.exs index 52fec1c..1f24224 100644 --- a/mix.exs +++ b/mix.exs @@ -53,6 +53,7 @@ defmodule Ravix.MixProject do {:tzdata, "~> 1.1"}, {:retry, "~> 0.16.0"}, {:inflex, "~> 2.1"}, + {:castore, "~> 0.1.17"}, {:gradient, github: "esl/gradient", only: [:dev, :test], runtime: false}, {:elixir_sense, github: "elixir-lsp/elixir_sense", only: [:dev]}, {:ex_doc, "~> 0.28.3", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 53a611b..69e9c63 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,7 @@ %{ "assertions": {:hex, :assertions, "0.19.0", "f177fcc22b55df6a41a58b151e430d189d0a1083dae3240522503dedaf8e1174", [:mix], [], "hexpm", "759bdbf977fe3e2d2b79f8a65d8674f29ac757781136a6cb4adf88f1574af1d8"}, "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "castore": {:hex, :castore, "0.1.17", "ba672681de4e51ed8ec1f74ed624d104c0db72742ea1a5e74edbc770c815182f", [:mix], [], "hexpm", "d9844227ed52d26e7519224525cb6868650c272d4a3d327ce3ca5570c12163f9"}, "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, From a5991a4de33eb80a1d82874f45dbf67b330c1ab8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 30 May 2022 20:04:04 +0000 Subject: [PATCH 2/4] v0.1.5 --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 1f24224..ba3dab8 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Ravix.MixProject do def project do [ app: :ravix, - version: "0.1.4", + version: "0.1.5", elixir: "~> 1.13", start_permanent: Mix.env() == :prod, deps: deps(), From 0f10a1618520f9a5a4fc7729af76fd363e7a59f4 Mon Sep 17 00:00:00 2001 From: Ygor Castor Date: Tue, 31 May 2022 15:44:50 +0200 Subject: [PATCH 3/4] [patch] Using the Erlang SSL configs directly --- README.md | 22 +++++++++++++++++---- lib/connection/connection_state_manager.ex | 1 + lib/connection/executor/request_executor.ex | 17 +++++++--------- lib/connection/models/connection_state.ex | 9 +++------ lib/connection/models/server_node.ex | 11 +++++------ 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 5811f5c..c2cd0b3 100644 --- a/README.md +++ b/README.md @@ -207,14 +207,28 @@ end ## Secure Server -To connect to a secure server, you can just inform the SSL certificate using the `certificate` or the `certificate_file` configuration. +To connect to a secure server, you can just inform the SSL certificates based on the [erlang ssl configs](https://www.erlang.org/doc/man/ssl.html). + +E.g: ```elixir config :ravix, Ravix.Test.Store, - urls: [System.get_env("RAVENDB_URL", "http://localhost:8080")], + urls: [System.get_env("RAVENDB_URL", "https://localhost:8080")], + database: "test", + ssl_config: [ + certfile: "certs/ravix_test.crt", + keyfile: "certs/ravix_test.key" + ] +``` +OR + +```elixir +config :ravix, Ravix.Test.Store, + urls: [System.get_env("RAVENDB_URL", "https://localhost:8080")], database: "test", - certificate: CERT_IN_BASE_64, - certificate_file: "/opt/certs/cert.pfx" + ssl_config: [ + certfile: "certs/ravix_test.pem" + ] ``` ## Ecto diff --git a/lib/connection/connection_state_manager.ex b/lib/connection/connection_state_manager.ex index fbf2e12..7343386 100644 --- a/lib/connection/connection_state_manager.ex +++ b/lib/connection/connection_state_manager.ex @@ -143,6 +143,7 @@ defmodule Ravix.Connection.State.Manager do |> Enum.map(fn node -> RequestExecutor.Supervisor.register_node_executor(state.store, node) end) + #|> IO.inspect() |> Enum.filter(fn pids -> elem(pids, 0) == :ok end) |> Enum.map(fn pid -> elem(pid, 1) end) diff --git a/lib/connection/executor/request_executor.ex b/lib/connection/executor/request_executor.ex index ce3d68e..1e4004b 100644 --- a/lib/connection/executor/request_executor.ex +++ b/lib/connection/executor/request_executor.ex @@ -30,7 +30,7 @@ defmodule Ravix.Connection.RequestExecutor do optional(:module) => any }} def init(%ServerNode{} = node) do - {:ok, conn_params} = build_params(node.certificate, node.protocol) + {:ok, conn_params} = build_params(node.ssl_config, node.protocol) Logger.info( "[RAVIX] Connecting to node '#{inspect(node)}' for store '#{inspect(node.store)}'" @@ -362,16 +362,13 @@ defmodule Ravix.Connection.RequestExecutor do defp build_params(_, :http), do: {:ok, []} - defp build_params(certificate, :https) do - case certificate do - %{certificate: nil, certificate_file: file} -> - {:ok, transport_opts: [cacertfile: file]} + defp build_params(ssl_config, :https) do + case ssl_config do + [] -> + {:error, :no_ssl_configurations_informed} - %{certificate: cert, certificate_file: nil} -> - {:ok, transport_opts: [cacert: cert]} - - _ -> - {:error, :invalid_ssl_certificate} + transport_ops -> + {:ok, transport_opts: transport_ops} end end diff --git a/lib/connection/models/connection_state.ex b/lib/connection/models/connection_state.ex index 4fbb870..f3dc289 100644 --- a/lib/connection/models/connection_state.ex +++ b/lib/connection/models/connection_state.ex @@ -4,8 +4,7 @@ defmodule Ravix.Connection.State do - store: Store atom for this state. E.g: Ravix.Test.Store - database: Name of the database. - - certificate: RavenDB emmited SSL certificate for the database user in base64 - - certificate_file: Same as above, but a path to the file in the disk + - ssl_config: SSL Configurations, E.g: https://www.erlang.org/doc/man/ssl.html - conventions: Document Configuration conventions - retry_on_failure: Automatic retry in retryable errors - retry_on_stale: Automatic retry when the query is stale @@ -21,8 +20,7 @@ defmodule Ravix.Connection.State do """ defstruct store: nil, database: nil, - certificate: nil, - certificate_file: nil, + ssl_config: [], retry_on_failure: true, retry_on_stale: false, retry_backoff: 100, @@ -41,8 +39,7 @@ defmodule Ravix.Connection.State do @type t :: %Ravix.Connection.State{ store: any(), database: String.t(), - certificate: String.t() | nil, - certificate_file: String.t() | nil, + ssl_config: Keyword.t(), retry_on_failure: boolean(), retry_on_stale: boolean(), retry_backoff: non_neg_integer(), diff --git a/lib/connection/models/server_node.ex b/lib/connection/models/server_node.ex index 8b8adc2..a32e773 100644 --- a/lib/connection/models/server_node.ex +++ b/lib/connection/models/server_node.ex @@ -6,7 +6,7 @@ defmodule Ravix.Connection.ServerNode do - url: URL of this node - port: port of this node - conn: TCP Connection State - - certificate: User SSL certificate for this node + - ssl_config: User SSL certificate config for this node - requests: Currently executing request calls to RavenDB - protocol: http or https - database: For which database is this executor @@ -17,7 +17,7 @@ defmodule Ravix.Connection.ServerNode do url: nil, port: nil, conn: nil, - certificate: nil, + ssl_config: nil, requests: %{}, protocol: nil, database: nil, @@ -32,7 +32,7 @@ defmodule Ravix.Connection.ServerNode do url: String.t(), port: non_neg_integer(), conn: Mint.HTTP.t() | nil, - certificate: map() | nil, + ssl_config: Keyword.t() | nil, requests: map(), protocol: atom(), database: String.t(), @@ -45,8 +45,7 @@ defmodule Ravix.Connection.ServerNode do """ @spec from_url(binary | URI.t(), ConnectionState.t()) :: ServerNode.t() def from_url(url, %ConnectionState{ - certificate: certificate, - certificate_file: certificate_file, + ssl_config: ssl_config, database: database }) do parsed_url = URI.new!(url) @@ -55,7 +54,7 @@ defmodule Ravix.Connection.ServerNode do url: parsed_url.host, port: parsed_url.port, protocol: String.to_atom(parsed_url.scheme), - certificate: %{certificate: certificate, certificate_file: certificate_file}, + ssl_config: ssl_config, database: database } end From 0bcd1607c6f51c16afa2f768cc532aae07d5fe20 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 31 May 2022 13:45:45 +0000 Subject: [PATCH 4/4] v0.1.6 --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index ba3dab8..d4700ec 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Ravix.MixProject do def project do [ app: :ravix, - version: "0.1.5", + version: "0.1.6", elixir: "~> 1.13", start_permanent: Mix.env() == :prod, deps: deps(),