def test_with_delay_for_propagation_false(
         self, mock_get_stack_info, mock_get_access_control_role_name,
         mock_create_role):
     id_data = {}
     role_utils.PROPAGATION_DELAY_SECONDS = 2
     start_time = time.clock()
     created_role_arn = role_utils.create_access_control_role(
         id_data,
         self.stack_arn,
         self.logical_role_name,
         self.assume_role_service,
         delay_for_propagation=False)
     stop_time = time.clock()
     delay_time = stop_time - start_time
     self.assertAlmostEqual(delay_time, 0, delta=0.1)
     self.assertEqual(created_role_arn, self.role_arn)
     self.assertEquals(
         id_data,
         {'AbstractRoleMappings': {
             self.logical_role_name: self.role_name
         }})
     mock_get_access_control_role_name.assert_called_once_with(
         self.stack_arn, self.logical_role_name)
     mock_create_role.assert_called_once_with(
         RoleName=self.role_name,
         AssumeRolePolicyDocument=self.assume_role_policy_document_matcher,
         Path=self.path)
     mock_get_stack_info.assert_called_once_with(self.stack_arn)
 def test_with_default_policy(self, mock_get_stack_info,
                              mock_get_access_control_role_name,
                              mock_put_role_policy, mock_create_role):
     id_data = {}
     created_role_arn = role_utils.create_access_control_role(
         id_data,
         self.stack_arn,
         self.logical_role_name,
         self.assume_role_service,
         delay_for_propagation=False,
         default_policy=self.default_policy)
     self.assertEqual(created_role_arn, self.role_arn)
     self.assertEquals(
         id_data,
         {'AbstractRoleMappings': {
             self.logical_role_name: self.role_name
         }})
     mock_get_access_control_role_name.assert_called_once_with(
         self.stack_arn, self.logical_role_name)
     mock_create_role.assert_called_once_with(
         RoleName=self.role_name,
         AssumeRolePolicyDocument=self.assume_role_policy_document_matcher,
         Path=self.path)
     mock_put_role_policy.assert_called_once_with(
         RoleName=self.role_name,
         PolicyName='Default',
         PolicyDocument=self.default_policy)
     mock_get_stack_info.assert_called_once_with(self.stack_arn)
Exemple #3
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)
Exemple #4
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)