def expand_role()

in aws/services/CloudFormation/MacrosExamples/ExecutionRoleBuilder/lambda/index.py [0:0]


def expand_role(rolefragment):
    # Debug output
    print ('This is the role fragment: {}'.format(rolefragment))
    
    # Extract shorthand properties for role type, name, and desired permissions
    roletype = rolefragment['Properties']['Type']
    rolename = rolefragment['Properties']['Name']
    permissions = rolefragment['Properties']['Permissions']
 
    # Get the basic role template (from policytemplates.py) and do a simple string
    # replace to set the name and the AWS service principal for the trust policy (e.g. lambda)
    returnval = roletemplate.replace('<ROLETYPE>',roletype.lower())
    returnval = returnval.replace('<ROLENAME>',rolename)
    # Load this as json to form the initial basis of the function return value
    returnvaljson = json.loads(returnval)

    # If the shorthand notation included a list of managed policy ARNs pass those though as-is
    if 'ManagedPolicyArns' in rolefragment['Properties']:
        returnvaljson['Properties']['ManagedPolicyArns'] = rolefragment['Properties']['ManagedPolicyArns']

    # If the shorthand notation included a permission boundary pass that through as-is
    if 'PermissionsBoundary' in rolefragment['Properties']:
        returnvaljson['Properties']['PermissionsBoundary'] = rolefragment['Properties']['PermissionsBoundary']

    # If the shorthand notation included a role path pass that through as-is
    # If it did not, provide an opinionated configuration using the variable above
    if 'Path' in rolefragment['Properties']:
        returnvaljson['Properties']['Path'] = rolefragment['Properties']['Path']
    else:
        returnvaljson['Properties']['Path'] = defaultrolepath

    # Loop through each of the short hand permissions
    for permission in permissions:
        # Debug output
        print ('permission: {}'.format(permission))
        # Split each shorthand permission into an action group (e.g. ReadOnly) and the associated Resource
        for actiongroup,resource in permission.items():
            print ('actiongroup: {}, resource: {}'.format(actiongroup,resource))
            # Use the function below to extract the service (e.g. S3) from the resource ARN
            service = servicefromresource(resource)
            print ('service: {}'.format(service))
            # Lookup the given policy snippet from policytemplates.py based on the service & action group
            # If the necessary snippet isn't included in policytemplates.py err out
            if service in policytemplates and actiongroup in policytemplates[service]:
                policytemplate = policytemplates[service][actiongroup]
            else:
                # TODO: Better error handling
                raise Exception('No policy template found for service: {} and actiongroup: {}'.format(service,actiongroup))
            # Substitute the placeholder in the template for the actual resource 
            policytemplate = policytemplate.replace('<RESOURCE>',resource)
            # Policy names must be unique, appending a UUID is a simple way to guarantee that
            uuidval = str(uuid.uuid4())
            policytemplate = policytemplate.replace('<UUID>', uuidval)
            # Convert the policy snippet to json and add it as an inline policy to the overall return values
            policytemplatejson = json.loads(policytemplate)
            print ('adding policy: {}'.format(policytemplate))
            returnvaljson['Properties']['Policies'].append(policytemplatejson)
      
    # In addition to the permissions in the shorthand notation add the 'allroles' policy template
    # This template is used to provide permissions like CloudWatchLogs instead of forcing each
    # developer to repeatedly specify common permissions
    uuidval = str(uuid.uuid4())
    allrolespolicytemplate = policytemplates['allroles']['default']
    allrolespolicytemplate = allrolespolicytemplate.replace('<UUID>', uuidval)
    allrolespolicytemplatejson = json.loads(allrolespolicytemplate)
    print ('adding policy: {}'.format(allrolespolicytemplate))
    returnvaljson['Properties']['Policies'].append(allrolespolicytemplatejson)
  
    # Return the expanded proper CloudFormation 
    return returnvaljson