in cfn_policy_validator/parsers/utils/intrinsic_functions/fn_get_att_evaluator.py [0:0]
def evaluate(self, get_att_lookup, visited_values=None):
if visited_values is None:
visited_values = []
validate_fn_get_att_schema(get_att_lookup)
logical_name_of_resource = get_att_lookup[0]
attribute_name = get_att_lookup[1]
resource = self.resources.get(logical_name_of_resource)
if resource is None:
raise ApplicationError(f'Unable to find referenced resource for GetAtt reference to {logical_name_of_resource}.{attribute_name}')
resource_type = resource['Type']
properties = resource.get('Properties', {})
explicit_name_property = name_hints.get(resource_type)
explicit_resource_name = properties.get(explicit_name_property)
if explicit_resource_name is None:
# if an explicit name is not specified, default to the logical name
resource_name = logical_name_of_resource
else:
# we found a valid property value for the name of the resources. this property may reference another resource,
# so check to see if we've already done that and we're stuck in a cycle
validate_no_cycle(logical_name_of_resource, explicit_name_property, visited_values)
resource_name = self.node_evaluator.eval(explicit_resource_name, visited_values=visited_values)
arn = self.arn_generator.try_generate_arn(resource_name, resource, attribute_name, visited_values=visited_values)
if arn is not None:
return arn
# if the GetAtt does not reference an ARN, see if we have a custom evaluation for this get_att.
# Useful in cases where an attribute returns something other than an ARN that's relevant to
# IAM policies (canonical username)
custom_get_att_eval = self.custom_get_att_evals.get(resource['Type'], {}).get(attribute_name)
if custom_get_att_eval is not None:
return custom_get_att_eval(self.region)
# For calls to GetAtt that are not ARNs, try to find a property with the same name. This is a last resort and
# should probably not occur often. We expect to almost always see GetAtt used for ARNs in the context of an
# IAM policy
properties = resource.get('Properties', {})
property_value = properties.get(attribute_name)
if property_value is None:
raise ApplicationError(f'Call to GetAtt not supported for: {logical_name_of_resource}.{attribute_name}')
# we may need to traverse to another resource, so check to see if we've already done that and
# we're stuck in a cycle
validate_no_cycle(logical_name_of_resource, attribute_name, visited_values)
# there are many return types for GetAtt, so it's the caller's responsibility to validate expected type
return self.node_evaluator.eval(property_value, visited_values=visited_values)