From 04f3d9892ba7a16b1431f07ac5dc031ff3bf285a Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Mon, 26 Jul 2010 11:20:18 +0000 Subject: Multi-part patch to enable white-listing of _config API values: 1. Refactor read-only config handlers to be near each other 2. Refactor PUT and DELETE config handlers to a wrapper 3. Support a whitelist for modifying the config via HTTP, itself stored in the config 4. Document the whitelist process Patch(es) by Jason Smith. Closes COUCHDB-835. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@979242 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/script/test/config.js | 92 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) (limited to 'share/www') diff --git a/share/www/script/test/config.js b/share/www/script/test/config.js index ef74934b..58e32776 100644 --- a/share/www/script/test/config.js +++ b/share/www/script/test/config.js @@ -50,7 +50,8 @@ couchTests.config = function(debug) { T(config.log.level); T(config.query_servers.javascript); - // test that settings can be altered + // test that settings can be altered, and that an undefined whitelist allows any change + TEquals(undefined, config.httpd.config_whitelist, "Default whitelist is empty"); xhr = CouchDB.request("PUT", "/_config/test/foo",{ body : JSON.stringify("bar"), headers: {"X-Couch-Persist": "false"} @@ -64,4 +65,93 @@ couchTests.config = function(debug) { xhr = CouchDB.request("GET", "/_config/test/foo"); config = JSON.parse(xhr.responseText); T(config == "bar"); + + // Non-term whitelist values allow further modification of the whitelist. + xhr = CouchDB.request("PUT", "/_config/httpd/config_whitelist",{ + body : JSON.stringify("!This is an invalid Erlang term!"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Set config whitelist to an invalid Erlang term"); + xhr = CouchDB.request("DELETE", "/_config/httpd/config_whitelist",{ + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Modify whitelist despite it being invalid syntax"); + + // Non-list whitelist values allow further modification of the whitelist. + xhr = CouchDB.request("PUT", "/_config/httpd/config_whitelist",{ + body : JSON.stringify("{[yes, a_valid_erlang_term, but_unfortunately, not_a_list]}"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Set config whitelist to an non-list term"); + xhr = CouchDB.request("DELETE", "/_config/httpd/config_whitelist",{ + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Modify whitelist despite it not being a list"); + + // Keys not in the whitelist may not be modified. + xhr = CouchDB.request("PUT", "/_config/httpd/config_whitelist",{ + body : JSON.stringify("[{httpd,config_whitelist}, {test,foo}]"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Set config whitelist to something valid"); + + ["PUT", "DELETE"].forEach(function(method) { + ["test/not_foo", "not_test/foo", "neither_test/nor_foo"].forEach(function(pair) { + var path = "/_config/" + pair; + var test_name = method + " to " + path + " disallowed: not whitelisted"; + + xhr = CouchDB.request(method, path, { + body : JSON.stringify("Bummer! " + test_name), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(400, xhr.status, test_name); + }); + }); + + // Keys in the whitelist may be modified. + ["PUT", "DELETE"].forEach(function(method) { + xhr = CouchDB.request(method, "/_config/test/foo",{ + body : JSON.stringify(method + " to whitelisted config variable"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Keys in the whitelist may be modified"); + }); + + // Non-2-tuples in the whitelist are ignored + xhr = CouchDB.request("PUT", "/_config/httpd/config_whitelist",{ + body : JSON.stringify("[{httpd,config_whitelist}, these, {are}, {nOt, 2, tuples}," + + " [so], [they, will], [all, become, noops], {test,foo}]"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Set config whitelist with some inert values"); + ["PUT", "DELETE"].forEach(function(method) { + xhr = CouchDB.request(method, "/_config/test/foo",{ + body : JSON.stringify(method + " to whitelisted config variable"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Update whitelisted variable despite invalid entries"); + }); + + // Atoms, binaries, and strings suffice as whitelist sections and keys. + ["{test,foo}", '{"test","foo"}', '{<<"test">>,<<"foo">>}'].forEach(function(pair) { + xhr = CouchDB.request("PUT", "/_config/httpd/config_whitelist",{ + body : JSON.stringify("[{httpd,config_whitelist}, " + pair + "]"), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Set config whitelist to include " + pair); + + var pair_format = {"t":"tuple", '"':"string", "<":"binary"}[pair[1]]; + ["PUT", "DELETE"].forEach(function(method) { + xhr = CouchDB.request(method, "/_config/test/foo",{ + body : JSON.stringify(method + " with " + pair_format), + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Whitelist works with " + pair_format); + }); + }); + + xhr = CouchDB.request("DELETE", "/_config/httpd/config_whitelist",{ + headers: {"X-Couch-Persist": "false"} + }); + TEquals(200, xhr.status, "Reset config whitelist to undefined"); }; -- cgit v1.2.3