Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add insight schemas API #23

Merged
merged 1 commit into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Release History
1.1.0 (2023-12-08)
------------------

- Add api-key limits
- Add api-key limits
- Add insight schemas API

1.0.8 (2023-12-06)
------------------
Expand Down
11 changes: 11 additions & 0 deletions cybsi/cloud/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .auth import APIKeyAuth, AuthAPI
from .client_config import Config
from .insight.api import InsightAPI, InsightAsyncAPI
from .internal import AsyncHTTPConnector, HTTPConnector
from .iocean import IOCeanAPI, IOCeanAsyncAPI

Expand Down Expand Up @@ -77,6 +78,11 @@ def iocean(self) -> IOCeanAPI:
"""IOCean API handle."""
return IOCeanAPI(self._connector)

@property
def insight(self) -> InsightAPI:
"""Insight API handle."""
return InsightAPI(self._connector)


class AsyncClient:
"""The asynchronous analog of :class:`Client`.
Expand Down Expand Up @@ -120,3 +126,8 @@ async def aclose(self) -> None:
def iocean(self) -> IOCeanAsyncAPI:
"""IOCean asynchronous API handle."""
return IOCeanAsyncAPI(self._connector)

@property
def insight(self) -> InsightAsyncAPI:
"""Insight asynchronous API handle."""
return InsightAsyncAPI(self._connector)
11 changes: 11 additions & 0 deletions cybsi/cloud/insight/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Use this section of API to access Insight schemas.
"""

from .api import InsightAPI, InsightAsyncAPI
from .schemas import (
SchemaAPI,
SchemaAsyncAPI,
SchemaView,
SchemaCommonView,
SchemaRegistrationView,
)
20 changes: 20 additions & 0 deletions cybsi/cloud/insight/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from ..internal import BaseAPI, BaseAsyncAPI
from .schemas import SchemaAPI, SchemaAsyncAPI


class InsightAPI(BaseAPI):
"""Insight API."""

@property
def schemas(self) -> SchemaAPI:
"""Get Insight schemas handle."""
return SchemaAPI(self._connector)


class InsightAsyncAPI(BaseAsyncAPI):
"""Insight asynchronous API."""

@property
def schemas(self) -> SchemaAsyncAPI:
"""Schemas asynchronous API handle."""
return SchemaAsyncAPI(self._connector)
251 changes: 251 additions & 0 deletions cybsi/cloud/insight/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
from typing import Optional

from ..api import Tag
from ..internal import BaseAPI, BaseAsyncAPI, JsonObject, JsonObjectView
from ..pagination import AsyncPage, Cursor, Page
from ..view import _TaggedView

_PATH = "/insight/schemas"


class SchemaAPI(BaseAPI):
"""Schema API."""

def register(self, schema: JsonObject) -> "SchemaRegistrationView":
"""Register an enrichment task result object schema.

Note:
Calls `POST /insight/schemas`.
Args:
schema: JSON schema of the enrichment task result object.
See :ref:`enrichment_result_schemas`
for information about schema structure.
Returns:
Schema registration view.
Raises:
:class:`~cybsi.cloud.error.InvalidRequestError`:
Provided values are invalid (see form value requirements).
:class:`~cybsi.cloud.error.ConflictError`: Form contains conflict errors.
Note:
Conflict error codes specific for this method:
* :attr:`~cybsi.cloud.error.ConflictErrorCodes.DuplicateSchema`
"""
resp = self._connector.do_post(path=_PATH, json=schema)
return SchemaRegistrationView(resp.json())

def update(
self,
*,
schema_id: str,
tag: Tag,
schema: JsonObject,
) -> None:
"""Update the enrichment task result object schema.

Note:
Calls `PUT /insight/schemas/{schema_id}`.
Args:
schema_id: URL friendly string, uniquely identifies json schema.
tag: :attr:`SchemaView.tag` value. Use :meth:`view` to retrieve it.
schema: JSON schema of the object. See :ref:`enrichment_result_schemas`
for information about schema structure.
Raises:
:class:`~cybsi.cloud.error.InvalidRequestError`:
Provided values are invalid (see form value requirements).
:class:`~cybsi.cloud.error.SemanticError`: Form contains logic errors.
:class:`~cybsi.cloud.error.ResourceModifiedError`:
Object schema changed since last request. Update tag and retry.
:class:`~cybsi.cloud.error.NotFoundError`: Object schema not found.
Note:
Semantic error codes specific for this method:
* :attr:`~cybsi.cloud.error.SemanticErrorCodes.InvalidSchemaID`
"""

path = f"{_PATH}/{schema_id}"
self._connector.do_put(path=path, tag=tag, json=schema)

def view(self, schema_id: str) -> "SchemaView":
"""Get the enrichment task result object schema view.

Note:
Calls `GET /insight/schemas/{schema_id}`.
Args:
schema_id: URL friendly string, uniquely identifies json schema.
Returns:
Schema view.
Raises:
:class:`~cybsi.cloud.error.NotFoundError`: Object schema not found.
"""

path = f"{_PATH}/{schema_id}"
resp = self._connector.do_get(path=path)
return SchemaView(resp)

def filter(
self,
*,
cursor: Optional[Cursor] = None,
limit: Optional[int] = None,
) -> Page["SchemaCommonView"]:
"""Get an enrichment task result object schemas filtration list.

Note:
Calls `GET /insight/schemas`.
Args:
cursor: Page cursor.
limit: Page limit.
Returns:
Page with schema common views and next page cursor.
Raises:
:class:`~cybsi.cloud.error.InvalidRequestError`:
Provided values are invalid (see form value requirements).
"""

params: JsonObject = {}
if cursor is not None:
params["cursor"] = str(cursor)
if limit is not None:
params["limit"] = limit
resp = self._connector.do_get(path=_PATH, params=params)
return Page(self._connector.do_get, resp, SchemaCommonView)


class SchemaAsyncAPI(BaseAsyncAPI):
"""Schema asynchronous API."""

async def register(self, schema: JsonObject) -> "SchemaRegistrationView":
"""Register an enrichment task result object schema.

Note:
Calls `POST /insight/schemas`.
Args:
schema: JSON schema of the object. See :ref:`enrichment_result_schemas`
for information about schema structure.
Returns:
Schema registration view.
Raises:
:class:`~cybsi.cloud.error.InvalidRequestError`:
Provided values are invalid (see form value requirements).
:class:`~cybsi.cloud.error.ConflictError`: Form contains conflict errors.
Note:
Conflict error codes specific for this method:
* :attr:`~cybsi.cloud.error.ConflictErrorCodes.DuplicateSchema`
"""
resp = await self._connector.do_post(path=_PATH, json=schema)
return SchemaRegistrationView(resp.json())

async def update(
self,
*,
schema_id: str,
tag: Tag,
schema: JsonObject,
) -> None:
"""Update the enrichment task result object schema.

Note:
Calls `PUT /insight/schemas/{schema_id}`.
Args:
schema_id: URL friendly string, uniquely identifies json schema.
tag: :attr:`SchemaView.tag` value. Use :meth:`view` to retrieve it.
schema: JSON schema of the object. See :ref:`enrichment_result_schemas`
for information about schema structure.
Raises:
:class:`~cybsi.cloud.error.InvalidRequestError`:
Provided values are invalid (see form value requirements).
:class:`~cybsi.cloud.error.SemanticError`: Form contains logic errors.
:class:`~cybsi.cloud.error.ResourceModifiedError`:
Object schema changed since last request. Update tag and retry.
:class:`~cybsi.cloud.error.NotFoundError`: Object schema not found.
Note:
Semantic error codes specific for this method:
* :attr:`~cybsi.cloud.error.SemanticErrorCodes.InvalidSchemaID`
"""

path = f"{_PATH}/{schema_id}"
await self._connector.do_put(path=path, tag=tag, json=schema)

async def view(self, schema_id: str) -> "SchemaView":
"""Get the enrichment task result object schema view.

Note:
Calls `GET /insight/schemas/{schema_id}`.
Args:
schema_id: URL friendly string, uniquely identifies json schema.
Returns:
Schema view.
Raises:
:class:`~cybsi.cloud.error.NotFoundError`: Object schema not found.
"""

path = f"{_PATH}/{schema_id}"
resp = await self._connector.do_get(path=path)
return SchemaView(resp)

async def filter(
self,
*,
cursor: Optional[Cursor] = None,
limit: Optional[int] = None,
) -> AsyncPage["SchemaCommonView"]:
"""Get an enrichment task result object schemas filtration list.

Note:
Calls `GET /insight/schemas`.
Args:
cursor: Page cursor.
limit: Page limit.
Returns:
Page with schema common views and next page cursor.
Raises:
:class:`~cybsi.cloud.error.InvalidRequestError`:
Provided values are invalid (see form value requirements).
"""

params: JsonObject = {}
if cursor is not None:
params["cursor"] = str(cursor)
if limit is not None:
params["limit"] = limit
resp = await self._connector.do_get(path=_PATH, params=params)
return AsyncPage(self._connector.do_get, resp, SchemaCommonView)


class SchemaRegistrationView(JsonObjectView):
"""Schema registration view"""

@property
def schema_id(self) -> str:
"""URL friendly string, uniquely identifies json schema."""
return self._get("schemaID")


class SchemaCommonView(JsonObjectView):
"""Schema common view"""

@property
def schema_id(self) -> str:
"""URL friendly string, uniquely identifies json schema."""
return self._get("schemaID")

@property
def title(self) -> str:
"""The human-readable name of the json schema."""
return self._get("title")


class SchemaView(_TaggedView):
"""Schema view"""

@property
def schema_id(self) -> str:
"""URL friendly string, uniquely identifies json schema."""
return self._get("schemaID")

@property
def schema(self) -> JsonObject:
"""JSON schema of the enrichment task result object

See :ref:`enrichment_result_schemas` for information about schema structure.
"""
return self.raw()
7 changes: 7 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ IOCean
:imported-members:
:inherited-members:

Insight
~~~~~~~
.. automodule:: cybsi.cloud.insight
:members:
:imported-members:
:inherited-members:

Common views and data types
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: cybsi.cloud.Null
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ instructions for getting the most out of Cybsi Cloud SDK.
user/data-model
user/advanced
user/authentication
user/enrichment


The API Documentation / Guide
Expand Down
23 changes: 23 additions & 0 deletions docs/user/enrichment.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.. _insight:

Cloud Enrichment Tasks
========================

.. _enrichment_result_schemas:

Enrichment result object schemas
--------------------------------

You can make enrichment using object schema
that defines attribute composition of the objects and data types of the attributes
(see :ref:`data_model` for more information).

To create enrichment tasks, you will need to specify the schema id of the objects that are the results of these tasks.

In the example bellow we get list of enrichment result object schemas.

.. literalinclude:: ../../examples/get_enrichment_results_schemas_chained.py

And one more example of getting schema by ID.

.. literalinclude:: ../../examples/get_enrichment_results_schema.py
10 changes: 10 additions & 0 deletions docs/user/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ Get object changes in the collection
In the example below we get objects changes happened in the collection.

.. literalinclude:: ../../examples/get_collection_objects_changes.py

.. _working_with_tasks:

Working with tasks
------------------

You also can working with enrichment tasks. Create tasks for enriching indicators and get their results.
The results of the enrichment are objects corresponding to a given schema.

See :ref:`enrichment tasks examples <insight>` for more information.
15 changes: 15 additions & 0 deletions examples/get_enrichment_results_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python3
from cybsi.cloud import Client, Config

if __name__ == "__main__":
config = Config(api_key="the cryptic string")

with Client(config) as client:
schema_id = "example-schema"

# Retrieve schema. It describes all attributes of objects you can encounter
# in the result object of the enrichment task with this schema.
schema_view = client.insight.schemas.view(schema_id="example-schema")

# Do something with the schema as SchemaView.
print(schema_view)
Loading