示例#1
0
def read_kv_conf(filepath):
    """Reads a flat Cuckoo key/value configuration file."""
    ret = {}
    for line in open(filepath, "rb"):
        line = line.strip()
        if not line or line.startswith("#"):
            continue

        if "=" not in line:
            raise CuckooConfigurationError(
                "Invalid flat configuration line: %s (missing '=' character)" %
                line)

        key, raw_value = line.split("=", 1)
        key, raw_value = key.replace(".", ":").strip(), raw_value.strip()
        try:
            value = cast(key, raw_value)
        except (CuckooConfigurationError, RuntimeError) as e:
            raise CuckooConfigurationError(
                "Invalid flat configuration line: %s (error %s)" % (line, e))

        if raw_value and value is None:
            raise CuckooConfigurationError(
                "Invalid flat configuration entry: %s is None" % key)

        a, b, c = key.split(":")
        ret[a] = ret.get(a, {})
        ret[a][b] = ret[a].get(b, {})
        ret[a][b][c] = value
    return ret
示例#2
0
def config(s, cfg=None, strict=False, raw=False, loose=False, check=False):
    """Fetch a configuration value, denoted as file:section:key."""
    if s.count(":") != 2:
        raise RuntimeError("Invalid configuration entry: %s" % s)

    file_name, section, key = s.split(":")

    if check:
        strict = raw = loose = True

    type_ = Config.configuration.get(file_name, {}).get(section, {}).get(key)
    if strict and type_ is None:
        raise CuckooConfigurationError(
            "No such configuration value exists: %s" % s
        )

    required = type_ is not None and type_.required
    index = file_name, cfg, cwd(), strict, raw, loose

    if index not in _cache:
        _cache[index] = Config(
            file_name, cfg=cfg, strict=strict, raw=raw, loose=loose
        )

    config = _cache[index]

    if strict and required and section not in config.sections:
        raise CuckooConfigurationError(
            "Configuration value %s not present! This may indicate that "
            "you've incorrectly filled out the Cuckoo configuration, "
            "please double check it." % s
        )

    section = config.sections.get(section, {})
    if strict and required and key not in section:
        raise CuckooConfigurationError(
            "Configuration value %s not present! This may indicate that "
            "you've incorrectly filled out the Cuckoo configuration, "
            "please double check it." % s
        )

    value = section.get(key, type_.default if type_ else None)

    if check and not type_.check(value):
        raise CuckooConfigurationError(
            "The configuration value %r found for %s is invalid. Please "
            "update your configuration!" % (value, s)
        )

    return value
示例#3
0
 def get_section_types(self, file_name, section, strict=False, loose=False):
     """Get types for a section entry."""
     section_types = get_section_types(file_name, section)
     if not section_types and not loose:
         log.error("Config section %s:%s not found!", file_name, section)
         if strict:
             raise CuckooConfigurationError(
                 "Config section %s:%s not found!", file_name, section)
         return
     return section_types
示例#4
0
    def get(self, section):
        """Get option.
        @param section: section to fetch.
        @raise CuckooConfigurationError: if section not found.
        @return: option value.
        """
        if section not in self.sections:
            raise CuckooConfigurationError(
                "Option %s is not found in configuration" % section)

        return self.sections[section]
示例#5
0
def cast(s, value):
    """Cast a configuration value as per its type."""
    if s.count(":") != 2:
        raise RuntimeError("Invalid configuration entry: %s" % s)

    file_name, section, key = s.split(":")
    type_ = get_section_types(file_name, section).get(key)
    if type_ is None:
        raise CuckooConfigurationError(
            "No such configuration value exists: %s" % s)

    return type_.parse(value)
示例#6
0
def config2(file_name, section):
    keys = get_section_types(file_name, section, strict=True)
    if not keys:
        raise CuckooConfigurationError(
            "No such configuration section exists: %s:%s" %
            (file_name, section))

    ret = Dictionary()
    for key in keys:
        if key == "__star__" or key == "*":
            continue
        ret[key] = config("%s:%s:%s" % (file_name, section, key))
    return ret
示例#7
0
    def __init__(self,
                 file_name="cuckoo",
                 cfg=None,
                 strict=False,
                 loose=False,
                 raw=False):
        """
        @param file_name: file name without extension.
        @param cfg: configuration file path.
        """
        env = {}
        for key, value in os.environ.items():
            if key.startswith("CUCKOO_"):
                env[key] = value

        env["CUCKOO_CWD"] = cwd()
        env["CUCKOO_APP"] = os.environ.get("CUCKOO_APP", "")
        config = ConfigParser.ConfigParser(env)

        self.env_keys = []
        for key in env.keys():
            self.env_keys.append(key.lower())

        self.sections = {}

        try:
            config.read(cfg or cwd("conf", "%s.conf" % file_name))
        except ConfigParser.ParsingError as e:
            raise CuckooConfigurationError(
                "There was an error reading in the $CWD/conf/%s.conf "
                "configuration file. Most likely there are leading "
                "whitespaces in front of one of the key=value lines defined. "
                "More information from the original exception: %s" %
                (file_name, e))

        if file_name not in self.configuration and not loose:
            log.error("Unknown config file %s.conf", file_name)
            return

        for section in config.sections():
            types = self.get_section_types(file_name, section, strict, loose)
            if types is None:
                continue

            self.sections[section] = Dictionary()
            setattr(self, section, self.sections[section])

            try:
                items = config.items(section)
            except ConfigParser.InterpolationMissingOptionError as e:
                log.error("Missing environment variable(s): %s", e)
                raise CuckooConfigurationError(
                    "Missing environment variable: %s" % e)
            except ValueError as e:
                if e.message == "incomplete format key":
                    raise CuckooConfigurationError(
                        "One of the fields that you've filled out in "
                        "$CWD/conf/%s contains the sequence '%(' which is "
                        "interpreted as environment variable sequence, e.g., "
                        "'%(PGPASSWORD)s' would locate a PostgreSQL "
                        "password. Please update the field to correctly "
                        "state the environment variable or change it in a "
                        "way that '%(' is no longer in the variable.")
                raise

            for name, raw_value in items:
                if name in self.env_keys:
                    continue

                if "\n" in raw_value:
                    wrong_key = "???"
                    try:
                        wrong_key = raw_value.split("\n", 1)[1].split()[0]
                    except:
                        pass

                    raise CuckooConfigurationError(
                        "There was an error reading in the $CWD/conf/%s.conf "
                        "configuration file. Namely, there are one or more "
                        "leading whitespaces before the definition of the "
                        "'%s' key/value pair in the '%s' section. Please "
                        "remove those leading whitespaces as Python's default "
                        "configuration parser is unable to handle those "
                        "properly." % (file_name, wrong_key, section))

                if not raw and name in types:
                    # TODO Is this the area where we should be checking the
                    # configuration values?
                    # if not types[name].check(raw_value):
                    #     print file_name, section, name, raw_value
                    #     raise

                    value = types[name].parse(raw_value)
                else:
                    if not loose:
                        log.error(
                            "Type of config parameter %s:%s:%s not found! "
                            "This may indicate that you've incorrectly filled "
                            "out the Cuckoo configuration, please double "
                            "check it.", file_name, section, name)
                    value = raw_value

                self.sections[section][name] = value
示例#8
0
def write_cuckoo_conf(cfg=None):
    if cfg is None:
        cfg = {}

    # Merge any provided configuration with the defaults and emit their values.
    raw = {}
    for filename, sections in Config.configuration.items():
        cfg[filename] = cfg.get(filename, {})
        raw[filename] = {}
        for section, entries in sections.items():
            if section == "__star__":
                continue

            # Process each entry.
            if not isinstance(entries, (tuple, list)):
                entries = entries,

            for entry in entries:
                real_section = entry.get("__section__", section)
                entries = cfg[filename].get(section, {})
                entries.update(cfg[filename].get(real_section, {}))
                cfg[filename][real_section] = entries
                raw[filename][real_section] = {}
                for key, value in entry.items():
                    if key == "__section__":
                        continue

                    raw_value = cfg[filename][real_section].get(key, value.default)
                    cfg[filename][real_section][key] = raw_value
                    raw[filename][real_section][key] = value.emit(raw_value)

        if "__star__" in sections:
            section, key = sections["__star__"]
            for entry in cfg[filename][section][key]:
                if entry not in cfg[filename]:
                    raise CuckooConfigurationError(
                        "A section was defined that has not been found: "
                        "%s:%s" % (section, entry)
                    )

                if isinstance(sections["*"], (tuple, list)):
                    section_types = sections["*"][0]
                else:
                    section_types = sections["*"]

                raw[filename][entry] = {}
                for key, value in section_types.items():
                    if key == "__section__":
                        continue

                    if key not in cfg[filename][entry]:
                        raw_value = cfg[filename][entry][key] = None
                    else:
                        raw_value = cfg[filename][entry][key]

                    raw[filename][entry][key] = value.emit(raw_value)

    def _config(s):
        filename, section, key = s.split(":")
        return cfg[filename][section][key]

    raw["config"] = _config
    for filename in os.listdir(cwd("cwd", "conf", private=True)):
        template = jinja2.Template(
            open(cwd("cwd", "conf", filename, private=True), "rb").read()
        )
        open(cwd("conf", filename), "wb").write(
            template.render(raw).rstrip() + "\n"
        )