Пример #1
0
def submit(exploit_dir, service_dir, branch, target, config_file, token=None):
    config = load_config(config_file)
    timeout = config["exploit_timeout"]["exercise_phase"]
    prompt_checkout_warning(service_dir)
    verified_branch = None
    result, _ = verify_exploit(exploit_dir, service_dir, branch, timeout,
                               config)
    if result:
        verified_branch = branch

    if verified_branch is None:
        print("[*] Your exploit did not work against any of the branch")
        sys.exit()

    print("[*] Your exploit has been verified against branch '%s'" %
          verified_branch)

    # Not encrypt exploit
    signer = config["player"]
    encrypted_exploit = encrypt_exploit(exploit_dir, target, config, signer)
    if encrypted_exploit is None:
        print "[*] Failed to encrypt exploit"
        sys.exit(0)

    # Submit an issue with the encrypted exploit
    issue_title = "exploit-%s" % verified_branch
    github = Github(config["player"], token)
    submit_issue(issue_title, encrypted_exploit, target, config, github)

    # Clean up
    rmfile(encrypted_exploit)
Пример #2
0
def fetch(team, issue_no, config, token=None):
    repo_owner = config['repo_owner']
    repo_name = config['teams'][team]['repo_name']
    github = Github(config["player"], token)

    _, submitter, create_time, content = \
        get_github_issue(repo_owner, repo_name, issue_no, github)

    # Write the fetched issue content to temp file
    tmpfile = "/tmp/gitctf_%s.issue" % random_string(6)
    with open(tmpfile, "w") as f:
        f.write(content)

    # Decrypt the exploit
    out_dir = "exploit-%s-%s" % (submitter, create_time)
    prompt_rmdir_warning(out_dir)
    rmdir(out_dir)
    mkdir(out_dir)
    team = config["player_team"]
    out_dir = decrypt_exploit(tmpfile, config, team, out_dir, submitter)
    if out_dir is not None:
        print "Exploit fetched into %s" % out_dir

    # Clean up
    rmfile(tmpfile)
Пример #3
0
def encrypt_exploit(exploit_dir, target_team, config, signer=None):
    # Remove trailing slash, for user convenience
    exploit_dir = remove_trailing_slash(exploit_dir)
    out_file = exploit_dir + ".zip.pgp"

    # Retrieve information from config
    teams = config["teams"]
    instructor_pubkey = teams["instructor"]["pub_key_id"]
    target_pubkey = teams[target_team]['pub_key_id']

    # Zip the directory
    tmp_path = "/tmp/gitctf_%s" % random_string(6)
    shutil.make_archive(tmp_path, "zip", exploit_dir)
    zip_file = tmp_path + ".zip"  # make_archive() automatically appends suffix.

    # Encrypt the zipped file

    encrypt_cmd = "gpg -o %s " % out_file
    if signer is not None:
        signer_pubkey = config["individual"][signer]['pub_key_id']
        encrypt_cmd += "--default-key %s --sign " % signer_pubkey
    encrypt_cmd += "-e -r %s -r %s " % (instructor_pubkey, target_pubkey)
    encrypt_cmd += "--armor %s" % zip_file
    _, err, ret = run_command(encrypt_cmd, None)
    rmfile(zip_file)  # Clean up zip file.
    if ret != 0:
        print "[*] Failed to sign/encrypt %s" % zip_file
        print err
        return None

    return out_file
Пример #4
0
    def clean_trees(self):
        """
        Delete any previously built pxelinux.cfg tree and virt tree info and then create
        directories.

        Note: for SELinux reasons, some information goes in /tftpboot, some in /var/www/cobbler
        and some must be duplicated in both.  This is because PXE needs tftp, and auto-kickstart
        and Virt operations need http.   Only the kernel and initrd images are duplicated, which is
        unfortunate, though SELinux won't let me give them two contexts, so symlinks are not
        a solution.  *Otherwise* duplication is minimal.
        """

        # clean out parts of webdir and all of /tftpboot/images and /tftpboot/pxelinux.cfg
        for x in os.listdir(self.settings.webdir):
            path = os.path.join(self.settings.webdir,x)
            if os.path.isfile(path):
                if not x.endswith(".py"):
                    utils.rmfile(path,logger=self.logger)
            if os.path.isdir(path):
                if not x in ["aux", "web", "webui", "localmirror","repo_mirror","ks_mirror","images","links","pub","repo_profile","repo_system","svc","rendered",".link_cache"] :
                    # delete directories that shouldn't exist
                    utils.rmtree(path,logger=self.logger)
                if x in ["kickstarts","kickstarts_sys","images","systems","distros","profiles","repo_profile","repo_system","rendered"]:
                    # clean out directory contents
                    utils.rmtree_contents(path,logger=self.logger)
        #
        self.make_tftpboot()
        utils.rmtree_contents(self.pxelinux_dir,logger=self.logger)
        utils.rmtree_contents(self.grub_dir,logger=self.logger)
        utils.rmtree_contents(self.images_dir,logger=self.logger)
        utils.rmtree_contents(self.s390_dir,logger=self.logger)
        utils.rmtree_contents(self.yaboot_bin_dir,logger=self.logger)
        utils.rmtree_contents(self.yaboot_cfg_dir,logger=self.logger)
        utils.rmtree_contents(self.rendered_dir,logger=self.logger)
Пример #5
0
    def clean_trees(self):
        """
        Delete any previously built pxelinux.cfg tree and virt tree info and then create
        directories.

        Note: for SELinux reasons, some information goes in /tftpboot, some in /var/www/cobbler
        and some must be duplicated in both.  This is because PXE needs tftp, and auto-kickstart
        and Virt operations need http.   Only the kernel and initrd images are duplicated, which is
        unfortunate, though SELinux won't let me give them two contexts, so symlinks are not
        a solution.  *Otherwise* duplication is minimal.
        """

        # clean out parts of webdir and all of /tftpboot/images and /tftpboot/pxelinux.cfg
        for x in os.listdir(self.settings.webdir):
            path = os.path.join(self.settings.webdir, x)
            if os.path.isfile(path):
                if not x.endswith(".py"):
                    utils.rmfile(path, logger=self.logger)
            if os.path.isdir(path):
                if x not in ["aux", "web", "webui", "localmirror", "repo_mirror", "ks_mirror", "images", "links", "pub", "repo_profile", "repo_system", "svc", "rendered", ".link_cache"]:
                    # delete directories that shouldn't exist
                    utils.rmtree(path, logger=self.logger)
                if x in ["kickstarts", "kickstarts_sys", "images", "systems", "distros", "profiles", "repo_profile", "repo_system", "rendered"]:
                    # clean out directory contents
                    utils.rmtree_contents(path, logger=self.logger)
        #
        self.make_tftpboot()
        utils.rmtree_contents(self.pxelinux_dir, logger=self.logger)
        utils.rmtree_contents(self.grub_dir, logger=self.logger)
        utils.rmtree_contents(self.images_dir, logger=self.logger)
        utils.rmtree_contents(self.yaboot_bin_dir, logger=self.logger)
        utils.rmtree_contents(self.yaboot_cfg_dir, logger=self.logger)
        utils.rmtree_contents(self.rendered_dir, logger=self.logger)
Пример #6
0
 def remove_single_profile(self, name, rebuild_menu=True):
     # delete profiles/$name file in webdir
     utils.rmfile(os.path.join(self.settings.webdir, "profiles", name))
     # delete contents on kickstarts/$name directory in webdir
     utils.rmtree(os.path.join(self.settings.webdir, "kickstarts", name))
     if rebuild_menu:
         self.sync.tftpgen.make_pxe_menu()
Пример #7
0
    def remove_single_system(self, name):
        bootloc = utils.tftpboot_location()
        system_record = self.systems.find(name=name)
        # delete contents of kickstarts_sys/$name in webdir
        system_record = self.systems.find(name=name)

        if self.settings.manage_dhcp:
            if self.settings.omapi_enabled: 
                for (name,interface) in system_record.interfaces.iteritems():
                    self.sync.dhcp.remove_dhcp_lease(
                        self.settings.omapi_port,
                        interface["dns_name"]
                    )

        itanic = False
        profile = self.profiles.find(name=system_record.profile)
        if profile is not None:
            distro = self.distros.find(name=profile.distro)
            if distro is not None and distro in [ "ia64", "IA64"]:
                itanic = True

        for (name,interface) in system_record.interfaces.iteritems():
            filename = utils.get_config_filename(system_record,interface=name)

            if not itanic:
                utils.rmfile(os.path.join(bootloc, "pxelinux.cfg", filename))
            else:
                utils.rmfile(os.path.join(bootloc, filename))
Пример #8
0
 def remove_single_profile(self, name, rebuild_menu=True):
     # delete profiles/$name file in webdir
     utils.rmfile(os.path.join(self.settings.webdir, "profiles", name))
     # delete contents on kickstarts/$name directory in webdir
     utils.rmtree(os.path.join(self.settings.webdir, "kickstarts", name))
     if rebuild_menu:
         self.sync.pxegen.make_pxe_menu()
Пример #9
0
 def remove_single_distro(self, name):
     bootloc = utils.tftpboot_location()
     # delete contents of images/$name directory in webdir
     utils.rmtree(os.path.join(self.settings.webdir, "images", name))
     # delete contents of images/$name in tftpboot
     utils.rmtree(os.path.join(bootloc, "images", name))
     # delete potential symlink to tree in webdir/links
     utils.rmfile(os.path.join(self.settings.webdir, "links", name)) 
Пример #10
0
 def remove_single_distro(self, name):
     bootloc = utils.tftpboot_location()
     # delete contents of images/$name directory in webdir
     utils.rmtree(os.path.join(self.settings.webdir, "images", name))
     # delete contents of images/$name in tftpboot
     utils.rmtree(os.path.join(bootloc, "images", name))
     # delete potential symlink to tree in webdir/links
     utils.rmfile(os.path.join(self.settings.webdir, "links", name))
Пример #11
0
    def remove_single_system(self, name):
        bootloc = utils.tftpboot_location()
        system_record = self.systems.find(name=name)
        # delete contents of kickstarts_sys/$name in webdir
        system_record = self.systems.find(name=name)

        for (name, interface) in system_record.interfaces.iteritems():
            filename = utils.get_config_filename(system_record, interface=name)
            utils.rmfile(os.path.join(bootloc, "pxelinux.cfg", filename))
            utils.rmfile(os.path.join(bootloc, "grub", filename.upper()))
Пример #12
0
    def remove_single_system(self, name):
        bootloc = utils.tftpboot_location()
        system_record = self.systems.find(name=name)
        # delete contents of kickstarts_sys/$name in webdir
        system_record = self.systems.find(name=name)

        for (name, interface) in system_record.interfaces.iteritems():
            filename = utils.get_config_filename(system_record, interface=name)
            utils.rmfile(os.path.join(bootloc, "pxelinux.cfg", filename))
            utils.rmfile(os.path.join(bootloc, "grub", filename.upper()))
Пример #13
0
def up(num, tmp_file, args):
    url = 'http://' + args.serverAddress + '/upload'
    try:
        for i in range(num, -1, -1):
            file = tmp_file + str(i)
            utils.upload(file, url)
            utils.rmfile(file)
            num -= 1
    except:
        utils.log('err_upload_data', args.file, 'error')
        return utils.log(
            'again_upload_data', 'python dic.py -u impact --file ' +
            args.file + ' --n ' + num + ' --job ' + args.job, 'error')
Пример #14
0
def commit_and_push(scoreboard_dir):
    _, _, r = run_command('git add score.csv', scoreboard_dir)
    if r != 0:
        print('[*] Failed to git add score.csv.')
        return False
    _, _, r = run_command('git commit -F %s' % msg_file, scoreboard_dir)
    if r != 0:
        print('[*] Failed to commit score.csv.')
        return False
    _, _, r = run_command('git push origin master', scoreboard_dir)
    if r != 0:
        print('[*] Failed to push the score.')
        return False
    rmfile(os.path.join(scoreboard_dir, msg_file))
    return True
Пример #15
0
    def remove_single_system(self, name):
        bootloc = utils.tftpboot_location()
        system_record = self.systems.find(name=name)
        # delete contents of kickstarts_sys/$name in webdir
        system_record = self.systems.find(name=name)

        itanic = False
        profile = self.profiles.find(name=system_record.profile)
        if profile is not None:
            distro = self.distros.find(name=profile.get_conceptual_parent().name)
            if distro is not None and distro in [ "ia64", "IA64"]:
                itanic = True

        for (name,interface) in system_record.interfaces.iteritems():
            filename = utils.get_config_filename(system_record,interface=name)

            if not itanic:
                utils.rmfile(os.path.join(bootloc, "pxelinux.cfg", filename))
            else:
                utils.rmfile(os.path.join(bootloc, filename))
Пример #16
0
def submit(exploit_dir, service_dir, branch, target, config_file, token=None, confirm=True):
    config = load_config(config_file)
    timeout = config["exploit_timeout"]["exercise_phase"]
    if confirm:
        prompt_checkout_warning(service_dir)
    verified_branch = None
    result, _ = verify_exploit(exploit_dir, service_dir, branch, timeout, config)
    if result:
        verified_branch = branch

    if verified_branch is None :
        print("[*] Your exploit did not work against any of the branch")
        sys.exit()

    print("[*] Your exploit has been verified against branch '%s'"
            % verified_branch)

    # Not encrypt exploit
    signer = config["player"]
    encrypted_exploit = encrypt_exploit(exploit_dir, target, config, signer)
    if encrypted_exploit is None:
        print("[*] Failed to encrypt exploit")
        sys.exit(0)

    # Submit an issue with the encrypted exploit
    issue_title = "exploit-%s" % verified_branch
    github = Github(config["player"], token)
    issue_number, issue_url = submit_issue(issue_title, encrypted_exploit, target, config, github)

    # Clean up
    rmfile(encrypted_exploit)

    # Add NetID
    signer_pubkey = config["individual"][signer]['pub_key_id']
    create_comment(config['repo_owner'], config['teams'][target]['repo_name'], issue_number, "My NetID is %s, and my pub key id is %s" % (config["player_team"], signer_pubkey), github)

    # Add Public Key
    public_key = export_public_key(config, signer)
    create_comment(config['repo_owner'], config['teams'][target]['repo_name'], issue_number, public_key, github)

    print("Success! Your issue url is:", issue_url)
Пример #17
0
def decrypt_exploit(encrypted_exploit_path, config, team, out_dir=None, \
        expected_signer=None):
    if out_dir is None:
        out_dir = "exploit"

    rmdir(out_dir)

    tmpzip = "/tmp/gitctf_%s.zip" % random_string(6)
    tmpdir = "/tmp/gitctf_%s" % random_string(6)
    tmpgpg = "/tmp/gitctf_%s.gpg" % random_string(6)

    if expected_signer == None:
        decrypt_cmd = 'gpg -o %s %s' % (tmpzip, encrypted_exploit_path)
    else:
        instructor_id = config['teams']['instructor']['pub_key_id']
        team_id = config['teams'][team]['pub_key_id']
        expected_signer_id = config['individual'][expected_signer][
            'pub_key_id']

        # Make keyring
        run_command("gpg -o %s --export %s %s %s" % (tmpgpg, \
                expected_signer_id, instructor_id, team_id), os.getcwd())

        decrypt_cmd = "gpg --no-default-keyring --keyring %s -o %s %s" \
                % (tmpgpg, tmpzip, encrypted_exploit_path)

    _, err, r = run_command(decrypt_cmd, os.getcwd())
    if r != 0:
        print "[*] Failed to decrypt/verify %s" % encrypted_exploit_path
        print err
        return None

    run_command('unzip %s -d %s' % (tmpzip, tmpdir), os.getcwd())
    shutil.move(tmpdir, out_dir)

    rmfile(tmpzip)
    rmfile(tmpgpg)
    rmdir(tmpdir)

    return out_dir
Пример #18
0
    def remove_single_system(self, name):
        bootloc = utils.tftpboot_location()
        system_record = self.systems.find(name=name)
        # delete contents of kickstarts_sys/$name in webdir
        system_record = self.systems.find(name=name)

        itanic = False
        profile = self.profiles.find(name=system_record.profile)
        if profile is not None:
            distro = self.distros.find(name=profile.get_conceptual_parent().name)
            if distro is not None and distro in [ "ia64", "IA64"]:
                itanic = True

        for (name,interface) in system_record.interfaces.iteritems():
            filename = utils.get_config_filename(system_record,interface=name)

            if not itanic:
                utils.rmfile(os.path.join(bootloc, "pxelinux.cfg", filename))
                utils.rmfile(os.path.join(bootloc, "grub", filename.upper()))
            else:
                utils.rmfile(os.path.join(bootloc, filename))
Пример #19
0
    def write_pxe_file(self, filename, system, profile, distro, arch,
                       image=None, include_header=True, metadata=None, format="pxe"):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        Can be used for different formats, "pxe" (default) and "grub".
        """
        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None     # nfs:// URLs or something, can't use for TFTP

        if metadata is None:
            metadata = {}

        (rval, settings) = utils.input_string_or_dict(self.settings.to_dict())
        if rval:
            for key in settings.keys():
                metadata[key] = settings[key]
        # ---
        # just some random variables
        template = None
        buffer = ""

        # ---
        autoinstall_path = None
        kernel_path = None
        initrd_path = None
        img_path = None

        if image is None:
            # not image based, it's something normalish

            img_path = os.path.join("/images", distro.name)

            if 'nexenta' == distro.breed:
                kernel_path = os.path.join("/images", distro.name, 'platform', 'i86pc', 'kernel', 'amd64', os.path.basename(distro.kernel))
                initrd_path = os.path.join("/images", distro.name, 'platform', 'i86pc', 'amd64', os.path.basename(distro.initrd))
            elif 'http' in distro.kernel and 'http' in distro.initrd:
                kernel_path = distro.kernel
                initrd_path = distro.initrd
            else:
                kernel_path = os.path.join("/images", distro.name, os.path.basename(distro.kernel))
                initrd_path = os.path.join("/images", distro.name, os.path.basename(distro.initrd))

            # Find the automatic installation file if we inherit from another profile
            if system:
                blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            autoinstall_path = blended.get("autoinstall", "")

            # update metadata with all known information
            # this allows for more powerful templating
            metadata.update(blended)

        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2", image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2", image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None

        if img_path is not None and "img_path" not in metadata:
            metadata["img_path"] = img_path
        if kernel_path is not None and "kernel_path" not in metadata:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None and "initrd_path" not in metadata:
            metadata["initrd_path"] = initrd_path

        # ---
        # choose a template
        if system:
            if format == "grub":
                if system.netboot_enabled:
                    template = os.path.join(self.settings.boot_loader_conf_template_dir, "grubsystem.template")
                else:
                    local = os.path.join(self.settings.boot_loader_conf_template_dir, "grublocal.template")
                    if os.path.exists(local):
                        template = local
            else:   # pxe
                if system.netboot_enabled:
                    template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem.template")

                    if arch.startswith("ppc"):
                        # to inherit the distro and system's boot_loader values correctly
                        blended_system = utils.blender(self.api, False, system)
                        if blended_system["boot_loader"] == "pxelinux":
                            template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem_ppc.template")
                        elif distro.boot_loader == "grub2" or blended_system["boot_loader"] == "grub2":
                            template = os.path.join(self.settings.boot_loader_conf_template_dir, "grub2_ppc.template")
                        else:
                            template = os.path.join(self.settings.boot_loader_conf_template_dir, "yaboot_ppc.template")
                    elif arch.startswith("arm"):
                        template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem_arm.template")
                    elif distro and distro.os_version.startswith("esxi"):
                        # ESXi uses a very different pxe method, using more files than
                        # a standard automatic installation file and different options -
                        # so giving it a dedicated PXE template makes more sense than
                        # shoe-horning it into the existing templates
                        template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem_esxi.template")
                else:
                    # local booting on ppc requires removing the system-specific dhcpd.conf filename
                    if arch is not None and arch.startswith("ppc"):
                        # Disable yaboot network booting for all interfaces on the system
                        for (name, interface) in system.interfaces.iteritems():

                            filename = "%s" % utils.get_config_filename(system, interface=name).lower()

                            # Remove symlink to the yaboot binary
                            f3 = os.path.join(self.bootloc, "ppc", filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)

                            # Remove the interface-specific config file
                            f3 = os.path.join(self.bootloc, "boot/grub", "grub.cfg-" + filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)
                            f3 = os.path.join(self.bootloc, "etc", filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)

                        # Yaboot/OF doesn't support booting locally once you've
                        # booted off the network, so nothing left to do
                        return None
                    else:
                        template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxelocal.template")
        else:
            # not a system record, so this is a profile record or an image
            if arch.startswith("arm"):
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxeprofile_arm.template")
            elif format == "grub":
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "grubprofile.template")
            elif distro and distro.os_version.startswith("esxi"):
                # ESXi uses a very different pxe method, see comment above in the system section
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxeprofile_esxi.template")
            elif 'nexenta' == format:
                template = os.path.join(self.settings.boot_loader_conf_template_dir, 'nexenta_profile.template')
            else:
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxeprofile.template")

        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        # generate the kernel options and append line:
        kernel_options = self.build_kernel_options(system, profile, distro,
                                                   image, arch, autoinstall_path)
        metadata["kernel_options"] = kernel_options

        if distro and distro.os_version.startswith("esxi") and filename is not None:
            append_line = "BOOTIF=%s" % (os.path.basename(filename))
        elif "initrd_path" in metadata and (not arch or arch not in ["ppc", "ppc64", "arm"]):
            append_line = "append initrd=%s" % (metadata["initrd_path"])
        else:
            append_line = "append "
        append_line = "%s%s" % (append_line, kernel_options)
        if arch.startswith("ppc"):
            # remove the prefix "append"
            # TODO: this looks like it's removing more than append, really
            # not sure what's up here...
            append_line = append_line[7:]
        if distro and distro.os_version.startswith("xenserver620"):
            append_line = "%s" % (kernel_options)
        metadata["append_line"] = append_line

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if arch not in ["ppc", "ppc64"]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name

        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer
Пример #20
0
 def remove_single_image(self, name):
     bootloc = utils.tftpboot_location()
     utils.rmfile(os.path.join(bootloc, "images2", name))
Пример #21
0
        key_id = matches.group(2)

        net_id_folder = "{}/{}".format(destination, net_id)

        if not os.path.isdir(net_id_folder):
            mkdir(net_id_folder)

        issue_folder = "{}/{}/".format(net_id_folder, issue_id)

        create_or_empty_folder(issue_folder)

        with open(issue_folder + "answer.zip.pgp", "w") as f:
            f.write(body)

        with open(issue_folder + "pub_key.asc", "w") as f:
            f.write(comments[1])

        run_command("gpg --import pub_key.asc", issue_folder)

        run_command("gpg -o answer.zip answer.zip.pgp", issue_folder)

        run_command("unzip answer.zip -d ./", issue_folder)

        rmfile(issue_folder + "answer.zip")

        shutil.make_archive("{}/{}".format(net_id_folder, issue_id), "zip",
                            issue_folder)

        # GitHub has a limitation for how many requests we can make per minute
        time.sleep(random.randint(1, 3))
Пример #22
0
    def write_pxe_file(self, filename, system, profile, distro, arch,
            image=None, include_header=True, metadata=None, format="pxe"):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        NOTE: relevant to tftp and pseudo-PXE (s390) only

        ia64 is mostly the same as syslinux stuff, s390 is a bit
        short-circuited and simpler.  All of it goes through the
        templating engine, see the templates in /etc/cobbler for
        more details

        Can be used for different formats, "pxe" (default) and "grub".
        """

        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None  # nfs:// URLs or something, can't use for TFTP

        if metadata is None:
            metadata = {}

        (rval,settings) = utils.input_string_or_hash(self.settings.to_datastruct())
        if rval:
            for key in settings.keys():
                metadata[key] = settings[key]
        # ---
        # just some random variables
        template = None
        buffer = ""

        # ---
        kickstart_path = None
        kernel_path = None
        initrd_path = None
        img_path = None

        if image is None: 
            # not image based, it's something normalish

            img_path = os.path.join("/images",distro.name)
            kernel_path = os.path.join("/images",distro.name,os.path.basename(distro.kernel))
            initrd_path = os.path.join("/images",distro.name,os.path.basename(distro.initrd))
        
            # Find the kickstart if we inherit from another profile
            if system:
                blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            kickstart_path = blended.get("kickstart","")
            
        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2",image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2",image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None

        if img_path is not None and not metadata.has_key("img_path"):
            metadata["img_path"] = img_path
        if kernel_path is not None and not metadata.has_key("kernel_path"):
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None and not metadata.has_key("initrd_path"):
            metadata["initrd_path"] = initrd_path

        # ---
        # choose a template
        if system:
            if format == "grub":
                template = os.path.join(self.settings.pxe_template_dir, "grubsystem.template")
            else: # pxe
                if system.netboot_enabled:
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem.template")

                    if arch.startswith("s390"):
                        template = os.path.join(self.settings.pxe_template_dir,"pxesystem_s390x.template")
                    elif arch == "ia64":
                        template = os.path.join(self.settings.pxe_template_dir,"pxesystem_ia64.template")
                    elif arch.startswith("ppc"):
                        template = os.path.join(self.settings.pxe_template_dir,"pxesystem_ppc.template")
                    elif arch.startswith("arm"):
                        template = os.path.join(self.settings.pxe_template_dir,"pxesystem_arm.template")
                    elif distro and distro.os_version.startswith("esxi"):
                        # ESXi uses a very different pxe method, using more files than
                        # a standard kickstart and different options - so giving it a dedicated
                        # PXE template makes more sense than shoe-horning it into the existing
                        # templates
                        template = os.path.join(self.settings.pxe_template_dir,"pxesystem_esxi.template")
                else:
                    # local booting on ppc requires removing the system-specific dhcpd.conf filename
                    if arch is not None and arch.startswith("ppc"):
                        # Disable yaboot network booting for all interfaces on the system
                        for (name,interface) in system.interfaces.iteritems():

                            filename = "%s" % utils.get_config_filename(system, interface=name).lower()

                            # Remove symlink to the yaboot binary
                            f3 = os.path.join(self.bootloc, "ppc", filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)

                            # Remove the interface-specific config file
                            f3 = os.path.join(self.bootloc, "etc", filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)

                        # Yaboot/OF doesn't support booting locally once you've
                        # booted off the network, so nothing left to do
                        return None
                    elif arch is not None and arch.startswith("s390"):
                        template = os.path.join(self.settings.pxe_template_dir,"pxelocal_s390x.template")
                    elif arch is not None and arch.startswith("ia64"):
                        template = os.path.join(self.settings.pxe_template_dir,"pxelocal_ia64.template")
                    else:
                        template = os.path.join(self.settings.pxe_template_dir,"pxelocal.template")
        else:
            # not a system record, so this is a profile record or an image
            if arch.startswith("s390"):
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile_s390x.template")
            if arch.startswith("arm"):
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile_arm.template")
            elif format == "grub":
                template = os.path.join(self.settings.pxe_template_dir,"grubprofile.template")
            elif distro and distro.os_version.startswith("esxi"):
                # ESXi uses a very different pxe method, see comment above in the system section
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile_esxi.template")
            else:
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile.template")


        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        # generate the kernel options and append line:
        kernel_options = self.build_kernel_options(system, profile, distro,
                image, arch, kickstart_path)
        metadata["kernel_options"] = kernel_options

        if distro and distro.os_version.startswith("esxi") and filename is not None:
            append_line = "BOOTIF=%s" % (os.path.basename(filename))
        elif metadata.has_key("initrd_path") and (not arch or arch not in ["ia64", "ppc", "ppc64", "arm"]):
            append_line = "append initrd=%s" % (metadata["initrd_path"])
        else:
            append_line = "append "
        append_line = "%s%s" % (append_line, kernel_options)
        if arch.startswith("ppc") or arch.startswith("s390"):
            # remove the prefix "append"
            # TODO: this looks like it's removing more than append, really
            # not sure what's up here...
            append_line = append_line[7:]
        metadata["append_line"] = append_line

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if not arch in [ "ia64", "ppc", "ppc64", "s390", "s390x" ]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name


        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer
Пример #23
0
    def write_all_system_files(self, system):

        profile = system.get_conceptual_parent()
        if profile is None:
            raise CX("system %(system)s references a missing profile %(profile)s" % { "system" : system.name, "profile" : system.profile})

        distro = profile.get_conceptual_parent()
        image_based = False
        image = None
        if distro is None:
            if profile.COLLECTION_TYPE == "profile":
               raise CX("profile %(profile)s references a missing distro %(distro)s" % { "profile" : system.profile, "distro" : profile.distro})
            else:
               image_based = True
               image = profile

        # hack: s390 generates files per system not per interface
        if not image_based and distro.arch.startswith("s390"):
            # Always write a system specific _conf and _parm file
            f2 = os.path.join(self.bootloc, "s390x", "s_%s" % system.name)
            cf = "%s_conf" % f2
            pf = "%s_parm" % f2
            template_cf = open("/etc/cobbler/pxe/s390x_conf.template")
            template_pf = open("/etc/cobbler/pxe/s390x_parm.template")
            blended = utils.blender(self.api, True, system)
            self.templar.render(template_cf, blended, cf)
            # FIXME: profiles also need this data!
            # FIXME: the _conf and _parm files are limited to 80 characters in length
            try: 
                ipaddress = socket.gethostbyname_ex(blended["http_server"])[2][0]
            except socket.gaierror:
                ipaddress = blended["http_server"]
            kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (ipaddress, system.name)
            # gather default kernel_options and default kernel_options_s390x
            kopts = blended.get("kernel_options","")
            hkopts = shlex.split(utils.hash_to_string(kopts))
            blended["kickstart_expanded"] = "ks=%s" % kickstart_path
            blended["kernel_options"] = hkopts
            self.templar.render(template_pf, blended, pf)

            # Write system specific zPXE file
            if system.is_management_supported():
                self.write_pxe_file(f2, system, profile, distro, distro.arch)
            else:
                # ensure the file doesn't exist
                utils.rmfile(f2)
            return

        pxe_metadata = {'pxe_menu_items': self.get_menu_items()['pxe'] }
 
        # generate one record for each described NIC ..
 
        for (name,interface) in system.interfaces.iteritems():

            ip = interface["ip_address"]

            f1 = utils.get_config_filename(system, interface=name)
            if f1 is None:
                self.logger.warning("invalid interface recorded for system (%s,%s)" % (system.name,name))
                continue;

            if image_based:
                working_arch = image.arch
            else:
                working_arch = distro.arch

            if working_arch is None:
                raise "internal error, invalid arch supplied"

            # for tftp only ...
            grub_path = None
            if working_arch in [ "i386", "x86", "x86_64", "arm", "standard"]:
                # pxelinux wants a file named $name under pxelinux.cfg
                f2 = os.path.join(self.bootloc, "pxelinux.cfg", f1)

                # Only generating grub menus for these arch's:
                grub_path = os.path.join(self.bootloc, "grub", f1.upper())

            elif working_arch == "ia64":
                # elilo expects files to be named "$name.conf" in the root
                # and can not do files based on the MAC address
                if ip is not None and ip != "":
                    self.logger.warning("Warning: Itanium system object (%s) needs an IP address to PXE" % system.name)

                filename = "%s.conf" % utils.get_config_filename(system,interface=name)
                f2 = os.path.join(self.bootloc, filename)

            elif working_arch.startswith("ppc"):
                # Determine filename for system-specific yaboot.conf
                filename = "%s" % utils.get_config_filename(system, interface=name).lower()
                f2 = os.path.join(self.bootloc, "etc", filename)

                # Link to the yaboot binary
                f3 = os.path.join(self.bootloc, "ppc", filename)
                if os.path.lexists(f3):
                    utils.rmfile(f3)
                os.symlink("../yaboot", f3)
            else:
                continue 

            if system.is_management_supported():
                if not image_based:
                    self.write_pxe_file(f2, system, profile, distro, working_arch, metadata=pxe_metadata)
                    if grub_path:
                        self.write_pxe_file(grub_path, system, profile, distro, 
                                working_arch, format="grub")
                else:
                    self.write_pxe_file(f2, system, None, None, working_arch, image=profile, metadata=pxe_metadata)
            else:
                # ensure the file doesn't exist
                utils.rmfile(f2)
                if grub_path:
                    utils.rmfile(grub_path)
Пример #24
0
    def write_all_system_files(self, system, menu_items):

        profile = system.get_conceptual_parent()
        if profile is None:
            raise CX("system %(system)s references a missing profile %(profile)s" % {"system": system.name, "profile": system.profile})

        distro = profile.get_conceptual_parent()
        image_based = False
        image = None
        if distro is None:
            if profile.COLLECTION_TYPE == "profile":
                raise CX("profile %(profile)s references a missing distro %(distro)s" % {"profile": system.profile, "distro": profile.distro})
            else:
                image_based = True
                image = profile

        pxe_metadata = {'pxe_menu_items': menu_items}

        # generate one record for each described NIC ..
        for (name, interface) in system.interfaces.iteritems():

            f1 = utils.get_config_filename(system, interface=name)
            if f1 is None:
                self.logger.warning("invalid interface recorded for system (%s,%s)" % (system.name, name))
                continue

            if image_based:
                working_arch = image.arch
            else:
                working_arch = distro.arch

            if working_arch is None:
                raise "internal error, invalid arch supplied"

            # for tftp only ...
            grub_path = None
            if working_arch in ["i386", "x86", "x86_64", "arm", "standard"]:
                # pxelinux wants a file named $name under pxelinux.cfg
                f2 = os.path.join(self.bootloc, "pxelinux.cfg", f1)

                # Only generating grub menus for these arch's:
                grub_path = os.path.join(self.bootloc, "grub", f1.upper())

            elif working_arch.startswith("ppc"):
                # Determine filename for system-specific yaboot.conf
                filename = "%s" % utils.get_config_filename(system, interface=name).lower()
                f2 = os.path.join(self.bootloc, "etc", filename)

                # Link to the yaboot binary
                f3 = os.path.join(self.bootloc, "ppc", filename)
                if os.path.lexists(f3):
                    utils.rmfile(f3)
                os.symlink("../yaboot", f3)
            else:
                continue

            if system.is_management_supported():
                if not image_based:
                    self.write_pxe_file(f2, system, profile, distro, working_arch, metadata=pxe_metadata)
                    if grub_path:
                        self.write_pxe_file(grub_path, system, profile, distro, working_arch, format="grub")
                else:
                    self.write_pxe_file(f2, system, None, None, working_arch, image=profile, metadata=pxe_metadata)
            else:
                # ensure the file doesn't exist
                utils.rmfile(f2)
                if grub_path:
                    utils.rmfile(grub_path)
Пример #25
0
    def write_pxe_file(self,filename,system,profile,distro,arch,image=None,include_header=True):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        NOTE: relevant to tftp and pseudo-PXE (s390) only

        ia64 is mostly the same as syslinux stuff, s390 is a bit
        short-circuited and simpler.  All of it goes through the
        templating engine, see the templates in /etc/cobbler for
        more details
        """

        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None  # nfs:// URLs or something, can't use for TFTP

        # ---
        # just some random variables
        template = None
        metadata = {}
        buffer = ""

        # ---
        kickstart_path = None
        kernel_path = None
        initrd_path = None

        if image is None: 
            # not image based, it's something normalish

            kernel_path = os.path.join("/images",distro.name,os.path.basename(distro.kernel))
            initrd_path = os.path.join("/images",distro.name,os.path.basename(distro.initrd))
        
            # Find the kickstart if we inherit from another profile
            if system:
	        blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            kickstart_path = blended.get("kickstart","")
            
        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2",image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2",image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None
        # ---
        # choose a template
        if system:
            if system.netboot_enabled:
                template = os.path.join(self.settings.pxe_template_dir,"pxesystem.template")
    
                if arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem_s390x.template")
                elif arch == "ia64":
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem_ia64.template")
                elif arch.startswith("ppc"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem_ppc.template")
            else:
                # local booting on ppc requires removing the system-specific dhcpd.conf filename
                if arch is not None and arch.startswith("ppc"):
                    # Disable yaboot network booting for all interfaces on the system
                    for (name,interface) in system.interfaces.iteritems():

                        filename = "%s" % utils.get_config_filename(system, interface=name).lower()

                        # Remove symlink to the yaboot binary
                        f3 = os.path.join(self.bootloc, "ppc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                        # Remove the interface-specific config file
                        f3 = os.path.join(self.bootloc, "etc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                    # Yaboot/OF doesn't support booting locally once you've
                    # booted off the network, so nothing left to do
                    return None
                elif arch is not None and arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxelocal_s390x.template")
                elif arch is not None and arch.startswith("ia64"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxelocal_ia64.template")
                else:
                    template = os.path.join(self.settings.pxe_template_dir,"pxelocal.template")
        else:
            # not a system record, so this is a profile record

            if arch.startswith("s390"):
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile_s390x.template")
            else:
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile.template")

        # now build the kernel command line
        if system is not None:
            blended = utils.blender(self.api, True, system)
        elif profile is not None:
            blended = utils.blender(self.api, True, profile)
        else:
            blended = utils.blender(self.api, True, image)
        kopts = blended.get("kernel_options","")

        # generate the append line
        hkopts = utils.hash_to_string(kopts)
        if initrd_path and (not arch or arch not in ["ia64", "ppc", "ppc64"]):
            append_line = "append initrd=%s %s" % (initrd_path, hkopts)
        else:
            append_line = "append %s" % hkopts

        # FIXME - the append_line length limit is architecture specific
        if len(append_line) >= 255 + len("append "):
            self.logger.warning("warning: kernel option length exceeds 255")

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_path != "":

            # FIXME: need to make shorter rewrite rules for these URLs

            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (blended["http_server"], system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (blended["http_server"], profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_path)
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto url=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = { 'ksdevice':"interface" , 'lang':"locale" }
                for k,v in translations.iteritems():
                    append_line = append_line.replace("%s="%k,"%s="%v)

                # interface=bootif causes a failure
                append_line = append_line.replace("interface=bootif","")
            elif distro.breed == "vmware":
                append_line = "%s vmkopts=debugLogToSerial:1 mem=512M ks=%s" % (append_line, kickstart_path)
                # interface=bootif causes a failure
                append_line = append_line.replace("ksdevice=bootif","")


        if distro is not None and (distro.breed in [ "debian", "ubuntu" ]):
            # Hostname is required as a parameter, the one in the preseed is
            # not respected, so calculate if we have one here.
            # We're trying: first part of FQDN in hostname field, then system
            # name, then profile name.
            # In Ubuntu, this is at least used for the volume group name when
            # using LVM.
            domain = "local.lan"
            if system is not None:
                if system.hostname is not None:
                    # If this is a FQDN, grab the first bit
                    hostname = system.hostname.split(".")[0]
                    _domain = system.hostname.split(".")[1:]
                    if _domain:
                        domain = ".".join( _domain )
                else:
                    hostname = system.name
            else:
                hostname = profile.name

            # At least for debian deployments configured for DHCP networking
            # this values are not used, but specifying here avoids questions
            append_line = "%s hostname=%s" % (append_line, hostname)
            append_line = "%s domain=%s" % (append_line, domain)

            # A similar issue exists with suite name, as installer requires
            # the existence of "stable" in the dists directory
            append_line = "%s suite=%s" % (append_line, distro.os_version)

        if arch.startswith("ppc") or arch.startswith("s390"):
            # remove the prefix "append"
            append_line = append_line[7:]

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if not arch in [ "ia64", "ppc", "ppc64", "s390", "s390x" ]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name

        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        metadata["append_line"] = append_line

        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"        

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer
Пример #26
0
 def remove_single_profile(self, name):
     # delete profiles/$name file in webdir
     utils.rmfile(os.path.join(self.settings.webdir, "profiles", name))
     # delete contents on kickstarts/$name directory in webdir
     utils.rmtree(os.path.join(self.settings.webdir, "kickstarts", name))
Пример #27
0
    def write_all_system_files(self, system, menu_items):

        profile = system.get_conceptual_parent()
        if profile is None:
            raise CX("system %(system)s references a missing profile %(profile)s" % {"system": system.name, "profile": system.profile})

        distro = profile.get_conceptual_parent()
        image_based = False
        image = None
        if distro is None:
            if profile.COLLECTION_TYPE == "profile":
                raise CX("profile %(profile)s references a missing distro %(distro)s" % {"profile": system.profile, "distro": profile.distro})
            else:
                image_based = True
                image = profile

        pxe_metadata = {'pxe_menu_items': menu_items}

        # generate one record for each described NIC ..
        for (name, interface) in system.interfaces.iteritems():

            f1 = utils.get_config_filename(system, interface=name)
            if f1 is None:
                self.logger.warning("invalid interface recorded for system (%s,%s)" % (system.name, name))
                continue

            if image_based:
                working_arch = image.arch
            else:
                working_arch = distro.arch

            if working_arch is None:
                raise "internal error, invalid arch supplied"

            # for tftp only ...
            grub_path = None
            if working_arch in ["i386", "x86", "x86_64", "arm", "standard"]:
                # pxelinux wants a file named $name under pxelinux.cfg
                f2 = os.path.join(self.bootloc, "pxelinux.cfg", f1)

                # Only generating grub menus for these arch's:
                grub_path = os.path.join(self.bootloc, "grub", f1.upper())

            elif working_arch.startswith("ppc"):
                # Determine filename for system-specific yaboot.conf
                filename = "%s" % utils.get_config_filename(system, interface=name).lower()
                f2 = os.path.join(self.bootloc, "etc", filename)

                # Link to the yaboot binary
                f3 = os.path.join(self.bootloc, "ppc", filename)
                if os.path.lexists(f3):
                    utils.rmfile(f3)
                os.symlink("../yaboot", f3)
            else:
                continue

            if system.is_management_supported():
                if not image_based:
                    self.write_pxe_file(f2, system, profile, distro, working_arch, metadata=pxe_metadata)
                    if grub_path:
                        self.write_pxe_file(grub_path, system, profile, distro, working_arch, format="grub")
                else:
                    self.write_pxe_file(f2, system, None, None, working_arch, image=profile, metadata=pxe_metadata)
            else:
                # ensure the file doesn't exist
                utils.rmfile(f2)
                if grub_path:
                    utils.rmfile(grub_path)
Пример #28
0
def verify_issue(defender,
                 repo_name,
                 issue_no,
                 config,
                 github,
                 target_commit=None):
    timeout = config["exploit_timeout"]["exercise_phase"]
    repo_owner = config['repo_owner']
    title, submitter, create_time, content = \
        get_github_issue(repo_owner, repo_name, issue_no, github)

    # Issue convention: "exploit-[branch_name]"
    target_branch = title[8:]

    clone(repo_owner, repo_name)

    # Write the fetched issue content to temp file
    tmpfile = "/tmp/gitctf_%s.issue" % random_string(6)
    tmpdir = "/tmp/gitctf_%s.dir" % random_string(6)

    with open(tmpfile, "w") as f:
        f.write(content)

    # Decrypt the exploit
    mkdir(tmpdir)

    team = defender
    decrypt_exploit(tmpfile, config, team, tmpdir, submitter)
    rmfile(tmpfile)

    # Now iterate through branches and verify exploit
    # zchn: not sure about this, was: branches = list_branches(repo_name)
    bug_branches = config['teams'][team]['bug_branches']
    branches = bug_branches + ['master'] if len(bug_branches) > 0 \
        else list_branches(repo_name)

    candidates = []
    if (target_branch in branches) and (target_commit is None):
        # Iterate through branches and collect candidates
        commit = get_latest_commit_hash(repo_name, create_time, target_branch)
        candidates.append((target_branch, commit))

    verified_branch = None
    verified_commit = None

    log = 'About %s (exploit-service branch)\n' % title

    for (branch, commit) in candidates:
        if branch in title:
            result, log = verify_exploit(tmpdir, repo_name, commit, timeout, \
                    config, log=log)
        else:
            result, _ = verify_exploit(tmpdir, repo_name, commit, timeout, \
                    config)

        if result:
            verified_branch = branch
            verified_commit = commit
            break

    rmdir(tmpdir)
    rmdir(repo_name)

    if verified_branch is None:
        print("[*] The exploit did not work against branch '%s'" % \
                target_branch)
    else:
        print("[*] The exploit has been verified against branch '%s'" %
              verified_branch)

    return (verified_branch, verified_commit, submitter, log)
Пример #29
0
    def write_pxe_file(self,
                       filename,
                       system,
                       profile,
                       distro,
                       arch,
                       image=None,
                       include_header=True):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        NOTE: relevant to tftp and pseudo-PXE (s390) only

        ia64 is mostly the same as syslinux stuff, s390 is a bit
        short-circuited and simpler.  All of it goes through the
        templating engine, see the templates in /etc/cobbler for
        more details
        """

        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None  # nfs:// URLs or something, can't use for TFTP

        # ---
        # just some random variables
        template = None
        metadata = {}
        buffer = ""

        # ---
        kickstart_path = None
        kernel_path = None
        initrd_path = None

        if image is None:
            # not image based, it's something normalish

            kernel_path = os.path.join("/images", distro.name,
                                       os.path.basename(distro.kernel))
            initrd_path = os.path.join("/images", distro.name,
                                       os.path.basename(distro.initrd))

            # Find the kickstart if we inherit from another profile
            if system:
                blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            kickstart_path = blended.get("kickstart", "")

        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2", image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2", image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None
        # ---
        # choose a template
        if system:
            if system.netboot_enabled:
                template = os.path.join(self.settings.pxe_template_dir,
                                        "pxesystem.template")

                if arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxesystem_s390x.template")
                elif arch == "ia64":
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxesystem_ia64.template")
                elif arch.startswith("ppc"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxesystem_ppc.template")
            else:
                # local booting on ppc requires removing the system-specific dhcpd.conf filename
                if arch is not None and arch.startswith("ppc"):
                    # Disable yaboot network booting for all interfaces on the system
                    for (name, interface) in system.interfaces.iteritems():

                        filename = "%s" % utils.get_config_filename(
                            system, interface=name).lower()

                        # Remove symlink to the yaboot binary
                        f3 = os.path.join(self.bootloc, "ppc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                        # Remove the interface-specific config file
                        f3 = os.path.join(self.bootloc, "etc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                    # Yaboot/OF doesn't support booting locally once you've
                    # booted off the network, so nothing left to do
                    return None
                elif arch is not None and arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxelocal_s390x.template")
                elif arch is not None and arch.startswith("ia64"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxelocal_ia64.template")
                else:
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxelocal.template")
        else:
            # not a system record, so this is a profile record

            if arch.startswith("s390"):
                template = os.path.join(self.settings.pxe_template_dir,
                                        "pxeprofile_s390x.template")
            else:
                template = os.path.join(self.settings.pxe_template_dir,
                                        "pxeprofile.template")

        # now build the kernel command line
        if system is not None:
            blended = utils.blender(self.api, True, system)
        elif profile is not None:
            blended = utils.blender(self.api, True, profile)
        else:
            blended = utils.blender(self.api, True, image)
        kopts = blended.get("kernel_options", "")

        # generate the append line
        hkopts = utils.hash_to_string(kopts)
        if initrd_path and (not arch or arch not in ["ia64", "ppc", "ppc64"]):
            append_line = "append initrd=%s %s" % (initrd_path, hkopts)
        else:
            append_line = "append %s" % hkopts

        # FIXME - the append_line length limit is architecture specific
        if len(append_line) >= 255 + len("append "):
            self.logger.warning("warning: kernel option length exceeds 255")

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_path != "":

            # FIXME: need to make shorter rewrite rules for these URLs

            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (
                    blended["http_server"], system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (
                    blended["http_server"], profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_path)
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto url=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = {'ksdevice': "interface", 'lang': "locale"}
                for k, v in translations.iteritems():
                    append_line = append_line.replace("%s=" % k, "%s=" % v)

                # interface=bootif causes a failure
                append_line = append_line.replace("interface=bootif", "")

        if distro is not None and (distro.breed in ["debian", "ubuntu"]):
            # Hostname is required as a parameter, the one in the preseed is
            # not respected, so calculate if we have one here.
            # We're trying: first part of FQDN in hostname field, then system
            # name, then profile name.
            # In Ubuntu, this is at least used for the volume group name when
            # using LVM.
            domain = "local.lan"
            if system is not None:
                if system.hostname is not None:
                    # If this is a FQDN, grab the first bit
                    hostname = system.hostname.split(".")[0]
                    _domain = system.hostname.split(".")[1:]
                    if _domain:
                        domain = ".".join(_domain)
                else:
                    hostname = system.name
            else:
                hostname = profile.name

            # At least for debian deployments configured for DHCP networking
            # this values are not used, but specifying here avoids questions
            append_line = "%s hostname=%s" % (append_line, hostname)
            append_line = "%s domain=%s" % (append_line, domain)

            # A similar issue exists with suite name, as installer requires
            # the existence of "stable" in the dists directory
            append_line = "%s suite=%s" % (append_line, distro.os_version)

        if arch.startswith("ppc") or arch.startswith("s390"):
            # remove the prefix "append"
            append_line = append_line[7:]

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if not arch in ["ia64", "ppc", "ppc64", "s390", "s390x"]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name

        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        metadata["append_line"] = append_line

        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer
Пример #30
0
    def write_pxe_file(self, filename, system, profile, distro, arch,
                       image=None, include_header=True, metadata=None, format="pxe"):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        Can be used for different formats, "pxe" (default) and "grub".
        """
        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None     # nfs:// URLs or something, can't use for TFTP

        if metadata is None:
            metadata = {}

        (rval, settings) = utils.input_string_or_dict(self.settings.to_dict())
        if rval:
            for key in settings.keys():
                metadata[key] = settings[key]
        # ---
        # just some random variables
        template = None
        buffer = ""

        # ---
        autoinstall_path = None
        kernel_path = None
        initrd_path = None
        img_path = None

        if image is None:
            # not image based, it's something normalish

            img_path = os.path.join("/images", distro.name)

            if 'nexenta' == distro.breed:
                kernel_path = os.path.join("/images", distro.name, 'platform', 'i86pc', 'kernel', 'amd64', os.path.basename(distro.kernel))
                initrd_path = os.path.join("/images", distro.name, 'platform', 'i86pc', 'amd64', os.path.basename(distro.initrd))
            elif 'http' in distro.kernel and 'http' in distro.initrd:
                kernel_path = distro.kernel
                initrd_path = distro.initrd
            else:
                kernel_path = os.path.join("/images", distro.name, os.path.basename(distro.kernel))
                initrd_path = os.path.join("/images", distro.name, os.path.basename(distro.initrd))

            # Find the automatic installation file if we inherit from another profile
            if system:
                blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            autoinstall_path = blended.get("autoinstall", "")

            # update metadata with all known information
            # this allows for more powerful templating
            metadata.update(blended)

        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2", image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2", image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None

        if img_path is not None and "img_path" not in metadata:
            metadata["img_path"] = img_path
        if kernel_path is not None and "kernel_path" not in metadata:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None and "initrd_path" not in metadata:
            metadata["initrd_path"] = initrd_path

        # ---
        # choose a template
        if system:
            if format == "grub":
                if system.netboot_enabled:
                    template = os.path.join(self.settings.boot_loader_conf_template_dir, "grubsystem.template")
                else:
                    local = os.path.join(self.settings.boot_loader_conf_template_dir, "grublocal.template")
                    if os.path.exists(local):
                        template = local
            else:   # pxe
                if system.netboot_enabled:
                    template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem.template")

                    if arch.startswith("ppc"):
                        # to inherit the distro and system's boot_loader values correctly
                        blended_system = utils.blender(self.api, False, system)
                        if blended_system["boot_loader"] == "pxelinux":
                            template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem_ppc.template")
                        elif distro.boot_loader == "grub2" or blended_system["boot_loader"] == "grub2":
                            template = os.path.join(self.settings.boot_loader_conf_template_dir, "grub2_ppc.template")
                        else:
                            template = os.path.join(self.settings.boot_loader_conf_template_dir, "yaboot_ppc.template")
                    elif arch.startswith("arm"):
                        template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem_arm.template")
                    elif distro and distro.os_version.startswith("esxi"):
                        # ESXi uses a very different pxe method, using more files than
                        # a standard automatic installation file and different options -
                        # so giving it a dedicated PXE template makes more sense than
                        # shoe-horning it into the existing templates
                        template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxesystem_esxi.template")
                else:
                    # local booting on ppc requires removing the system-specific dhcpd.conf filename
                    if arch is not None and arch.startswith("ppc"):
                        # Disable yaboot network booting for all interfaces on the system
                        for (name, interface) in system.interfaces.iteritems():

                            filename = "%s" % utils.get_config_filename(system, interface=name).lower()

                            # Remove symlink to the yaboot binary
                            f3 = os.path.join(self.bootloc, "ppc", filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)

                            # Remove the interface-specific config file
                            f3 = os.path.join(self.bootloc, "boot/grub", "grub.cfg-" + filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)
                            f3 = os.path.join(self.bootloc, "etc", filename)
                            if os.path.lexists(f3):
                                utils.rmfile(f3)

                        # Yaboot/OF doesn't support booting locally once you've
                        # booted off the network, so nothing left to do
                        return None
                    else:
                        template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxelocal.template")
        else:
            # not a system record, so this is a profile record or an image
            if arch.startswith("arm"):
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxeprofile_arm.template")
            elif format == "grub":
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "grubprofile.template")
            elif distro and distro.os_version.startswith("esxi"):
                # ESXi uses a very different pxe method, see comment above in the system section
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxeprofile_esxi.template")
            elif 'nexenta' == format:
                template = os.path.join(self.settings.boot_loader_conf_template_dir, 'nexenta_profile.template')
            else:
                template = os.path.join(self.settings.boot_loader_conf_template_dir, "pxeprofile.template")

        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        # generate the kernel options and append line:
        kernel_options = self.build_kernel_options(system, profile, distro,
                                                   image, arch, autoinstall_path)
        metadata["kernel_options"] = kernel_options

        if distro and distro.os_version.startswith("esxi") and filename is not None:
            append_line = "BOOTIF=%s" % (os.path.basename(filename))
        elif "initrd_path" in metadata and (not arch or arch not in ["ppc", "ppc64", "arm"]):
            append_line = "append initrd=%s" % (metadata["initrd_path"])
        else:
            append_line = "append "
        append_line = "%s%s" % (append_line, kernel_options)
        if arch.startswith("ppc"):
            # remove the prefix "append"
            # TODO: this looks like it's removing more than append, really
            # not sure what's up here...
            append_line = append_line[7:]
        if distro and distro.os_version.startswith("xenserver620"):
            append_line = "%s" % (kernel_options)
        metadata["append_line"] = append_line

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if arch not in ["ppc", "ppc64"]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name

        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer
Пример #31
0
 def remove_single_image(self, name):
     bootloc = utils.tftpboot_location()
     utils.rmfile(os.path.join(bootloc, "images2", name))