Example #1
0
def handler(event, context):
    """Entry point for the Custom::ResourceGroupConfiguration resource handler."""

    props = properties.load(
        event, {
            'ConfigurationBucket': properties.String(),
            'ConfigurationKey': properties.String(),
            'ResourceGroupName': properties.String()
        })

    data = {
        'ConfigurationBucket':
        props.ConfigurationBucket,
        'ConfigurationKey':
        '{}/resource-group/{}'.format(props.ConfigurationKey,
                                      props.ResourceGroupName),
        'TemplateURL':
        'https://s3.amazonaws.com/{}/{}/resource-group/{}/{}'.format(
            props.ConfigurationBucket, props.ConfigurationKey,
            props.ResourceGroupName, constant.RESOURCE_GROUP_TEMPLATE_FILENAME)
    }

    physical_resource_id = 'CloudCanvas:LambdaConfiguration:{stack_name}:{resource_group_name}'.format(
        stack_name=aws_utils.get_stack_name_from_stack_arn(event['StackId']),
        resource_group_name=props.ResourceGroupName)

    return custom_resource_response.success_response(data,
                                                     physical_resource_id)
def handler(event, context):
    request_type = event['RequestType']
    stack_arn = event['StackId']
    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(stack_arn) + '-' + event['LogicalResourceId']
    data = {}
    stack_manager = stack_info.StackInfoManager()
    stack = stack_manager.get_stack_info(stack_arn)

    if request_type == 'Delete':
        _clear_interface_refs(stack)
        return custom_resource_response.success_response(data, physical_resource_id)

    if not stack.is_deployment_stack:
        raise RuntimeError("InterfaceDependecyResolver can only be stood up on a deployment stack")

    resource_groups = stack.resource_groups

    configuration_bucket_name = stack.project.configuration_bucket
    if not configuration_bucket_name:
        raise RuntimeError('Not adding service settings because there is no project configuration bucket.')
    service_directory = ServiceDirectory(configuration_bucket_name)


    interface_deps = event["ResourceProperties"].get("InterfaceDependencies", {})
    _clear_interface_refs(stack)
    for gem, interface_list in interface_deps.iteritems():
        for interface in interface_list:
            print "getting url for interface {} from gem {} to use in {}:{}".format(interface["id"], interface["gem"], gem, interface["function"])
            interfaces = service_directory.get_interface_services(stack.deployment_name, interface["id"])
            if len(interfaces) > 0:
                _add_url_to_lambda(interfaces[0], gem, interface["function"], stack)
            else:
                print "Failed to lookup interface {}".format(len(interfaces))

    return custom_resource_response.success_response(data, physical_resource_id)
def handler(event, context):
    '''Entry point for the Custom::AccessControl resource handler.'''

    # Validate RequestType
    request_type = event['RequestType']
    if request_type not in ['Create', 'Update', 'Delete']:
        raise RuntimeError('Unexpected request type: {}'.format(request_type))

    # Get stack_info for the AccessControl resource's stack.
    stack_arn = event['StackId']
    stack_manager = stack_info.StackInfoManager()
    stack = stack_manager.get_stack_info(stack_arn)

    # Physical ID is always the same.
    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(
        stack_arn) + '-' + event['LogicalResourceId']

    # The AccessControl resource has no output values.
    data = {}

    # Accumlate problems encountered so we can give a full report.
    problems = ProblemList()

    # Apply access control as determined by the Cloud Canvas stack type.
    if stack.stack_type == stack.STACK_TYPE_RESOURCE_GROUP:
        were_changes = _apply_resource_group_access_control(
            request_type, stack, problems)
    elif stack.stack_type == stack.STACK_TYPE_DEPLOYMENT_ACCESS:
        were_changes = _apply_deployment_access_control(
            request_type, stack, event['ResourceProperties']['Gem'], problems)
    elif stack.stack_type == stack.STACK_TYPE_PROJECT:
        were_changes = _apply_project_access_control(request_type, stack,
                                                     problems)
    else:
        raise RuntimeError(
            'The Custom::AccessControl resource can only be used in resource group, deployment access, or project stack templates.'
        )

    # If there were any problems, provide an error message with all the details.
    if problems:
        raise RuntimeError(
            'Found invalid AccessControl metadata:\n    {}'.format(problems))

    # If there were changes, wait a few seconds for them to propagate
    if were_changes:
        print 'Delaying {} seconds for change propagation'.format(
            PROPAGATION_DELAY_SECONDS)
        time.sleep(PROPAGATION_DELAY_SECONDS)

    # Successful execution.
    return custom_resource_response.success_response(data,
                                                     physical_resource_id)
Example #4
0
def handler(event, context):

    props = properties.load(event, {
        'Input': properties.Dictionary(),
    })

    stack_name = aws_utils.get_stack_name_from_stack_arn(event['StackId'])
    physical_resource_id = stack_name + '-' + event['LogicalResourceId']

    output = _process_dict(props.Input)

    return custom_resource_response.success_response(output,
                                                     physical_resource_id)
def handler(event, context):
    request_type = event['RequestType']
    stack_arn = event['StackId']
    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(stack_arn) + '-' + event['LogicalResourceId']
    data = {}
    stack_manager = stack_info.StackInfoManager()
    stack = stack_manager.get_stack_info(stack_arn)

    if request_type == 'Delete':
        _clear_interface_refs(stack)
        return custom_resource_response.success_response(data, physical_resource_id)

    if not stack.is_deployment_stack:
        raise RuntimeError("InterfaceDependencyResolver can only be stood up on a deployment stack")

    configuration_bucket_name = stack.project.configuration_bucket
    if not configuration_bucket_name:
        raise RuntimeError('Not adding service settings because there is no project configuration bucket.')
    service_directory = ServiceDirectory(configuration_bucket_name)

    interface_deps = event["ResourceProperties"].get("InterfaceDependencies", {})
    # start by clearing the refs this function and role have to make sure no old permissions/interfaces linger
    _clear_interface_refs(stack)

    for gem, interface_list in iteritems(interface_deps):
        gem_function_info = {}
        for interface in interface_list:
            if not interface['function'] in gem_function_info:
                gem_function_info[interface['function']] = {"interfaces": []}
            interface_function_info = {"id": interface['id'], "gem": interface.get("gem", "CloudGemFramework")}
            if interface_function_info["gem"] == "CloudGemFramework":
                interface_function_info["url"] = _get_project_url(
                    service_directory, interface['id'])
                interface_function_info["permittedArns"] = _get_permitted_arns(
                    _get_resource_group(gem, stack),
                    _get_project_interface_description(
                        service_directory, interface["id"])
                )
            else:
                interface_function_info["url"] = _get_url(
                    service_directory, stack, interface['id'])
                interface_function_info["permittedArns"] = _get_permitted_arns(
                    _get_resource_group(gem, stack),
                    _get_interface_description(service_directory, stack, interface["id"])
                )
            gem_function_info[interface['function']]["interfaces"].append(
                interface_function_info)

        _put_gem_function_info(gem, gem_function_info, stack)

    return custom_resource_response.success_response(data, physical_resource_id)
Example #6
0
def handler(event, context):
    
    # This resource does nothing. It exists so that deployment stacks can be created
    # before any resource groups have been defined. In such cases the Resources list 
    # would be empty, which CloudFormation doesn't allow, so the lmbr_aws client inserts
    # this resource into the deployment template when no other resources are defined
    # by the template.

    props = properties.load(event, {})

    data = {}

    physical_resource_id = 'CloudCanvas:EmptyDeployment:{}'.format(aws_utils.get_stack_name_from_stack_arn(event['StackId']))

    return custom_resource_response.success_response(data, physical_resource_id)
Example #7
0
 def __init__(self, stack_arn, source_resource_name, resource_type_name,
              data):
     self.__stack_arn = stack_arn
     self.__stack_name = aws_utils.get_stack_name_from_stack_arn(stack_arn)
     self.__source_resource_name = source_resource_name
     self.__resource_type_name = resource_type_name
     self.__permission_metadata = data.get('PermissionMetadata', {})
     self.__service_api = data.get('ServiceApi', None)
     self.__arn_format = data.get('ArnFormat', None)
     self.__arn_url = data.get('ArnUrl', None)
     self.__display_info = data.get('DisplayInfo', None)
     self.__handler_url = data.get('HandlerUrl', None)
     self.__arn_function = data.get('ArnFunction', None)
     self.__handler_function = data.get('HandlerFunction', None)
     self._validate()
Example #8
0
def get_access_control_role_name(stack_arn, logical_role_name):
    """Generates a role name based on a stack name and a logical role name.

    Args:
        stack_arn - The arn of the stack.

        logical_role_name: Appended to the stack name to construct the actual role name.

    """

    # Expecting stack names like: {project-name}-{deployment-name}-{resource-group-name}-{random-stuff}.
    # In practice role names are truncated to the max allowable length.

    stack_name = aws_utils.get_stack_name_from_stack_arn(stack_arn)
    role_name = sanitize_role_name(stack_name + '-' + logical_role_name)

    return role_name
Example #9
0
def handler(event, context):
    properties = event["ResourceProperties"]
    stack_arn = event['StackId']
    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(
            stack_arn) + '-' + event['LogicalResourceId']

    buckets = properties.get("Buckets", [])
    if not buckets:
        print "There were no buckets in the resource properties, returning early"
        return custom_resource_response.success_response({}, physical_resource_id)

    if event["RequestType"] != "Delete":
        return custom_resource_response.success_response({}, physical_resource_id)

    for bucket_name in buckets:
        clear_bucket(bucket_name)
    return custom_resource_response.success_response({}, physical_resource_id)
Example #10
0
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(),
        'ConfigurationKey': properties.String(),
        'ResourceGroupName': properties.String()})

    data = {
        'ConfigurationBucket': props.ConfigurationBucket,
        'ConfigurationKey': '{}/resource-group/{}'.format(props.ConfigurationKey, props.ResourceGroupName),
        'TemplateURL': 'https://s3.amazonaws.com/{}/{}/resource-group/{}/resource-template.json'.format(props.ConfigurationBucket, props.ConfigurationKey, props.ResourceGroupName)
    }

    physical_resource_id = 'CloudCanvas:LambdaConfiguration:{stack_name}:{resource_group_name}'.format(
        stack_name=aws_utils.get_stack_name_from_stack_arn(event['StackId']),
        resource_group_name=props.ResourceGroupName)

    response.succeed(event, context, data, physical_resource_id)
Example #11
0
def handler(event, context):
    stack_arn = event['StackId']
    stack = stack_info.StackInfoManager().get_stack_info(stack_arn)

    if not stack.is_project_stack:
        raise RuntimeError(
            "Custom::ExternalResourceInstance can only be defined in the project stack."
        )

    request_type = event['RequestType']
    if request_type not in ['Create', 'Update', 'Delete']:
        raise RuntimeError('Unexpected request type: {}'.format(request_type))

    if request_type in ['Create', 'Update']:
        _create_reference_metadata(event, stack)
    else:
        _delete_reference_metadata(event['LogicalResourceId'], stack)

    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(
        stack_arn) + '-' + event['LogicalResourceId']

    return custom_resource_response.success_response({}, physical_resource_id)
Example #12
0
def handler(event, context):

    # Validate RequestType
    request_type = event['RequestType']
    if request_type not in ['Create', 'Update', 'Delete']:
        raise RuntimeError('Unexpected request type: {}'.format(request_type))

    stack_arn = event['StackId']
    stack_manager = stack_info.StackInfoManager()
    stack = stack_manager.get_stack_info(stack_arn)

    # Physical ID is always the same.
    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(stack_arn) + '-' + event['LogicalResourceId']

    if request_type == 'Delete':
        _delete_iot_policy(physical_resource_id)
    elif request_type == 'Update':
        _update_iot_policy(physical_resource_id, stack)
    elif request_type == 'Create':
        _create_iot_policy(physical_resource_id, stack)

    return custom_resource_response.success_response({}, physical_resource_id)
Example #13
0
    def __init__(self, stack_arn, source_resource_name, resource_type_name,
                 lambda_dictionary, deleted, data):
        self.__stack_arn = stack_arn
        self.__stack_name = aws_utils.get_stack_name_from_stack_arn(stack_arn)
        self.__source_resource_name = source_resource_name
        self.__resource_type_name = resource_type_name
        self.__deleted = deleted
        self.__permission_metadata = data.get('PermissionMetadata', {})
        self.__service_api = data.get('ServiceApi', None)
        self.__arn_format = data.get('ArnFormat', None)
        self.__arn_url = data.get('ArnUrl', None)
        self.__display_info = data.get('DisplayInfo', None)
        self.__handler_url = data.get('HandlerUrl', None)
        self.__arn_function = data.get('ArnFunction', None)
        self.__handler_function = data.get('HandlerFunction', None)
        self.__handler_function_version = None

        if self.__handler_function:
            lambda_data = lambda_dictionary.get(
                self.get_custom_resource_lambda_function_name(), None)
            self.__handler_function_version = lambda_data[
                'v'] if lambda_data else None  # Backwards compatibility

        self._validate()
def handler(event, context):

    props = properties.load(
        event,
        {
            'ConfigurationBucket':
            properties.String(),
            'ConfigurationKey':
            properties.String(
            ),  ##this is only here to force the resource handler to execute on each update to the deployment
            'IdentityPoolName':
            properties.String(),
            'UseAuthSettingsObject':
            properties.String(),
            'AllowUnauthenticatedIdentities':
            properties.String(),
            'DeveloperProviderName':
            properties.String(default=''),
            'Roles':
            properties.Object(default={}, schema={'*': properties.String()}),
            'RoleMappings':
            properties.Object(
                default={},
                schema={
                    'Cognito':
                    properties.Object(
                        default={},
                        schema={
                            'Type': properties.String(''),
                            'AmbiguousRoleResolution': properties.String('')
                        })
                })
        })

    #give the identity pool a unique name per stack
    stack_manager = stack_info.StackInfoManager()
    stack_name = aws_utils.get_stack_name_from_stack_arn(event['StackId'])
    identity_pool_name = stack_name + props.IdentityPoolName
    identity_pool_name = identity_pool_name.replace('-', ' ')
    identity_client = identity_pool.get_identity_client()
    identity_pool_id = custom_resource_utils.get_embedded_physical_id(
        event.get('PhysicalResourceId'))
    found_pool = identity_pool.get_identity_pool(identity_pool_id)

    request_type = event['RequestType']
    if request_type == 'Delete':
        if found_pool != None:
            identity_client.delete_identity_pool(
                IdentityPoolId=identity_pool_id)
        data = {}

    else:
        use_auth_settings_object = props.UseAuthSettingsObject.lower(
        ) == 'true'
        supported_login_providers = {}

        if use_auth_settings_object == True:
            #download the auth settings from s3
            player_access_key = 'player-access/' + constant.AUTH_SETTINGS_FILENAME
            auth_doc = json.loads(
                _load_doc_from_s3(props.ConfigurationBucket,
                                  player_access_key))

            #if the doc has entries add them to the supported_login_providers dictionary
            if len(auth_doc) > 0:
                for key, value in auth_doc.iteritems():
                    supported_login_providers[
                        value['provider_uri']] = value['app_id']

        cognito_identity_providers = identity_pool.get_cognito_identity_providers(
            stack_manager, event['StackId'], event['LogicalResourceId'])

        print 'Identity Providers: ', cognito_identity_providers
        allow_anonymous = props.AllowUnauthenticatedIdentities.lower(
        ) == 'true'
        #if the pool exists just update it, otherwise create a new one

        args = {
            'IdentityPoolName': identity_pool_name,
            'AllowUnauthenticatedIdentities': allow_anonymous,
            'SupportedLoginProviders': supported_login_providers,
            'CognitoIdentityProviders': cognito_identity_providers
        }

        if props.DeveloperProviderName:
            args['DeveloperProviderName'] = props.DeveloperProviderName

        if found_pool != None:
            identity_client.update_identity_pool(
                IdentityPoolId=identity_pool_id, **args)
        else:
            response = identity_client.create_identity_pool(**args)
            identity_pool_id = response['IdentityPoolId']

        #update the roles for the pool
        role_mappings = {}
        if props.RoleMappings.Cognito.Type and len(
                cognito_identity_providers) > 0:
            print 'Adding role mappings for cognito', props.RoleMappings.Cognito.__dict__
            role_mappings['{}:{}'.format(
                cognito_identity_providers[0]['ProviderName'],
                cognito_identity_providers[0]
                ['ClientId'])] = props.RoleMappings.Cognito.__dict__

        print "Role Mappings: ", role_mappings
        identity_client.set_identity_pool_roles(
            IdentityPoolId=identity_pool_id,
            Roles=props.Roles.__dict__,
            RoleMappings=role_mappings)

        data = {
            'IdentityPoolName': identity_pool_name,
            'IdentityPoolId': identity_pool_id
        }

    physical_resource_id = identity_pool_id

    return custom_resource_response.success_response(data,
                                                     physical_resource_id)
Example #15
0
def handler(event, context):
    request_type = event['RequestType']
    logical_resource_id = event['LogicalResourceId']
    properties = event['ResourceProperties']
    physical_resource_id = aws_utils.get_stack_name_from_stack_arn(
        event['StackId']) + "-" + logical_resource_id
    domain_name = physical_resource_id + "-domain"
    workflow_type_name = physical_resource_id + "-workflow-type"

    if request_type == "Create":
        swf_client.register_domain(name=domain_name,
                                   workflowExecutionRetentionPeriodInDays="15")

        swf_client.register_workflow_type(
            domain=domain_name,
            name=workflow_type_name,
            version="1.0",
            defaultTaskStartToCloseTimeout=properties[
                'TaskStartToCloseTimeout'],
            defaultExecutionStartToCloseTimeout=properties[
                'ExecutionStartToCloseTimeout'],
            defaultTaskList=properties['TaskList'],
            defaultChildPolicy=properties['ChildPolicy'])

        for activity_type in properties['ActivityTypes']:
            swf_client.register_activity_type(domain=domain_name,
                                              name=activity_type,
                                              version="1.0")

    elif request_type == "Update":
        existing_types = set()
        params = {'domain': domain_name, 'registrationStatus': "REGISTERED"}

        while True:
            response = swf_client.list_activity_types(**params)
            existing_types.update(
                set([
                    item['activityType']['name']
                    for item in response['typeInfos']
                ]))

            if 'nextPageToken' in response:
                params['nextPageToken'] = response['nextPageToken']
            else:
                break

        for activity_type in properties['ActivityTypes']:
            if activity_type in existing_types:
                existing_types.discard(activity_type)
            else:
                swf_client.register_activity_type(domain=domain_name,
                                                  name=activity_type,
                                                  version="1.0")

        for activity_type in existing_types:
            swf_client.deprecate_activity_type(domain=domain_name,
                                               activityType={
                                                   'name': activity_type,
                                                   'version': "1.0"
                                               })

    elif request_type == "Delete":
        swf_client.deprecate_domain(name=domain_name)

    outputs = {
        'DomainName': domain_name,
        'WorkflowTypeName': workflow_type_name,
        'ActivityTypes': properties['ActivityTypes'],
        'TaskList': properties['TaskList']['name']
    }

    return custom_resource_response.success_response(outputs,
                                                     physical_resource_id)
Example #16
0
 def stack_name(self):
     return aws_utils.get_stack_name_from_stack_arn(self.stack_arn)
def handler(event, context):
    props = properties.load(event, {
            'ClientApps': properties.StringOrListOfString(),
            'ExplicitAuthFlows': properties.StringOrListOfString(default=[]),
            'RefreshTokenValidity': properties.String('30'),
            'ConfigurationKey': properties.String(), ##this is only here to force the resource handler to execute on each update to the deployment
            'LambdaConfig': properties.Dictionary({}),
            'PoolName': properties.String(),
            'Groups': properties.ObjectOrListOfObject(default=[],
                                                      schema={
                                                          'Name': properties.String(),
                                                          'Description': properties.String(''),
                                                          'Role': properties.String(),
                                                          'Precedence': properties.String('99')
                                                      }),
            'AllowAdminCreateUserOnly': properties.String('')
        })

    #give the identity pool a unique name per stack
    stack_manager = stack_info.StackInfoManager()
    stack_name = aws_utils.get_stack_name_from_stack_arn(event['StackId'])
    stack_name = stack_name.replace('-', ' ') # Prepare stack_name to be used by _associate_user_pool_with_player_access
    pool_name = props.PoolName.replace('-', ' ')
    pool_name = stack_name+pool_name
    cognito_idp_client = user_pool.get_idp_client()
    pool_id = event.get('PhysicalResourceId')
    found_pool = user_pool.get_user_pool(pool_id)

    request_type = event['RequestType']

    if request_type == 'Delete':
        if found_pool != None:
            cognito_idp_client.delete_user_pool(UserPoolId = pool_id) 
        data = {}

    else:
        #if the pool exists just update it, otherwise create a new one
        
        mfaConfig = 'OFF'   # MFA is currently unsupported by Lumberyard
        # Users are automatically prompted to verify these things. 
        # At least one auto-verified thing (email or phone) is required to allow password recovery.
        auto_verified_attributes = [ 'email' ]
        
        client_app_data = {};
        lambda_config = props.LambdaConfig

        user_pool.validate_identity_metadata(stack_manager, event['StackId'], event['LogicalResourceId'], props.ClientApps)
        admin_create_user_config = __get_admin_create_user_config(props.AllowAdminCreateUserOnly)
        print json.dumps(admin_create_user_config)

        if found_pool != None:  # Update
            response = cognito_idp_client.update_user_pool(
                    UserPoolId=pool_id,
                    MfaConfiguration=mfaConfig,
                    AutoVerifiedAttributes=auto_verified_attributes,
                    LambdaConfig=lambda_config,
                    AdminCreateUserConfig=admin_create_user_config
                )

            existing_client_apps = user_pool.get_client_apps(pool_id)
            client_app_data = update_client_apps(pool_id, props.ClientApps, existing_client_apps, False, props.ExplicitAuthFlows, props.RefreshTokenValidity)

            response = cognito_idp_client.list_groups(
                UserPoolId=pool_id
            )

            found_groups = {}
            for actual_group in response['Groups']:
                group_name = actual_group['GroupName']
                for requested_group in props.Groups:
                    # does the group exist in the resource template
                    if group_name == requested_group.Name:
                        found_groups.update({group_name: True})
                        break


                #delete the group as it is no longer in the resource template
                if group_name not in found_groups:
                    cognito_idp_client.delete_group(
                        GroupName=actual_group['GroupName'],
                        UserPoolId=pool_id
                    )

            print "Found groups=>", json.dumps(found_groups)
            #iterate the groups defined in the user pool resource template
            for group in props.Groups:
                #update the group as it is currently a group in the user pool
                group_definition = __generate_group_defintion(pool_id, group)
                print "Group '{}' is defined by {}".format(group.Name, json.dumps(group_definition))
                if group.Name in found_groups:
                    cognito_idp_client.update_group(**group_definition)
                else:
                    #group is a new group on the user pool
                    cognito_idp_client.create_group(**group_definition)

        else: # Create
            response = cognito_idp_client.create_user_pool(
                    PoolName=pool_name,
                    MfaConfiguration=mfaConfig,
                    AutoVerifiedAttributes=auto_verified_attributes,
                    LambdaConfig=lambda_config,
                    AdminCreateUserConfig=admin_create_user_config
                )
            pool_id = response['UserPool']['Id']
            print 'User pool creation response: ', response
            for group in props.Groups:
                group_definition = __generate_group_defintion(pool_id, group)
                print "Group '{}' is defined by {}".format(group.Name, json.dumps(group_definition))
                cognito_idp_client.create_group(**group_definition)

            client_app_data = update_client_apps(pool_id, props.ClientApps, [], False, props.ExplicitAuthFlows, props.RefreshTokenValidity)

        updated_resources = {
            event['StackId']: {
                event['LogicalResourceId']: {
                    'physical_id': pool_id,
                    'client_apps': {client_app['ClientName']: {'client_id': client_app['ClientId']} for client_app in client_app_data['Created'] + client_app_data['Updated']}
                }
            }
        }

        identity_pool.update_cognito_identity_providers(stack_manager, event['StackId'], pool_id, updated_resources)

        data = {
            'UserPoolName': pool_name,
            'UserPoolId': pool_id,
            'ClientApps': client_app_data,
        }
    
    physical_resource_id = pool_id

    return custom_resource_response.success_response(data, physical_resource_id)