https://cerbos.dev logo
#help
Title
# help
a

Alex Ermolin

05/09/2023, 4:43 PM
Hi, Cerbos team, First of all thank you for this great product! We started using it to implement authorization for our saas system. We have a backend written in python fastapi that will handle verifying that logged in users have the necessary permissions. We want to define in the code what kinds of resources exist and. what actions are defined for each user, so that each service can use values from those classes, instead of strings when calling cerbos. We thought of using pydantic models for that, since fastapi is tightly integrated with the pydantic ecosystem. Is there maybe an example blueprint of what is the recommended way to do it?
c

Charith (Cerbos)

05/09/2023, 5:03 PM
Hi. That's a nice idea. We don't have an example of how to do it, I am afraid. I am not familiar with pydantic but if I was going to implement something similar, I'd probably define the constant values in a structured file format like YAML or JSON. That would allow me to share those values with both my application and Cerbos policies. In the application I could just load the data into a lookup data structure or generate a file with constant definitions. For the policies, I would use a tool like ytt to render the policies by injecting the same constant values into resource names and actions and so on .
a

Alex Ermolin

05/09/2023, 7:53 PM
Thanks 🙂 We actually prefer to define everything in our python code, if it's possible, so it's our single source of truth. I came up with a minimal example. Currently it is detached from the cerbos yaml policies which are defined in yaml, we might in the future also define our policies in python use a CI process to generate the policy yaml files. Here is the code, if anyone needs: schemas/authorization/base.py
Copy code
from enum import Enum
from typing import Generic, TypeVar

from pydantic.generics import GenericModel


class ResourceActions(Enum):
    pass


T = TypeVar("T", bound=ResourceActions)


class ResourceType(GenericModel, Generic[T]):
    kind: str
    actions: type[T]
schemas/authorization/resources.py:
Copy code
from typing import TypeVar

from schemas.authorization.base import ResourceType, ResourceActions


class MyResourceActions(ResourceActions):
    read = "read"
    write = "write"


my_resource_type = ResourceType[MyResourceActions](
    kind="MyResource",
    actions=MyResourceActions,
)


class AnotherResourceActions(ResourceActions):
    copy = "copy"


another_resource_type = ResourceType[AnotherResourceActions](
    kind="AnotherResource",
    actions=AnotherResourceActions,
)


print(my_resource_type.actions.read) # You get autocomplete for .red and .write


X = TypeVar("X")


def do_actions_on_resource_type(resource_type: ResourceType[X], actions: list[X]):
    for action in actions:
        print(f"Performing {action} on resource type {resource_type.kind}")


do_actions_on_resource_type(
    my_resource_type,
    [my_resource_type.actions.read, my_resource_type.actions.write],
)


do_actions_on_resource_type(another_resource_type, [another_resource_type.actions.copy])

# This runs but pycharm highlights it a warning
do_actions_on_resource_type(another_resource_type, [my_resource_type.actions.read])
4 Views