예제 #1
0
def _prepare_resource_block(resource: DictNode, conf: Optional[DictNode]) -> Tuple[Dict[str, Dict[str, Any]], bool]:
    """hclify resource if pre-conditions met.

    :param resource: tf planned_values resource block
    :param conf: tf configuration resource block

    :returns:
        - resource_block: a list of strings representing the header columns
        - prepared: whether conditions met to prepare data
    """

    resource_block: Dict[str, Dict[str, Any]] = {}
    resource_block[resource["type"]] = {}
    prepared = False
    mode = ""
    if "mode" in resource:
        mode = resource.get("mode")
    # Rare cases where data block appears in resources with same name as resource block and only partial values
    # and where *_module resources don't have values field
    if mode == "managed" and "values" in resource:
        expressions = conf.get("expressions") if conf else None
        resource_block[resource["type"]][resource.get("name", "default")] = _hclify(resource["values"], expressions)
        resource_block[resource["type"]][resource.get("name", "default")]["__address__"] = resource.get("address")
        prepared = True
    return resource_block, prepared
예제 #2
0
 def extract_resource_attributes(resource: DictNode) -> DictNode:
     resource_type = resource.get("Type")
     attributes = resource.get("Properties", {})
     attributes["resource_type"] = resource_type
     attributes["__startline__"] = resource["__startline__"]
     attributes["__endline__"] = resource["__endline__"]
     attributes.start_mark = resource.start_mark
     attributes.end_mark = attributes.end_mark
     return attributes
예제 #3
0
    def scan_resource_conf(self, conf: DictNode) -> CheckResult:
        # IAM authentication is only supported for MySQL and PostgreSQL
        engine = conf.get("Properties", {}).get("Engine", {})
        if engine not in ("mysql", "postgres"):
            return CheckResult.UNKNOWN

        return super().scan_resource_conf(conf)
예제 #4
0
    def scan_resource_conf(self, conf: DictNode) -> CheckResult:
        params = conf.get("Properties", {}).get("Parameters", {})

        if params.get("audit_logs") == "enabled":
            return CheckResult.PASSED

        return CheckResult.FAILED
예제 #5
0
    def scan_resource_conf(self, conf: DictNode) -> CheckResult:
        params = conf.get("Properties", {}).get("Parameters", {})

        for param in params:
            if param.get("ParameterName") == "require_ssl" and param.get("ParameterValue") == "true":
                return CheckResult.PASSED

        return CheckResult.FAILED
예제 #6
0
 def scan_resource_conf(self, conf: DictNode) -> CheckResult:
     aws_kms_alias = "aws/"
     properties = conf.get("Properties")
     if properties:
         kms_key_id = properties.get("KmsKeyId")
         if kms_key_id and aws_kms_alias not in kms_key_id:
             return CheckResult.PASSED
     return CheckResult.FAILED
예제 #7
0
    def scan_resource_conf(self, conf: DictNode) -> CheckResult:
        log_types = ["audit"]

        logs_exports = conf.get("Properties",
                                {}).get("EnableCloudwatchLogsExports", [])
        if all(elem in logs_exports for elem in log_types):
            return CheckResult.PASSED

        return CheckResult.FAILED
예제 #8
0
def _hclify(obj: DictNode,
            conf: Optional[DictNode] = None,
            parent_key: Optional[str] = None) -> Dict[str, List[Any]]:
    ret_dict = {}
    if not isinstance(obj, dict):
        raise Exception("this method receives only dicts")
    if hasattr(obj, "start_mark") and hasattr(obj, "end_mark"):
        obj["start_line"] = obj.start_mark.line
        obj["end_line"] = obj.end_mark.line
    for key, value in obj.items():
        if _is_simple_type(value) or _is_list_of_simple_types(value):
            if parent_key == "tags":
                ret_dict[key] = value
            else:
                ret_dict[key] = [value]

        if _is_list_of_dicts(value):
            child_list = []
            conf_val = conf.get(key, []) if conf else []
            for internal_val, internal_conf_val in itertools.zip_longest(
                    value, conf_val):
                if isinstance(internal_val, dict):
                    child_list.append(
                        _hclify(internal_val,
                                internal_conf_val,
                                parent_key=key))
            if key == "tags":
                ret_dict[key] = [child_list]
            else:
                ret_dict[key] = child_list
        if isinstance(value, dict):
            child_dict = _hclify(value, parent_key=key)
            if parent_key == "tags":
                ret_dict[key] = child_dict
            else:
                ret_dict[key] = [child_dict]
    if conf and isinstance(conf, dict):
        for conf_key in conf.keys() - obj.keys():
            ref = next((x for x in conf[conf_key].get("references", [])
                        if not x.startswith(("var.", "local."))), None)
            if ref:
                ret_dict[conf_key] = [ref]

    return ret_dict
예제 #9
0
 def check_duplicates(self, ordered_pairs, beg_mark, end_mark):
     """
         Check for duplicate keys on the current level, this is not desirable
         because a dict does not support this. It overwrites it with the last
         occurance, which can give unexpected results
     """
     mapping = DictNode({}, beg_mark, end_mark)
     for key, value in ordered_pairs:
         if not self.allow_nulls and value is None:
             raise NullError('"{}"'.format(key))
         if key in mapping:
             raise DuplicateError('"{}"'.format(key))
         mapping[key] = value
     return mapping
예제 #10
0
 def extract_resource_attributes(resource: DictNode) -> DictNode:
     resource_type = resource.get("Type")
     attributes = resource.get("Properties", {})
     if not isinstance(attributes, dict):
         attributes = DictNode({}, resource.start_mark,
                               resource.end_mark)
     attributes["resource_type"] = resource_type
     attributes["__startline__"] = resource["__startline__"]
     attributes["__endline__"] = resource["__endline__"]
     attributes.start_mark = resource.start_mark
     attributes.end_mark = attributes.end_mark
     return attributes
예제 #11
0
    def construct_yaml_map(self, node):

        # Check for duplicate keys on the current level, this is not desirable
        # because a dict does not support this. It overwrites it with the last
        # occurance, which can give unexpected results
        mapping = {}
        self.flatten_mapping(node)
        for key_node, value_node in node.value:
            key = self.construct_object(key_node, False)
            value = self.construct_object(value_node, False)

            if key in mapping:
                raise CfnParseError(
                    self.filename,
                    'Duplicate resource found "{}" (line {})'.format(
                        key, key_node.start_mark.line + 1),
                    key_node.start_mark.line, key_node.start_mark.column, key)
            mapping[key] = value

        obj, = SafeConstructor.construct_yaml_map(self, node)
        return DictNode(obj, node.start_mark, node.end_mark)
예제 #12
0
def multi_constructor(loader, tag_suffix, node):
    """
    Deal with !Ref style function format
    """

    if tag_suffix not in UNCONVERTED_SUFFIXES:
        tag_suffix = '{}{}'.format(FN_PREFIX, tag_suffix)

    constructor = None
    if tag_suffix == 'Fn::GetAtt':
        constructor = construct_getatt
    elif isinstance(node, ScalarNode):
        constructor = loader.construct_scalar
    elif isinstance(node, SequenceNode):
        constructor = loader.construct_sequence
    elif isinstance(node, MappingNode):
        constructor = loader.construct_mapping
    else:
        raise 'Bad tag: !{}'.format(tag_suffix)

    return DictNode({tag_suffix: constructor(node)}, node.start_mark,
                    node.end_mark)