return str.str();
}
+ void toStringVector(vector<string>* vec) const
+ {
+ for(container_t::const_iterator iter = d_masks.begin(); iter != d_masks.end(); ++iter) {
+ vec->push_back(iter->toString());
+ }
+ }
+
void toMasks(const string &ips)
{
vector<string> parts;
bool g_weDistributeQueries; // if true, only 1 thread listens on the incoming query sockets
-static __thread NetmaskGroup* t_allowFrom;
+__thread NetmaskGroup* t_allowFrom;
static NetmaskGroup* g_initialAllowFrom; // new thread needs to be setup with this
NetmaskGroup* g_dontQuery;
}
};
extern __thread RemoteKeeper* t_remotes;
+extern __thread NetmaskGroup* t_allowFrom;
string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end);
void parseACLs();
#include "rapidjson/writer.h"
#include "webserver.hh"
#include "ws-api.hh"
+#include "logger.hh"
using namespace rapidjson;
ofconf.close();
}
+static void apiServerConfigAllowFrom(HttpRequest* req, HttpResponse* resp)
+{
+ if (req->method == "PUT") {
+ Document document;
+ req->json(document);
+
+ if (!document.IsArray()) {
+ throw ApiException("Supplied JSON must be an array");
+ }
+
+ ostringstream ss;
+
+ // Clear allow-from-file if set, so our changes take effect
+ ss << "allow-from-file=" << endl;
+
+ // Clear allow-from, and provide a "parent" value
+ ss << "allow-from=" << endl;
+ for (SizeType i = 0; i < document.Size(); ++i) {
+ ss << "allow-from+=" << document[i].GetString() << endl;
+ }
+
+ apiWriteConfigFile("allow-from", ss.str());
+
+ parseACLs();
+
+ // fall through to GET
+ } else if (req->method != "GET") {
+ throw HttpMethodNotAllowedException();
+ }
+
+ // Return currently configured ACLs
+ Document document;
+ document.SetArray();
+
+ vector<string> entries;
+ t_allowFrom->toStringVector(&entries);
+
+ BOOST_FOREACH(const string& entry, entries) {
+ Value jentry(entry.c_str(), document.GetAllocator()); // copy
+ document.PushBack(jentry, document.GetAllocator());
+ }
+
+ resp->setBody(document);
+}
+
RecursorWebServer::RecursorWebServer(FDMultiplexer* fdm)
{
RecursorControlParser rcp; // inits
// legacy dispatch
d_ws->registerApiHandler("/jsonstat", boost::bind(&RecursorWebServer::jsonstat, this, _1, _2));
+ d_ws->registerApiHandler("/servers/localhost/config/allow-from", &apiServerConfigAllowFrom);
d_ws->registerApiHandler("/servers/localhost/config", &apiServerConfig);
d_ws->registerApiHandler("/servers/localhost/search-log", &apiServerSearchLog);
d_ws->registerApiHandler("/servers/localhost/statistics", &apiServerStatistics);
/*.controlsocket
/named.conf
/*.pyc
+acl.conf
zone "example.com" { type master; file "example.com"; };
"""
+ACL_LIST_TPL = """
+# Generated by runtests.py
+# local host
+127.0.0.1
+::1
+"""
+
daemon = (len(sys.argv) == 2) and sys.argv[1] or None
if daemon not in ('authoritative', 'recursor'):
print "Usage: ./runtests (authoritative|recursor)"
pdnscmd = ("../pdns/pdns_server --daemon=no --local-port=5300 --socket-dir=./ --no-shuffle --launch=gsqlite3 --gsqlite3-dnssec --send-root-referral --allow-2136-from=127.0.0.0/8 --experimental-rfc2136=yes --cache-ttl=0 --no-config --gsqlite3-database="+SQLITE_DB+" --experimental-json-interface=yes --webserver=yes --webserver-port="+WEBPORT+" --webserver-address=127.0.0.1 --query-logging --webserver-password="+WEBPASSWORD).split()
else:
+ with open('acl.list', 'w') as acl_list:
+ acl_list.write(ACL_LIST_TPL)
- # No preparations for recursor
- pdnscmd = ("../pdns/pdns_recursor --daemon=no --socket-dir=. --local-port=5555 --experimental-json-interface=yes --experimental-webserver=yes --experimental-webserver-port="+WEBPORT+" --experimental-webserver-address=127.0.0.1 --experimental-webserver-password="+WEBPASSWORD).split()
+ pdnscmd = ("../pdns/pdns_recursor --daemon=no --socket-dir=. --config-dir=. --allow-from-file=acl.list --local-port=5555 --experimental-json-interface=yes --experimental-webserver=yes --experimental-webserver-port="+WEBPORT+" --experimental-webserver-address=127.0.0.1 --experimental-webserver-password="+WEBPASSWORD).split()
# Now run pdns and the tests.
--- /dev/null
+import json
+import requests
+import unittest
+from test_helper import ApiTestCase, isRecursor
+
+
+@unittest.skipIf(not isRecursor(), "Only applicable to recursors")
+class RecursorConfig(ApiTestCase):
+
+ def test_ConfigAllowFromGet(self):
+ r = self.session.get(self.url("/servers/localhost/config/allow-from"))
+ self.assertSuccessJson(r)
+
+ def test_ConfigAllowFromReplace(self):
+ payload = ["127.0.0.1"]
+ r = self.session.put(
+ self.url("/servers/localhost/config/allow-from"),
+ data=json.dumps(payload),
+ headers={'content-type': 'application/json'})
+ self.assertSuccessJson(r)
+ data = r.json()
+ self.assertEquals("127.0.0.1/32", data[0])