Ejemplo n.º 1
0
def arn_handler(event, context):
    stack = stack_info.StackInfoManager().get_stack_info(event['StackId'])
    reference_name = aws_utils.get_data_from_custom_physical_resource_id(
        event['ResourceName']).get('ReferenceName')

    result = {'Arn': _get_reference_arn(stack, reference_name)}

    return result
Ejemplo n.º 2
0
def _get_reference_permission(resource):
    reference_name = aws_utils.get_data_from_custom_physical_resource_id(
        resource.physical_id).get('ReferenceName')
    reference_metadata = reference_type_utils.get_reference_metadata(
        resource.stack.project_stack.configuration_bucket,
        resource.stack.project_stack.project_name, reference_name)

    return reference_metadata.get('Permissions', {})
    def get_service_api_id(self, stack_arn):
        """Extracts the Service api Id for a given stack"""
        resource_description = self.get_stack_resource(stack_arn, 'ServiceApi')
        physical_resource_id = resource_description['PhysicalResourceId']

        # physical resource id is a mini json document, so need to pull out required data from id field
        id_data = aws_utils.get_data_from_custom_physical_resource_id(physical_resource_id)
        rest_api_id = id_data.get('RestApiId', '')
        return rest_api_id
Ejemplo n.º 4
0
def arn_handler(event, context):
    id_data = aws_utils.get_data_from_custom_physical_resource_id(
        event['ResourceName'])
    rest_api_id = id_data.get('RestApiId', '')
    arn = "arn:aws:execute-api:{region}:{account_id}:{resource_name}".format(
        region=event['Region'],
        account_id=event['AccountId'],
        resource_name=rest_api_id)
    result = {'Arn': arn}

    return result
def _get_implicit_role_mappings(resource_info, problems):

    '''Looks in a resource group stack for roles created by custom resources such as Custom::LambdaConfiguration
    and Custom::ServiceApi.

    Args:

        resource_info - a StackInfo object representing the stack with the metadata.  Can be of type ProjectInfo or ResourceGroupInfo

        problems - A ProblemList object used to report problems

    Returns:

        A dictionary containing the following data for each role discovered:

          {
            "<role-physical-resource-id>": [
              {
                "Effect": "<allow-or-deny>",
                "AbstractRole": [ ["<resource-group-name>", "<abstract-role-name>"], ... ],
              },
              ...
            ]
          }

    '''

    role_mappings = {}
    for resource in resource_info.resources:
        if resource.type.startswith('Custom::'):
            id_data = aws_utils.get_data_from_custom_physical_resource_id(resource.physical_id)
            resource_role_mappings = role_utils.get_id_data_abstract_role_mappings(id_data)
            for abstract_role_name, physical_role_name in resource_role_mappings.iteritems():
                print 'Adding implicit abstract role {} mapping to physical role {} for stack {}.'.format(abstract_role_name, physical_role_name, resource_info.stack_name)
                role_mapping_list = role_mappings.setdefault(
                    physical_role_name,
                    [
                        {
                            'Effect': 'Allow',
                            'AbstractRole': []
                        }
                    ]
                )
                role_mapping_list[0]['AbstractRole'].append(
                    [
                        resource_info.permission_context_name,
                        abstract_role_name
                    ]
                )

    return role_mappings
def handler(event, context):
    props = properties.load(event, PROPERTIES_SCHEMA)

    request_type = event['RequestType']
    stack_arn = event['StackId']
    logical_role_name = props.FunctionName
    stack_manager = stack_info.StackInfoManager()

    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:
        stack = stack_manager.get_stack_info(stack_arn)

        if request_type == 'Create':

            project_service_lambda_arn = _get_project_service_lambda_arn(stack)
            assume_role_service = 'lambda.amazonaws.com'
            role_arn = role_utils.create_access_control_role(
                stack_manager,
                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)
        # Check if we have a folder just for this function, if not use the default
        output_key = input_key = _get_input_key(props)
        if not props.IgnoreAppendingSettingsToZip:
            output_key = _inject_settings(props.Settings.__dict__,
                                          props.Runtime,
                                          props.ConfigurationBucket, input_key,
                                          props.FunctionName)

        cc_settings = copy.deepcopy(props.Settings.__dict__)
        # Remove "Services" from settings because they get injected into the python code package during _inject_settings
        # TODO: move handling of project-level service interfaces to the same code as cross-gem interfaces
        if "Services" in cc_settings:
            del cc_settings["Services"]

        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),
            'ComposedLambdaConfiguration': {
                'Code': {
                    'S3Bucket': props.ConfigurationBucket,
                    'S3Key': output_key
                },
                "Environment": {
                    "Variables": cc_settings
                },
                'Role': role_arn,
                'Runtime': props.Runtime
            },
            "CCSettings":
            cc_settings
        }

    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)
Ejemplo n.º 7
0
def handler(event, context):
    """Entry point for the Custom::ServiceApi resource handler."""
    stack_id = event['StackId']
    request_type = event['RequestType']
    logical_resource_id = event['LogicalResourceId']
    logical_role_name = logical_resource_id
    stack_manager = stack_info.StackInfoManager()
    stack = stack_manager.get_stack_info(stack_id)

    rest_api_resource_name = stack.stack_name + '-' + logical_resource_id
    id_data = aws_utils.get_data_from_custom_physical_resource_id(
        event.get('PhysicalResourceId', None))

    response_data = {}
    project_tags = {
        constant.PROJECT_NAME_TAG: stack.project_stack.project_name,
        constant.STACK_ID_TAG: stack_id
    }

    if request_type == 'Create':

        props = properties.load(event, PROPERTY_SCHEMA)
        role_arn = role_utils.create_access_control_role(
            stack_manager, id_data, stack.stack_arn, logical_role_name,
            API_GATEWAY_SERVICE_NAME)
        swagger_content = get_configured_swagger_content(
            stack, props, role_arn, rest_api_resource_name)
        rest_api_id = create_api_gateway(rest_api_resource_name, props,
                                         swagger_content)
        service_url = get_service_url(rest_api_id, stack.region)

        register_service_interfaces(stack, service_url, swagger_content)
        update_api_gateway_tags(rest_api_id, event, project_tags)

        response_data['Url'] = service_url
        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(
            stack, props, role_arn, rest_api_resource_name)
        update_api_gateway(rest_api_id, props, swagger_content)
        service_url = get_service_url(rest_api_id, stack.region)
        register_service_interfaces(stack, service_url, swagger_content)

        update_api_gateway_tags(rest_api_id, event, project_tags)

        response_data['Url'] = service_url

    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. Apparently Cloud Formation has an internal temporary id for the
            # resource and uses it for the delete request.
            #
            # Unfortunately 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.')

        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)
            service_url = get_service_url(rest_api_id, stack.region)
            unregister_service_interfaces(stack, service_url)

            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)

    return custom_resource_response.success_response(response_data,
                                                     physical_resource_id)
def handler(event, context):

    props = properties.load(event, PROPERTIES_SCHEMA)

    request_type = event['RequestType']
    stack_arn = event['StackId']
    logical_role_name = props.FunctionName
    stack_manager = stack_info.StackInfoManager()

    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:

        stack = stack_manager.get_stack_info(stack_arn)

        if request_type == 'Create':

            project_service_lambda_arn = _get_project_service_lambda_arn(stack)
            assume_role_service = 'lambda.amazonaws.com'
            role_arn = role_utils.create_access_control_role(
                stack_manager,
                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)
        # give access to project level ServiceDirectory APIs
        # Other deployment-level APIs are handled in InterfaceDependeny resolver custom resource type
        permitted_arns = _add_services_settings(stack, props.Settings.__dict__, props.Services)
        _add_service_access_policy_to_role(role_arn, permitted_arns)
        # Check if we have a folder just for this function, if not use the default
        output_key = input_key = _get_input_key(props)
        if not props.IgnoreAppendingSettingsToZip:
            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),
            'ComposedLambdaConfiguration': {
                'Code': {
                    'S3Bucket': props.ConfigurationBucket,
                    'S3Key': output_key
                },
                'Role': role_arn,
                'Runtime': props.Runtime
            }
        }
        
    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)