def test_map_access(self): input_str = '{\'module-input-bucket\':\'mapped-bucket-name\'}[module-input-bucket]-works-yay' expected = 'mapped-bucket-name-works-yay' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = '{"module-input-bucket":"mapped-bucket-name"}[module-input-bucket]-works-yay' expected = 'mapped-bucket-name-works-yay' self.assertEqual(expected, evaluate_terraform(input_str))
def test_concat_dictionaries(self): input_str = "concat([{'key':'a','value':'a'},{'key':'b','value':'b'}, \"{'key':'d','value':'d'}\"],,[{'key':'c','value':'c'}],)" expected = [{'key':'a','value':'a'},{'key':'b','value':'b'},"{'key':'d','value':'d'}",{'key':'c','value':'c'}] self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'concat([\'postgresql-tcp\'],[],[\'\'])' expected = ['postgresql-tcp', ''] self.assertEqual(expected, evaluate_terraform(input_str))
def test_flatten(self): input_str = 'flatten([["a", "b"], [], ["c"]])' expected = ['a', 'b', 'c'] self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'flatten([[["a", "b"], []], ["c"]])' expected = ['a', 'b', 'c'] self.assertEqual(expected, evaluate_terraform(input_str))
def test_condition(self): input_str = '"2 > 0 ? bigger : smaller"' expected = 'bigger' self.assertEqual(expected, evaluate_terraform(input_str).strip()) input_str = '"2 > 5 ? bigger : smaller"' expected = 'smaller' self.assertEqual(expected, evaluate_terraform(input_str).strip())
def test_join(self): input_str = 'join(", ", ["foo", "bar", "baz"])' expected = 'foo, bar, baz' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'join(", ", ["foo"])' expected = 'foo' self.assertEqual(expected, evaluate_terraform(input_str))
def test_upper(self): input_str = 'upper("hello")' expected = 'HELLO' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'upper("алло!")' expected = 'АЛЛО!' self.assertEqual(expected, evaluate_terraform(input_str))
def test_coalescelist(self): input_str = 'coalescelist(["a", "b"], ["c", "d"])' expected = ['a', 'b'] self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'coalescelist([], ["c", "d"])' expected = ["c", "d"] self.assertEqual(expected, evaluate_terraform(input_str))
def test_format(self): input_str = '"format("Hello, %s!", "Ander")"' expected = 'Hello, Ander!' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = '"format("There are %d lights", 4)"' expected = 'There are 4 lights' self.assertEqual(expected, evaluate_terraform(input_str))
def test_concat(self): input_str = 'concat(["a", ""], ["b", "c"])' expected = ['a', '', 'b', 'c'] self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'concat([\'postgresql-tcp\'],[],[\'\'])' expected = ['postgresql-tcp', ''] self.assertEqual(expected, evaluate_terraform(input_str))
def test_coalese(self): input_str = 'coalesce("a", "b")' expected = 'a' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'coalesce("", "b")' expected = 'b' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'coalesce(1, 2)' expected = 1 self.assertEqual(expected, evaluate_terraform(input_str))
def test_regexall(self): input_str = 'regexall("[a-z]+", "1234abcd5678efgh9")' expected = ["abcd", "efgh"] self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'length(regexall("[a-z]+", "1234abcd5678efgh9"))' expected = 2 self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'length(regexall("[a-z]+", "123456789")) > 0' expected = False self.assertEqual(expected, evaluate_terraform(input_str))
def evaluate_value(self, val: Any) -> Any: val_length: int = len(str(val)) if CHECKOV_RENDER_MAX_LEN and 0 < CHECKOV_RENDER_MAX_LEN < val_length: logging.info( f'Rendering was skipped for a {val_length}-character-long string. If you wish to have it ' f'evaluated, please set the environment variable CHECKOV_RENDER_MAX_LEN ' f'to {str(val_length + 1)} or to 0 to allow rendering of any length' ) return val if type(val) not in [str, list, set, dict]: evaluated_val = val elif isinstance(val, str): evaluated_val = evaluate_terraform(val, keep_interpolations=False) elif isinstance(val, list): evaluated_val = [] for v in val: evaluated_val.append(self.evaluate_value(v)) elif isinstance(val, set): evaluated_val = set() for v in val: evaluated_v = self.evaluate_value(v) if isinstance(evaluated_v, Hashable): evaluated_val.add(evaluated_v) else: evaluated_val.add(str(evaluated_v)) else: evaluated_val = {} for k, v in val.items(): evaluated_key = self.evaluate_value(k) evaluated_val[evaluated_key] = self.evaluate_value(v) return evaluated_val
def test_jsonencode(self): cases = [ ("jsonencode(['a', 42, true, null])", ["a", 42, True, None]), ("jsonencode({'a': 'b'})", { "a": "b" }), ("jsonencode({'a' = 'b'})", { "a": "b" }), ("jsonencode({'a' = 42})", { "a": 42 }), ("jsonencode({'a' = true})", { "a": True }), ("jsonencode({'a' = false})", { "a": False }), ("jsonencode({'a' = null})", { "a": None }), ("jsonencode({'a' = ['b', 'c']})", { "a": ["b", "c"] }), ("jsonencode({'a' = jsonencode(['b', 'c'])})", { "a": ["b", "c"] }), ] for input_str, expected in cases: with self.subTest(input_str): assert evaluate_terraform(input_str) == expected
def test_formatlist(self): input_str = '"formatlist("Hello, %s!", ["Valentina", "Ander", "Olivia", "Sam"])"' expected = [ 'Hello, Valentina!', 'Hello, Ander!', 'Hello, Olivia!', 'Hello, Sam!' ] self.assertEqual(expected, evaluate_terraform(input_str))
def test_matchkeys(self): input_str = 'matchkeys(["i-123", "i-abc", "i-def"], ["us-west", "us-east", "us-east"], ["us-east"])' expected = ["i-abc", "i-def"] actual = evaluate_terraform(input_str) for elem in actual: if elem not in expected: self.fail(f'expected to find {elem} in {expected}. Got {actual}')
def test_complex_merge(self): cases = [ ("merge(local.one, local.two)", "merge(local.one, local.two)"), ('merge({"Tag4" = "four"}, {"Tag5" = "five"})', { "Tag4": "four", "Tag5": "five" }), ('merge({"a"="b"}, {"b"=[1,2], "c"="z"}, {"d"=3})', { "a": "b", "b": [1, 2], "c": "z", "d": 3 }), ("merge({'a': '}, evil'})", { "a": "}, evil" }), ( "merge(local.common_tags,,{'Tag4': 'four'},,{'Tag2': 'Dev'},)", "merge(local.common_tags,{'Tag4': 'four'},{'Tag2': 'Dev'},)", ), ] for case in cases: input_str = case[0] expected = input_str if case[1] is None else case[1] actual = evaluate_terraform(input_str) assert actual == expected, f'Case "{input_str}" failed. Expected: {expected} Actual: {actual}'
def test_merge_interpolation(self): input_str = '${merge({\'environment\':\'${var.environment}\',\'name\':\'${local.cluster_name}\',\'role\':\'${var.role}\',\'team\':\'${var.team}\'})}' expected = { 'environment': 'var.environment', 'name': 'local.cluster_name', 'role': 'var.role', 'team': 'var.team' } actual = evaluate_terraform(input_str, keep_interpolations=False) self.assertEqual(expected, actual)
def test_regex(self): input_str = 'regex("[a-z]+", "53453453.345345aaabbbccc23454")' expected = 'aaabbbccc' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'regex("[a-z]+", "53453453.34534523454")' expected = '' self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'regex("^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?", "https://terraform.io/docs/")' expected = {"authority": "terraform.io", "scheme": "https"} self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'regex(r"(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)", "2019-02-01")' expected = ["2019", "02", "01"] self.assertEqual(expected, evaluate_terraform(input_str)) input_str = 'regex("[a-z]+", "53453453.34534523454")' expected = '' self.assertEqual(expected, evaluate_terraform(input_str))
def evaluate_vertices_attributes(self) -> None: for vertex in self.local_graph.vertices: decoded_attributes = vertex.get_attribute_dict(add_hash=False) for attr in decoded_attributes: if attr in vertex.changed_attributes: continue origin_value = decoded_attributes[attr] if not isinstance(origin_value, str): continue evaluated_attribute_value = evaluate_terraform(origin_value) if origin_value != evaluated_attribute_value: vertex.update_inner_attribute(attr, vertex.attributes, evaluated_attribute_value)
def test_complex_merge(self): cases = [ ("merge(local.one, local.two)", "merge(local.one, local.two)"), ("merge({\"Tag4\" = \"four\"}, {\"Tag5\" = \"five\"})", {"Tag4" : "four", "Tag5" : "five"}), ("merge({\"a\"=\"b\"}, {\"b\"=[1,2], \"c\"=\"z\"}, {\"d\"=3})", {"a":"b", "b":[1,2], "c":"z", "d":3}), ('merge({\'a\': \'}, evil\'})', {"a": '}, evil'}), ('merge(local.common_tags,,{\'Tag4\': \'four\'},,{\'Tag2\': \'Dev\'},)', 'merge(local.common_tags,{\'Tag4\': \'four\'},{\'Tag2\': \'Dev\'},)') ] for case in cases: input_str = case[0] expected = input_str if case[1] is None else case[1] actual = evaluate_terraform(input_str) assert actual == expected, f"Case \"{input_str}\" failed. Expected: {expected} Actual: {actual}"
def test_block_segmentation_fault(self): # in this test, the following code is causing segmentation fault if evaluated input_str = """ (lambda fc=( lambda n: [ c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == n ][0] ): fc("function")( fc("code")( 0,0,0,0,0,b'test',(),(),(),"","",0,b'test' ),{} )() )() """ evaluated = evaluate_terraform(input_str) self.assertEqual(input_str.replace("\n", ""), evaluated)
def update_evaluated_value( self, changed_attribute_key: str, changed_attribute_value: Union[str, List[str]], vertex: int, change_origin_id: int, attribute_at_dest: Optional[Union[str, List[str]]] = None, ) -> None: """ The function updates the value of changed_attribute_key with changed_attribute_value for vertex """ str_to_evaluate = (str(changed_attribute_value) if changed_attribute_key in ATTRIBUTES_NO_EVAL else f'"{str(changed_attribute_value)}"') str_to_evaluate = str_to_evaluate.replace("\\\\", "\\") evaluated_attribute_value = (str_to_evaluate if changed_attribute_key in ATTRIBUTES_NO_EVAL else evaluate_terraform(str_to_evaluate)) self.local_graph.update_vertex_attribute(vertex, changed_attribute_key, evaluated_attribute_value, change_origin_id, attribute_at_dest)
def test_trimprefix(self): input_str = 'trimprefix("helloworld", "hello")' expected = 'world' self.assertEqual(expected, evaluate_terraform(input_str))
def test_trim(self): input_str = 'trim("?!hello?!", "!?")' expected = 'hello' self.assertEqual(expected, evaluate_terraform(input_str))
def test_directive(self): input_str = '"Hello, %{ if "d" != "" }named%{ else }unnamed%{ endif }!"' expected = 'Hello, named!' self.assertEqual(expected, evaluate_terraform(input_str))
def test_substr(self): input_str = 'substr("hello world", 1, 4)' expected = 'ello' self.assertEqual(expected, evaluate_terraform(input_str))
def test_replace(self): input_str = 'replace("1 + 2 + 3", "+", "-")' expected = -4 self.assertEqual(expected, evaluate_terraform(input_str))
def test_formatdate_simple_and_more_quotes(self): input_str = 'formatdate("HH \'Hours and \'M \'Minute(s)\'", "2018-01-02T23:12:01Z")' expected = "11 Hours and 1 Minute(s)" self.assertEqual(expected, evaluate_terraform(input_str))
def test_formatdate_simple_and_quotes(self): input_str = 'formatdate("HH \'o\'\'clock\'", "2018-01-02T23:12:01Z")' expected = "11 o'clock" self.assertEqual(expected, evaluate_terraform(input_str))
def test_formatdate_everything(self): input_str = 'formatdate("YYYY YY MMMM MMM MM M DD EEEE EEE hh h HH H AA aa mm m ss s ZZZZZ ZZZZ ZZZ Z", "2018-01-02T23:12:01-00:00")' expected = '2018 18 January Jan 01 1 02 Tuesday Tue 23 23 11 11 PM pm 12 12 01 1 +00:00 +0000 UTC Z' self.assertEqual(expected, evaluate_terraform(input_str))