From 39b586067b106c492b701f0f6e85b4abcbf5faa1 Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 17 Apr 2020 09:02:52 -0500 Subject: [PATCH] update wampex lib --- config/config.exs | 2 + config/dev.exs | 1 + config/prod.exs | 1 + config/test.exs | 14 +++++++ lib/client.ex | 3 +- mix.exs | 5 ++- mix.lock | 5 ++- test/support/authentication.ex | 71 +++++++++++++++++++++++++++++++++ test/support/authorization.ex | 7 ++++ test/support/test_subscriber.ex | 3 +- test/wampex_test.exs | 51 +++++++++++++++++------ 11 files changed, 143 insertions(+), 20 deletions(-) create mode 100644 config/dev.exs create mode 100644 config/prod.exs create mode 100644 config/test.exs create mode 100644 test/support/authentication.ex create mode 100644 test/support/authorization.ex diff --git a/config/config.exs b/config/config.exs index d2d855e..8233fe9 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1 +1,3 @@ use Mix.Config + +import_config "#{Mix.env()}.exs" diff --git a/config/dev.exs b/config/dev.exs new file mode 100644 index 0000000..d2d855e --- /dev/null +++ b/config/dev.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/config/prod.exs b/config/prod.exs new file mode 100644 index 0000000..d2d855e --- /dev/null +++ b/config/prod.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/config/test.exs b/config/test.exs new file mode 100644 index 0000000..f0ee68e --- /dev/null +++ b/config/test.exs @@ -0,0 +1,14 @@ +use Mix.Config + +config :wampex_router, + topologies: [ + kv: [ + strategy: Cluster.Strategy.Epmd, + config: [ + hosts: [] + ], + connect: {:net_kernel, :connect_node, []}, + disconnect: {:erlang, :disconnect_node, []}, + list_nodes: {:erlang, :nodes, [:connected]} + ] + ] diff --git a/lib/client.ex b/lib/client.ex index 90b980f..fada2f2 100644 --- a/lib/client.ex +++ b/lib/client.ex @@ -6,8 +6,7 @@ defmodule Wampex.Client do alias Wampex.Client.Session, as: Sess alias Wampex.Roles.{Callee, Subscriber} - alias Wampex.Roles.Callee.Yield - alias Wampex.Roles.Callee.Register + alias Wampex.Roles.Callee.{Register, Yield} alias Wampex.Roles.Caller alias Wampex.Roles.Caller.Call alias Wampex.Roles.Dealer.Result diff --git a/mix.exs b/mix.exs index 8223037..df55a94 100644 --- a/mix.exs +++ b/mix.exs @@ -45,10 +45,11 @@ defmodule Wampex.Client.MixProject do {:msgpack, "~> 0.7.0"}, {:pbkdf2, "~> 2.0"}, {:states_language, "~> 0.2"}, - # {:wampex, path: "../wampex"}, {:wampex, git: "https://gitlab.com/entropealabs/wampex.git", - tag: "7d656d9748cb0e4d08c625d87e315839afecb4b2"}, + tag: "ecba713117f1e048829be79f19373952638c6ece"}, + {:wampex_router, + git: "https://gitlab.com/entropealabs/wampex_router.git", tag: "master", only: [:test]}, {:websockex, "~> 0.4.2"} ] end diff --git a/mix.lock b/mix.lock index f598d2f..e89542e 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,7 @@ %{ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"}, + "cluster_kv": {:git, "https://gitlab.com/entropealabs/cluster_kv.git", "d3bb958de67ef22304f24641661261a1c2df684d", [tag: "d3bb958de67ef22304f24641661261a1c2df684d"]}, "conv_case": {:hex, :conv_case, "0.2.2", "5a98b74ab8f7ddbad670e5c7bb39ff280e60699aa3b25c7062ceccf48137433c", [:mix], [], "hexpm", "561c550ab6d55b2a4d4c14449e58c9957798613eb26ea182e14a962965377bca"}, "credo": {:hex, :credo, "1.3.1", "082e8d9268a489becf8e7aa75671a7b9088b1277cd6c1b13f40a55554b3f5126", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "0da816ed52fa520b9ea0e5d18a0d3ca269e0bd410b1174d88d8abd94be6cce3c"}, "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, @@ -17,6 +18,7 @@ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "msgpack": {:hex, :msgpack, "0.7.0", "128ae0a2227c7e7a2847c0f0f73551c268464f8c1ee96bffb920bc0a5712b295", [:rebar3], [], "hexpm", "4649353da003e6f438d105e4b1e0f17757f6f5ec8687a6f30875ff3ac4ce2a51"}, + "msgpax": {:hex, :msgpax, "2.2.4", "7b3790ef684089076b63c0f08c2f4b079c6311daeb006b69e4ed2bf67518291e", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b351b6d992d79624a8430a99d21a41b36b1b90edf84326a294e9f4a2de11f089"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, "pbkdf2": {:hex, :pbkdf2, "2.0.0", "11c23279fded5c0027ab3996cfae77805521d7ef4babde2bd7ec04a9086cf499", [:rebar3], [], "hexpm", "1e793ce6fdb0576613115714deae9dfc1d1537eaba74f07efb36de139774488d"}, @@ -24,7 +26,8 @@ "states_language": {:hex, :states_language, "0.2.8", "f9dfd3c0bd9a9d7bda25ef315f2d90944cd6b2022a7f3c403deb1d4ec451825e", [:mix], [{:elixpath, "~> 0.1.0", [hex: :elixpath, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:json_xema, "~> 0.4.0", [hex: :json_xema, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:xema, "~> 0.11.0", [hex: :xema, repo: "hexpm", optional: false]}], "hexpm", "a5231691e7cb37fe32dc7de54c2dc86d1d60e84c4f0379f3246e55be2a85ec78"}, "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"}, - "wampex": {:git, "https://gitlab.com/entropealabs/wampex.git", "61d834a784f5f14ec90508cf7556a5ebaec113c3", [tag: "61d834a784f5f14ec90508cf7556a5ebaec113c3"]}, + "wampex": {:git, "https://gitlab.com/entropealabs/wampex.git", "ecba713117f1e048829be79f19373952638c6ece", [tag: "ecba713117f1e048829be79f19373952638c6ece"]}, + "wampex_router": {:git, "https://gitlab.com/entropealabs/wampex_router.git", "0dd5879951be976e533cdae554e581202d557c17", [tag: "master"]}, "websockex": {:hex, :websockex, "0.4.2", "9a3b7dc25655517ecd3f8ff7109a77fce94956096b942836cdcfbc7c86603ecc", [:mix], [], "hexpm", "803cd76e91544b56f0e655e36790be797fa6436db9224f7c303db9b9df2a3df4"}, "xema": {:hex, :xema, "0.11.0", "7b5118418633cffc27092110d02d4faeea938149dd3f6c64299e41e747067e80", [:mix], [{:conv_case, "~> 0.2.2", [hex: :conv_case, repo: "hexpm", optional: false]}, {:decimal, "~> 1.7", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "51491c9a953d65069d4b30aa2f70bc45ff99fd1bc3345bc72ce4e644d01ea14e"}, } diff --git a/test/support/authentication.ex b/test/support/authentication.ex new file mode 100644 index 0000000..ac048e8 --- /dev/null +++ b/test/support/authentication.ex @@ -0,0 +1,71 @@ +defmodule Wampex.Router.AuthenticationImpl do + @moduledoc false + @behaviour Wampex.Router.Authentication + require Logger + + alias Wampex.Crypto + alias Wampex.Serializers.JSON + + @wampcra "wampcra" + @auth_provider "userdb" + @auth_role "user" + @auth_password "bnASR5qF9y8k/sHF6S+NneCOhvVI0zFkvoKQpc2F+hA=" + @salt "test" + @keylen 32 + @iterations 10 + + @impl true + def authenticate?(methods) do + can_auth(methods) + end + + @impl true + def method, do: @wampcra + + @impl true + def challenge(_realm, authid, session_id) do + now = DateTime.to_iso8601(DateTime.utc_now()) + + %{ + challenge: + JSON.serialize!(%{ + nonce: Crypto.random_string(@keylen), + authprovider: @auth_provider, + authid: authid, + timestamp: now, + authrole: @auth_role, + authmethod: @wampcra, + session: session_id + }), + salt: @salt, + keylen: @keylen, + iterations: @iterations + } + end + + @impl true + def parse_challenge(challenge) do + ch = JSON.deserialize!(challenge.challenge) + + {get_in(ch, ["authid"]), get_in(ch, ["authrole"]), get_in(ch, ["authmethod"]), get_in(ch, ["authprovider"])} + end + + @impl true + def authenticate(signature, realm, authid, %{ + challenge: challenge + }) do + authed = + authid + |> get_secret(realm) + |> Crypto.hash_challenge(challenge) + |> :pbkdf2.compare_secure(signature) + + {authed, %{}} + end + + defp get_secret(_authid, _uri), do: Crypto.pbkdf2(@auth_password, @salt, @iterations, @keylen) + + defp can_auth([]), do: false + defp can_auth([@wampcra | _]), do: true + defp can_auth([_ | t]), do: can_auth(t) +end diff --git a/test/support/authorization.ex b/test/support/authorization.ex new file mode 100644 index 0000000..f0a55d7 --- /dev/null +++ b/test/support/authorization.ex @@ -0,0 +1,7 @@ +defmodule Wampex.Router.AuthorizationImpl do + @moduledoc false + @behaviour Wampex.Router.Authorization + + @impl true + def authorized?(_, _, _), do: true +end diff --git a/test/support/test_subscriber.ex b/test/support/test_subscriber.ex index 7bdd652..36c2dd4 100644 --- a/test/support/test_subscriber.ex +++ b/test/support/test_subscriber.ex @@ -3,8 +3,7 @@ defmodule TestSubscriber do use GenServer require Logger alias Wampex.Client - alias Wampex.Roles.Subscriber - alias Subscriber.Subscribe + alias Wampex.Roles.Subscriber.Subscribe def start_link(test, name, topic) do GenServer.start_link(__MODULE__, {test, name, topic}) diff --git a/test/wampex_test.exs b/test/wampex_test.exs index 62b8456..9992cc7 100644 --- a/test/wampex_test.exs +++ b/test/wampex_test.exs @@ -10,9 +10,12 @@ defmodule WampexTest do alias Wampex.Roles.Dealer.{Invocation, Result} alias Wampex.Roles.Peer.{Error, Hello} alias Wampex.Roles.Publisher.Publish + alias Wampex.Router + alias Wampex.Router.AuthenticationImpl + alias Wampex.Router.AuthorizationImpl require Logger - @url "ws://localhost:4000/ws" + @url "ws://localhost:5999/ws" @authid "admin" @auth_password "test1234" @realm_uri "admin" @@ -23,10 +26,27 @@ defmodule WampexTest do @session %Session{url: @url, realm: @realm, roles: @roles} + setup_all do + topologies = Application.get_env(:wampex_router, :topologies) + + [ + server: + Router.start_link( + name: TestRouter, + port: 5999, + topologies: topologies, + replicas: 1, + quorum: 1, + authentication_module: AuthenticationImpl, + authorization_module: AuthorizationImpl + ) + ] + end + @tag :client test "callee registration" do name = TestCalleeRegistration - Client.start_link(name: name, session: @session) + Client.start_link(name: name, session: @session, reconnect: false) TestCallee.start_link(self(), name, @device) assert_receive {:registered, id} end @@ -35,15 +55,20 @@ defmodule WampexTest do test "abort" do Process.flag(:trap_exit, true) callee_name = TestAbort - {:ok, pid} = Client.start_link(name: callee_name, session: @session) - Client.cast(callee_name, Peer.hello(%Hello{realm: "test", roles: [Callee]})) - assert_receive {:EXIT, ^pid, :shutdown}, 1000 + {:ok, _pid} = Client.start_link(name: callee_name, session: @session, reconnect: false) + + try do + Client.cast(callee_name, Peer.hello(%Hello{realm: "test", roles: [Callee]})) + catch + :exit, er -> + assert {:normal, _} = er + end end @tag :client test "caller receives error when calling unknown procedure" do caller_name = TestExistCaller - Client.start_link(name: caller_name, session: @session) + Client.start_link(name: caller_name, session: @session, reconnect: false) assert %Error{error: "wamp.error.no_registration"} = Client.call( @@ -59,7 +84,7 @@ defmodule WampexTest do @tag :client test "admin callee is invoked and responds and caller gets result" do caller_name = TestAdminCaller - Client.start_link(name: caller_name, session: @session) + Client.start_link(name: caller_name, session: @session, reconnect: false) assert %Result{arg_kw: %{"authid" => "chris"}} = Client.call( @@ -80,7 +105,7 @@ defmodule WampexTest do @tag :client test "admin callee is invoked and responds with error" do caller_name = TestAdminErrorCaller - Client.start_link(name: caller_name, session: @session) + Client.start_link(name: caller_name, session: @session, reconnect: false) assert %Error{error: "error"} = Client.call( @@ -101,11 +126,11 @@ defmodule WampexTest do @tag :client test "callee is invoked and responds and caller gets result" do callee_name = TestCalleeRespond - Client.start_link(name: callee_name, session: @session) + Client.start_link(name: callee_name, session: @session, reconnect: false) TestCallee.start_link(self(), callee_name, @device) assert_receive {_, _} caller_name = TestCaller - Client.start_link(name: caller_name, session: @session) + Client.start_link(name: caller_name, session: @session, reconnect: false) %Result{arg_list: ["ok"], arg_kw: %{"color" => "#FFFFFF"}} = Client.call( @@ -123,7 +148,7 @@ defmodule WampexTest do @tag :client test "subscriber registration" do name = TestSubscriberRegister - Client.start_link(name: name, session: @session) + Client.start_link(name: name, session: @session, reconnect: false) TestSubscriber.start_link(self(), name, "com.data.temp") assert_receive {:subscribed, id} end @@ -131,11 +156,11 @@ defmodule WampexTest do @tag :client test "subscriber receives events from publisher" do name = TestSubscriberEvents - Client.start_link(name: name, session: @session) + Client.start_link(name: name, session: @session, reconnect: false) TestSubscriber.start_link(self(), name, "com.data.test.temp") assert_receive {:subscribed, id} - Client.start_link(name: TestPublisher, session: @session) + Client.start_link(name: TestPublisher, session: @session, reconnect: false) Client.publish( TestPublisher, -- 2.45.3