Exemplo n.º 1
0
    def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:
        handle_dynamic_values(conf)

        excluded_key = self.get_excluded_key()
        if excluded_key is not None:
            if dpath.search(conf, excluded_key) != {}:
                value = dpath.get(conf, excluded_key)
                if isinstance(value, list) and len(value) == 1:
                    value = value[0]
                if self.check_excluded_condition(value):
                    return CheckResult.PASSED

        inspected_key = self.get_inspected_key()
        bad_values = self.get_forbidden_values()
        if dpath.search(conf, inspected_key) != {}:
            value = dpath.get(conf, inspected_key)
            if isinstance(value, list) and len(value) == 1:
                value = value[0]
            if get_referenced_vertices_in_value(value=value,
                                                aliases={},
                                                resources_types=[]):
                # we don't provide resources_types as we want to stay provider agnostic
                return CheckResult.UNKNOWN
            if value in bad_values or ANY_VALUE in bad_values:
                return CheckResult.FAILED
            else:
                return CheckResult.PASSED

        return self.missing_attribute_result
Exemplo n.º 2
0
def my_path(my_dictionary: dict = None, path=None, value=None):
    items = path.split('/')
    # if the last character is a digit
    if items[-1].isdigit():
        items.pop()
        new_path = "/".join(items)
        # Check the element before the digit is already in the dictionary
        if dpath.search(my_dictionary, new_path):
            # Is it a list ?
            if isinstance(dpath.get(my_dictionary, new_path), list):
                dpath.new(my_dictionary, path, value)
            else:
                raise ValueError("The following entry can not be added: {}. "
                                 "This is not a list".format(
                                     my_dictionary[items[-2]]))
        # Not in the dictionary
        else:
            dpath.new(my_dictionary, new_path, [])
            dpath.new(my_dictionary, path, value)
    else:
        if dpath.search(my_dictionary, path):
            # Set the new value
            dpath.set(my_dictionary, path, value)
        else:
            dpath.new(my_dictionary, path, value)
    return my_dictionary
Exemplo n.º 3
0
    def scan_spec_conf(self, conf):
        metadata = {}

        if conf['kind'] == 'Pod':
            security_profile = dpath.search(
                conf, 'spec/securityContext/seccompProfile/type')
            if security_profile:
                security_profile = dpath.get(
                    conf, 'spec/securityContext/seccompProfile/type')
                return CheckResult.PASSED if security_profile == 'RuntimeDefault' else CheckResult.FAILED
            if "metadata" in conf:
                metadata = conf["metadata"]
        if conf['kind'] == 'Deployment':
            security_profile = dpath.search(
                conf, 'spec/template/spec/securityContext/seccompProfile/type')
            if security_profile:
                security_profile = dpath.get(
                    conf,
                    'spec/template/spec/securityContext/seccompProfile/type')
                return CheckResult.PASSED if security_profile == 'RuntimeDefault' else CheckResult.FAILED
            if "metadata" in conf:
                metadata = conf["metadata"]
        if conf['kind'] == 'StatefulSet':
            security_profile = dpath.search(
                conf, 'spec/template/spec/securityContext/seccompProfile/type')
            if security_profile:
                security_profile = dpath.get(
                    conf,
                    'spec/template/spec/securityContext/seccompProfile/type')
                return CheckResult.PASSED if security_profile == 'RuntimeDefault' else CheckResult.FAILED
            if "metadata" in conf:
                metadata = conf["metadata"]
        elif conf['kind'] == 'CronJob':
            if "spec" in conf:
                if "jobTemplate" in conf["spec"]:
                    if "spec" in conf["spec"]["jobTemplate"]:
                        if "template" in conf["spec"]["jobTemplate"]["spec"]:
                            if "metadata" in conf["spec"]["jobTemplate"][
                                    "spec"]["template"]:
                                metadata = conf["spec"]["jobTemplate"]["spec"][
                                    "template"]["metadata"]
        else:
            if "spec" in conf:
                if "template" in conf["spec"]:
                    if "metadata" in conf["spec"]["template"]:
                        metadata = conf["spec"]["template"]["metadata"]

        if metadata:
            if "annotations" in metadata and isinstance(
                    metadata['annotations'], dict):
                if "seccomp.security.alpha.kubernetes.io/pod" in metadata[
                        "annotations"]:
                    if ("docker/default" in metadata["annotations"]
                        ["seccomp.security.alpha.kubernetes.io/pod"]
                            or "runtime/default" in metadata["annotations"]
                        ["seccomp.security.alpha.kubernetes.io/pod"]):
                        return CheckResult.PASSED
        return CheckResult.FAILED
Exemplo n.º 4
0
    def scan_spec_conf(self, conf):
        metadata = {}

        if conf['kind'] == 'Pod':
            security_profile = dpath.search(
                conf, 'spec/securityContext/seccompProfile/type')
            if security_profile:
                security_profile = dpath.get(
                    conf, 'spec/securityContext/seccompProfile/type')
                return CheckResult.PASSED if security_profile == 'RuntimeDefault' else CheckResult.FAILED
            if "metadata" in conf:
                metadata = conf["metadata"]
        if conf['kind'] == 'Deployment':
            security_profile = dpath.search(
                conf, 'spec/template/spec/securityContext/seccompProfile/type')
            if security_profile:
                security_profile = dpath.get(
                    conf,
                    'spec/template/spec/securityContext/seccompProfile/type')
                return CheckResult.PASSED if security_profile == 'RuntimeDefault' else CheckResult.FAILED
            if "metadata" in conf:
                metadata = conf["metadata"]
        if conf['kind'] == 'StatefulSet':
            security_profile = dpath.search(
                conf, 'spec/template/spec/securityContext/seccompProfile/type')
            if security_profile:
                security_profile = dpath.get(
                    conf,
                    'spec/template/spec/securityContext/seccompProfile/type')
                return CheckResult.PASSED if security_profile == 'RuntimeDefault' else CheckResult.FAILED
            if "metadata" in conf:
                metadata = conf["metadata"]
        elif conf['kind'] == 'CronJob':
            if "spec" in conf:
                if "jobTemplate" in conf["spec"]:
                    if "spec" in conf["spec"]["jobTemplate"]:
                        if "template" in conf["spec"]["jobTemplate"]["spec"]:
                            if "metadata" in conf["spec"]["jobTemplate"][
                                    "spec"]["template"]:
                                metadata = conf["spec"]["jobTemplate"]["spec"][
                                    "template"]["metadata"]
        else:
            inner_metadata = self.get_inner_entry(conf, "metadata")
            metadata = inner_metadata if inner_metadata else metadata

        if metadata:
            if metadata.get('annotations'):
                for annotation in force_list(metadata["annotations"]):
                    for key in annotation:
                        if "seccomp.security.alpha.kubernetes.io/pod" in key:
                            if "docker/default" in annotation[
                                    key] or "runtime/default" in annotation[
                                        key]:
                                return CheckResult.PASSED
        return CheckResult.FAILED
Exemplo n.º 5
0
 def _bulk_meta_error(cls, error):
     try:
         _, err_type = next(dpath.search(error, "*/error/type", yielded=True))
         _, reason = next(dpath.search(error, "*/error/reason", yielded=True))
         if err_type == "cluster_block_exception":
             raise errors.server_error.LowDiskSpace(
                 "metrics, logs and all indexed data is in read-only mode!",
                 reason=re.sub(r"^index\s\[.*?\]\s", "", reason) if reason else ""
             )
         return
     except StopIteration:
         pass
    def finalize_variables_init(self):
        for variable_name, holder in self._holders.items():
            periods = holder.buffer.keys()
            # We need to handle small periods first for set_input to work
            sorted_periods = sorted(periods, key=key_period_size)
            for period in sorted_periods:
                array = holder.buffer[period]
                try:
                    holder.set_input(period, array)
                except PeriodMismatchError as e:
                    # This errors happens when we try to set a variable value for a period that doesn't match its definition period
                    # It is only raised when we consume the buffer. We thus don't know which exact key caused the error.
                    # We do a basic research to find the culprit path
                    culprit_path = next(
                        dpath.search(self.entities_json,
                                     "*/{}/{}".format(e.variable_name,
                                                      str(e.period)),
                                     yielded=True), None)
                    if culprit_path:
                        path = [self.plural] + culprit_path[0].split('/')
                    else:
                        path = [
                            self.plural
                        ]  # Fallback: if we can't find the culprit, just set the error at the entities level

                    raise SituationParsingError(path, e.message)
 def _locate_variables_assignments(self, definition_type, folder, var_name):
     var_assignments_paths = {}
     assignment_regex = self._generate_evaluation_regex(
         definition_type, var_name)
     for source_file in [
             file for file in os.listdir(folder) if file.endswith('.tf')
             and self.tf_definitions.get(os.path.join(folder, file))
     ]:
         file_path = os.path.join(folder, source_file)
         var_entries = dpath.search(
             self.tf_definitions[file_path],
             '**',
             afilter=lambda x: re.findall(assignment_regex, str(x)),
             yielded=True)
         var_assignments_paths[file_path] = []
         for definition_path, expression in var_entries:
             context_path, definition_name = self.extract_context_path(
                 definition_path)
             var_assignments_paths[file_path].append({
                 'definition_name':
                 definition_name,
                 'definition_expression':
                 expression,
                 'definition_path':
                 definition_path
             })
     var_assignments_paths = {
         k: v
         for (k, v) in var_assignments_paths.items() if len(v) > 0
     }
     return var_assignments_paths
Exemplo n.º 8
0
 def _search(doc_cls, obj, path, only_values=True):
     """ Call dpath.search with yielded=True, collect result values """
     norm_path = doc_cls.get_dpath_translated_path(path)
     return [
         v if only_values else (k, v) for k, v in dpath.search(
             obj, norm_path, separator='.', yielded=True)
     ]
Exemplo n.º 9
0
    def bulk_error(cls, e, _, **__):
        if not e.errors:
            return

        # Else try returning a better error string
        for _, reason in dpath.search(e.errors[0],
                                      "*/error/reason",
                                      yielded=True):
            return reason
Exemplo n.º 10
0
 def _evaluate_folder_variables(self, folder):
     assignment_files = dpath.search(self.definitions_context, f'**.assignments', separator='.')
     variable_file_object = {k: v for k, v in assignment_files.items() if folder in k}
     if variable_file_object:
         for var_file, variable_assignments in variable_file_object.items():
             relative_var_file = f'/{os.path.relpath(var_file, self.root_folder)}'
             for var_name, var_value in variable_assignments['variable']['assignments'].items():
                 evaluated_definitions = self._locate_assignments(folder, var_name)
                 var_assignments = {'definitions': evaluated_definitions, 'var_file': relative_var_file}
                 self._assign_definition_value(var_name, var_value, var_assignments)
    def scan_resource_conf(self, conf):
        excluded_key = self.get_excluded_key()
        if excluded_key is not None:
            if dpath.search(conf, excluded_key) != {}:
                value = dpath.get(conf, excluded_key)
                if isinstance(value, list) and len(value) == 1:
                    value = value[0]
                if self.check_excluded_condition(value):
                    return CheckResult.PASSED

        inspected_key = self.get_inspected_key()
        bad_values = self.get_forbidden_values()
        if dpath.search(conf, inspected_key) != {}:
            value = dpath.get(conf, inspected_key)
            if isinstance(value, list) and len(value) == 1:
                value = value[0]
            if value in bad_values or ANY_VALUE in bad_values:
                return CheckResult.FAILED

        return CheckResult.PASSED
Exemplo n.º 12
0
    def plot(self,
             view_settings={},
             build_label=build_label_default,
             build_marker=build_marker_default,
             build_color=build_color_default
             ):

        probe_view_settings = {k: {} for k in self.probes}
        logging.debug(probe_view_settings)

        master_tag_dict = {p.master_tag: p for p in self.probes}
        # TODO: can the following nested loop be recast into a single loop?
        for pattern, settings in view_settings.items():
            for p in dpath.search(master_tag_dict, "/" + pattern).values():
                probe_view_settings[p].update(settings)

        logging.debug(probe_view_settings)

        fig = plt.figure(figsize=(10, 10))
        plt.xlabel(self.x_label)
        plt.ylabel(self.y_label)
        plt.title(self.title)
        plt.grid(True)
        plt.gca().ticklabel_format(useOffset=False, style='sci')
        tickFormat = mtick.FormatStrFormatter("%.4e")
        plt.gca().get_yaxis().set_major_formatter(tickFormat)
        if len(self.x_range) > 0:
            plt.xlim(self.x_range[0], self.x_range[1])
        if len(self.y_range) > 0:
            plt.ylim(self.y_range[0], self.y_range[1])

        for probe in self.probes:
            logging.debug(probe.file_name
                          + " "
                          + probe.variable_name)
            x, var = probe.data
            # TODO : can we write this if-then in a more pythonist way?
            if build_label == None:
                probe_label = None
            else:
                probe_label = build_label(probe)
            if build_color == None:
                probe_color = None
            else:
                probe_color = build_color(probe)

            plot_args = probe_view_settings[probe]
#             plotArgs.update({'label' : probe_label})
            plot_args['label'] = probe_label
#            logging.debug(plotArgs)
            plt.plot(x, var, **plot_args)

        plt.legend(loc='best', frameon=False)
        plt.show(fig)
Exemplo n.º 13
0
 def _evaluate_folder_variables(self, folder):
     """
     Locate all assignments extracted by the context parser, and assigns them to corresponding variables found in
     tf_definitions
     :param folder: folder to assign variables in
     :return:
     """
     assignment_files = dpath.search(self.definitions_context, f'**.assignments', separator='.')
     assignment_files = {k: v for k, v in assignment_files.items() if folder in k}
     if assignment_files:
         self._assign_definitions(assignment_files, folder)
Exemplo n.º 14
0
    def bulk_error(cls, e, _, **__):
        if not e.errors:
            return

        # Currently we only handle the first error
        error = e.errors[0]

        cls._bulk_meta_error(error)

        # Else try returning a better error string
        for _, reason in dpath.search(e.errors[0], "*/error/reason", yielded=True):
            return reason
Exemplo n.º 15
0
    def raise_period_mismatch(self, entity, json, e):
        # This error happens when we try to set a variable value for a period that doesn't match its definition period
        # It is only raised when we consume the buffer. We thus don't know which exact key caused the error.
        # We do a basic research to find the culprit path
        culprit_path = next(
            dpath.search(json, "*/{}/{}".format(e.variable_name, str(e.period)), yielded = True),
            None)
        if culprit_path:
            path = [entity.plural] + culprit_path[0].split('/')
        else:
            path = [entity.plural]  # Fallback: if we can't find the culprit, just set the error at the entities level

        raise SituationParsingError(path, e.message)
Exemplo n.º 16
0
 def _get_single(item_):
     values_ = sorted(
         list(
             dpath.search(_ProjectGlobalConfig.config,
                          item_,
                          yielded=True)))
     if not values_:
         return None
     if len(values_) > 1:
         values_ = [v[1] for v in values_]
     else:
         values_ = values_[0][1]
     return values_
Exemplo n.º 17
0
    def raise_period_mismatch(self, entity, json, e):
        # This error happens when we try to set a variable value for a period that doesn't match its definition period
        # It is only raised when we consume the buffer. We thus don't know which exact key caused the error.
        # We do a basic research to find the culprit path
        culprit_path = next(
            dpath.search(json, "*/{}/{}".format(e.variable_name, str(e.period)), yielded = True),
            None)
        if culprit_path:
            path = [entity.plural] + culprit_path[0].split('/')
        else:
            path = [entity.plural]  # Fallback: if we can't find the culprit, just set the error at the entities level

        raise SituationParsingError(path, e.message)
Exemplo n.º 18
0
    def plot(self,
             view_settings={},
             build_label=build_label_default,
             build_marker=build_marker_default,
             build_color=build_color_default):

        probe_view_settings = {k: {} for k in self.probes}
        logging.debug(probe_view_settings)

        master_tag_dict = {p.master_tag: p for p in self.probes}
        # TODO: can the following nested loop be recast into a single loop?
        for pattern, settings in view_settings.items():
            for p in dpath.search(master_tag_dict, "/" + pattern).values():
                probe_view_settings[p].update(settings)

        logging.debug(probe_view_settings)

        fig = plt.figure(figsize=(10, 10))
        plt.xlabel(self.x_label)
        plt.ylabel(self.y_label)
        plt.title(self.title)
        plt.grid(True)
        plt.gca().ticklabel_format(useOffset=False, style='sci')
        tickFormat = mtick.FormatStrFormatter("%.4e")
        plt.gca().get_yaxis().set_major_formatter(tickFormat)
        if len(self.x_range) > 0:
            plt.xlim(self.x_range[0], self.x_range[1])
        if len(self.y_range) > 0:
            plt.ylim(self.y_range[0], self.y_range[1])

        for probe in self.probes:
            logging.debug(probe.file_name + " " + probe.variable_name)
            x, var = probe.data
            # TODO : can we write this if-then in a more pythonist way?
            if build_label == None:
                probe_label = None
            else:
                probe_label = build_label(probe)
            if build_color == None:
                probe_color = None
            else:
                probe_color = build_color(probe)

            plot_args = probe_view_settings[probe]
            #             plotArgs.update({'label' : probe_label})
            plot_args['label'] = probe_label
            #            logging.debug(plotArgs)
            plt.plot(x, var, **plot_args)

        plt.legend(loc='best', frameon=False)
        plt.show(fig)
Exemplo n.º 19
0
    def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:
        self.handle_dynamic_values(conf)

        excluded_key = self.get_excluded_key()
        if excluded_key is not None:
            if dpath.search(conf, excluded_key) != {}:
                value = dpath.get(conf, excluded_key)
                if isinstance(value, list) and len(value) == 1:
                    value = value[0]
                if self.check_excluded_condition(value):
                    return CheckResult.PASSED

        inspected_key = self.get_inspected_key()
        bad_values = self.get_forbidden_values()
        if dpath.search(conf, inspected_key) != {}:
            value = dpath.get(conf, inspected_key)
            if isinstance(value, list) and len(value) == 1:
                value = value[0]
            if value in bad_values or ANY_VALUE in bad_values:
                return CheckResult.FAILED
            else:
                return CheckResult.PASSED

        return self.missing_attribute_result
Exemplo n.º 20
0
    def parse_section_title(self, cell, current_section=None):
        if not isinstance(cell.internal_value, str):
            raise SheetParsingError(
                "Enable to parse summary: Unexpected value in cell '{}'".
                format(cell.coordinate))
        description = ''.join(cell.internal_value.split('.')[1:]).strip()
        key = slugify(description, stopwords=True)
        path = f"subparams/{current_section}/subparams/{key}" if current_section else f"subparams/{key}"
        if dpath.search(self.sections, path):
            raise SheetParsingError(
                "Name collision: section '{}' alredy exists.".format(path))
        dpath.new(self.sections, path, {
            'description': description,
            'metadata': {
                'order': []
            }
        })

        # Keep track of the order
        order_path = f'subparams/{current_section}/metadata/order' if current_section else 'metadata/order'
        dpath.get(self.sections, order_path).append(key)

        return path
Exemplo n.º 21
0
def execute_postponed_actions(context,
                              is_data: bool = True,
                              actions_switcher: dict = None):
    """
    Execute postponed actions
    :param actions_switcher: the automaton list of actions which can be postponed
    :param context: the current context
    :param is_data:  boolean, True means set only data, False means execute actions (use models)
    :return: None
    """
    log.debug("postponed_action")

    if is_data:
        #  Do settings
        log.debug("is data statement")
        key_list = set(ATTRIBUTE_LIST).intersection(
            context.pre_conditions["postponed"].keys())
        for key in key_list:
            log.debug("Key : {}".format(str(key)))
            while context.pre_conditions["postponed"][key]:
                log.debug("Context.pre_conditions[postponed][key]: {} ".format(
                    context.pre_conditions["postponed"][key]))
                elem = context.pre_conditions["postponed"][key].pop(0)
                log.debug("elem contains: {}".format(elem))
                try:
                    # Check the path exist
                    if dpath.search(context.pre_conditions[key], elem["path"]):
                        dpath.set(context.pre_conditions[key], elem["path"],
                                  elem["value"])
                    else:
                        # Create a new entry
                        dpath.new(context.pre_conditions[key], elem["path"],
                                  elem["value"])
                except AssertionError as assertion:
                    log.error("Update data failed.\n '{}'".format(
                        assertion.args[0]))
                    raise_exception(
                        AssertionError,
                        "Update data failed.\n '{}'".format(assertion.args[0]),
                        context.evidence_folder)
                log.debug("pre_conditions : {}".format(
                    str(context.pre_conditions[key])))
    else:
        #  Do execute steps
        log.debug("else statement")
        postponed_actions = deepcopy(
            context.pre_conditions["postponed"]["execution"])
        context.pre_conditions["postponed"]["execution"].clear()
        for index, action in enumerate(postponed_actions):
            log.debug("Index: {}, action: {}".format(index, action))
            if isinstance(action, str):
                context.execute_steps(action)
            elif isinstance(action, tuple) and len(action) == 2:
                log.debug("action switcher: {}".format(action))
                actions_switcher[action[0]](**action[1])
                sleep(0.5)
            else:
                raise Exception("Unknown action to process.\n"
                                "Get '{}'".format(repr(action)))

    log.debug("End of postponed_action ")