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.2.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

telicent_label_builder_service-0.1.2-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.2.tar.gz.

File metadata

File hashes

Hashes for telicent_label_builder_service-0.1.2.tar.gz
Algorithm Hash digest
SHA256 1796616aeecb9e8a20dba4ca121383bdd65aa4b5e8461eab5514e7de5b72bee1
MD5 fc5a0b7882bad8f5656cbd90879194ca
BLAKE2b-256 55c2ea8d3114cd32d2f33c7413820b88010417afc7e7ee1d0e787324a5714801

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for telicent_label_builder_service-0.1.2-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 00f1a01f52b6f782e6d89b0abe82cc0998357a491f1601f4da89c65595a5dcbc
MD5 211c808e324b2aa31b74fc6290859484
BLAKE2b-256 050c31926ae1f11b76eda8d7efcb086bac1593e1298afca6d78a4446d5bc60be

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