def test_all_config_written(): set_cwd(tempfile.mkdtemp()) cuckoo_create() cfg = Config.from_confdir(cwd("conf")) # This one is extra, ignore. cfg["virtualbox"].pop("honeyd", None) set_cwd(tempfile.mkdtemp()) mkdir(cwd("conf")) lookups = [] class LookupDict(dict): parents = [] def __getitem__(self, key): lookups.append(":".join(self.parents + [key])) return dict.__getitem__(key) class Template(jinja2.Template): def render(self, kw): orig_config = kw["config"] def lookup_config(s): # For some reason this is called multiple times (?). if s not in lookups: lookups.append(s) return orig_config(s) kw["config"] = lookup_config for key, value in kw.items(): if key == "config": continue for key2, value2 in value.items(): value[key2] = LookupDict(value2) value[key2].parents = [key, key2] return jinja2.Template.render(self, kw) with mock.patch("cuckoo.core.init.jinja2") as p: p.Template = Template write_cuckoo_conf(cfg) print cfg["cuckoo"] # Force port was removed/now unused for backwards compatibility cfg["cuckoo"]["resultserver"].pop("force_port", None) # Pool size is a hidden option for now cfg["cuckoo"]["resultserver"].pop("pool_size", None) for key, value in cfg.items(): for key2, value2 in value.items(): for key3, value3 in value2.items(): assert "%s:%s:%s" % (key, key2, key3) in lookups assert sorted(lookups) == sorted(set(lookups))
def setup(self): set_cwd(tempfile.mkdtemp()) Folders.create(cwd(), "conf") write_cuckoo_conf() with mock.patch("cuckoo.common.abstracts.Database") as p: p.return_value = mock.MagicMock() self.m = QEMU() self.m.set_options(Config("qemu"))
def test_all_config_written(): set_cwd(tempfile.mkdtemp()) cuckoo_create() cfg = Config.from_confdir(cwd("conf")) # This one is extra, ignore. cfg["virtualbox"].pop("honeyd", None) set_cwd(tempfile.mkdtemp()) mkdir(cwd("conf")) # Add the force_port entry as it has been deleted from the config files, # but remains in the config.py to prevent errors with users that have it # in their config. lookups = ["cuckoo:resultserver:force_port"] class LookupDict(dict): parents = [] def __getitem__(self, key): lookups.append(":".join(self.parents + [key])) return dict.__getitem__(key) class Template(jinja2.Template): def render(self, kw): orig_config = kw["config"] def lookup_config(s): # For some reason this is called multiple times (?). if s not in lookups: lookups.append(s) return orig_config(s) kw["config"] = lookup_config for key, value in kw.items(): if key == "config": continue for key2, value2 in value.items(): value[key2] = LookupDict(value2) value[key2].parents = [key, key2] return jinja2.Template.render(self, kw) with mock.patch("cuckoo.core.init.jinja2") as p: p.Template = Template write_cuckoo_conf(cfg) for key, value in cfg.items(): for key2, value2 in value.items(): for key3, value3 in value2.items(): assert "%s:%s:%s" % (key, key2, key3) in lookups assert sorted(lookups) == sorted(set(lookups))
def cuckoo_machine(vmname, action, ip, platform, options, tags, interface, snapshot, resultserver): db = Database() cfg = Config.from_confdir(cwd("conf")) machinery = cfg["cuckoo"]["cuckoo"]["machinery"] machines = cfg[machinery][machinery]["machines"] if action == "add": if not ip: sys.exit("You have to specify a legitimate IP address for --add.") if db.view_machine(vmname): sys.exit("A Virtual Machine with this name already exists!") if vmname in machines: sys.exit("A Virtual Machine with this name already exists!") if resultserver and resultserver.count(":") == 1: resultserver_ip, resultserver_port = resultserver.split(":") resultserver_port = int(resultserver_port) else: resultserver_ip = cfg["cuckoo"]["resultserver"]["ip"] resultserver_port = cfg["cuckoo"]["resultserver"]["port"] machines.append(vmname) cfg[machinery][vmname] = { "label": vmname, "platform": platform, "ip": ip, "options": options, "snapshot": snapshot, "interface": interface, "resultserver_ip": resultserver_ip, "resultserver_port": resultserver_port, "tags": tags, } db.add_machine( vmname, vmname, ip, platform, options, tags, interface, snapshot, resultserver_ip, int(resultserver_port) ) db.unlock_machine(vmname) if action == "delete": # TODO Add a db.del_machine() function for runtime modification. if vmname not in machines: sys.exit("A Virtual Machine with this name doesn't exist!") machines.remove(vmname) cfg[machinery].pop(vmname) write_cuckoo_conf(cfg=cfg)
def setup(self): set_cwd(tempfile.mkdtemp()) Folders.create(cwd(), "conf") write_cuckoo_conf() with mock.patch("cuckoo.common.abstracts.Database") as p: p.return_value = mock.MagicMock() self.m = QEMU() self.m.db.clean_machines.assert_called_once() self.m.set_options(Config("qemu"))
def setup(self): set_cwd(tempfile.mkdtemp()) Folders.create(cwd(), "conf") write_cuckoo_conf() with mock.patch("cuckoo.common.abstracts.Database") as p: p.return_value = mock.MagicMock() self.m = VirtualBox() self.m.db.clean_machines.assert_called_once() self.m.set_options(Config("virtualbox"))
def test_star_not_found(self): with pytest.raises(CuckooConfigurationError) as e: write_cuckoo_conf(cfg={ "routing": { "vpn": { "vpns": [ "a", ], }, }, }) e.match("A section was defined that")
def test_default_star(self): write_cuckoo_conf() assert self.value("routing:vpn0:name") == "vpn0" assert self.rawvalue("routing:vpn0:name") == "vpn0" assert self.value("virtualbox:cuckoo1:ip") == "192.168.56.101" assert self.value("avd:cuckoo1:platform") == "android" assert self.value("esx:analysis1:ip") == "192.168.122.101" assert self.value("physical:physical1:label") == "physical1" assert self.value("qemu:vm1:label") == "vm1" assert self.value("vmware:cuckoo1:vmx_path") == "../cuckoo1/cuckoo1.vmx" assert self.value("vsphere:analysis1:snapshot") == "snapshot_name" assert self.value("xenserver:cuckoo1:uuid") == "00000000-0000-0000-0000-000000000000"
def test_all_config_written(): set_cwd(tempfile.mkdtemp()) cuckoo_create() cfg = Config.from_confdir(cwd("conf")) # This one is extra, ignore. cfg["virtualbox"].pop("honeyd", None) set_cwd(tempfile.mkdtemp()) mkdir(cwd("conf")) lookups = [] class LookupDict(dict): parents = [] def __getitem__(self, key): lookups.append(":".join(self.parents + [key])) return dict.__getitem__(key) class Template(jinja2.Template): def render(self, kw): orig_config = kw["config"] def lookup_config(s): # For some reason this is called multiple times (?). if s not in lookups: lookups.append(s) return orig_config(s) kw["config"] = lookup_config for key, value in kw.items(): if key == "config": continue for key2, value2 in value.items(): value[key2] = LookupDict(value2) value[key2].parents = [key, key2] return jinja2.Template.render(self, kw) with mock.patch("cuckoo.core.init.jinja2") as p: p.Template = Template write_cuckoo_conf(cfg) for key, value in cfg.items(): for key2, value2 in value.items(): for key3, value3 in value2.items(): assert "%s:%s:%s" % (key, key2, key3) in lookups assert sorted(lookups) == sorted(set(lookups))
def test_invalid_machinery(): set_cwd(tempfile.mkdtemp()) Folders.create(cwd(), "conf") write_cuckoo_conf({ "cuckoo": { "cuckoo": { "machinery": "foobar", }, }, }) with pytest.raises(CuckooStartupError) as e: check_configs() e.match("unknown machinery")
def init(ctx, conf): """Initializes Cuckoo and its configuration.""" if conf and os.path.exists(conf): cfg = read_kv_conf(conf) else: cfg = None # If this is a new install, also apply the provided configuration. cuckoo_init(logging.INFO, ctx.parent, cfg) # If this is an existing install, overwrite the supervisord.conf # configuration file (if needed) as well as the Cuckoo configuration. write_supervisor_conf(ctx.parent.user or getuser()) write_cuckoo_conf(cfg)
def cuckoo_create(username=None, cfg=None, quiet=False): """Create a new Cuckoo Working Directory.""" if not quiet: print jinja2.Environment().from_string( open(cwd("cwd", "init-pre.jinja2", private=True), "rb").read() ).render(cwd=cwd, yellow=yellow, red=red) if not os.path.exists(cwd(".cwd", private=True)): print red( "The cuckoo/private/.cwd file is missing. Please run " "'python setup.py sdist' before 'pip install ...'!" ) return if not os.path.isdir(cwd()): os.mkdir(cwd()) def _ignore_pyc(src, names): """Don't copy .pyc files.""" return [name for name in names if name.endswith(".pyc")] # The following effectively nops the first os.makedirs() call that # shutil.copytree() does as we've already created the destination # directory ourselves (assuming it didn't exist already). orig_makedirs = shutil.os.makedirs def _ignore_first_makedirs(dst): shutil.os.makedirs = orig_makedirs shutil.os.makedirs = _ignore_first_makedirs shutil.copytree( os.path.join(cuckoo.__path__[0], "data"), cwd(), symlinks=True, ignore=_ignore_pyc ) # Drop our version of the CWD. our_version = open(cwd(".cwd", private=True), "rb").read() open(cwd(".cwd"), "wb").write(our_version) # Write the supervisord.conf configuration file. write_supervisor_conf(username or getuser()) write_cuckoo_conf(cfg=cfg) if not quiet: print print jinja2.Environment().from_string( open(cwd("cwd", "init-post.jinja2", private=True), "rb").read() ).render()
def task(task_id, options, conf, results, filename="a.txt"): Folders.create(cwd(), ["conf", "storage"]) Folders.create(cwd("storage"), ["analyses", "binaries"]) Folders.create(cwd("storage", "analyses"), "%s" % task_id) Folders.create(cwd("storage", "analyses", "%s" % task_id), ["reports"]) write_cuckoo_conf({ "reporting": conf, }) task = { "id": task_id, "options": options, "target": filename, } RunReporting(task, results).run()
def test_route_network_socks5_noport(self, mr): write_cuckoo_conf(cfg={ "auxiliary": { "redsocks": { "enabled": True } } }) route = Route(FakeTask(options={ "route": "socks5" }), FakeMachine()) route.route_network() assert route.route == "none" assert route.task.options["route"] is "none" assert route.interface is None assert route.rt_table is None mr.assert_not_called()
def task(task_id, options, conf, results, filename="a.txt"): Folders.create(cwd(), ["conf", "storage"]) Folders.create(cwd("storage"), ["analyses", "binaries"]) Folders.create(cwd("storage", "analyses"), "%s" % task_id) Folders.create(cwd("storage", "analyses", "%s" % task_id), [ "reports" ]) write_cuckoo_conf({ "reporting": conf, }) task = { "id": task_id, "options": options, "target": filename, } RunReporting(task, results).run()
def test_route_network_socks5(self, mr): write_cuckoo_conf(cfg={ "auxiliary": { "redsocks": { "enabled": True } } }) route = Route(FakeTask(options={ "route": "socks5", "socks5.localport": 4242 }), FakeMachine()) route.route_network() assert route.route == "socks5" assert route.interface is None assert route.rt_table is None mr.assert_called_once_with( "proxy_enable", "192.168.56.10", "192.168.56.1", "53", "4242" )
def test_star_single(self): write_cuckoo_conf( cfg={ "routing": { "vpn": { "vpns": ["a"], }, "a": { "description": "VPN a", }, }, }) assert self.value("routing:vpn:vpns") == ["a"] assert self.rawvalue("routing:vpn:vpns") == "a" assert self.value("routing:a:name") is None assert self.rawvalue("routing:a:name") == "" assert self.value("routing:a:description") == "VPN a" assert self.rawvalue("routing:a:description") == "VPN a"
def test_star_multiple(self): write_cuckoo_conf( cfg={ "virtualbox": { "virtualbox": { "machines": ["a", "b"], }, "a": { "ip": "1.2.3.4", }, "b": { "ip": "5.6.7.8", }, }, }) assert self.value("virtualbox:virtualbox:machines") == ["a", "b"] assert self.rawvalue("virtualbox:virtualbox:machines") == "a, b" assert self.value("virtualbox:a:ip") == "1.2.3.4" assert self.rawvalue("virtualbox:a:ip") == "1.2.3.4"
def test_simple(self): write_cuckoo_conf(cfg={ "cuckoo": { "cuckoo": { "version_check": False, }, }, }) assert self.value("cuckoo:cuckoo:version_check") is False with pytest.raises(ValueError): self.value("a") with pytest.raises(KeyError): self.value("a:b:c") with pytest.raises(KeyError): self.value("cuckoo:a:b") with pytest.raises(KeyError): self.value("cuckoo:cuckoo:c")
def test_star_multiple(self): write_cuckoo_conf(cfg={ "virtualbox": { "virtualbox": { "machines": [ "a", "b" ], }, "a": { "ip": "1.2.3.4", }, "b": { "ip": "5.6.7.8", }, }, }) assert self.value("virtualbox:virtualbox:machines") == ["a", "b"] assert self.rawvalue("virtualbox:virtualbox:machines") == "a, b" assert self.value("virtualbox:a:ip") == "1.2.3.4" assert self.rawvalue("virtualbox:a:ip") == "1.2.3.4"
def test_star_single(self): write_cuckoo_conf(cfg={ "routing": { "vpn": { "vpns": [ "a" ], }, "a": { "description": "VPN a", }, }, }) assert self.value("routing:vpn:vpns") == ["a"] assert self.rawvalue("routing:vpn:vpns") == "a" assert self.value("routing:a:name") is None assert self.rawvalue("routing:a:name") == "" assert self.value("routing:a:description") == "VPN a" assert self.rawvalue("routing:a:description") == "VPN a"
def test_route_network_internet(self, mr): write_cuckoo_conf(cfg={ "routing": { "routing": { "internet": "eth0" } } }) # Clear config cache so it will load new values config._cache = {} mr.return_value = True route = Route(FakeTask(options={"route": "internet"}), FakeMachine()) route.route_network() assert route.route == "internet" assert route.interface == "eth0" assert route.rt_table == "main" mr.assert_has_calls([ mock.call("nic_available", "eth0"), mock.call("drop_enable", "192.168.56.10", "192.168.56.1", "2042"), mock.call("forward_enable", "tap0", "eth0", "192.168.56.10"), mock.call("srcroute_enable", "main", "192.168.56.10") ])
def test_default_simple(self): write_cuckoo_conf() assert self.value("cuckoo:feedback:name") is None assert self.value("cuckoo:cuckoo:max_vmstartup_count") == 10 assert self.rawvalue("cuckoo:cuckoo:max_vmstartup_count") == "10"
def test_cuckoo_conf(self): Folders.create(cwd(), "conf") write_cuckoo_conf()