You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ju...@apache.org on 2020/03/17 22:48:42 UTC

[couchdb] branch 3.0.x updated: 3.0.x merge - Port elixir proxyauth tests from js to elixir (#2660)
 (#2674)

This is an automated email from the ASF dual-hosted git repository.

juanjo pushed a commit to branch 3.0.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/3.0.x by this push:
     new cc42c37  3.0.x merge - Port elixir proxyauth tests from js to elixir (#2660)
 (#2674)
cc42c37 is described below

commit cc42c375e81bdb4bed0dc85d670e89867a6c51fe
Author: Juanjo Rodriguez <jj...@gmail.com>
AuthorDate: Tue Mar 17 23:48:31 2020 +0100

    3.0.x merge - Port elixir proxyauth tests from js to elixir (#2660)
 (#2674)
    
    * Port elixir proxyauth tests from js to elixir (#2660)
    * Add support for specify a custom config file for CouchDB startup during testing
---
 Makefile                                |   5 +-
 dev/run                                 |  27 ++++++
 test/elixir/README.md                   |   2 +-
 test/elixir/lib/couch.ex                |   4 +-
 test/elixir/test/config/test-config.ini |   2 +
 test/elixir/test/proxyauth_test.exs     | 163 ++++++++++++++++++++++++++++++++
 test/elixir/test/users_db_test.exs      |   3 +-
 test/javascript/tests/proxyauth.js      |   4 +-
 8 files changed, 203 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index e229ee5..7d56dd1 100644
--- a/Makefile
+++ b/Makefile
@@ -223,7 +223,10 @@ python-black-update: .venv/bin/black
 elixir: export MIX_ENV=integration
 elixir: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1
 elixir: elixir-init elixir-check-formatted elixir-credo devclean
-	@dev/run "$(TEST_OPTS)" -a adm:pass -n 1 --enable-erlang-views --no-eval 'mix test --trace --exclude without_quorum_test --exclude with_quorum_test $(EXUNIT_OPTS)'
+	@dev/run "$(TEST_OPTS)" -a adm:pass -n 1 \
+		--enable-erlang-views \
+		--locald-config test/elixir/test/config/test-config.ini \
+		--no-eval 'mix test --trace --exclude without_quorum_test --exclude with_quorum_test $(EXUNIT_OPTS)'
 
 .PHONY: elixir-init
 elixir-init: MIX_ENV=test
diff --git a/dev/run b/dev/run
index a96817d..573c80c 100755
--- a/dev/run
+++ b/dev/run
@@ -211,6 +211,14 @@ def get_args_parser():
         default=None,
         help="Extra arguments to pass to beam process",
     )
+    parser.add_option(
+        "-l",
+        "--locald-config",
+        dest="locald_configs",
+        action="append",
+        default=[],
+        help="Path to config to place in 'local.d'. Can be repeated",
+    )
     return parser
 
 
@@ -238,6 +246,7 @@ def setup_context(opts, args):
         "reset_logs": True,
         "procs": [],
         "auto_ports": opts.auto_ports,
+        "locald_configs": opts.locald_configs,
     }
 
 
@@ -279,9 +288,24 @@ def setup_configs(ctx):
             "_default": "",
         }
         write_config(ctx, node, env)
+        write_locald_configs(ctx, node, env)
     generate_haproxy_config(ctx)
 
 
+def write_locald_configs(ctx, node, env):
+    for locald_config in ctx["locald_configs"]:
+        config_src = os.path.join(ctx["rootdir"], locald_config)
+        if os.path.exists(config_src):
+            config_filename = os.path.basename(config_src)
+            config_tgt = os.path.join(
+                ctx["devdir"], "lib", node, "etc", "local.d", config_filename
+            )
+            with open(config_src) as handle:
+                content = handle.read()
+            with open(config_tgt, "w") as handle:
+                handle.write(content)
+
+
 def generate_haproxy_config(ctx):
     haproxy_config = os.path.join(ctx["devdir"], "lib", "haproxy.cfg")
     template = os.path.join(ctx["rootdir"], "rel", "haproxy.cfg")
@@ -382,6 +406,8 @@ def write_config(ctx, node, env):
         with open(tgt, "w") as handle:
             handle.write(content)
 
+    ensure_dir_exists(etc_tgt, "local.d")
+
 
 def boot_haproxy(ctx):
     if not ctx["with_haproxy"]:
@@ -580,6 +606,7 @@ def boot_node(ctx, node):
         "-couch_ini",
         os.path.join(node_etcdir, "default.ini"),
         os.path.join(node_etcdir, "local.ini"),
+        os.path.join(node_etcdir, "local.d"),
         "-reltool_config",
         os.path.join(reldir, "reltool.config"),
         "-parent_pid",
diff --git a/test/elixir/README.md b/test/elixir/README.md
index 6a19c24..f163dd0 100644
--- a/test/elixir/README.md
+++ b/test/elixir/README.md
@@ -60,7 +60,7 @@ X means done, - means partially
   - [X] Port lots_of_docs.js
   - [ ] Port method_override.js
   - [X] Port multiple_rows.js
-  - [ ] Port proxyauth.js
+  - [X] Port proxyauth.js
   - [ ] Port purge.js
   - [ ] Port reader_acl.js
   - [ ] Port recreate_doc.js
diff --git a/test/elixir/lib/couch.ex b/test/elixir/lib/couch.ex
index 3aef07f..7819299 100644
--- a/test/elixir/lib/couch.ex
+++ b/test/elixir/lib/couch.ex
@@ -127,8 +127,8 @@ defmodule Couch do
   def set_auth_options(options) do
     if Keyword.get(options, :cookie) == nil do
       headers = Keyword.get(options, :headers, [])
-
-      if headers[:basic_auth] != nil or headers[:authorization] != nil do
+      if headers[:basic_auth] != nil or headers[:authorization] != nil
+         or List.keymember?(headers, :"X-Auth-CouchDB-UserName", 0) do
         options
       else
         username = System.get_env("EX_USERNAME") || "adm"
diff --git a/test/elixir/test/config/test-config.ini b/test/elixir/test/config/test-config.ini
new file mode 100644
index 0000000..72a13a7
--- /dev/null
+++ b/test/elixir/test/config/test-config.ini
@@ -0,0 +1,2 @@
+[chttpd]
+authentication_handlers = {chttpd_auth, proxy_authentication_handler}, {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, default_authentication_handler}
diff --git a/test/elixir/test/proxyauth_test.exs b/test/elixir/test/proxyauth_test.exs
new file mode 100644
index 0000000..6f2d49a
--- /dev/null
+++ b/test/elixir/test/proxyauth_test.exs
@@ -0,0 +1,163 @@
+defmodule ProxyAuthTest do
+  use CouchTestCase
+
+  @moduletag :authentication
+
+  @tag :with_db
+  test "proxy auth with secret", context do
+    db_name = context[:db_name]
+
+    design_doc = %{
+      _id: "_design/test",
+      language: "javascript",
+      shows: %{
+        welcome: """
+           function(doc,req) {
+          return "Welcome " + req.userCtx["name"];
+        }
+        """,
+        role: """
+          function(doc, req) {
+          return req.userCtx['roles'][0];
+        }
+        """
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, design_doc)
+
+    users_db_name = random_db_name()
+    create_db(users_db_name)
+
+    secret = generate_secret(64)
+
+    server_config = [
+      %{
+        :section => "chttpd_auth",
+        :key => "authentication_db",
+        :value => users_db_name
+      },
+      %{
+        :section => "couch_httpd_auth",
+        :key => "proxy_use_secret",
+        :value => "true"
+      },
+      %{
+        :section => "couch_httpd_auth",
+        :key => "secret",
+        :value => secret
+      }
+    ]
+
+    run_on_modified_server(server_config, fn ->
+      test_fun(db_name, users_db_name, secret)
+    end)
+    delete_db(users_db_name)
+  end
+
+  defp generate_secret(len) do
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+    |> String.splitter("", trim: true)
+    |> Enum.take_random(len)
+    |> Enum.join("")
+  end
+
+  defp hex_hmac_sha1(secret, message) do
+    signature = :crypto.hmac(:sha, secret, message)
+    Base.encode16(signature, case: :lower)
+  end
+
+  def test_fun(db_name, users_db_name, secret) do
+    user = prepare_user_doc(name: "couch@apache.org", password: "test")
+    create_doc(users_db_name, user)
+
+    resp =
+      Couch.get("/_session",
+        headers: [authorization: "Basic Y291Y2hAYXBhY2hlLm9yZzp0ZXN0"]
+      )
+
+    assert resp.body["userCtx"]["name"] == "couch@apache.org"
+    assert resp.body["info"]["authenticated"] == "default"
+
+    headers = [
+      "X-Auth-CouchDB-UserName": "couch@apache.org",
+      "X-Auth-CouchDB-Roles": "test",
+      "X-Auth-CouchDB-Token": hex_hmac_sha1(secret, "couch@apache.org")
+    ]
+    resp = Couch.get("/#{db_name}/_design/test/_show/welcome", headers: headers)
+    assert resp.body == "Welcome couch@apache.org"
+
+    resp = Couch.get("/#{db_name}/_design/test/_show/role", headers: headers)
+    assert resp.body == "test"
+  end
+
+  @tag :with_db
+  test "proxy auth without secret", context do
+    db_name = context[:db_name]
+
+    design_doc = %{
+      _id: "_design/test",
+      language: "javascript",
+      shows: %{
+        welcome: """
+           function(doc,req) {
+          return "Welcome " + req.userCtx["name"];
+        }
+        """,
+        role: """
+          function(doc, req) {
+          return req.userCtx['roles'][0];
+        }
+        """
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, design_doc)
+
+    users_db_name = random_db_name()
+    create_db(users_db_name)
+
+    server_config = [
+      %{
+        :section => "chttpd_auth",
+        :key => "authentication_db",
+        :value => users_db_name
+      },
+      %{
+        :section => "couch_httpd_auth",
+        :key => "proxy_use_secret",
+        :value => "false"
+      }
+    ]
+
+    run_on_modified_server(server_config, fn ->
+      test_fun_no_secret(db_name, users_db_name)
+    end)
+
+    delete_db(users_db_name)
+  end
+
+  def test_fun_no_secret(db_name, users_db_name) do
+    user = prepare_user_doc(name: "couch@apache.org", password: "test")
+    create_doc(users_db_name, user)
+
+    resp =
+      Couch.get("/_session",
+        headers: [authorization: "Basic Y291Y2hAYXBhY2hlLm9yZzp0ZXN0"]
+      )
+
+    assert resp.body["userCtx"]["name"] == "couch@apache.org"
+    assert resp.body["info"]["authenticated"] == "default"
+
+    headers = [
+      "X-Auth-CouchDB-UserName": "couch@apache.org",
+      "X-Auth-CouchDB-Roles": "test"
+    ]
+
+    resp = Couch.get("/#{db_name}/_design/test/_show/welcome", headers: headers)
+    assert resp.body == "Welcome couch@apache.org"
+
+    resp = Couch.get("/#{db_name}/_design/test/_show/role", headers: headers)
+    assert resp.body == "test"
+  end
+end
diff --git a/test/elixir/test/users_db_test.exs b/test/elixir/test/users_db_test.exs
index 71ab2f7..1d34d8c 100644
--- a/test/elixir/test/users_db_test.exs
+++ b/test/elixir/test/users_db_test.exs
@@ -147,7 +147,8 @@ defmodule UsersDbTest do
     assert resp.body["userCtx"]["name"] == "jchris@apache.org"
     assert resp.body["info"]["authenticated"] == "default"
     assert resp.body["info"]["authentication_db"] == @users_db_name
-    assert resp.body["info"]["authentication_handlers"] == ["cookie", "default"]
+    assert Enum.member?(resp.body["info"]["authentication_handlers"], "cookie")
+    assert Enum.member?(resp.body["info"]["authentication_handlers"], "default")
 
     resp =
       Couch.get(
diff --git a/test/javascript/tests/proxyauth.js b/test/javascript/tests/proxyauth.js
index cc75faa..7f2e097 100644
--- a/test/javascript/tests/proxyauth.js
+++ b/test/javascript/tests/proxyauth.js
@@ -11,10 +11,10 @@
 // the License.
  
  
- 
+couchTests.elixir = true;
 couchTests.proxyauth = function(debug) {
   // this test proxy authentification handler
-
+  return console.log('done in test/elixir/test/proxyauth_test.exs');
   var users_db_name = get_random_db_name();
   var usersDb = new CouchDB(users_db_name, {"X-Couch-Full-Commit":"false"});
   usersDb.createDb();