示例#1
0
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(), # Currently not used
        'ConfigurationKey': properties.String(),    # Depend on unique upload id in key to force Cloud Formation to call handler
        'FeatureStack': properties.String(default=''),
        'DeploymentStack': properties.String(default='')})

    if props.FeatureStack is '' and props.DeploymentStack is '':
        raise ValidationError('A value for the FeatureStack property or the DeploymentStack property must be provided.')

    if props.FeatureStack is not '' and props.DeploymentStack is not '':
        raise ValidationError('A value for only the FeatureStack property or the DeploymentStack property can be provided.')

    data = {}
    physical_resource_id = 'CloudCanvas:PlayerAccess:{stack_name}'.format(
        stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId']))

    if props.FeatureStack is not '':
        
        feature_info = discovery_utils.FeatureInfo(props.FeatureStack)

        # The PlayerAccess resources in feature stacks will be created before
        # the deployment access stack, and the Player role, is created. In 
        # this case it is OK for us to do nothing and wait for the PlayerAccess
        # resource defined by the deployment access stack to be created. It
        # will initialize the role at athat time.
        role_name = _find_player_role(feature_info.deployment)
        if role_name is not None:
            _process_feature_stack(event['RequestType'], feature_info, role_name)

    else: # DeploymentStack
        _process_deployment_stack(event['RequestType'], props.DeploymentStack)

    custom_resource_response.succeed(event, context, data, physical_resource_id)
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=discovery_utils.get_stack_name_from_stack_arn(
            event['StackId']),
        resource_group_name=props.ResourceGroupName)

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)
    def test_succeed(self):

        event = {
            'StackId': 'test-stack-id',
            'RequestId': 'test-request-id',
            'LogicalResourceId': 'test-logical-resource-id',
            'ResponseURL': 'https://test-host/test-path/test-path?test-arg=test-value'
        }

        context = {
        }

        data = {
            'test-data-key': 'test-data-value'
        }

        physical_resource_id = 'test-physical-resoruce-id'

        with mock.patch('httplib.HTTPSConnection') as mock_HTTPSConnection:

            mock_connection = mock_HTTPSConnection.return_value
            mock_getresponse = mock_connection.getresponse

            mock_response = mock.MagicMock()
            mock_response.status = httplib.OK
            mock_getresponse.return_value = mock_response

            mock_request = mock_connection.request

            custom_resource_response.succeed(event, context, data, physical_resource_id)

            mock_HTTPSConnection.assert_called_with('test-host')
            mock_request.assert_called_with('PUT', '/test-path/test-path?test-arg=test-value', '{"Status": "SUCCESS", "StackId": "test-stack-id", "PhysicalResourceId": "test-physical-resoruce-id", "RequestId": "test-request-id", "Data": {"test-data-key": "test-data-value"}, "LogicalResourceId": "test-logical-resource-id"}')
示例#4
0
def handler(event, context):

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

    data = {
        'ConfigurationBucket':
        props.ConfigurationBucket,
        'ConfigurationKey':
        '{}/deployment/{}'.format(props.ConfigurationKey,
                                  props.DeploymentName),
        'DeploymentTemplateURL':
        'https://s3.amazonaws.com/{}/{}/deployment/{}/deployment-template.json'
        .format(props.ConfigurationBucket, props.ConfigurationKey,
                props.DeploymentName),
        'AccessTemplateURL':
        'https://s3.amazonaws.com/{}/{}/deployment-access-template-{}.json'.
        format(props.ConfigurationBucket, props.ConfigurationKey,
               props.DeploymentName),
        'DeploymentName':
        props.DeploymentName
    }

    physical_resource_id = 'CloudCanvas:DeploymentConfiguration:{}:{}'.format(
        discovery_utils.get_stack_name_from_stack_arn(event['StackId']),
        props.DeploymentName)

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)
示例#5
0
def handler(event, context):
    '''Entry point for the Custom::AccessControl resource handler.'''

    props = properties.load(
        event,
        {
            'ConfigurationBucket': properties.String(),  # Currently not used
            'ConfigurationKey': properties.String()
        }
    )  # Depend on unique upload id in key to force Cloud Formation to call 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 = stack_info.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, 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.
    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(), # Currently not used
        'ConfigurationKey': properties.String(),    # Depend on unique upload id in key to force Cloud Formation to call handler
        'RoleLogicalId': properties.String(),
        'MetadataKey': properties.String(),
        'PhysicalResourceId': properties.String(),
        'UsePropagationDelay': properties.String(),
        'RequireRoleExists': properties.String(default='true'),
        'ResourceGroupStack': properties.String(default=''),
        'DeploymentStack': properties.String(default='')})

    if props.ResourceGroupStack is '' and props.DeploymentStack is '':
        raise ValidationError('A value for the ResourceGroupStack property or the DeploymentStack property must be provided.')

    if props.ResourceGroupStack is not '' and props.DeploymentStack is not '':
        raise ValidationError('A value for only the ResourceGroupStack property or the DeploymentStack property can be provided.')

    use_propagation_delay = props.UsePropagationDelay.lower() == 'true'
    
    data = {}
    stack_infos = []
    
    if props.ResourceGroupStack is not '':
        resource_group_info = stack_info.ResourceGroupInfo(props.ResourceGroupStack)
        
        # create a list of stack-infos, starting at the resource group level and working our way upward
        stack_infos = _build_stack_infos_list(resource_group_info) 
        
    else: # DeploymentStack
        deployment_info = stack_info.DeploymentInfo(props.DeploymentStack)
        
        # create a list of stack-infos, starting at the deployment level and working our way upward
        stack_infos = _build_stack_infos_list(deployment_info)
    
    # go through each of the stack infos, trying to find the specified role
    for stack in stack_infos:
        role = stack.resources.get_by_logical_id(props.RoleLogicalId, expected_type='AWS::IAM::Role', optional=True)
        
        if role is not None:
            break

    role_physical_id = None
    if role is not None:
        role_physical_id = role.physical_id

    if role_physical_id is None:
        if props.RequireRoleExists.lower() == 'true':
            raise ValidationError('Could not find role \'{}\'.'.format(props.RoleLogicalId))
    else:
        if type(stack_infos[0]) is stack_info.ResourceGroupInfo:
            _process_resource_group_stack(event['RequestType'], stack_infos[0], role_physical_id, props.MetadataKey, use_propagation_delay)
        else:
            for resource_group_info in stack_infos[0].resource_groups:
                _process_resource_group_stack(event['RequestType'], resource_group_info, role_physical_id, props.MetadataKey, use_propagation_delay)

    custom_resource_response.succeed(event, context, data, props.PhysicalResourceId)
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(),
        'ConfigurationKey': properties.String(),
        'FunctionName': properties.String(),
        'Settings': properties.Object( default={}, 
            schema={
                '*': properties.String()
            }),
        'Runtime': properties.String()
        })

    request_type = event['RequestType']

    if request_type == 'Delete':

        physical_resource_name = event['PhysicalResourceId']
        resource_uuid = physical_resource_name.split(':')[4]

        _delete_role(resource_uuid)

        data = {}

    else:

        if request_type == 'Create':

            resource_uuid = uuid4()

            physical_resource_name = 'CloudCanvas:LambdaConfiguration:{stack_name}:{function_name}:{uuid}'.format(
                stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId']), 
                function_name=props.FunctionName,
                uuid=resource_uuid)

            role_arn = _create_role(event['StackId'], props.FunctionName, resource_uuid)

        else: # Update

            physical_resource_name = event['PhysicalResourceId']
            resource_uuid = physical_resource_name.split(':')[4]
            role_arn = _update_role(event['StackId'], props.FunctionName, resource_uuid)

        output_key = '{}/feature-code.zip'.format(props.ConfigurationKey)
        output_key = _inject_settings(props.Settings.__dict__, props.Runtime, props.ConfigurationBucket, output_key, props.FunctionName)

        data = {
            'ConfigurationBucket': props.ConfigurationBucket,
            'ConfigurationKey': output_key,
            'Runtime': props.Runtime,
            'Role': role_arn
        }

    custom_resource_response.succeed(event, context, data, physical_resource_name)
示例#8
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)

    custom_resource_response.succeed(event, context, output,
                                     physical_resource_id)
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']))

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)
示例#10
0
def handler(event, context):

    props = properties.load(
        event,
        {
            'ConfigurationBucket': properties.String(),  # Currently not used
            'ConfigurationKey': properties.String(
            ),  # Depend on unique upload id in key to force Cloud Formation to call handler
            'FeatureStack': properties.String(default=''),
            'DeploymentStack': properties.String(default='')
        })

    if props.FeatureStack is '' and props.DeploymentStack is '':
        raise ValidationError(
            'A value for the FeatureStack property or the DeploymentStack property must be provided.'
        )

    if props.FeatureStack is not '' and props.DeploymentStack is not '':
        raise ValidationError(
            'A value for only the FeatureStack property or the DeploymentStack property can be provided.'
        )

    data = {}
    physical_resource_id = 'CloudCanvas:PlayerAccess:{stack_name}'.format(
        stack_name=discovery_utils.get_stack_name_from_stack_arn(
            event['StackId']))

    if props.FeatureStack is not '':

        feature_info = discovery_utils.FeatureInfo(props.FeatureStack)

        # The PlayerAccess resources in feature stacks will be created before
        # the deployment access stack, and the Player role, is created. In
        # this case it is OK for us to do nothing and wait for the PlayerAccess
        # resource defined by the deployment access stack to be created. It
        # will initialize the role at athat time.
        role_name = _find_player_role(feature_info.deployment)
        if role_name is not None:
            _process_feature_stack(event['RequestType'], feature_info,
                                   role_name)

    else:  # DeploymentStack
        _process_deployment_stack(event['RequestType'], props.DeploymentStack)

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(),
        'ConfigurationKey': properties.String(),
        'FeatureName': properties.String()})

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

    physical_resource_id = 'CloudCanvas:LambdaConfiguration:{stack_name}:{feature_name}'.format(
        stack_name=discovery_utils.get_stack_name_from_stack_arn(event['StackId']),
        feature_name=props.FeatureName)

    custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(),
        'ConfigurationKey': properties.String(),
        'DeploymentName': properties.String()})

    data = {
        'ConfigurationBucket': props.ConfigurationBucket,
        'ConfigurationKey': '{}/deployment/{}'.format(props.ConfigurationKey, props.DeploymentName),
        'DeploymentTemplateURL': 'https://s3.amazonaws.com/{}/{}/deployment/{}/deployment-template.json'.format(props.ConfigurationBucket, props.ConfigurationKey, props.DeploymentName),
        'AccessTemplateURL': 'https://s3.amazonaws.com/{}/{}/deployment-access-template-{}.json'.format(props.ConfigurationBucket, props.ConfigurationKey, props.DeploymentName),
        'DeploymentName': props.DeploymentName
    }

    physical_resource_id = 'CloudCanvas:DeploymentConfiguration:{}:{}'.format(discovery_utils.get_stack_name_from_stack_arn(event['StackId']), props.DeploymentName)

    custom_resource_response.succeed(event, context, data, physical_resource_id)
def handler(event, context):

    props = properties.load(event, {'MainBucket': properties.String()})

    s3 = boto3.client('s3')

    if event['RequestType'] == 'Create':
        for file_name in bucket_data:
            s3.put_object(Bucket=props.MainBucket,
                          Key=file_name,
                          Body=bucket_data[file_name])
    elif event['RequestType'] == 'Delete':
        for file_name in bucket_data:
            s3.delete_object(Bucket=props.MainBucket, Key=file_name)

    physical_id = 'CloudCanvas:PopulateMainBucket:{stack_name}'.format(
        stack_name=discovery_utils.get_stack_name_from_stack_arn(
            event['StackId']))

    return custom_resource_response.succeed(event, context, {}, physical_id)
示例#14
0
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_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 = 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(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

    custom_resource_response.succeed(event, context, data, physical_resource_id)
示例#15
0
def handler(event, context):

    props = properties.load(
        event, {
            'ConfigurationBucket':
            properties.String(),
            'ConfigurationKey':
            properties.String(),
            'FunctionName':
            properties.String(),
            'Settings':
            properties.Object(default={}, schema={'*': properties.String()}),
            'Runtime':
            properties.String()
        })

    request_type = event['RequestType']
    stack_arn = event['StackId']
    logical_role_name = props.FunctionName

    id_data = aws_utils.get_data_from_custom_physical_resource_id(
        event.get('PhysicalResourceId', None))

    if request_type == 'Delete':

        role_utils.delete_access_control_role(id_data, logical_role_name)

        response_data = {}

    else:

        if request_type == 'Create':

            project_service_lambda_arn = _get_project_service_lambda_arn(
                stack_arn)

            assume_role_service = 'lambda.amazonaws.com'
            role_arn = role_utils.create_access_control_role(
                id_data,
                stack_arn,
                logical_role_name,
                assume_role_service,
                default_policy=get_default_policy(project_service_lambda_arn))

        elif request_type == 'Update':

            role_arn = role_utils.get_access_control_role_arn(
                id_data, logical_role_name)

        else:
            raise RuntimeError(
                'Unexpected request type: {}'.format(request_type))

        _add_built_in_settings(props.Settings.__dict__, stack_arn)

        # Check if we have a folder just for this function, if not use the default
        input_key = _get_input_key(props)

        output_key = _inject_settings(props.Settings.__dict__, props.Runtime,
                                      props.ConfigurationBucket, input_key,
                                      props.FunctionName)

        response_data = {
            'ConfigurationBucket':
            props.ConfigurationBucket,
            'ConfigurationKey':
            output_key,
            'Runtime':
            props.Runtime,
            'Role':
            role_arn,
            'RoleName':
            role_utils.get_access_control_role_name(stack_arn,
                                                    logical_role_name)
        }

    physical_resource_id = aws_utils.construct_custom_physical_resource_id_with_data(
        stack_arn, event['LogicalResourceId'], id_data)

    custom_resource_response.succeed(event, context, response_data,
                                     physical_resource_id)
示例#16
0
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(),
            'Roles':
            properties.Object(default={}, schema={'*': properties.String()}),
        })

    #give the identity pool a unique name per stack
    stack_name = discovery_utils.get_stack_name_from_stack_arn(
        event['StackId'])
    identity_pool_name = props.IdentityPoolName + stack_name
    identity_pool_name = identity_pool_name.replace('-', ' ')
    cognito_client = boto3.client('cognito-identity')
    found_pool = _find_identity_pool(cognito_client, identity_pool_name)
    identity_pool_id = None

    request_type = event['RequestType']
    if request_type == 'Delete':
        if found_pool != None:
            identity_pool_id = found_pool['IdentityPoolId']
            cognito_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/auth-settings.json'
            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']

        allow_anonymous = props.AllowUnauthenticatedIdentities.lower(
        ) == 'true'
        #if the pool exists just update it, otherwise create a new one
        if found_pool != None:
            response = cognito_client.update_identity_pool(
                IdentityPoolId=found_pool['IdentityPoolId'],
                IdentityPoolName=identity_pool_name,
                AllowUnauthenticatedIdentities=allow_anonymous,
                SupportedLoginProviders=supported_login_providers)
            identity_pool_id = found_pool['IdentityPoolId']

        else:
            response = cognito_client.create_identity_pool(
                IdentityPoolName=identity_pool_name,
                AllowUnauthenticatedIdentities=allow_anonymous,
                SupportedLoginProviders=supported_login_providers)
            identity_pool_id = response['IdentityPoolId']

        #now update the roles for the pool
        cognito_client.set_identity_pool_roles(IdentityPoolId=identity_pool_id,
                                               Roles=props.Roles.__dict__)

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

    physical_resource_id = identity_pool_id

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)
def handler(event, context):

    props = properties.load(
        event, {
            'ConfigurationBucket':
            properties.String(),
            'ConfigurationKey':
            properties.String(),
            'FunctionName':
            properties.String(),
            'Settings':
            properties.Object(default={}, schema={'*': properties.String()}),
            'Runtime':
            properties.String()
        })

    request_type = event['RequestType']
    stack_arn = event['StackId']
    logical_role_name = event['LogicalResourceId']
    physical_resource_name = event.get('PhysicalResourceId',
                                       None)  # None when create request

    if request_type == 'Delete':

        role_utils.delete_role(stack_arn, logical_role_name, POLICY_NAME)

        data = {}

    else:

        policy_metadata_filter = lambda entry: _policy_metadata_filter(
            entry, props.FunctionName)

        if request_type == 'Create':

            physical_resource_name = discovery_utils.get_stack_name_from_stack_arn(
                stack_arn) + '-' + event['LogicalResourceId']

            assume_role_service = 'lambda.amazonaws.com'
            role_arn = role_utils.create_role(stack_arn, logical_role_name,
                                              POLICY_NAME, assume_role_service,
                                              DEFAULT_POLICY_STATEMENTS,
                                              policy_metadata_filter)

        elif request_type == 'Update':

            role_arn = role_utils.update_role(stack_arn, logical_role_name,
                                              POLICY_NAME,
                                              DEFAULT_POLICY_STATEMENTS,
                                              policy_metadata_filter)

        else:
            raise ValidationError(
                'Unexpected request type: {}'.format(request_type))

        input_key = '{}/lambda-function-code.zip'.format(
            props.ConfigurationKey)
        output_key = _inject_settings(props.Settings.__dict__, props.Runtime,
                                      props.ConfigurationBucket, input_key,
                                      props.FunctionName)

        data = {
            'ConfigurationBucket': props.ConfigurationBucket,
            'ConfigurationKey': output_key,
            'Runtime': props.Runtime,
            'Role': role_arn
        }

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_name)
示例#18
0
def handler(event, context):

    props = properties.load(
        event, {
            'ConfigurationBucket':
            properties.String(),
            'ConfigurationKey':
            properties.String(),
            'FunctionName':
            properties.String(),
            'Settings':
            properties.Object(default={}, schema={'*': properties.String()}),
            'Runtime':
            properties.String()
        })

    request_type = event['RequestType']

    if request_type == 'Delete':

        physical_resource_name = event['PhysicalResourceId']
        resource_uuid = physical_resource_name.split(':')[4]

        _delete_role(resource_uuid)

        data = {}

    else:

        if request_type == 'Create':

            resource_uuid = uuid4()

            physical_resource_name = 'CloudCanvas:LambdaConfiguration:{stack_name}:{function_name}:{uuid}'.format(
                stack_name=discovery_utils.get_stack_name_from_stack_arn(
                    event['StackId']),
                function_name=props.FunctionName,
                uuid=resource_uuid)

            role_arn = _create_role(event['StackId'], props.FunctionName,
                                    resource_uuid)

        else:  # Update

            physical_resource_name = event['PhysicalResourceId']
            resource_uuid = physical_resource_name.split(':')[4]
            role_arn = _update_role(event['StackId'], props.FunctionName,
                                    resource_uuid)

        output_key = '{}/feature-code.zip'.format(props.ConfigurationKey)
        output_key = _inject_settings(props.Settings.__dict__, props.Runtime,
                                      props.ConfigurationBucket, output_key,
                                      props.FunctionName)

        data = {
            'ConfigurationBucket': props.ConfigurationBucket,
            'ConfigurationKey': output_key,
            'Runtime': props.Runtime,
            'Role': role_arn
        }

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_name)
示例#19
0
def handler(event, context):

    request_type = event['RequestType']
    logical_resource_id = event['LogicalResourceId']
    logical_role_name = logical_resource_id
    owning_stack_info = stack_info.get_stack_info(event['StackId'])
    rest_api_resource_name = owning_stack_info.stack_name + '-' + logical_resource_id
    id_data = aws_utils.get_data_from_custom_physical_resource_id(
        event.get('PhysicalResourceId', None))

    response_data = {}

    if request_type == 'Create':

        props = properties.load(event, PROPERTY_SCHEMA)
        role_arn = role_utils.create_access_control_role(
            id_data, owning_stack_info.stack_arn, logical_role_name,
            API_GATEWAY_SERVICE_NAME)
        swagger_content = get_configured_swagger_content(
            owning_stack_info, props, role_arn, rest_api_resource_name)
        rest_api_id = create_api_gateway(props, swagger_content)
        response_data['Url'] = get_api_url(rest_api_id,
                                           owning_stack_info.region)
        id_data['RestApiId'] = rest_api_id

    elif request_type == 'Update':

        rest_api_id = id_data.get('RestApiId', None)
        if not rest_api_id:
            raise RuntimeError(
                'No RestApiId found in id_data: {}'.format(id_data))

        props = properties.load(event, PROPERTY_SCHEMA)
        role_arn = role_utils.get_access_control_role_arn(
            id_data, logical_role_name)
        swagger_content = get_configured_swagger_content(
            owning_stack_info, props, role_arn, rest_api_resource_name)
        update_api_gateway(rest_api_id, props, swagger_content)
        response_data['Url'] = get_api_url(rest_api_id,
                                           owning_stack_info.region)

    elif request_type == 'Delete':

        if not id_data:

            # The will be no data in the id if Cloud Formation cancels a resource creation
            # (due to a failure in another resource) before it processes the resource create
            # response. Appearently Cloud Formation has an internal temporary id for the
            # resource and uses it for the delete request.
            #
            # Unfortunalty there isn't a good way to deal with this case. We don't have the
            # id data, so we can't clean up the things it identifies. At best we can allow the
            # stack cleanup to continue, leaving the rest API behind and role behind.

            print 'WARNING: No id_data provided on delete.'.format(id_data)

        else:

            rest_api_id = id_data.get('RestApiId', None)
            if not rest_api_id:
                raise RuntimeError(
                    'No RestApiId found in id_data: {}'.format(id_data))

            delete_api_gateway(rest_api_id)
            del id_data['RestApiId']

            role_utils.delete_access_control_role(id_data, logical_role_name)

    else:

        raise RuntimeError('Invalid RequestType: {}'.format(request_type))

    physical_resource_id = aws_utils.construct_custom_physical_resource_id_with_data(
        event['StackId'], logical_resource_id, id_data)

    custom_resource_response.succeed(event, context, response_data,
                                     physical_resource_id)
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(),            
            'Roles': properties.Object( default={}, 
            schema={
                '*': properties.String()
            }),         
        })

    #give the identity pool a unique name per stack
    stack_name = discovery_utils.get_stack_name_from_stack_arn(event['StackId'])
    identity_pool_name = props.IdentityPoolName + stack_name
    identity_pool_name = identity_pool_name.replace('-', ' ')
    cognito_client = boto3.client('cognito-identity') 
    found_pool = _find_identity_pool(cognito_client, identity_pool_name)
    identity_pool_id = None

    request_type = event['RequestType']
    if request_type == 'Delete':
        if found_pool != None:
            identity_pool_id = found_pool['IdentityPoolId']
            cognito_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/auth-settings.json'
            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']         
        
       
        allow_anonymous = props.AllowUnauthenticatedIdentities.lower() == 'true'
        #if the pool exists just update it, otherwise create a new one
        if found_pool != None:
           response = cognito_client.update_identity_pool(IdentityPoolId=found_pool['IdentityPoolId'], IdentityPoolName=identity_pool_name, AllowUnauthenticatedIdentities=allow_anonymous,
                                                             SupportedLoginProviders=supported_login_providers)    
           identity_pool_id=found_pool['IdentityPoolId']        
                        
        else:
           response = cognito_client.create_identity_pool(IdentityPoolName = identity_pool_name, AllowUnauthenticatedIdentities=allow_anonymous,
                                                            SupportedLoginProviders=supported_login_providers) 
           identity_pool_id=response['IdentityPoolId'] 

        #now update the roles for the pool   
        cognito_client.set_identity_pool_roles(IdentityPoolId=identity_pool_id, Roles=props.Roles.__dict__)    

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

    custom_resource_response.succeed(event, context, data, physical_resource_id)
示例#21
0
def handler(event, context):
    
    if event['RequestType'] != 'Create':
        return custom_resource_response.succeed(event, context, {}, "PopulateTables")

    props = properties.load(event, {
        'AchievementsTable': properties.String(),
        'DailyGiftTable': properties.String(),
        'ItemTable': properties.String(),
        'MessageOfTheDayTable': properties.String(),
        'MissionTable': properties.String(),
        'GameDataLUTable' : properties.String()
        })

    achievementsTable = dynamodb.Table(props.AchievementsTable)
    dailyGiftTable = dynamodb.Table(props.DailyGiftTable)
    itemTable = dynamodb.Table(props.ItemTable)
    messageOfTheDayTable = dynamodb.Table(props.MessageOfTheDayTable)
    missionTable = dynamodb.Table(props.MissionTable)
    gameDataLUTable = dynamodb.Table(props.GameDataLUTable)

    achievement = {
        "CompletionCriteria": "player.LastScore > 300",
        "Description": "You survived for 300 seconds!",
        "ItemReward": "FancyShip",
        "Name": "300SecondSurvival"
    }

    achievementsTable.put_item(Item=achievement)

    dailyGift = {
        "Date": "12-06-2015",
        "EndDate": "infinity",
        "Gifts": [
            {
                "Name": "ShieldMission",
                "Type": "mission"
            }
        ]
    }

    dailyGiftTable.put_item(Item=dailyGift)

    shieldItem = {
        "Name" : "Shield",
        "Persist" : False
    }

    fancyShipItem = {
        "Name" : "FancyShip",
        "Persist" : True
    }

    itemTable.put_item(Item=shieldItem)
    itemTable.put_item(Item=fancyShipItem)

    messageOfTheDay = {
        "Date": "12-06-2015",
        "EndDate": "infinity",
        "Message": "Message of the Day!"
    }

    messageOfTheDayTable.put_item(Item=messageOfTheDay)

    mission = {
        "CompletionText": "You completed the Shield Mission!",
        "Description": "Complete 1 game to get the Shield!",
        "ItemReward": "Shield",
        "Name": "ShieldMission",
        "NumberOfGamesReq": 1
    }

    missionTable.put_item(Item=mission)

    dailyGiftCached = {
        "CachedItem": {
            "Date": "12-06-2015",
            "EndDate": "infinity",
            "Gifts": [
                {
                    "Name": "ShieldMission",
                    "Type": "mission"
                }
            ]
        },
        "CachedItemName": "TodaysGift"
    }

    messageOfTheDayCached = {
        "CachedItem": {
            "Date": "12-06-2015",
            "EndDate": "infinity",
            "Message": "Message of the Day!"
        },
        "CachedItemName": "TodaysMessage"
    }

    gameDataLUTable.put_item(Item=dailyGiftCached)
    gameDataLUTable.put_item(Item=messageOfTheDayCached)

    custom_resource_response.succeed(event, context, {}, "PopulateTables")
def handler(event, context):
    custom_resource_response.succeed(event, context, {}, '*')
示例#23
0
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_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(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(
            event['StackId'], pool_id, updated_resources)

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

    physical_resource_id = pool_id

    custom_resource_response.succeed(event, context, data,
                                     physical_resource_id)