Use REST handlers to allow external services to call into Splunk Phantom
REST handlers allow external services to call into Splunk Phantom. When you create an app, you can use REST handlers in a variety of ways. Two particularly useful ways are for reparsing your data to push it into Splunk Phantom and for using OAuth with test connectivity. When reparsing your data, you can also use the REST Data Source app and supply a data transformation script. For more information see Use a Custom Script in the REST API Reference for Splunk Phantom Manual. The ability to write your own implementation is also provided, if you need more flexibility.
Using REST handlers
When you make an API request to Splunk Phantom, your code is called with a Django request object and a list of URL parts. To use a REST handler, follow these steps:
- Enter the URL you want to use in the REST handler after the prefix
rest/handler/[appname]_[appid]/[asset_name]
. You can find the URL by navigating to the main menu and clicking Apps > Configure New Asset > Asset Settings after your REST handler is configured and the app JSON code is updated. Splunk Phantom then calls into your function. - Parse your desired data from the request object and the URL fragments.
- Parse the authentication header from the request object.
- Create appropriate containers and artifacts through the Splunk Phantom REST API, using the parsed authentication header. For more information on creating containers and artifacts, see REST Containers and REST Artifact in the Splunk Phantom REST API Manual.
- Return your desired response.
REST handlers can't import any Splunk Phantom platform code. But, REST handlers can import any dependencies defined in your app JSON, and any of Django's built-in modules, but calling anything that depends on django.setup()
fails.
Arguments
REST handlers receive the following arguments:
Name | Description |
---|---|
Request | This is a standard Django request object, but with a few exceptions. For example, this object doesn't have any attributes set by the middleware or application such as request.user, request.session, or request.site. |
path_parts | This is a list of strings that contains all the URL parts after the REST handler prefix. For example, if you call the URLhttps://your.phantom.url/rest/handler/[appname]_[appid]/[asset_name]/part1/part2/part3/ , the path_parts would be ["part1", "part2", part3"]. You can use this URL to help you create a URL structure for your REST handler.
|
Return values
You can return any of the Django HTTPResponse objects from your REST handler, but in most cases returning either HTTPResponse or JSONResponse, or raising HTTP404 is sufficient. For more information, search for HttpResponse objects on the Django website.
Example: ingestion
For the example_app_rest_handler.py file name, you must add your REST handler to the app JSON. In the following example, the correct value is "rest_handler": "example_app_rest_handler.handle_request".
import json import requests import logging from django.http import HttpResponse, JsonResponse from phantom_common.install_info import get_rest_base_url logger = logging.getLogger(__name__) REST_BASE_URL = get_rest_base_url() def _get_auth_token_from_request(request): """Parse authentication information from request headers.""" auth_token = request.META.get('HTTP_PH_AUTH_TOKEN') if not auth_token: raise Exception('Invalid request. Please use "ph-auth-token" to authenticate the request') return auth_token def handle_request(request, path_parts): """Example rest_handler function.""" data = json.loads(request.body) # Parse the received data and convert it to a dict that can be sent to Phantom REST api # Here we're just gonna assume data['container'] already contains the correct data. container_data = data['container'] # Headers to authenticate calls to phantom REST api headers = {'ph-auth-token': _get_auth_token_from_request(request)} # Build the correct url url = REST_BASE_URL + 'container/' # Send a request to Phantom REST api response = requests.post(url, json=container_data, headers=headers) response_json = response.json() # Check if container was successfully created. if response_json.get('success', False) is True: container_id = response_json.get('id') return JsonResponse({'success': True, 'created_container_id': container_id}) else: return HttpResponse( 'Container creation failed. Response: {}'.format(response_json), status=400)
Debugging REST handlers
Your REST handler is executed by an app interface module, and all its errors (as well as all logs created by the REST handlers, logs related to custom views created by apps, and other information helpful for debugging) are recorded in the /var/log/phantom/app_interface.log file, unless your function was incorrectly defined. In that case, the error is logged in /var/log/phantom/wsgi.log
To debug a REST handler, follow the guidance that best matches your situation:
Using Python logging to debug a REST handler
You can use Python logging in your REST handler for debugging purposes. Any logging at level WARNING or higher is logged into the /var/log/phantom/app_interface.log file. Use the following command to define your logger:
import logging
logger = logging.getLogger(__name__)
After you define your logger, use the following command to log a message:
logger.warning('Example warning')
Debugging a ViewDoesNotExist exception
A ViewDoesNotExist exception is a common error. This error often occurs due to the following issues:
- The__init__.py file is missing from the app folder.
- The view file name doesn't match the name specified in the JSON file.
- The function name doesn't match the name specified in the JSON file.
Use custom views to render results in your app | Tutorial: Use the app wizard to develop an app framework |
This documentation applies to the following versions of Splunk® Phantom (Legacy): 4.9, 4.10, 4.10.1, 4.10.2, 4.10.3, 4.10.4, 4.10.6, 4.10.7
Feedback submitted, thanks!