|
| 1 | +# Python API Wrapper Module |
| 2 | + |
| 3 | +## Overview |
| 4 | +The API wrapper module provides a developer with basic create/update/delete utilities for multiple areas of the Stream API. |
| 5 | +Additionally, many input/output-specific modules have been incorporated into this to help facilitate |
| 6 | +easier creation of these items in a Stream deployment, such as S3 and Splunk sources and destinations. |
| 7 | + |
| 8 | + |
| 9 | +### Prerequisites |
| 10 | +- Python 3.7 and above |
| 11 | + |
| 12 | +- build module (e.g. `pip3 install build`) |
| 13 | + |
| 14 | +### General Structure |
| 15 | +The distribution can be visualized as follows: |
| 16 | +``` |
| 17 | +├── release |
| 18 | +├── src |
| 19 | +│ ├── cribl |
| 20 | +│ │ ├── auth |
| 21 | +│ │ ├── collectors |
| 22 | +│ │ ├── event_breaker_rules |
| 23 | +│ │ ├── executors |
| 24 | +│ │ ├── groups |
| 25 | +│ │ ├── inputs |
| 26 | +│ │ ├── lib |
| 27 | +│ │ ├── lookups |
| 28 | +│ │ ├── outputs |
| 29 | +│ │ ├── packs |
| 30 | +│ │ ├── parsers |
| 31 | +│ │ ├── pipelines |
| 32 | +│ │ ├── preview |
| 33 | +│ │ ├── routes |
| 34 | +│ │ ├── system |
| 35 | +│ │ ├── users |
| 36 | +│ │ └── versioning |
| 37 | +│ └── dist |
| 38 | +``` |
| 39 | + |
| 40 | +### Build |
| 41 | +To build the API wrapper module, execute the following command - srcdir will contain the `pyproject.toml` file, which contains configuration for the build process: |
| 42 | + |
| 43 | +`python3 -m build /path/to/srcdir` |
| 44 | + |
| 45 | +This will create two files: |
| 46 | + |
| 47 | +- `cribl-1.0-py3-none-any.whl` |
| 48 | + |
| 49 | +- `cribl-1.0.tar.gz` |
| 50 | + |
| 51 | +The `.whl` file will be used for the installation which will be covered in the next section. |
| 52 | + |
| 53 | +### Installation |
| 54 | +The wheel file can be installed via the following command (change the path as appropriate): |
| 55 | + |
| 56 | +`python3 -m pip install /path/to/dist/cribl-1.0-py3-none-any.whl --force-reinstall` |
| 57 | + |
| 58 | +### Requests Library |
| 59 | +The requests library (https://requests.readthedocs.io/en/latest/) is utilized by the API wrapper module for HTTP operations. |
| 60 | + |
| 61 | +### Use in Python Scripts |
| 62 | +Before anything, the developer must retrieve an authorization token from the Cribl instance. The following values must be provided: |
| 63 | +- base_url - the base URL of for the API, e.g. `http://<host>:<port>/api/v1` |
| 64 | +- username - the user that will be making the API calls, e.g. admin |
| 65 | +- password - the user's password |
| 66 | + |
| 67 | +Once these are available to the script, the API token can be fetched as follows: |
| 68 | +``` |
| 69 | + from cribl.auth import * |
| 70 | + |
| 71 | + response = api_get_auth_data(base_url=base_url, username=username, password=password) |
| 72 | + |
| 73 | + if response.json() and "token" in response.json(): |
| 74 | + cribl_auth_token = response.json()["token"] |
| 75 | +
|
| 76 | +``` |
| 77 | +The "token" should be present in the response's JSON payload if the request is successful. This value should be saved and used in subsequent calls to the API. |
| 78 | + |
| 79 | +#### Get/Create/Update/Delete of Configuration Items |
| 80 | +The configuration items from the above list follow a get/create/update/delete |
| 81 | +pattern. Using `inputs` as an example, the following methods are available: |
| 82 | + |
| 83 | +- `get_inputs(base_url, cribl_auth_token, worker_group=None)` |
| 84 | + |
| 85 | +- `get_input_by_id(base_url, cribl_auth_token, input_id, worker_group=None)` |
| 86 | + |
| 87 | +- `create_input(base_url, cribl_auth_token, create_config, worker_group=None)` |
| 88 | + |
| 89 | +- `update_input(base_url, cribl_auth_token, input_id, update_config, worker_group=None)` |
| 90 | + |
| 91 | +- `delete_input(base_url, cribl_auth_token, input_id, worker_group=None)` |
| 92 | + |
| 93 | +#### Status information for Configuration Items |
| 94 | +Status information can be retrieved from one or more inputs/outputs: |
| 95 | + |
| 96 | +- `get_input_statuses(base_url, cribl_auth_token, worker_group=None)` |
| 97 | + |
| 98 | +- `get_input_status_by_id(base_url, cribl_auth_token, input_name, worker_group=None)` |
| 99 | + |
| 100 | +- `get_output_statuses(base_url, cribl_auth_token, worker_group=None)` |
| 101 | + |
| 102 | +- `get_output_status_by_id(base_url, cribl_auth_token, output_name, worker_group=None)` |
| 103 | + |
| 104 | +The response JSON will contain status (health and metrics) information for the input or output. |
| 105 | + |
| 106 | +##### URL |
| 107 | +In each of these methods, we pass the base URL, which is structured as `http://<host>:<port>/api/v1`. |
| 108 | +These methods will work out how to construct the full URL based on the endpoint being called. |
| 109 | + |
| 110 | +##### Cribl Auth Token |
| 111 | +`cribl_auth_token` must be passed with each request to the API. The method called will create the required HTTP headers and add |
| 112 | +the bearer token to them. |
| 113 | + |
| 114 | +##### Worker Group |
| 115 | +If the Cribl deployment is single mode, the worker_group need not be passed to the method. |
| 116 | + |
| 117 | +If the Cribl deployment is distributed, the worker_group must be set to the name of the Worker Group in which the changes are |
| 118 | +to be made. |
| 119 | + |
| 120 | +##### Return Values |
| 121 | +Each method will return a Response (https://requests.readthedocs.io/en/latest/api/?highlight=Response#requests.Response) object. This will allow the caller access |
| 122 | +to the full contents of the API response - JSON payload, response code, headers, response text, etc. |
| 123 | + |
| 124 | +When calling these methods, the JSON payload from the response can be accessed via the Response's json() method, for example: |
| 125 | +``` |
| 126 | + inputs = get_inputs(base_url=base_url, cribl_auth_token=cribl_auth_token, worker_group=worker_group) |
| 127 | + print(f"Input (JSON body): %s" % json.dumps(inputs.json(), indent=4)) |
| 128 | +``` |
| 129 | + |
| 130 | +This will yield the following - a list called 'items', which contains a JSON object for each input configured for the worker group (truncated): |
| 131 | +``` |
| 132 | +{ |
| 133 | + "items": [ |
| 134 | + { |
| 135 | + "id": "http", |
| 136 | + "disabled": true, |
| 137 | + "type": "http", |
| 138 | + "host": "0.0.0.0", |
| 139 | + "port": 10080, |
| 140 | + "elasticAPI": "/elastic", |
| 141 | + "criblAPI": "/cribl", |
| 142 | + "splunkHecAPI": "/services/collector", |
| 143 | + "status": { |
| 144 | + "health": "Green", |
| 145 | + "timestamp": 1669306686561, |
| 146 | + "metrics": { |
| 147 | + "numRequests": 0, |
| 148 | + "numPushed": 0, |
| 149 | + "numHealth": 0, |
| 150 | + "numErrors": 0, |
| 151 | + "numDropped": 0, |
| 152 | + "activeCxn": 0, |
| 153 | + "openCxn": 0, |
| 154 | + "closeCxn": 0, |
| 155 | + "rejectCxn": 0, |
| 156 | + "abortCxn": 0, |
| 157 | + "numInProgress": 0 |
| 158 | + } |
| 159 | + } |
| 160 | + }, |
| 161 | + . |
| 162 | + . |
| 163 | + . |
| 164 | + ] |
| 165 | +} |
| 166 | +``` |
| 167 | + |
| 168 | +##### Payloads |
| 169 | +Payloads sent to the API for create and update operations must be formatted in JSON and have the required parameters depending |
| 170 | +upon the item that being created. |
| 171 | + |
| 172 | +#### A Note on Route Operations |
| 173 | +Handling routes through the API is a bit different than the other configuration items. In a Stream deployment, there is one route table with an ID of "default", which is just a list of route objects. |
| 174 | +Creating a route is actually updating "default" route table by adding the route object to the list, so the HTTP method used is PATCH, and not POST. Similarly, deleting a route involves |
| 175 | +updating the "default" route table by removing the route object from the list. |
| 176 | + |
| 177 | +To make things easier, the API wrapper module provides the following methods to deal with the route table: |
| 178 | + |
| 179 | +- `get_routes(base_url, cribl_auth_token, worker_group)` |
| 180 | + |
| 181 | +- `get_routes_by_id(base_url, cribl_auth_token, route_id, worker_group)` |
| 182 | + |
| 183 | +- `add_route(base_url, cribl_auth_token, route_config, position="start", worker_group=None)` |
| 184 | + |
| 185 | +- `delete_route(base_url, cribl_auth_token, route_id, worker_group=None)` |
| 186 | + |
| 187 | +The add/delete methods update the route table accordingly; the add_route option also allows the developer to specify whether to place the route |
| 188 | +at the beginning or end of the list by exposing a `position` parameter. The value, a string, can be either: |
| 189 | +- `start` |
| 190 | + |
| 191 | +- `end` |
| 192 | + |
| 193 | +If no position is specified, the route is added to the beginning of the list. |
| 194 | + |
| 195 | +#### Specific input and output types |
| 196 | + |
| 197 | +Where applicable, the API wrapper module offers helper functions to create/update/delete specific inputs and outputs. This is done for the developer in order to avoid constructing the entire |
| 198 | +JSON payload when creating one of these components. |
| 199 | + |
| 200 | +An example of the create/update/delete cycle for an HTTP source input can be depicted as follows: |
| 201 | +``` |
| 202 | + from cribl.inputs.http import * |
| 203 | + |
| 204 | + response = create_http_source(base_url=base_url, cribl_auth_token=cribl_auth_token, |
| 205 | + source_id="my_http_source", |
| 206 | + host="localhost", |
| 207 | + port=18000, |
| 208 | + disabled=False, |
| 209 | + enable_proxy_header=False |
| 210 | + worker_group=worker_group) |
| 211 | + print(f"create response: %s " % response.text) |
| 212 | +
|
| 213 | + update_data = { |
| 214 | + "host": "nuc-ubuntu", |
| 215 | + "port": 12345, |
| 216 | + "pqEnabled": True, |
| 217 | + "enableProxyHeader": True |
| 218 | + } |
| 219 | + response = update_http_source(base_url=base_url, cribl_auth_token=cribl_auth_token, source_id="my_http_source", |
| 220 | + update_data=update_data, |
| 221 | + worker_group=worker_group) |
| 222 | + print(f"update response: %s " % response.text) |
| 223 | +
|
| 224 | + response = delete_http_source(base_url=base_url, cribl_auth_token=cribl_auth_token, |
| 225 | + source_id="my_http_source", worker_group=worker_group) |
| 226 | + print(f"delete response: %s " % response.text) |
| 227 | +``` |
| 228 | + |
| 229 | +#### Expert Mode |
| 230 | +Any area of the API may be called via the API wrapper module using the generic methods in lib/http_operations.py: |
| 231 | + |
| 232 | +- `get(url, headers, payload)` |
| 233 | + |
| 234 | +- `post(url, headers, payload)` |
| 235 | + |
| 236 | +- `put(url, headers, data)` |
| 237 | + |
| 238 | +- `patch(url, headers, payload)` |
| 239 | + |
| 240 | +- `delete(url, headers)` |
| 241 | + |
| 242 | +You must explicitly work out the URL to call, construct the headers appropriately, and pass the correct payload |
| 243 | +(or no payload, if not required by the HTTP method in use). The API documentation should be followed when using these |
| 244 | +methods. |
| 245 | + |
| 246 | +#### Notes |
| 247 | +- Each function must have the base_url and cribl_auth token passed to it. In distributed deployments, the worker group name must be passed to most functions (besides system-wide items such as versioning, system, etc) as shown above. |
| 248 | +- Parameters in API wrapper module functions, such as `enable_proxy_header` in the create function, follow snake case. |
| 249 | +- Update functions require a parameter called `update_data`. This is a JSON object that contains the required fields (in this case, host and port) as well as other fields that the developer wishes to change. |
| 250 | +- Note that camel case is used for the field names in these updates in order to align with the API. See documentation at https://docs.cribl.io/api. |
| 251 | +- In this example, `enable_proxy_header` in the `create_http_source` function corresponds to the `enableProxyHeader` field in the update data. |
| 252 | +- It is recommended to use an IDE such as PyCharm or VSCode to assist in development. Auto-complete/code completion should help provide guidance on how to call methods if not explicitly documented. |
| 253 | + |
| 254 | +#### Supplemental API Documentation |
| 255 | +Information on all aspects of the API can be found in the Cribl UI (Settings -> API Reference) or |
| 256 | +at https://docs.cribl.io/api/ |
| 257 | +- This can be referred to for more details on schemas, how to construct payloads when creating/updating configuration items, etc. |
0 commit comments