<div align="center">
<img width="60px" src="https://pts-project.org/android-chrome-512x512.png">
<h1>Python 3 Colander REST client</h1>
<p>
Brings your project the ability to populate your <a href="https://github.com/PiRogueToolSuite/colander" alt="Colander repository">Colander</a> server with collected data.
</p>
<p>
License: GPLv3
</p>
<p>
<a href="https://pts-project.org">Website</a> |
<a href="https://pts-project.org/docs/colander/overview/">Documentation</a> |
<a href="https://discord.gg/qGX73GYNdp">Support</a>
</p>
</div>
## Installation
```
pip install colander-client
```
## Project status
* Cases : Query / Create
* Devices : Query / Create
* Observables : Query / Create
* PiRogueExperiment : Query / Create
* Artifacts : Query / Create
* Teams : Query
_Refer to Colander documentation for data type explanation._
_For a quick overview of changes, take a look at [revisions](#Revisions)_
> [!WARNING]
> Deprecation warnings have been introduced.
> Keep an eye on those. Backward compatibilities support will be dropped sooner of later.
## Usage example
### Instancing
```python
from colander_client.client import Client
base_url = 'https://my-colander-server'
api_key = 'my-user-api-key'
client = Client(base_url=base_url, api_key=api_key)
```
The library also support the following environment variables :
* `COLANDER_PYTHON_CLIENT_BASE_URL`
* `COLANDER_PYTHON_CLIENT_API_KEY`
Having such environment variables set, you can just do:
```python
from colander_client.client import Client
client = Client()
```
### Case management
Before all, you need a case to work with:
```python
# Assuming the given case id :
case_id = 'current-case-id-im-working-on'
case = client.get_case(case_id)
```
Your Case will be asked for each futur creation calls:
```python
artifact = client.upload_artifact(case=case, filepath='/tmp/dump', ...)
experiment = client.create_pirogue_experiment(case=case, pcap=pcap_artifact, ...)
```
Since, the Case is somehow the workspace you are working on during a Colander populating session,
you can use the following handy function:
```python
client.switch_case(case)
```
Then you may avoid mentioning case in futur creation calls:
```python
artifact = client.upload_artifact(filepath='/tmp/dump', ...)
experiment = client.create_pirogue_experiment(pcap=pcap_artifact, ...)
```
To disable case switching:
```python
client.switch_case(None)
```
In any state, Case presence at function call takes precedence.
### Case creation
You may want to create a case on the fly. Since v1.0.4, you can create a case like this:
```python
from colander_client.domain import TlpPap
fresh_case = client.create_case(name='My beaufiful new case',
description='Sensitive stuff',
tlp=TlpPap.AMBER,
pap=TlpPap.RED)
```
> [!IMPORTANT]
> Even if it is optional, we encourage you to specify `tlp` and `pap` levels
> for new cases.
You may want to specify which teams you want to share this case with.
For that, you have to query for teams beforehand:
```python
my_team_list = client.get_teams(name='my team')
shared_fresh_case = client.create_case(name='My beaufiful new case',
description='Sensitive stuff',
teams=my_team_list,
tlp=TlpPap.WHITE,
pap=TlpPap.GREEN)
```
Or with a specific team:
```python
my_team = client.get_team('a-team-id-i-know')
shared_fresh_case = client.create_case(name='My beaufiful new case',
description='Sensitive stuff',
teams=[my_team])
```
> [!NOTE]
> Be careful to provide a list of team
### Artifact uploads
```python
a_type = client.get_artifact_type_by_short_name( 'SAMPLE' )
# Assuming we have switched to a Case
artifact = client.upload_artifact(
filepath='/tmp/captured.file', artifact_type=a_type)
```
Large file upload progression can be followed with a progress callback:
```python
def progress(what, percent, status):
print(f"{what} is at {percent}%, currently it is: {status}")
# in case of artifact upload progress 'what' is the given filepath
a_type = client.get_artifact_type_by_short_name( 'SAMPLE' )
# Assuming we have switched to a Case
artifact = client.upload_artifact(
filepath='/tmp/captured.file', artifact_type=a_type, progress_callback=progress)
```
When you have many uploads to proceed, you can globally set a callback on the client,
avoiding repetitively passing it at function calls:
```python
client.set_global_progress_callback(progress)
```
In any state, callback presence at function call takes precedence.
### PiRogue Experiment creation
```python
experiment = client.create_pirogue_experiment(
name='My today investigation',
pcap=pcap_artifact,
socket_trace=socket_trace_artifact,
sslkeylog=sslkeylog_artifact)
```
### Device creation
Device can be specified on Artifact or PiRogue Experiment.
The creation is as follow:
```python
d_type = client.get_device_type_by_short_name('LAPTOP')
pul_device = client.create_device(name='Potential unsecure laptop', device_type=d_type)
```
Then specified at Artifact or PiRogue Experiment creation:
```python
artifact = client.upload_artifact(
filepath='/tmp/captured.file', artifact_type=a_type,
extra_params={
'extracted_from': pul_device
})
experiment = client.create_pirogue_experiment(
name='My today investigation',
pcap=pcap_artifact,
socket_trace=socket_trace_artifact,
sslkeylog=sslkeylog_artifact,
extra_params={
'target_device': pul_device
})
```
### Relations
You can create entities relation like this:
```python
artifact_1 = client.upload_artifact( [...] )
artifact_2 = client.upload_artifact( [...] )
device_1 = client.create_device( [...] )
relation_1 = client.creation_relation(name='internally refers',
obj_from=artifact_1,
obj_to=artifact_2)
relation_2 = client.creation_relation(name='mentions victim name',
obj_from=artifact_2,
obj_to=device_1)
```
## Revisions
### 1.0.4 - August 1st 2024
* Add teams basic support (query)
* Add case creation support
* Add entity relations support (query and creation)
* Client domains refactor
* Some minor deprecation introduction
### 1.0.3 - January 22th 2024
* Add observables support (query and creation)
### 1.0.2 - January 16th 2023
* Add case search by name
* Add device creation support
Raw data
{
"_id": null,
"home_page": "https://github.com/PiRogueToolSuite/colander-python-client.git",
"name": "colander-client",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "U+039b",
"author_email": "esther@pts-project.org",
"download_url": "https://files.pythonhosted.org/packages/9f/36/4cb4693a46eefc95b12db0017a44bcdb62b164ec3d7554d3c0ef07359e49/colander-client-1.0.5.tar.gz",
"platform": null,
"description": "<div align=\"center\">\n<img width=\"60px\" src=\"https://pts-project.org/android-chrome-512x512.png\">\n<h1>Python 3 Colander REST client</h1>\n<p>\nBrings your project the ability to populate your <a href=\"https://github.com/PiRogueToolSuite/colander\" alt=\"Colander repository\">Colander</a> server with collected data.\n</p>\n<p>\nLicense: GPLv3\n</p>\n<p>\n<a href=\"https://pts-project.org\">Website</a> | \n<a href=\"https://pts-project.org/docs/colander/overview/\">Documentation</a> | \n<a href=\"https://discord.gg/qGX73GYNdp\">Support</a>\n</p>\n</div>\n\n## Installation\n\n```\npip install colander-client\n```\n\n## Project status\n\n* Cases : Query / Create\n* Devices : Query / Create\n* Observables : Query / Create\n* PiRogueExperiment : Query / Create\n* Artifacts : Query / Create\n* Teams : Query\n\n_Refer to Colander documentation for data type explanation._\n\n_For a quick overview of changes, take a look at [revisions](#Revisions)_ \n\n> [!WARNING]\n> Deprecation warnings have been introduced.\n> Keep an eye on those. Backward compatibilities support will be dropped sooner of later. \n\n## Usage example\n\n### Instancing\n\n```python\nfrom colander_client.client import Client\n\nbase_url = 'https://my-colander-server'\napi_key = 'my-user-api-key'\n\nclient = Client(base_url=base_url, api_key=api_key)\n```\n\nThe library also support the following environment variables :\n* `COLANDER_PYTHON_CLIENT_BASE_URL`\n* `COLANDER_PYTHON_CLIENT_API_KEY`\n\nHaving such environment variables set, you can just do:\n\n```python\nfrom colander_client.client import Client\n\nclient = Client()\n```\n\n### Case management\n\nBefore all, you need a case to work with:\n\n```python\n# Assuming the given case id :\ncase_id = 'current-case-id-im-working-on'\n\ncase = client.get_case(case_id)\n```\n\nYour Case will be asked for each futur creation calls:\n\n```python\nartifact = client.upload_artifact(case=case, filepath='/tmp/dump', ...)\nexperiment = client.create_pirogue_experiment(case=case, pcap=pcap_artifact, ...)\n```\n\nSince, the Case is somehow the workspace you are working on during a Colander populating session,\nyou can use the following handy function:\n\n```python\nclient.switch_case(case)\n```\n\nThen you may avoid mentioning case in futur creation calls:\n```python\nartifact = client.upload_artifact(filepath='/tmp/dump', ...)\nexperiment = client.create_pirogue_experiment(pcap=pcap_artifact, ...)\n```\n\nTo disable case switching:\n```python\nclient.switch_case(None)\n```\n\nIn any state, Case presence at function call takes precedence.\n\n### Case creation\n\nYou may want to create a case on the fly. Since v1.0.4, you can create a case like this:\n```python\nfrom colander_client.domain import TlpPap\n\nfresh_case = client.create_case(name='My beaufiful new case',\n description='Sensitive stuff',\n tlp=TlpPap.AMBER,\n pap=TlpPap.RED)\n```\n> [!IMPORTANT]\n> Even if it is optional, we encourage you to specify `tlp` and `pap` levels\n> for new cases.\n\nYou may want to specify which teams you want to share this case with.\nFor that, you have to query for teams beforehand:\n\n```python\nmy_team_list = client.get_teams(name='my team')\n\nshared_fresh_case = client.create_case(name='My beaufiful new case',\n description='Sensitive stuff',\n teams=my_team_list,\n tlp=TlpPap.WHITE,\n pap=TlpPap.GREEN)\n```\n\nOr with a specific team:\n```python\nmy_team = client.get_team('a-team-id-i-know')\n\nshared_fresh_case = client.create_case(name='My beaufiful new case',\n description='Sensitive stuff',\n teams=[my_team])\n```\n> [!NOTE]\n> Be careful to provide a list of team\n\n### Artifact uploads\n\n```python\na_type = client.get_artifact_type_by_short_name( 'SAMPLE' )\n# Assuming we have switched to a Case\nartifact = client.upload_artifact(\n filepath='/tmp/captured.file', artifact_type=a_type)\n```\n\nLarge file upload progression can be followed with a progress callback:\n```python\ndef progress(what, percent, status):\n print(f\"{what} is at {percent}%, currently it is: {status}\")\n # in case of artifact upload progress 'what' is the given filepath\n\na_type = client.get_artifact_type_by_short_name( 'SAMPLE' )\n# Assuming we have switched to a Case\nartifact = client.upload_artifact(\n filepath='/tmp/captured.file', artifact_type=a_type, progress_callback=progress)\n```\n\nWhen you have many uploads to proceed, you can globally set a callback on the client,\navoiding repetitively passing it at function calls:\n```python\nclient.set_global_progress_callback(progress)\n```\n\nIn any state, callback presence at function call takes precedence.\n\n### PiRogue Experiment creation\n\n```python\nexperiment = client.create_pirogue_experiment(\n name='My today investigation',\n pcap=pcap_artifact,\n socket_trace=socket_trace_artifact,\n sslkeylog=sslkeylog_artifact)\n```\n\n### Device creation\n\nDevice can be specified on Artifact or PiRogue Experiment.\nThe creation is as follow:\n```python\nd_type = client.get_device_type_by_short_name('LAPTOP')\n\npul_device = client.create_device(name='Potential unsecure laptop', device_type=d_type)\n```\n\nThen specified at Artifact or PiRogue Experiment creation:\n```python\nartifact = client.upload_artifact(\n filepath='/tmp/captured.file', artifact_type=a_type,\n extra_params={\n 'extracted_from': pul_device\n })\n\nexperiment = client.create_pirogue_experiment(\n name='My today investigation',\n pcap=pcap_artifact,\n socket_trace=socket_trace_artifact,\n sslkeylog=sslkeylog_artifact,\n extra_params={\n 'target_device': pul_device\n })\n```\n\n### Relations\n\nYou can create entities relation like this:\n```python\nartifact_1 = client.upload_artifact( [...] )\nartifact_2 = client.upload_artifact( [...] )\ndevice_1 = client.create_device( [...] )\n\nrelation_1 = client.creation_relation(name='internally refers',\n obj_from=artifact_1,\n obj_to=artifact_2)\n\nrelation_2 = client.creation_relation(name='mentions victim name',\n obj_from=artifact_2,\n obj_to=device_1)\n```\n\n\n## Revisions\n### 1.0.4 - August 1st 2024\n * Add teams basic support (query)\n * Add case creation support\n * Add entity relations support (query and creation)\n * Client domains refactor\n * Some minor deprecation introduction\n\n### 1.0.3 - January 22th 2024\n * Add observables support (query and creation)\n\n### 1.0.2 - January 16th 2023\n * Add case search by name\n * Add device creation support\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Colander REST API Python client",
"version": "1.0.5",
"project_urls": {
"Homepage": "https://github.com/PiRogueToolSuite/colander-python-client.git"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "22e189588837f7cefbd38ef7301ae13ef90f73a32c5c90cf160b16bfdd77742f",
"md5": "45fa483c68cb20590332b2b4c603d813",
"sha256": "79e75a5e76c5e0116c14b86103fe57472b81ceecbe43bae6b193a0455b824929"
},
"downloads": -1,
"filename": "colander_client-1.0.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "45fa483c68cb20590332b2b4c603d813",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 23866,
"upload_time": "2024-09-06T08:03:23",
"upload_time_iso_8601": "2024-09-06T08:03:23.365492Z",
"url": "https://files.pythonhosted.org/packages/22/e1/89588837f7cefbd38ef7301ae13ef90f73a32c5c90cf160b16bfdd77742f/colander_client-1.0.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9f364cb4693a46eefc95b12db0017a44bcdb62b164ec3d7554d3c0ef07359e49",
"md5": "da7d5afb3a64dd0bb1c76c0a795598ab",
"sha256": "dc67fda385385a1e824fc5db82c3b5c95a4f7717ba4406ffe86ae47b2714006b"
},
"downloads": -1,
"filename": "colander-client-1.0.5.tar.gz",
"has_sig": false,
"md5_digest": "da7d5afb3a64dd0bb1c76c0a795598ab",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 22743,
"upload_time": "2024-09-06T08:03:24",
"upload_time_iso_8601": "2024-09-06T08:03:24.962735Z",
"url": "https://files.pythonhosted.org/packages/9f/36/4cb4693a46eefc95b12db0017a44bcdb62b164ec3d7554d3c0ef07359e49/colander-client-1.0.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-09-06 08:03:24",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "PiRogueToolSuite",
"github_project": "colander-python-client",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "colander-client"
}