in cfn_policy_validator/parsers/resource/lambda_aws.py [0:0]
def parse(self, _, resource):
evaluated_resource = resource.eval(lambda_permission_schema)
properties = evaluated_resource['Properties']
action = properties['Action']
function_name = properties['FunctionName']
principal_name = properties['Principal']
source_account = properties.get('SourceAccount')
source_arn = properties.get('SourceArn')
policy_statement = {
'Effect': 'Allow',
'Action': action
}
if 'amazonaws' in principal_name:
# this is a permission to a service
policy_statement['Principal'] = {'Service': principal_name}
else:
# otherwise this is a permission to an account
policy_statement['Principal'] = {'AWS': principal_name}
# function name can be a full ARN, a partial ARN (a full suffix of an ARN) or the actual function name
if function_name.startswith('arn:'): # full ARN
policy_statement['Resource'] = function_name
elif 'function:' in function_name: # partial ARN
# partial arn must include at least function: and ":" is not a valid function name character
arn_parts = function_name.split(":")
# grab all parts of the partial ARN up until "function:"
parts_before_function = list(itertools.takewhile(lambda part: part.lower() != 'function', arn_parts))
# a list of a valid ARN before "function:"
valid_arn_parts_before_function = ["arn", self.partition, "lambda", self.region, self.account_id]
# construct the base_arn based on what's missing in the partial ARN
number_of_missing_arn_parts = len(valid_arn_parts_before_function) - len(parts_before_function)
base_arn = ":".join(valid_arn_parts_before_function[:number_of_missing_arn_parts])
policy_statement['Resource'] = f'{base_arn}:{function_name}'
else: # just the function name
policy_statement['Resource'] = f'arn:{self.partition}:lambda:{self.region}:{self.account_id}:function:{function_name}'
if source_account is not None:
policy_statement['Condition'] = {'StringEquals': {'AWS:SourceAccount': source_account}}
if source_arn is not None:
condition = policy_statement.get('Condition', {})
condition['ArnLike'] = {'AWS:SourceArn': source_arn}
policy_statement['Condition'] = condition
# The permissions policies dictionary holds the statements per lambda function. The statements are built
# into an actual policy when they are retrieved.
function_arn = policy_statement['Resource']
statements = self.permissions_policies[function_arn]
statements.append(policy_statement)