Skip to main content

Общая библиотека контроля доступа для микросервисов

Project description

Общая библиотека контроля доступа для микросервисов

Подключение

settings.py:

INSTALLED_APPS = [
    # другие приложение
    'testapp.core',
    'librbac',                         # для management команды rbac
    'librbac.contrib.migrations',      # для поддержки миграций
]

# Опционально. 
# Подойдёт любая имплементация, где `request.user` поддерживает `librbac.domain.permissions.UserProtocol` 
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'oidc_auth.authentication.JSONWebTokenAuthentication',
    ),
}

OIDC_AUTH = {
    # URL сервиса аутентификации, необходимо указать своё значение
    'OIDC_ENDPOINT': 'http://testserver/oauth',
    
    # Функция преобразующая токен в объект пользователя. Указать как есть.
    'OIDC_RESOLVE_USER_FUNCTION': 'librbac.contrib.oidc.auth.get_user_from_token',
    
    # Заголовок в котором хранится токен. Указать как есть.
    'JWT_AUTH_HEADER_PREFIX': 'Bearer',

    # The Claims Options can now be defined by a static string.
    # ref: https://docs.authlib.org/en/latest/jose/jwt.html#jwt-payload-claims-validation
    # The old OIDC_AUDIENCES option is removed in favor of this new option.
    # `aud` is only required, when you set it as an essential claim.
    'OIDC_CLAIMS_OPTIONS': {
        'iss': {
            'essential': True,
        }
    },
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

testapp/__init__.py:

from typing import TYPE_CHECKING

from explicit.contrib.messagebus.event_registry import Registry


if TYPE_CHECKING:
    from explicit.messagebus.messagebus import MessageBus  # noqa


default_app_config = f'{__package__}.apps.AppConfig'


bus: 'MessageBus'

event_registry = Registry()

testapp/apps.py:

from django.apps.config import AppConfig as AppConfigBase


class AppConfig(AppConfigBase):
    name = __package__

    _rbac_permissions_topic = 'test.rbac.permission'

    def _bootstrap(self):
        """Предоставление общей шины ядра."""
        ...

    def _setup_rbac(self):
        from librbac.infrastructure.rest_framework.collector import (
            AppsPermissionsCollector)
        from librbac.infrastructure.rest_framework.backend import (
            RestFrameworkBackend)
        from librbac.infrastructure.explicit.publisher import (
            ServiceBusPublisher)
        from librbac.manager import RBACManager
        from testapp.core.adapters.messaging import adapter

        RBACManager.bootstrap(
            collector_cls=AppsPermissionsCollector,
            backend_cls=RestFrameworkBackend,
            publisher=ServiceBusPublisher(adapter=adapter, topic=self._rbac_permissions_topic),
            # или если нужно отправлять события в локальную шину
            # publisher=LocalBusPermissionsPublisher(bus=bus),
        )

    # Опционально, если нужны миграции
    def _setup_rbac_migrations(self):
        from librbac.contrib.migrations import config
        from testapp import core
        from testapp.core.adapters import messaging

        class Config(config.IConfig):
            bus = core.bus
            adapter = messaging.adapter
            rbac_topic_permission = self._rbac_permissions_topic

        config.migrations_config = Config()

    def ready(self):
        self._bootstrap()
        self._setup_rbac()
        self._setup_rbac_migrations()

testapp/rest/persons/permissions/rules.py

from testapp.core.persons.models import Person


def is_own_person(
    context: 'GenericViewSet',
    request: 'Request',
    user: 'UserProtocol',
):
    """Проверка отношения пользователя к ФЛ."""
    person_id = context.get_rbac_rule_data()

    user_id = user.pk
    return Person.objects.filter(id=person_id, user_id=user_id).exists()

testapp/rest/persons/permissions/__init__.py

from librbac.domain.permissions import PermissionGroup, Permission

from . import rules

PERM_NAMESPACE_TEST = 'test'

PERM_RESOURCE__PERSON = 'person'
PERM__PERSON__READ = Permission(
    # (namespace, resource, action, scope)
    PERM_NAMESPACE_TEST, PERM_RESOURCE__PERSON, 'read'
)
PERM__PERSON__WRITE_OWN = Permission(
    PERM_NAMESPACE_TEST, PERM_RESOURCE__PERSON, 'write', 'own'
)
# Описание разрешений
# -----------------------------------------------------------------------------
permissions = (
    (PERM__PERSON__READ, 'Просмотр ФЛ'),
    (PERM__PERSON__WRITE_OWN, 'Редактирование своего ФЛ'),
)

dependencies = {
    PERM__PERSON__WRITE_OWN: {
        PERM__PERSON__READ,
    },
}
# Описание связей разделов и групп разрешений
# -----------------------------------------------------------------------------
partitions = {
    'Администрирование': (
        PermissionGroup(PERM_NAMESPACE_TEST, PERM_RESOURCE__PERSON),
    ),
}
# Описание правил доступа
# -----------------------------------------------------------------------------
rules = {
    PERM__PERSON__WRITE_OWN: (rules.is_own_person,),
}

# Сопоставление представлений с разрешениями (взаимоисключающее с RBACMixin)
# -----------------------------------------------------------------------------
viewset_permission_mapping = {
    'testapp.rest.persons.views.PersonViewSet': dict(
        create=(PERM__PERSON__WRITE_OWN,),
        partial_update=(PERM__PERSON__WRITE_OWN,),
        destroy=(PERM__PERSON__WRITE_OWN,),
        retrieve=(PERM__PERSON__READ,),
        list=(PERM__PERSON__READ,),
    )
}

testapp/views.py

from rest_framework.viewsets import ModelViewSet

from librbac.infrastructure.django.rest_framework.viewsets import RBACMixin

from .permissions import PERM__PERSON__READ
from .permissions import PERM__PERSON__WRITE


class PersonViewSet(RBACMixin, ModelViewSet):
    
    # сопоставление действий с разрешениями (взаимоисключающее с permissions.viewset_permission_mapping)
    perm_map = dict(
        create=(PERM__PERSON__WRITE,),
        partial_update=(PERM__PERSON__WRITE,),
        destroy=(PERM__PERSON__WRITE,),
        retrieve=(PERM__PERSON__READ,),
        list=(PERM__PERSON__READ,),
    )

    ...

Миграции разрешений

Описание в модуле миграций

Работа над пакетом

Подготовка среды разработки

Необходимый набор инструментов:

  • tox — оркестрация окружений и запуск команд
  • tox-uv — для управления окружениями в tox
  • tox-docker — для запуска инфраструктурных сервисов, необходимых в тестах.

Быстрый старт

  1. Установите необходимые инструменты:
uv tool install tox --with tox-uv --with tox-docker
  1. Клонируйте репозиторий и перейдите в директорию проекта:
git clone ssh://git@stash.bars-open.ru:7999/edueo/librbac.git
cd librbac
  1. Запустите тесты и проверки:
tox

Проверка качества и форматирование кода

tox -e lint

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

librbac-4.0.0.tar.gz (27.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

librbac-4.0.0-py3-none-any.whl (38.2 kB view details)

Uploaded Python 3

File details

Details for the file librbac-4.0.0.tar.gz.

File metadata

  • Download URL: librbac-4.0.0.tar.gz
  • Upload date:
  • Size: 27.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.23

File hashes

Hashes for librbac-4.0.0.tar.gz
Algorithm Hash digest
SHA256 f651d1bf7f11c1fe2faf151c6505835fd287b0843f85e5b002cab8f29339fef7
MD5 ebc9f40014bf4062a20d119a3a5e6454
BLAKE2b-256 46d8fa875673bc4e7a1f58f71cdd784f17394cffb992486eb51180912fd3fcec

See more details on using hashes here.

File details

Details for the file librbac-4.0.0-py3-none-any.whl.

File metadata

  • Download URL: librbac-4.0.0-py3-none-any.whl
  • Upload date:
  • Size: 38.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.23

File hashes

Hashes for librbac-4.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 603bcbbbc8ce23d549298d0ec80474590af5641cd4fe2e10581e65361390ec01
MD5 fcda3ab5b4eafaf0ab784c87bccb29cb
BLAKE2b-256 8a9542436bcf033aae055f4f96189c7902892dd9cfb8ec580bc253d4a7414edd

See more details on using hashes here.

Supported by

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