summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lehnardt <jan@apache.org>2020-01-04 20:12:58 +0100
committerGitHub <noreply@github.com>2020-01-04 20:12:58 +0100
commit3fc054d86f0844bdf851e402b05df5db08b1c230 (patch)
tree953092f6131067c342a3b41c685f06a5b26f870b
parent9eeebabecbf6d4dd20de28ec11353cc315553858 (diff)
downloadcouchdb-3fc054d86f0844bdf851e402b05df5db08b1c230.tar.gz
Feature/user db security obj readonly (#2395)
* Allow to set the user db security object to readonly - Add the default config - Deny update on _security if the database is the user db and if the config is to false - Add unit test * Allow edits on _users security for the JS test Co-authored-by: Alexis Côté <popojargo@users.noreply.github.com>
-rw-r--r--rel/overlay/etc/default.ini3
-rw-r--r--src/chttpd/src/chttpd_db.erl11
-rw-r--r--src/chttpd/test/eunit/chttpd_security_tests.erl24
-rw-r--r--test/javascript/tests/users_db_security.js20
4 files changed, 53 insertions, 5 deletions
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index a0c26174c..7bfbbe941 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -80,6 +80,9 @@ default_engine = couch
; document. Default is 24 hours.
;index_lag_warn_seconds = 86400
+; Allow edits on the _security object in the user db. By default, it's disabled.
+users_db_security_editable = false
+
[couchdb_engines]
; The keys in this section are the filename extension that
; the specified engine module will use. This is important so
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 1787e3929..6a3df6def 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -781,6 +781,8 @@ db_req(#httpd{path_parts=[_,<<"_revs_diff">>]}=Req, _Db) ->
db_req(#httpd{method='PUT',path_parts=[_,<<"_security">>],user_ctx=Ctx}=Req,
Db) ->
+ DbName = ?b2l(couch_db:name(Db)),
+ validate_security_can_be_edited(DbName),
SecObj = chttpd:json_body(Req),
case fabric:set_security(Db, SecObj, [{user_ctx, Ctx}]) of
ok ->
@@ -1886,6 +1888,15 @@ extract_header_rev(Req, ExplicitRev) ->
throw({bad_request, "Document rev and etag have different values"})
end.
+validate_security_can_be_edited(DbName) ->
+ UserDbName = config:get("chttpd_auth", "authentication_db", "_users"),
+ CanEditUserSecurityObject = config:get("couchdb","users_db_security_editable","false"),
+ case {DbName,CanEditUserSecurityObject} of
+ {UserDbName,"false"} ->
+ Msg = "You can't edit the security object of the user database.",
+ throw({forbidden, Msg});
+ {_,_} -> ok
+ end.
validate_attachment_names(Doc) ->
lists:foreach(fun(Att) ->
diff --git a/src/chttpd/test/eunit/chttpd_security_tests.erl b/src/chttpd/test/eunit/chttpd_security_tests.erl
index 955b4ff01..0bea9dbcd 100644
--- a/src/chttpd/test/eunit/chttpd_security_tests.erl
+++ b/src/chttpd/test/eunit/chttpd_security_tests.erl
@@ -137,7 +137,8 @@ security_object_validate_test_() ->
fun should_return_ok_for_sec_obj_with_roles_and_names/1,
fun should_return_error_for_sec_obj_with_incorrect_roles_and_names/1,
fun should_return_error_for_sec_obj_with_incorrect_roles/1,
- fun should_return_error_for_sec_obj_with_incorrect_names/1
+ fun should_return_error_for_sec_obj_with_incorrect_names/1,
+ fun should_return_error_for_sec_obj_in_user_db/1
]
}
}
@@ -382,3 +383,24 @@ should_return_error_for_sec_obj_with_incorrect_names([Url,_UsersUrl]) ->
{<<"reason">>,<<"no_majority">>}
]}, ResultJson)
].
+
+should_return_error_for_sec_obj_in_user_db([_,_UsersUrl]) ->
+ SecurityUrl = lists:concat([_UsersUrl, "/_security"]),
+ SecurityProperties = [
+ {<<"admins">>, {[{<<"names">>,[<<?TEST_ADMIN>>]},
+ {<<"roles">>,[<<?TEST_ADMIN>>]}]}},
+ {<<"members">>,{[{<<"names">>,[<<?TEST_MEMBER>>]},
+ {<<"roles">>,[<<?TEST_MEMBER>>]}]}}
+ ],
+
+ Body = jiffy:encode({SecurityProperties}),
+ {ok, Status, _, RespBody} = test_request:put(SecurityUrl,
+ [?CONTENT_JSON, ?AUTH], Body),
+ ResultJson = ?JSON_DECODE(RespBody),
+ [
+ ?_assertEqual(403, Status),
+ ?_assertEqual({[
+ {<<"error">>,<<"forbidden">>},
+ {<<"reason">>,<<"You can't edit the security object of the user database.">>}
+ ]}, ResultJson)
+ ].
diff --git a/test/javascript/tests/users_db_security.js b/test/javascript/tests/users_db_security.js
index 1db6c14c5..faffd8c27 100644
--- a/test/javascript/tests/users_db_security.js
+++ b/test/javascript/tests/users_db_security.js
@@ -374,10 +374,22 @@ couchTests.users_db_security = function(debug) {
};
run_on_modified_server(
- [{section: "couch_httpd_auth",
- key: "iterations", value: "1"},
- {section: "admins",
- key: "jan", value: "apple"}],
+ [
+ {
+ section:"couchdb",
+ key:"users_db_security_editable",
+ value:"true"
+ },
+ {
+ section: "couch_httpd_auth",
+ key: "iterations",
+ value: "1"
+ },
+ {
+ section: "admins",
+ key: "jan",
+ value: "apple"
+ }],
function() {
try {
testFun();