Пример #1
0
    def to_statement(self, parameter_values):
        """
        With the given values for each parameter, this method will return a policy statement that can be used
        directly with IAM.

        :param dict parameter_values: Dict containing values for each parameter defined in the template
        :return dict: Dictionary containing policy statement
        :raises InvalidParameterValues: If parameter values is not a valid dictionary or does not contain values for all parameters
        :raises InsufficientParameterValues: If the parameter values don't have values for all required parameters
        """

        missing = self.missing_parameter_values(parameter_values)
        if len(missing) > 0:
            # str() of elements of list to prevent any `u` prefix from being displayed in user-facing error message
            raise InsufficientParameterValues("Following required parameters of template '{}' don't have values: {}"
                                              .format(self.name, [str(m) for m in missing]))

        # Select only necessary parameter_values. this is to prevent malicious or accidental
        # injection of values for parameters not intended in the template. This is important because "Ref" resolution
        # will substitute any references for which a value is provided.
        necessary_parameter_values = {name: value for name, value in parameter_values.items()
                                      if name in self.parameters}

        # Only "Ref" is supported
        supported_intrinsics = {
            RefAction.intrinsic_name: RefAction()
        }

        resolver = IntrinsicsResolver(necessary_parameter_values, supported_intrinsics)
        definition_copy = copy.deepcopy(self.definition)

        return resolver.resolve_parameter_refs(definition_copy)
Пример #2
0
    def to_statement(self, parameter_values):
        """
        With the given values for each parameter, this method will return a policy statement that can be used
        directly with IAM.

        :param dict parameter_values: Dict containing values for each parameter defined in the template
        :return dict: Dictionary containing policy statement
        :raises InvalidParameterValues: If parameter values is not a valid dictionary or does not contain values for all parameters
        :raises InsufficientParameterValues: If the parameter values don't have values for all required parameters
        """

        missing = self.missing_parameter_values(parameter_values)
        if len(missing) > 0:
            # str() of elements of list to prevent any `u` prefix from being displayed in user-facing error message
            raise InsufficientParameterValues(
                "Following required parameters of template '{}' don't have values: {}"
                .format(self.name, [str(m) for m in missing]))

        # Select only necessary parameter_values. this is to prevent malicious or accidental
        # injection of values for parameters not intended in the template. This is important because "Ref" resolution
        # will substitute any references for which a value is provided.
        necessary_parameter_values = {
            name: value
            for name, value in parameter_values.items()
            if name in self.parameters
        }

        # Only "Ref" is supported
        supported_intrinsics = {RefAction.intrinsic_name: RefAction()}

        resolver = IntrinsicsResolver(necessary_parameter_values,
                                      supported_intrinsics)
        definition_copy = copy.deepcopy(self.definition)

        return resolver.resolve_parameter_refs(definition_copy)
    def test_short_circuit_on_empty_parameters(self):
        resolver = IntrinsicsResolver({})
        resolver._try_resolve_parameter_refs = Mock()  # Mock other methods to detect any actual calls
        input = {"Ref": "foo"}
        expected = {"Ref": "foo"}

        self.assertEqual(resolver.resolve_parameter_refs(input), expected)
        resolver._try_resolve_parameter_refs.assert_not_called()
    def test_short_circuit_on_empty_parameters(self):
        resolver = IntrinsicsResolver({})
        resolver._try_resolve_parameter_refs = Mock()  # Mock other methods to detect any actual calls
        input = {"Ref": "foo"}
        expected = {"Ref": "foo"}

        self.assertEqual(resolver.resolve_parameter_refs(input), expected)
        resolver._try_resolve_parameter_refs.assert_not_called()
class TestParameterReferenceResolution(TestCase):
    def setUp(self):
        self.parameter_values = {
            "param1": "value1",
            "param2": "value2",
            "param3": "value3"
        }

        self.resolver = IntrinsicsResolver(self.parameter_values)

    def test_must_resolve_top_level_direct_refs(self):
        input = {
            "key1": {
                "Ref": "param1"
            },
            "key2": {
                "Ref": "param2"
            },
            "key3": {
                "a": "b"
            }
        }

        expected = {
            "key1": self.parameter_values["param1"],
            "key2": self.parameter_values["param2"],
            "key3": {
                "a": "b"
            },
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_nested_refs(self):
        input = {
            "key1": {
                "sub1": {
                    "sub2": {
                        "sub3": {
                            "Ref": "param1"
                        },
                        "list": [1, "b", {
                            "Ref": "param2"
                        }]
                    }
                }
            }
        }

        expected = {
            "key1": {
                "sub1": {
                    "sub2": {
                        "sub3": self.parameter_values["param1"],
                        "list": [1, "b", self.parameter_values["param2"]]
                    }
                }
            }
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_direct_refs(self):
        input = {"Ref": "param1"}
        expected = self.parameter_values["param1"]

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_array_refs(self):
        input = ["foo", 1, 2, {"Ref": "param1"}]
        expected = ["foo", 1, 2, self.parameter_values["param1"]]

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_skip_unknown_refs(self):
        input = {"key1": {"Ref": "someresource"}, "key2": {"Ref": "param1"}}

        expected = {
            "key1": {
                "Ref": "someresource"
            },
            "key2": self.parameter_values["param1"]
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_inside_sub_strings(self):
        input = {
            "Fn::Sub": "prefix ${param1} ${param2} ${param3} ${param1} suffix"
        }

        expected = {"Fn::Sub": "prefix value1 value2 value3 value1 suffix"}

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_skip_over_sub_literals(self):
        input = {"Fn::Sub": "prefix ${!MustNotBeReplaced} suffix"}

        expected = {"Fn::Sub": "prefix ${!MustNotBeReplaced} suffix"}

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_refs_inside_other_intrinsics(self):
        input = {
            "key1": {
                "Fn::Join": ["-", [{
                    "Ref": "param1"
                }, "some other value"]]
            }
        }

        expected = {
            "key1": {
                "Fn::Join":
                ["-", [self.parameter_values["param1"], "some other value"]]
            }
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_skip_invalid_values_for_ref(self):
        input = {"Ref": ["ref cannot have list value"]}

        expected = {"Ref": ["ref cannot have list value"]}
        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_skip_invalid_values_for_sub(self):
        input = {
            # Invalid Sub resource, must never be parsed, and must not error out
            "Fn::Sub": [{
                "a": "b"
            }]
        }

        expected = {"Fn::Sub": [{"a": "b"}]}

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_throw_on_empty_parameters(self):
        with self.assertRaises(TypeError):
            IntrinsicsResolver(None).resolve_parameter_refs({})

    def test_throw_on_non_dict_parameters(self):
        with self.assertRaises(TypeError):
            IntrinsicsResolver([1, 2, 3]).resolve_parameter_refs({})

    def test_short_circuit_on_empty_parameters(self):
        resolver = IntrinsicsResolver({})
        resolver._try_resolve_parameter_refs = Mock(
        )  # Mock other methods to detect any actual calls
        input = {"Ref": "foo"}
        expected = {"Ref": "foo"}

        self.assertEqual(resolver.resolve_parameter_refs(input), expected)
        resolver._try_resolve_parameter_refs.assert_not_called()
class TestParameterReferenceResolution(TestCase):

    def setUp(self):
        self.parameter_values = {
            "param1": "value1",
            "param2": "value2",
            "param3": "value3"
        }

        self.resolver = IntrinsicsResolver(self.parameter_values)

    def test_must_resolve_top_level_direct_refs(self):
        input = {
            "key1": {
                "Ref": "param1"
            },
            "key2": {
                "Ref": "param2"
            },
            "key3": {
                "a": "b"
            }
        }

        expected = {
            "key1": self.parameter_values["param1"],
            "key2": self.parameter_values["param2"],
            "key3": {
                "a": "b"
            }
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_nested_refs(self):
        input = {
            "key1": {
                "sub1": {
                    "sub2": {
                        "sub3": {
                            "Ref": "param1"
                        },
                        "list": [1, "b", {"Ref": "param2"}]
                    }
                }
            }
        }

        expected = {
            "key1": {
                "sub1": {
                    "sub2": {
                        "sub3": self.parameter_values["param1"],
                        "list": [1, "b", self.parameter_values["param2"]]
                    }
                }
            }
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_direct_refs(self):
        input = {"Ref": "param1"}
        expected = self.parameter_values["param1"]

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_array_refs(self):
        input = ["foo", 1, 2, {"Ref": "param1"}]
        expected = ["foo", 1, 2, self.parameter_values["param1"]]

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_skip_unknown_refs(self):
        input = {
            "key1": {
                "Ref": "someresource"
            },
            "key2": {
                "Ref": "param1"
            }
        }

        expected = {
            "key1": {
                "Ref": "someresource"
            },
            "key2": self.parameter_values["param1"]
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_inside_sub_strings(self):
        input = {
            "Fn::Sub": "prefix ${param1} ${param2} ${param3} ${param1} suffix"
        }

        expected = {
            "Fn::Sub": "prefix value1 value2 value3 value1 suffix"
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_skip_over_sub_literals(self):
        input = {
            "Fn::Sub": "prefix ${!MustNotBeReplaced} suffix"
        }

        expected = {
            "Fn::Sub": "prefix ${!MustNotBeReplaced} suffix"
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_must_resolve_refs_inside_other_intrinsics(self):
        input = {
            "key1": {
                "Fn::Join": ["-", [{"Ref": "param1"}, "some other value"]]
            }
        }

        expected = {
            "key1": {
                "Fn::Join": ["-", [self.parameter_values["param1"], "some other value"]]
            }
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_skip_invalid_values_for_ref(self):
        input = {
            "Ref": ["ref cannot have list value"]
        }

        expected = {
            "Ref": ["ref cannot have list value"]
        }
        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_skip_invalid_values_for_sub(self):
        input = {
            # Invalid Sub resource, must never be parsed, and must not error out
            "Fn::Sub": [{"a": "b"}]
        }

        expected = {
            "Fn::Sub": [{"a": "b"}]
        }

        output = self.resolver.resolve_parameter_refs(input)
        self.assertEqual(output, expected)

    def test_throw_on_empty_parameters(self):
        with self.assertRaises(TypeError):
            IntrinsicsResolver(None).resolve_parameter_refs({})

    def test_throw_on_non_dict_parameters(self):
        with self.assertRaises(TypeError):
            IntrinsicsResolver([1,2,3]).resolve_parameter_refs({})

    def test_short_circuit_on_empty_parameters(self):
        resolver = IntrinsicsResolver({})
        resolver._try_resolve_parameter_refs = Mock()  # Mock other methods to detect any actual calls
        input = {"Ref": "foo"}
        expected = {"Ref": "foo"}

        self.assertEqual(resolver.resolve_parameter_refs(input), expected)
        resolver._try_resolve_parameter_refs.assert_not_called()