Skip to main content

A helper package to create security labels from data header

Project description

label-builder-service

label-builder-service integrates with telicent-label-builder to allow wrapping a model in a rest-api default endpoint is /api/v1/ingest which would convert a model to a label

Installation

pip install telicent-label-builder-service

Configuration

The application could only be configured through environment variables. When used in conjunction with telicent-label-builder there is no way to pass a configuration to rest_serivice.py->run_api_service

Configuration lives under telicent-lbapi/api_config/config.py and can be used for reference.

Supported env variables:

LOGGING_LEVEL - sets the log level for the REST Application - Default: INFO

CACHE_TIMEOUT - sets cache expiry time in seconds - Default: 5min

RESTAPI_PORT - the port to run the server on - Default: 8000

RESTAPI_HOST - the adress to run the server on - Default: 0.0.0.0

LOG_TO_CONSOLE - propagates logs to STDOUT - Default: true

LOGING_DIR - logfile storage directory, path will be created, ensure path is writable

Default: UNIX systems - /tmp/logs Windows - <TEMP>/logs

LOG_FILENAME - filename to use for the log file - Default: label-builder-service.log


Detail

Each request would be given a unique ID which is propagated in logs, the format is as follows:

"%(asctime)s [%(levelname)s] [%(name)s:%(funcName)s:%(lineno)d]" 
" [Request ID: %(request_id)s]"
" [Model Class: %(model_class)s] - %(message)s"

RequestID is preserved across the lifecycle of the request. The library supports additional endpoints definitions, see USAGE below. There is a concept of model_class, this is usually the model that was implemented using the label builder. Any endpoints which do data validation would try and use that model unless specified otherwise by the "@set_model_class" decorator. When the decorator is used a middleware, will revert the model back to the original one for this instance of the application.

e.g in the usage case below a call to /custom-endpoint-failing would use MyModel internally, after response is issued the model will be set back to TelicentModel.

The API provides a single endpoint /api/v1/ingest - it tries to convert a model instance to security labels, model in use must implement build_security_labels method, otherwise the endpoint would fail.

In cases where no additional endpoints are required, a function to run the model as a service utilising the /ingest endpoint could be achieved by wrapping run_api_service in a class method within the model itself.

All endpoints including customer defined ones are available under docs or redoc endpoint, default: http://localhost:8000/docs or http://localhost:8000/redoc

E.g:

from telicent_lbapi.rest_service import run_api_service

class MyModel(TelicentMixin):
    testSth: str | None = "sth"
    identifier: str
    classification: str
    orGroups: list[str]
    andGroups: list[str]
    permittedOrgs: list[str]
    permittedNats: list[str]

    def additional_method(self):
        print("Custom functionality here")

    def build_security_labels(self):
        return {"labels": "custom"}
    
    @classmethod
    def run_as_api(cls):
        run_api_service(cls)
    

Usage

from fastapi import APIRouter, Request, HTTPException
from telicent_lbapi.context import ModelContext
from telicent_labels.telicent_model import TelicentMixin
from telicent_lbapi.services.label_builder_service import build_security_labels
from telicent_lbapi.decorators import set_model_class
from pydantic import BaseModel, ValidationError


class MyModel(TelicentMixin):
    testSth: str | None = "sth"
    identifier: str
    classification: str
    orGroups: list[str]
    andGroups: list[str]
    permittedOrgs: list[str]
    permittedNats: list[str]

    def additional_method(self):
        print("Custom functionality here")

    def build_security_labels(self):
        return {"labels": "custom"}


class AnotherModel:
    def additional_method(self):
        print("Another custom functionality here")

    def build_security_labels(self):
        return {"labels": "another_custom"}


custom_router = APIRouter()


@custom_router.get("/custom-endpoint-failing")
@set_model_class(MyModel)
async def custom_endpoint_mymodel(request: Request):
    test_policy = {
        "testSth": "a",
        "classification": "b",
        "permittedOrgs": [
            "ABC",
        ],
        "permittedNats": [
            "GBR",
        ],
        "orGroups": [
            "Apple",
        ],
        "andGroups": [
            "doctor",
        ],
        "originator": "TestOriginator",
        "custodian": "TestCustodian",
        "policyRef": "TestPolicyRef"
    }
    try:
        labels = build_security_labels(data_header=test_policy)
    except ValidationError as e:
        raise HTTPException(status_code=400, detail=str(e)) from e

    return {"message": f"This is a custom endpoint using {MyModel.__name__}", "labels": labels}


@custom_router.get("/custom-endpoint-mymodel")
@set_model_class(MyModel)
async def custom_endpoint_mymodel(request: Request):
    test_policy = {
        "testSth": "a",
        "identifier": "sth",
        "classification": "b",
        "permittedOrgs": [
            "ABC",
        ],
        "permittedNats": [
            "GBR",
        ],
        "orGroups": [
            "Apple",
        ],
        "andGroups": [
            "doctor",
        ],
        "originator": "TestOriginator",
        "custodian": "TestCustodian",
        "policyRef": "TestPolicyRef"
    }
    try:
        labels = build_security_labels(data_header=test_policy)
    except ValidationError as e:
        raise HTTPException(status_code=400, detail=str(e)) from e

    return {"message": f"This is a custom endpoint using {MyModel.__name__}", "labels": labels}


@custom_router.get("/custom-endpoint-anothermodel")
@set_model_class(AnotherModel)
async def custom_endpoint_anothermodel(request: Request):
    return {"message": f"This is a custom endpoint using {ModelContext.get_model_class()}"}


if __name__ == "__main__":
    from telicent_labels import TelicentModel
    from telicent_lbapi.rest_service import run_api_service

    # TelicentModel used here just to illustrate the ability to switch models, the api is model driven.
    run_api_service(model_class=TelicentModel, custom_router=custom_router)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

telicent_label_builder_service-0.1.3.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

telicent_label_builder_service-0.1.3-py2.py3-none-any.whl (30.6 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file telicent_label_builder_service-0.1.3.tar.gz.

File metadata

File hashes

Hashes for telicent_label_builder_service-0.1.3.tar.gz
Algorithm Hash digest
SHA256 cce1f531a06489ae1fbeccf5b1b1ff0725d529ca51094cf69536f900530438f8
MD5 3047e505d31ae7f05bcad1f15c525041
BLAKE2b-256 b0238e935e82ae115925411aa06719513b1ec5c6fd355084a302230fecd9799f

See more details on using hashes here.

File details

Details for the file telicent_label_builder_service-0.1.3-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for telicent_label_builder_service-0.1.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 5d05f078d66713e9ccdfcde8bf4bfc48d6efacbc27c4ad8923ea9f2f00ad8295
MD5 333ec38622b0a6b519096fb6931b8bac
BLAKE2b-256 e226b73a87ed77b5c1f0a58358115d61e46cbdd7f31715ce263c832c6c9ccee6

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page