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

Uploaded Source

Built Distribution

telicent_label_builder_service-0.1.4-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.4.tar.gz.

File metadata

File hashes

Hashes for telicent_label_builder_service-0.1.4.tar.gz
Algorithm Hash digest
SHA256 7115710f30003a33014a6aa047a89fb4270d5b8193a98c7bb5f847db1433938e
MD5 d75825b1011696b75c51d7d683e8fa2f
BLAKE2b-256 d289992959053c4642d2ce797f5cfe66c2297325f91214881c34103eff52e9fd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for telicent_label_builder_service-0.1.4-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 24489a0350b6a0d60f4f39fbb88f46703d1088846c50f08963d2346b95dcd67c
MD5 79d1760fc61694fdd7f757c8841fcf09
BLAKE2b-256 7ef81a6f10d65a3f0e50a01f83b36775e572aa46c382a47999d037d1508dd6ab

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