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
def scan_entity_conf(self, conf: Dict[str, List[Any]], entity_type: str) -> CheckResult: self.entity_type = entity_type if conf.get("count") == [0]: return CheckResult.UNKNOWN handle_dynamic_values(conf) return self.scan_resource_conf(conf)
def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult: handle_dynamic_values(conf) inspected_key = self.get_inspected_key() expected_values = self.get_expected_values() if dpath.search(conf, inspected_key) != {}: # Inspected key exists value = dpath.get(conf, inspected_key) if isinstance(value, list) and len(value) == 1: value = value[0] if value is None or (isinstance(value, list) and not value): return self.missing_block_result if ANY_VALUE in expected_values and value is not None and ( not isinstance(value, str) or value): # Key is found on the configuration - if it accepts any value, the check is PASSED return CheckResult.PASSED if self._is_variable_dependant(value): # If the tested attribute is variable-dependant, then result is PASSED return CheckResult.PASSED if value in expected_values: return CheckResult.PASSED 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 return CheckResult.FAILED else: # Look for the configuration in a bottom-up fashion inspected_attributes = self._filter_key_path(inspected_key) for attribute in reversed(inspected_attributes): for sub_key, sub_conf in dpath.search(conf, f"**/{attribute}", yielded=True): filtered_sub_key = self._filter_key_path(sub_key) # Only proceed with check if full path for key is similar - not partial match if inspected_attributes == filtered_sub_key: if self._is_nesting_key(inspected_attributes, filtered_sub_key): if isinstance(sub_conf, list) and len(sub_conf) == 1: sub_conf = sub_conf[0] if sub_conf in self.get_expected_values(): return CheckResult.PASSED if self._is_variable_dependant(sub_conf): # If the tested attribute is variable-dependant, then result is PASSED return CheckResult.PASSED return self.missing_block_result
def _add_resource(self, blocks: List[Dict[str, Dict[str, Any]]], path: str) -> None: for resource_dict in blocks: for resource_type, resources in resource_dict.items(): self.resources_types.add(resource_type) for name, resource_conf in resources.items(): attributes = self.clean_bad_characters(resource_conf) if not isinstance(attributes, dict): continue handle_dynamic_values(attributes) provisioner = attributes.get("provisioner") if provisioner: self._handle_provisioner(provisioner, attributes) attributes["resource_type"] = [resource_type] resource_block = TerraformBlock( block_type=BlockType.RESOURCE, name=f"{resource_type}.{name}", config=self.clean_bad_characters(resource_dict), path=path, attributes=attributes, id=f"{resource_type}.{name}", source=self.source, ) self._add_to_blocks(resource_block)