Skip to content
Snippets Groups Projects

perxis-python

Расширения

Локальная разработка

Для работы расширения требуется указание системного контекста при выполнении запросов. Это возможно только в случае прямой работы с сервисами perxis минуя envoy, для этого они должны быть в одной сети. Поэтому нужен локально запущенный экземпляр perxis. Для его запуска нужно в каталоге perxis выполнить команду make run-local. После этого в контейнере в той же сети можно запустить сервис с расширением

Пример написания сервиса расширений

Готовый пример с реализацией простого сервиса можно посмотреть в каталоге examples/extension_service

Аутентификация

gRPC Python предоставляет способ перехвата RPC и добавления метаданных, связанных с аутентификацией, через AuthMetadataPlugin. Те, кому нужен специальный метод аутентификации, могут просто предоставить конкретную реализацию следующего интерфейса:

class AuthMetadataPlugin:
    """A specification for custom authentication."""

    def __call__(self, context, callback):
        """Implements authentication by passing metadata to a callback.

        Implementations of this method must not block.

        Args:
          context: An AuthMetadataContext providing information on the RPC that
            the plugin is being called to authenticate.
          callback: An AuthMetadataPluginCallback to be invoked either
            synchronously or asynchronously.
        """

Затем передайте экземпляр конкретной реализации в функцию grpc.metadata_call_credentials, которая будет преобразована в объект CallCredentials.

ОБРАТИТЕ ВНИМАНИЕ, что можно передать объект функции Python напрямую, но мы рекомендуем наследовать от базового класса, чтобы гарантировать правильность реализации.

def metadata_call_credentials(metadata_plugin, name=None):
    """Construct CallCredentials from an AuthMetadataPlugin.

    Args:
      metadata_plugin: An AuthMetadataPlugin to use for authentication.
      name: An optional name for the plugin.

    Returns:
      A CallCredentials.
    """

Объект CallCredentials можно передать непосредственно в RPC, например:

call_credentials = grpc.metadata_call_credentials(my_foo_plugin)
stub.FooRpc(request, credentials=call_credentials)

Пример авторизации и аутентификации OAuth2

import grpc
from oauthlib.oauth2 import Client
from oauthlib.oauth2.rfc6749.parameters import prepare_token_request
from auth import OAuth2Plugin
from users.users_pb2 import GetRequest
from users.users_pb2_grpc import UsersStub

# Могут быть использованы как встроенные клиенты, такие как WebApplicationClient, BackendApplicationClient, 
# так и допускается реализовать собственный класс с кастомным поведением

class ExtendedClient(Client):
    def __init__(self, client_id, grant_type, username, password, **kwargs):
        self.grant_type = grant_type
        self.username = username
        self.password = password
        super(ExtendedClient, self).__init__(client_id, **kwargs)

    def prepare_request_body(self, body='', scope=None, include_client_id=False, **kwargs):
        kwargs['client_id'] = self.client_id
        kwargs['include_client_id'] = include_client_id
        return prepare_token_request(self.grant_type, body=body, username=self.username,
                                     password=self.password, scope=scope, **kwargs)

oauth2_plugin = OAuth2Plugin(
    client=ExtendedClient(client_id='client_id', grant_type='password', username='user', password='pass'), 
    client_secret='client_secret', 
    token_url='https://example.com/oauth/token', 
    audience='audience'
)

call_credentials = grpc.metadata_call_credentials(oauth2_plugin)

with grpc.insecure_channel('localhost:50051') as channel:
    request = GetRequest(user_id=1)
    stub = UsersStub(channel)
    stub.Get(request, credentials=call_credentials)