コード例 #1
0
    def handle_fn_get_azs(self, intrinsic_value, ignore_errors):
        """
        { "Fn::GetAZs" : "" }
        { "Fn::GetAZs" : { "Ref" : "AWS::Region" } }
        { "Fn::GetAZs" : "us-east-1" }
        This intrinsic function will get the availability zones specified for the specified region. This is usually used
        with {"Ref": "AWS::Region"}. If it is an empty string, it will get the default region.

        This intrinsic function will resolve all the objects within the function's value and check their type.
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::GetAZs intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        intrinsic_value = self.intrinsic_property_resolver(
            intrinsic_value,
            ignore_errors,
            parent_function=IntrinsicResolver.FN_GET_AZS)
        verify_intrinsic_type_str(intrinsic_value,
                                  IntrinsicResolver.FN_GET_AZS)

        if not intrinsic_value:
            intrinsic_value = self._symbol_resolver.handle_pseudo_region()

        if intrinsic_value not in self._symbol_resolver.REGIONS:
            raise InvalidIntrinsicException(
                "Invalid region string passed in to {}".format(
                    IntrinsicResolver.FN_GET_AZS))

        return self._symbol_resolver.REGIONS.get(intrinsic_value)
コード例 #2
0
    def handle_fn_ref(self, intrinsic_value, ignore_errors):
        """
        {"Ref": "Logical ID"}
        This intrinsic function gets the reference to a certain attribute. Some Ref's have different functionality with
        different resource types.

        This intrinsic function will resolve all the objects within the function's value and check their type.
        This calls the symbol resolver in order to resolve the relevant attribute.
        Parameter
        ----------
        intrinsic_value: str
           This is the value of the object inside the Ref intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value,
            ignore_errors,
            parent_function=IntrinsicResolver.REF)
        verify_intrinsic_type_str(arguments, IntrinsicResolver.REF)

        return self._symbol_resolver.resolve_symbols(arguments,
                                                     IntrinsicResolver.REF)
コード例 #3
0
    def handle_fn_getatt(self, intrinsic_value, ignore_errors):
        """
        { "Fn::GetAtt" : [ "logicalNameOfResource", "attributeName" ] }
        This intrinsic function gets the attribute for logical_resource specified. Each attribute might have a different
        functionality depending on the type.

        This intrinsic function will resolve all the objects within the function's value and check their type.
        This calls the symbol resolver in order to resolve the relevant attribute.
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::GetAtt intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value, ignore_errors, parent_function=IntrinsicResolver.FN_GET_ATT
        )
        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_GET_ATT)
        verify_number_arguments(arguments, IntrinsicResolver.FN_GET_ATT, num=2)

        logical_id = self.intrinsic_property_resolver(
            arguments[0], ignore_errors, parent_function=IntrinsicResolver.FN_GET_ATT
        )
        resource_type = self.intrinsic_property_resolver(
            arguments[1], ignore_errors, parent_function=IntrinsicResolver.FN_GET_ATT
        )

        verify_intrinsic_type_str(logical_id, IntrinsicResolver.FN_GET_ATT)
        verify_intrinsic_type_str(resource_type, IntrinsicResolver.FN_GET_ATT)

        return self._symbol_resolver.resolve_symbols(logical_id, resource_type)
コード例 #4
0
    def handle_fn_split(self, intrinsic_value, ignore_errors):
        """
        { "Fn::Split" : [ "delimiter", "source string" ] }
        This function will then split the source_string based on the delimiter

        This intrinsic function will resolve all the objects within the function's value and check their type.
        Parameter
        ----------
        intrinsic_value: list, dict
            This is the value of the object inside the Fn::Split intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value, ignore_errors, parent_function=IntrinsicResolver.FN_SPLIT
        )

        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_SPLIT)

        delimiter = arguments[0]

        verify_intrinsic_type_str(delimiter, IntrinsicResolver.FN_SPLIT, position_in_list="first")

        source_string = self.intrinsic_property_resolver(
            arguments[1], ignore_errors, parent_function=IntrinsicResolver.FN_SPLIT
        )

        verify_intrinsic_type_str(source_string, IntrinsicResolver.FN_SPLIT, position_in_list="second")

        return source_string.split(delimiter)
コード例 #5
0
    def handle_fn_and(self, intrinsic_value):
        """
        {"Fn::And": [{condition}, {...}]}
        This intrinsic checks that every item in the list evaluates to a boolean. The items in the list can either
        be of the format {Condition: condition_name} which finds and evaluates the Conditions dictionary of another
        intrinsic function.

        The Conditions dictionary will have the following format:
        {
            "Conditions": {
                "condition_name": True/False or "{Intrinsic Function}"
            }
        }

        This intrinsic function will resolve all the objects within the function's value and check their type.
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::Join intrinsic function property

        Return
        -------
        A boolean depending on if all of the properties in Fn::And evaluate to True
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value, parent_function=IntrinsicResolver.FN_AND
        )
        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_AND)

        for i, argument in enumerate(arguments):
            if isinstance(argument, dict) and "Condition" in argument:
                condition_name = argument.get("Condition")
                verify_intrinsic_type_str(condition_name, IntrinsicResolver.FN_AND)

                condition = self._conditions.get(condition_name)
                verify_non_null(
                    condition,
                    IntrinsicResolver.FN_AND,
                    position_in_list=self.get_prefix_position_in_list(i),
                )

                condition_evaluated = self.intrinsic_property_resolver(
                    condition, parent_function=IntrinsicResolver.FN_AND
                )
                verify_intrinsic_type_bool(
                    condition_evaluated, IntrinsicResolver.FN_AND
                )

                if not condition_evaluated:
                    return False
            else:
                condition = self.intrinsic_property_resolver(
                    argument, parent_function=IntrinsicResolver.FN_AND
                )
                verify_intrinsic_type_bool(condition, IntrinsicResolver.FN_AND)

                if not condition:
                    return False

        return True
コード例 #6
0
    def handle_fn_if(self, intrinsic_value, ignore_errors):
        """
        {"Fn::If": [condition_name, value_if_true, value_if_false]}
        This intrinsic function will evaluate the condition from the Conditions dictionary and then return value_if_true
        or value_if_false depending on the value.

        The Conditions dictionary will have the following format:
        {
            "Conditions": {
                "condition_name": True/False or "{Intrinsic Function}"
            }
        }

        This intrinsic function will resolve all the objects within the function's value and check their type.
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::Join intrinsic function property

        Return
        -------
        This will return value_if_true and value_if_false depending on how the condition is evaluated
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value, ignore_errors, parent_function=IntrinsicResolver.FN_IF
        )
        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_IF)
        verify_number_arguments(arguments, IntrinsicResolver.FN_IF, num=3)

        condition_name = self.intrinsic_property_resolver(
            arguments[0], ignore_errors, parent_function=IntrinsicResolver.FN_IF
        )
        verify_intrinsic_type_str(condition_name, IntrinsicResolver.FN_IF)

        value_if_true = self.intrinsic_property_resolver(
            arguments[1], ignore_errors, parent_function=IntrinsicResolver.FN_IF
        )
        value_if_false = self.intrinsic_property_resolver(
            arguments[2], ignore_errors, parent_function=IntrinsicResolver.FN_IF
        )

        condition = self._conditions.get(condition_name)
        verify_intrinsic_type_dict(
            condition,
            IntrinsicResolver.FN_IF,
            message="The condition is missing in the Conditions dictionary for {}".format(IntrinsicResolver.FN_IF),
        )

        condition_evaluated = self.intrinsic_property_resolver(
            condition, ignore_errors, parent_function=IntrinsicResolver.FN_IF
        )
        verify_intrinsic_type_bool(
            condition_evaluated,
            IntrinsicResolver.FN_IF,
            message="The result of {} must evaluate to bool".format(IntrinsicResolver.FN_IF),
        )

        return value_if_true if condition_evaluated else value_if_false
コード例 #7
0
    def intrinsic_property_resolver(self, intrinsic, parent_function="template"):
        """
        This resolves the intrinsic of the format
        {
            intrinsic: dict
        } by calling the function with the relevant intrinsic function resolver.

        This also supports returning a string, list, boolean, int since they may be intermediate steps in the recursion
        process. No transformations are done on these.

        By default this will just return the item if non of the types match. This is because of the function
        resolve_all_attributes which will recreate the resources by processing every aspect of resource.

        This code resolves in a top down depth first fashion in order to create a functional style recursion that
        doesn't mutate any of the properties.

        Parameters
        ----------
        intrinsic: dict, str, list, bool, int
            This is an intrinsic property or an intermediate step
        parent_function: str
            In case there is a missing property, this is used to figure out where the property resolved is missing.
        Return
        ---------
        The simplified version of the intrinsic function. This could be a list,str,dict depending on the format required
        """
        if intrinsic is None:
            raise InvalidIntrinsicException("Missing Intrinsic property in {}".format(parent_function))
        if isinstance(intrinsic, list):
            return [self.intrinsic_property_resolver(item) for item in intrinsic]
        if not isinstance(intrinsic, dict) or intrinsic == {}:
            return intrinsic

        # `intrinsic` is a dict at this point.

        keys = list(intrinsic.keys())
        key = keys[0]

        if key in self.intrinsic_key_function_map:
            intrinsic_value = intrinsic.get(key)
            return self.intrinsic_key_function_map.get(key)(intrinsic_value)
        elif key in self.conditional_key_function_map:
            intrinsic_value = intrinsic.get(key)
            return self.conditional_key_function_map.get(key)(intrinsic_value)

        # In this case, it is a dictionary that doesn't directly contain an intrinsic resolver, we must recursively
        # resolve each of it's sub properties.
        sanitized_dict = {}
        for key, val in intrinsic.items():
            sanitized_key = self.intrinsic_property_resolver(key, parent_function=parent_function)
            sanitized_val = self.intrinsic_property_resolver(val, parent_function=parent_function)
            verify_intrinsic_type_str(sanitized_key,
                                      message="The keys of the dictionary {} in {} must all resolve to a string".format(
                                          sanitized_key, parent_function
                                      ))
            sanitized_dict[sanitized_key] = sanitized_val
        return sanitized_dict
コード例 #8
0
    def handle_fn_join(self, intrinsic_value, ignore_errors):
        """
        { "Fn::Join" : [ "delimiter", [ comma-delimited list of values ] ] }
        This function will join the items in the list together based on the string using the python join.

        This intrinsic function will resolve all the objects within the function's value and check their type.

        Parameter
        ----------
        intrinsic_value: list, dict
            This is the value of the object inside the Fn::Join intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value,
            ignore_errors,
            parent_function=IntrinsicResolver.FN_JOIN)

        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_JOIN)

        delimiter = arguments[0]

        verify_intrinsic_type_str(delimiter,
                                  IntrinsicResolver.FN_JOIN,
                                  position_in_list="first")

        value_list = self.intrinsic_property_resolver(
            arguments[1],
            ignore_errors,
            parent_function=IntrinsicResolver.FN_JOIN)

        verify_intrinsic_type_list(
            value_list,
            IntrinsicResolver.FN_JOIN,
            message="The list of values in {} after the "
            "delimiter must be a list".format(IntrinsicResolver.FN_JOIN),
        )

        sanitized_value_list = [
            self.intrinsic_property_resolver(
                item, ignore_errors, parent_function=IntrinsicResolver.FN_JOIN)
            for item in value_list
        ]
        verify_all_list_intrinsic_type(
            sanitized_value_list,
            verification_func=verify_intrinsic_type_str,
            property_type=IntrinsicResolver.FN_JOIN)

        return delimiter.join(sanitized_value_list)
コード例 #9
0
    def handle_fn_sub(self, intrinsic_value, ignore_errors):
        """
        { "Fn::Sub" : [ String, { Var1Name: Var1Value, Var2Name: Var2Value } ] } or { "Fn::Sub" : String }
        This intrinsic function will substitute the variables specified in the list into the string provided. The string
        will also parse out pseudo properties and anything of the form ${}.

        This intrinsic function will resolve all the objects within the function's value and check their type.
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::Join intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """

        def resolve_sub_attribute(intrinsic_item, symbol_resolver):
            if "." in intrinsic_item:
                (logical_id, attribute_type) = intrinsic_item.rsplit(".", 1)
            else:
                (logical_id, attribute_type) = intrinsic_item, IntrinsicResolver.REF
            return symbol_resolver.resolve_symbols(logical_id, attribute_type, ignore_errors=True)

        if isinstance(intrinsic_value, str):
            intrinsic_value = [intrinsic_value, {}]

        verify_intrinsic_type_list(
            intrinsic_value, IntrinsicResolver.FN_SUB, message="The arguments to a Fn::Sub must be a list or a string"
        )

        verify_number_arguments(intrinsic_value, IntrinsicResolver.FN_SUB, num=2)

        sub_str = self.intrinsic_property_resolver(
            intrinsic_value[0], ignore_errors, parent_function=IntrinsicResolver.FN_SUB
        )
        verify_intrinsic_type_str(sub_str, IntrinsicResolver.FN_SUB, position_in_list="first")

        variables = intrinsic_value[1]
        verify_intrinsic_type_dict(variables, IntrinsicResolver.FN_SUB, position_in_list="second")

        sanitized_variables = self.intrinsic_property_resolver(
            variables, ignore_errors, parent_function=IntrinsicResolver.FN_SUB
        )

        subable_props = re.findall(string=sub_str, pattern=IntrinsicResolver._REGEX_SUB_FUNCTION)
        for sub_item in subable_props:
            sanitized_item = sanitized_variables[sub_item] if sub_item in sanitized_variables else sub_item
            result = resolve_sub_attribute(sanitized_item, self._symbol_resolver)
            sub_str = re.sub(pattern=r"\$\{" + sub_item + r"\}", string=sub_str, repl=str(result))
        return sub_str
コード例 #10
0
    def handle_fn_not(self, intrinsic_value, ignore_errors):
        """
        {"Fn::Not": [{condition}]}
        This intrinsic function will negate the evaluation of the condition specified.

        This intrinsic function will resolve all the objects within the function's value and check their type.
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::Join intrinsic function property

        Return
        -------
        A boolean that is the opposite of the condition evaluated
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value,
            ignore_errors,
            parent_function=IntrinsicResolver.FN_NOT)
        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_NOT)
        verify_number_arguments(arguments, IntrinsicResolver.FN_NOT, num=1)
        argument_sanitised = self.intrinsic_property_resolver(
            arguments[0],
            ignore_errors,
            parent_function=IntrinsicResolver.FN_NOT)
        if isinstance(argument_sanitised,
                      dict) and "Condition" in arguments[0]:
            condition_name = argument_sanitised.get("Condition")
            verify_intrinsic_type_str(condition_name, IntrinsicResolver.FN_NOT)

            condition = self._conditions.get(condition_name)
            verify_non_null(condition,
                            IntrinsicResolver.FN_NOT,
                            position_in_list="first")

            argument_sanitised = self.intrinsic_property_resolver(
                condition,
                ignore_errors,
                parent_function=IntrinsicResolver.FN_NOT)

        verify_intrinsic_type_bool(
            argument_sanitised,
            IntrinsicResolver.FN_NOT,
            message="The result of {} must evaluate to bool".format(
                IntrinsicResolver.FN_NOT),
        )
        return not argument_sanitised
コード例 #11
0
    def handle_fn_base64(self, intrinsic_value, ignore_errors):
        """
        { "Fn::Base64" : valueToEncode }
        This intrinsic function will then base64 encode the string using python's base64.

        This function will resolve all the intrinsic properties in valueToEncode
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::Base64 intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        data = self.intrinsic_property_resolver(
            intrinsic_value, ignore_errors, parent_function=IntrinsicResolver.FN_BASE64
        )

        verify_intrinsic_type_str(data, IntrinsicResolver.FN_BASE64)
        # Encoding then decoding is required to return a string of the data
        return base64.b64encode(data.encode()).decode()
コード例 #12
0
    def handle_find_in_map(self, intrinsic_value, ignore_errors):
        """
        { "Fn::FindInMap" : [ "MapName", "TopLevelKey", "SecondLevelKey"] } This function will then lookup the
        specified dictionary in the Mappings dictionary as mappings[map_name][top_level_key][second_level_key].

        This intrinsic function will resolve all the objects within the function's value and check their type.

        The format of the Mappings dictionary is:
        "Mappings": {
            "map_name": {
                "top_level_key": {
                    "second_level_key": "value"
                    }
                }
            }
        }
        Parameter
        ----------
        intrinsic_value: list, dict
           This is the value of the object inside the Fn::FindInMap intrinsic function property

        Return
        -------
        A string with the resolved attributes
        """
        arguments = self.intrinsic_property_resolver(
            intrinsic_value,
            ignore_errors,
            parent_function=IntrinsicResolver.FN_FIND_IN_MAP)

        verify_intrinsic_type_list(arguments, IntrinsicResolver.FN_FIND_IN_MAP)

        verify_number_arguments(arguments,
                                num=3,
                                property_type=IntrinsicResolver.FN_FIND_IN_MAP)

        map_name = self.intrinsic_property_resolver(
            arguments[0],
            ignore_errors,
            parent_function=IntrinsicResolver.FN_FIND_IN_MAP)
        top_level_key = self.intrinsic_property_resolver(
            arguments[1],
            ignore_errors,
            parent_function=IntrinsicResolver.FN_FIND_IN_MAP)
        second_level_key = self.intrinsic_property_resolver(
            arguments[2],
            ignore_errors,
            parent_function=IntrinsicResolver.FN_FIND_IN_MAP)

        verify_intrinsic_type_str(map_name,
                                  IntrinsicResolver.FN_FIND_IN_MAP,
                                  position_in_list="first")
        verify_intrinsic_type_str(top_level_key,
                                  IntrinsicResolver.FN_FIND_IN_MAP,
                                  position_in_list="second")
        verify_intrinsic_type_str(second_level_key,
                                  IntrinsicResolver.FN_FIND_IN_MAP,
                                  position_in_list="third")

        map_value = self._mapping.get(map_name)
        verify_intrinsic_type_dict(
            map_value,
            IntrinsicResolver.FN_FIND_IN_MAP,
            position_in_list="first",
            message=
            "The MapName is missing in the Mappings dictionary in Fn::FindInMap  for {}"
            .format(map_name),
        )

        top_level_value = map_value.get(top_level_key)
        verify_intrinsic_type_dict(
            top_level_value,
            IntrinsicResolver.FN_FIND_IN_MAP,
            message=
            "The TopLevelKey is missing in the Mappings dictionary in Fn::FindInMap "
            "for {}".format(top_level_key),
        )

        second_level_value = top_level_value.get(second_level_key)
        verify_intrinsic_type_str(
            second_level_value,
            IntrinsicResolver.FN_FIND_IN_MAP,
            message=
            "The SecondLevelKey is missing in the Mappings dictionary in Fn::FindInMap  "
            "for {}".format(second_level_key),
        )

        return second_level_value