Beispiel #1
0
def snapshot_import(name, bucket, full, zpool):
    local_install = InstallInfo.try_load()
    if local_install is not None:
        click.confirm(
            "Detected local snapshot. It will be REMOVED. Continue?", abort=True
        )

    mc = get_minio_client(conf)

    if not mc.bucket_exists(bucket):
        logging.error("Bucket %s doesn't exist", bucket)
        return

    ensure_dirs()

    try:
        if full:
            logging.warning(
                "Importing full snapshot. This may not work if hardware is different"
            )
            do_import_full(mc, name, bucket, zpool)
        else:
            do_import_minimal(mc, name, bucket, zpool)

            # This could probably use some refactoring
            # We're duplicating quite a lot of code from install function
            install_info = InstallInfo.load()
            generate_vm_conf(install_info, 0)
            backend = get_storage_backend(install_info)
            backend.rollback_vm_storage(0)

            net_enable = int(conf["drakrun"].get("net_enable", "0"))
            out_interface = conf["drakrun"].get("out_interface", "")
            dns_server = conf["drakrun"].get("dns_server", "")
            setup_vm_network(
                vm_id=0,
                net_enable=net_enable,
                out_interface=out_interface,
                dns_server=dns_server,
            )

            if net_enable:
                start_dnsmasq(vm_id=0, dns_server=dns_server, background=True)

            cfg_path = os.path.join(VM_CONFIG_DIR, "vm-0.cfg")

            try:
                subprocess.run(["xl" "create", cfg_path], check=True)
            except subprocess.CalledProcessError:
                logging.exception("Failed to launch VM vm-0")
                return

            logging.info("Minimal snapshots require postinstall to work correctly")
            logging.info(
                "Please VNC to the port 5900 to ensure the OS booted correctly"
            )
            logging.info("After that, execute this command to finish the setup")
            logging.info("# draksetup postinstall")
    except NoSuchKey:
        logging.error("Import failed. Missing files in bucket.")
def create_missing_profiles():
    """
    Creates usermode profiles by restoring vm-1 and extracting the DLLs.
    Assumes that injector is configured properly, i.e. kernel and runtime
    profiles exist and that vm-1 is free to use.
    """

    # Prepare injector
    with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f:
        runtime_info = RuntimeInfo.load(runtime_f)
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    injector = Injector("vm-1", runtime_info, kernel_profile)

    # restore vm-1
    out_interface = conf["drakrun"].get("out_interface", "")
    dns_server = conf["drakrun"].get("dns_server", "")
    install_info = InstallInfo.load()
    backend = get_storage_backend(install_info)

    generate_vm_conf(install_info, 1)
    setup_vm_network(vm_id=1,
                     net_enable=False,
                     out_interface=out_interface,
                     dns_server=dns_server)
    vm = VirtualMachine(backend, 1)
    vm.restore()

    # Ensure that all declared usermode profiles exist
    # This is important when upgrade defines new entries in dll_file_list and compulsory_dll_file_list
    for profile in compulsory_dll_file_list:
        if not profiles_exist(profile.dest):
            create_rekall_profile(injector, profile, True)

    for profile in dll_file_list:
        if not profiles_exist(profile.dest):
            try:
                create_rekall_profile(injector, profile)
            except Exception:
                log.exception(
                    "Unexpected exception from create_rekall_profile!")

    build_os_info(APISCOUT_PROFILE_DIR, vmi_win_guid(vm.vm_name), backend)

    dll_basename_list = [dll.dest for dll in dll_file_list]
    static_apiscout_profile = build_static_apiscout_profile(
        APISCOUT_PROFILE_DIR, dll_basename_list)
    with open(
            Path(APISCOUT_PROFILE_DIR) / "static_apiscout_profile.json",
            "w") as f:
        json.dump(static_apiscout_profile, f)

    vm.destroy()
    delete_vm_network(vm_id=1,
                      net_enable=False,
                      out_interface=out_interface,
                      dns_server=dns_server)
Beispiel #3
0
def network_setup_test():
    if not tool_exists('brctl'):
        pytest.skip("brctl does not exist")

    setup_vm_network(1, True, find_default_interface(), '8.8.8.8')
    assert iptable_rule_exists(
        "INPUT -i drak1 -p udp --dport 67:68 --sport 67:68 -j ACCEPT") is True

    # setting up network again should not run
    setup_vm_network(1, True, find_default_interface(), '8.8.8.8')
Beispiel #4
0
    def init_drakrun(self):
        generate_vm_conf(self.install_info, self.instance_id)

        if not self.backend.minio.bucket_exists("drakrun"):
            self.backend.minio.make_bucket(bucket_name="drakrun")

        out_interface = self.config.config["drakrun"].get("out_interface", "")
        dns_server = self.config.config["drakrun"].get("dns_server", "")

        setup_vm_network(self.instance_id, self.net_enable, out_interface, dns_server)
Beispiel #5
0
    def init_drakrun(self):
        generate_vm_conf(self.install_info, self.instance_id)

        if not self.backend.minio.bucket_exists('drakrun'):
            self.backend.minio.make_bucket(bucket_name='drakrun')

        out_interface = self.config.config['drakrun'].get('out_interface', '')
        dns_server = self.config.config['drakrun'].get('dns_server', '')

        setup_vm_network(self.instance_id, self.net_enable, out_interface,
                         dns_server)
Beispiel #6
0
    def init_drakrun(self):

        generate_vm_conf(self.install_info, self.instance_id)

        if not self.backend.minio.bucket_exists("drakrun"):
            self.backend.minio.make_bucket(bucket_name="drakrun")

        out_interface = self.config.config["drakrun"].get("out_interface", "")
        dns_server = self.config.config["drakrun"].get("dns_server", "")

        setup_vm_network(self.instance_id, self.net_enable, out_interface, dns_server)

        self.log.info("Calculating snapshot hash...")
        self.snapshot_sha256 = file_sha256(os.path.join(VOLUME_DIR, "snapshot.sav"))
def postupgrade():
    if not check_root():
        return

    with open(os.path.join(ETC_DIR, 'scripts/cfg.template'), 'r') as f:
        template = f.read()

    passwd_characters = string.ascii_letters + string.digits
    passwd = ''.join(secrets.choice(passwd_characters) for _ in range(20))
    template = template.replace('{{ VNC_PASS }}', passwd)

    with open(os.path.join(ETC_DIR, 'scripts', 'cfg.template'), 'w') as f:
        f.write(template)

    detect_defaults()

    install_info = InstallInfo.try_load()
    if not install_info:
        logging.info("Postupgrade done. DRAKVUF Sandbox not installed.")
        return

    # Prepare injector
    with open(os.path.join(PROFILE_DIR, "runtime.json"), 'r') as runtime_f:
        runtime_info = RuntimeInfo.load(runtime_f)
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    injector = Injector('vm-1', runtime_info, kernel_profile)

    stop_all_drakruns()

    # Use vm-1 for generating profiles
    out_interface = conf['drakrun'].get('out_interface', '')
    dns_server = conf['drakrun'].get('dns_server', '')
    setup_vm_network(vm_id=1,
                     net_enable=False,
                     out_interface=out_interface,
                     dns_server=dns_server)
    backend = get_storage_backend(install_info)
    vm = VirtualMachine(backend, 1)
    vm.restore()

    create_missing_profiles(injector)

    vm.destroy()
    delete_vm_network(vm_id=1,
                      net_enable=False,
                      out_interface=out_interface,
                      dns_server=dns_server)
    start_enabled_drakruns()
Beispiel #8
0
def create_missing_profiles():
    """
    Creates usermode profiles by restoring vm-1 and extracting the DLLs.
    Assumes that injector is configured properly, i.e. kernel and runtime
    profiles exist and that vm-1 is free to use.
    """

    # Prepare injector
    with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f:
        runtime_info = RuntimeInfo.load(runtime_f)
    kernel_profile = os.path.join(PROFILE_DIR, "kernel.json")
    injector = Injector("vm-1", runtime_info, kernel_profile)

    # restore vm-1
    out_interface = conf["drakrun"].get("out_interface", "")
    dns_server = conf["drakrun"].get("dns_server", "")
    install_info = InstallInfo.load()
    backend = get_storage_backend(install_info)

    generate_vm_conf(install_info, 1)
    setup_vm_network(vm_id=1,
                     net_enable=False,
                     out_interface=out_interface,
                     dns_server=dns_server)
    vm = VirtualMachine(backend, 1)
    vm.restore()

    # Ensure that all declared usermode profiles exist
    # This is important when upgrade defines new entries in dll_file_list and compulsory_dll_file_list
    for profile in compulsory_dll_file_list:
        if not profile_exists(profile):
            create_rekall_profile(injector, profile, True)

    for profile in dll_file_list:
        if not profile_exists(profile):
            try:
                create_rekall_profile(injector, profile)
            except Exception:
                # silence per-dll errors
                pass

    vm.destroy()
    delete_vm_network(vm_id=1,
                      net_enable=False,
                      out_interface=out_interface,
                      dns_server=dns_server)
    def __init__(self, vm_id: int, dns: str):
        install_info = InstallInfo.load()
        backend = get_storage_backend(install_info)

        generate_vm_conf(install_info, vm_id)
        self.vm = VirtualMachine(backend, vm_id)

        with open(Path(PROFILE_DIR) / "runtime.json", 'r') as f:
            self.runtime_info = RuntimeInfo.load(f)
        self.desktop = WinPath(r"%USERPROFILE%") / "Desktop"

        self.kernel_profile = Path(PROFILE_DIR) / "kernel.json"
        self.injector = Injector(
            self.vm.vm_name,
            self.runtime_info,
            self.kernel_profile,
        )
        setup_vm_network(vm_id, True, find_default_interface(), dns)
Beispiel #10
0
def test_network_setup():
    setup_vm_network(1, True, find_default_interface(), '8.8.8.8')
    assert iptable_rule_exists(
        "INPUT -i drak1 -p udp --dport 67:68 --sport 67:68 -j ACCEPT") is True
Beispiel #11
0
def install(vcpus, memory, storage_backend, disk_size, iso_path, zfs_tank_name,
            lvm_volume_group, unattended_xml):
    if not check_root():
        return

    if storage_backend == "lvm" and lvm_volume_group is None:
        raise Exception("lvm storage backend requires --lvm-volume-group")
    if storage_backend == "zfs" and zfs_tank_name is None:
        raise Exception("zfs storage backend requires --zfs-tank-name")

    if not sanity_check():
        logging.error("Sanity check failed.")
        return

    stop_all_drakruns()

    logging.info("Performing installation...")

    if vcpus < 1:
        logging.error("Your VM must have at least 1 vCPU.")
        return

    if memory < 512:
        logging.error("Your VM must have at least 512 MB RAM.")
        return

    if memory < 1536:
        logging.warning(
            "Using less than 1.5 GB RAM per VM is not recommended for any supported system."
        )

    if unattended_xml:
        logging.info("Baking unattended.iso for automated installation")
        with tempfile.TemporaryDirectory() as tmpdir:
            tmp_xml_path = os.path.join(tmpdir, 'autounattend.xml')

            with open(tmp_xml_path, 'wb') as fw:
                with open(unattended_xml, 'rb') as fr:
                    fw.write(fr.read())

            try:
                subprocess.check_output([
                    'genisoimage', '-o',
                    os.path.join(VOLUME_DIR, "unattended.iso"), '-J', '-r',
                    tmp_xml_path
                ],
                                        stderr=subprocess.STDOUT)
            except subprocess.CalledProcessError:
                logging.exception("Failed to generate unattended.iso.")

    sha256_hash = hashlib.sha256()

    logging.info("Calculating hash of iso")
    iso_file_size = os.stat(iso_path).st_size
    block_size = 128 * 1024
    with tqdm(total=iso_file_size, unit_scale=True) as pbar:
        with open(iso_path, "rb") as f:
            for byte_block in iter(lambda: f.read(block_size), b""):
                pbar.update(block_size)
                sha256_hash.update(byte_block)

            iso_sha256 = sha256_hash.hexdigest()

    install_info = InstallInfo(vcpus=vcpus,
                               memory=memory,
                               storage_backend=storage_backend,
                               disk_size=disk_size,
                               iso_path=os.path.abspath(iso_path),
                               zfs_tank_name=zfs_tank_name,
                               lvm_volume_group=lvm_volume_group,
                               enable_unattended=unattended_xml is not None,
                               iso_sha256=iso_sha256)
    install_info.save()

    try:
        subprocess.check_output('xl uptime vm-0',
                                shell=True,
                                stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        pass
    else:
        logging.info('Detected that vm-0 is already running, stopping it.')
        subprocess.run('xl destroy vm-0', shell=True, check=True)

    generate_vm_conf(install_info, 0)

    backend = get_storage_backend(install_info)
    backend.initialize_vm0_volume(disk_size)

    try:
        subprocess.check_output("brctl show", shell=True)
    except subprocess.CalledProcessError:
        logging.exception(
            "Failed to execute brctl show. Make sure you have bridge-utils installed."
        )
        return

    net_enable = conf['drakrun'].getboolean('net_enable', fallback=False)
    out_interface = conf['drakrun'].get('out_interface', '')
    dns_server = conf['drakrun'].get('dns_server', '')

    setup_vm_network(vm_id=0,
                     net_enable=net_enable,
                     out_interface=out_interface,
                     dns_server=dns_server)

    if net_enable:
        start_dnsmasq(vm_id=0, dns_server=dns_server, background=True)

    cfg_path = os.path.join(VM_CONFIG_DIR, "vm-0.cfg")

    try:
        subprocess.run('xl create {}'.format(shlex.quote(cfg_path)),
                       shell=True,
                       check=True)
    except subprocess.CalledProcessError:
        logging.exception("Failed to launch VM vm-0")
        return

    logging.info("-" * 80)
    logging.info("Initial VM setup is complete and the vm-0 was launched.")
    logging.info(
        "Please now VNC to the port 5900 on this machine to perform Windows installation."
    )
    logging.info(
        "After you have installed Windows and booted it to the desktop, please execute:"
    )
    logging.info("# draksetup postinstall")

    with open(cfg_path, "r") as f:
        data = f.read()
        m = re.search(r'vncpasswd[ ]*=(.*)', data)
        if m:
            passwd = m.group(1).strip()
            if passwd[0] == '"' and passwd[-1] == '"':
                passwd = passwd[1:-1]

            logging.info("Your configured VNC password is:")
            logging.info(passwd)

    logging.info(
        "Please note that on some machines, system installer may boot for up to 10 minutes"
    )
    logging.info(
        "and may look unresponsive during the process. Please be patient.")
    logging.info("-" * 80)
Beispiel #12
0
def install(storage_backend, disk_size, iso_path, zfs_tank_name,
            unattended_xml):
    logging.info("Ensuring that drakrun@* services are stopped...")
    subprocess.check_output('systemctl stop \'drakrun@*\'',
                            shell=True,
                            stderr=subprocess.STDOUT)

    logging.info("Performing installation...")

    if unattended_xml:
        logging.info("Baking unattended.iso for automated installation")
        with tempfile.TemporaryDirectory() as tmpdir:
            tmp_xml_path = os.path.join(tmpdir, 'autounattend.xml')

            with open(tmp_xml_path, 'wb') as fw:
                with open(unattended_xml, 'rb') as fr:
                    fw.write(fr.read())

            try:
                subprocess.check_output([
                    'genisoimage', '-o',
                    os.path.join(VOLUME_DIR, "unattended.iso"), '-J', '-r',
                    tmp_xml_path
                ],
                                        stderr=subprocess.STDOUT)
            except subprocess.CalledProcessError:
                logging.exception("Failed to generate unattended.iso.")

    sha256_hash = hashlib.sha256()

    with open(iso_path, "rb") as f:
        for byte_block in iter(lambda: f.read(4096), b""):
            sha256_hash.update(byte_block)

        iso_sha256 = sha256_hash.hexdigest()

    install_info = InstallInfo(storage_backend=storage_backend,
                               disk_size=disk_size,
                               iso_path=os.path.abspath(iso_path),
                               zfs_tank_name=zfs_tank_name,
                               enable_unattended=unattended_xml is not None,
                               iso_sha256=iso_sha256)
    install_info.save()

    logging.info("Checking xen-detect...")
    proc = subprocess.run('xen-detect -N', shell=True)

    if proc.returncode != 1:
        logging.error(
            'It looks like the system is not running on Xen. Please reboot your machine into Xen hypervisor.'
        )
        return

    logging.info("Testing if xl tool is sane...")

    try:
        subprocess.check_output('xl info',
                                shell=True,
                                stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        logging.exception("Failed to test xl command.")
        return

    try:
        subprocess.check_output('xl uptime vm-0',
                                shell=True,
                                stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        pass
    else:
        logging.info('Detected that vm-0 is already running, stopping it.')
        subprocess.run('xl destroy vm-0', shell=True, check=True)

    generate_vm_conf(install_info, 0)

    backend = get_storage_backend(install_info)
    backend.initialize_vm0_volume(disk_size)

    try:
        subprocess.check_output("brctl show", shell=True)
    except subprocess.CalledProcessError:
        logging.exception(
            "Failed to execute brctl show. Make sure you have bridge-utils installed."
        )
        return

    net_enable = int(conf['drakrun'].get('net_enable', '0'))
    out_interface = conf['drakrun'].get('out_interface', '')
    dns_server = conf['drakrun'].get('dns_server', '')

    setup_vm_network(vm_id=0,
                     net_enable=net_enable,
                     out_interface=out_interface,
                     dns_server=dns_server)

    if net_enable:
        start_dnsmasq(vm_id=0, dns_server=dns_server, background=True)

    cfg_path = os.path.join(VM_CONFIG_DIR, "vm-0.cfg")

    try:
        subprocess.run('xl create {}'.format(shlex.quote(cfg_path)),
                       shell=True,
                       check=True)
    except subprocess.CalledProcessError:
        logging.exception("Failed to launch VM vm-0")
        return

    logging.info("-" * 80)
    logging.info("Initial VM setup is complete and the vm-0 was launched.")
    logging.info(
        "Please now VNC to the port 5900 on this machine to perform Windows installation."
    )
    logging.info(
        "After you have installed Windows and booted it to the desktop, please execute:"
    )
    logging.info("# draksetup postinstall")

    with open(cfg_path, "r") as f:
        data = f.read()
        m = re.search(r'vncpasswd[ ]*=(.*)', data)
        if m:
            passwd = m.group(1).strip()
            if passwd[0] == '"' and passwd[-1] == '"':
                passwd = passwd[1:-1]

            logging.info("Your configured VNC password is:")
            logging.info(passwd)

    logging.info(
        "Please note that on some machines, system installer may boot for up to 10 minutes"
    )
    logging.info(
        "and may look unresponsive during the process. Please be patient.")
    logging.info("-" * 80)