Skip to content

Commit 43a80df

Browse files
committed
migrate to github
1 parent e3887dc commit 43a80df

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+3978
-0
lines changed

src/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Cribl
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

src/Pipfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[[source]]
2+
url = "https://pypi.org/simple"
3+
verify_ssl = true
4+
name = "pypi"
5+
6+
[packages]
7+
python-api = {editable = true, path = "."}
8+
9+
[dev-packages]
10+
11+
[requires]
12+
python_version = "3.9"

src/README.md

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
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.

src/cribl/__init__.py

Whitespace-only changes.

src/cribl/auth/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .auth_operations import *

src/cribl/auth/auth_operations.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from ..lib.http_operations import *
2+
3+
4+
def api_get_auth_data(base_url, username, password):
5+
headers = {"Content-type": "application/json"}
6+
payload = {"username": username,
7+
"password": password}
8+
try:
9+
return post(base_url + "/auth/login",
10+
headers=headers, payload=payload)
11+
12+
except Exception as e:
13+
raise Exception("General exception raised while attempting to get auth data from Cribl: %s" % str(e))

src/cribl/collectors/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .collector_operations import *
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from ..lib.http_operations import *
2+
3+
4+
def get_collectors(base_url, cribl_auth_token, worker_group=None):
5+
headers = {"Content-type": "application/json",
6+
"Authorization": "Bearer " + cribl_auth_token}
7+
payload = None
8+
9+
try:
10+
if worker_group is not None:
11+
return get(base_url + "/m/" + worker_group + "/collectors",
12+
headers=headers, payload=payload)
13+
else:
14+
return get(base_url + "/collectors",
15+
headers=headers, payload=payload)
16+
17+
except Exception as e:
18+
raise Exception(
19+
"General exception raised while attempting to get collector information from Cribl: %s" % str(e))
20+
21+
22+
def get_collector_by_id(base_url, cribl_auth_token, collector_id, worker_group=None):
23+
headers = {"Content-type": "application/json",
24+
"Authorization": "Bearer " + cribl_auth_token}
25+
26+
payload = collector = None
27+
28+
try:
29+
if worker_group is not None:
30+
return get(base_url + "/m/" + worker_group + "/collectors/" + collector_id,
31+
headers=headers, payload=payload)
32+
else:
33+
return get(base_url + "/collectors/" + collector_id,
34+
headers=headers, payload=payload)
35+
36+
except Exception as e:
37+
raise Exception(
38+
"General exception raised while attempting to get collector information from Cribl: %s" % str(e))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .event_breaker_rules_operations import *

0 commit comments

Comments
 (0)