in cfn_policy_validator/parsers/utils/node_evaluator.py [0:0]
def eval(self, value: Any, resource_properties_to_eval=None, visited_values=None):
""" Evaluates the value of a CloudFormation key/value pair by evaluating intrinsic functions and pseudo
parameters in the template and returns the evaluated value.
value: the value of a key/value pair in a CloudFormation template
resource_properties_to_eval: only evaluate these properties for a resource. This limits the scope of intrinsic
function support to be only those functions that we'd expect to exist in an IAM policy
(e.g. Fn::GetAZs is not likely to appear)
visited_values: tracks visited values to detect circular references in a CloudFormation template
"""
visited_values = [] if visited_values is None else visited_values
if isinstance(value, list):
# when passing the list of visited values to child list items, we create a separate copy for each so
# that they don't share the same visited references
return [self.eval(item, copy.deepcopy(visited_values)) for item in value]
elif isinstance(value, CfnObject):
# intrinsic functions must be the only key, so we only need to look at the first key
first_key = next(iter(value), None)
evaluator = self.evaluators.get(first_key)
if evaluator is not None:
intrinsic_function_value = value.get(first_key)
return evaluator.evaluate(intrinsic_function_value, visited_values=visited_values)
# if it's not an intrinsic function, recursively traverse through child nodes
for key in value.keys():
# we only want to evaluate resource properties that we care about for IAM policies
# if we were to evaluate all resource properties, the scope of supported intrinsic functions and
# CFN parameters that would need to be passed would be larger. This will ignore properties that we
# don't care about.
if value.parent == 'Properties':
if resource_properties_to_eval is not None and \
key not in resource_properties_to_eval:
continue
# when passing the list of visited values to child evals, create a separate copy for each so
# that they don't share the same visited references
copy_of_visited_values = copy.deepcopy(visited_values)
value[key] = self.eval(value[key], resource_properties_to_eval, copy_of_visited_values)
return dict(value)
else:
return value