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)
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)
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)