Skip to content

Gateway

Warning

The cattle_grid gateway is meant for testing cattle_grid and for demonstration purposes. The main drawback of this gateway is that it assumes that the user is always connected.

cattle_grid.gateway

The exchanges used by cattle_grid are using routing keys to make processing easier. The cattle_grid gateway takes these messages and readdresses them with routing keys based on an user. Here an user can have multiple actors.

Furthermore, convenience methods are provided to manage users and actors through a HTTP Api. This is in difference to interacting with the Fediverse, which is done through a message queue.

create_gateway_blueprint(config)

Creates a blueprint for HTTP methods of the gateway. One should note that these mostly exist to fulfill secondary concerns of the gateway. Most of the work is done by the router.

Parameters:

Name Type Description Default
config GatewayConfig
required

Returns:

Type Description
Blueprint
Source code in cattle_grid/gateway/__init__.py
def create_gateway_blueprint(config: GatewayConfig) -> Blueprint:
    """Creates a blueprint for HTTP methods of the gateway.
    One should note that these mostly exist to fulfill secondary
    concerns of the gateway. Most of the work is done by the router.

    :param config:
    :return:
    """
    blueprint = Blueprint("gateway_blueprint", __name__)

    if config.enable_authentication:
        blueprint.register_blueprint(gateway_auth_blueprint)

    blueprint.register_blueprint(
        create_user_blueprint(config.admin), url_prefix="/ap/admin"
    )

    return blueprint

create_gateway_router(config)

Creates a router that moves messages to be routed by user.

Parameters:

Name Type Description Default
config GatewayConfig
required

Returns:

Type Description
RabbitRouter
Source code in cattle_grid/gateway/__init__.py
def create_gateway_router(config: GatewayConfig) -> RabbitRouter:
    """Creates a router that moves messages to be routed by user.

    :param config:
    :returns:
    """
    gateway_router = RabbitRouter()
    gateway_router.include_router(router)

    return gateway_router

Authentication

One can allow access to this gateway through either the web_mqtt or web_stomp plugins of RabbitMQ. Then the following module can be used to provide a form of authentication.

This mechanism can be disabled by setting enable_authentication to false.

cattle_grid.gateway.auth

Implementation of a HTTP auth backend for rabbitmq.

A possible configuration can be in the form of

/etc/rabbitmq/conf.d/03_http_auth.conf
auth_backends.1 = internal

auth_backends.2 = http
auth_http.http_method = post
auth_http.user_path = http://cattle_grid/admin/rabbitmq/user
auth_http.vhost_path = http://cattle_grid/admin/rabbitmq/vhost
auth_http.resource_path = http://cattle_grid/admin/rabbitmq/resource
auth_http.topic_path = http://cattle_grid/admin/rabbitmq/topic

gateway_auth_blueprint = Blueprint('gateway_auth', __name__, url_prefix='/admin') module-attribute

Blueprint to be included to provide the endpoints for authentication with rabbitmq

topic_auth() async

Checks if topic is allowed. Currently allowed are

exchange = "amq.topic"

and the routing keys send.username and receive.username

Source code in cattle_grid/gateway/auth.py
@rabbit_blueprint.post("/topic")
async def topic_auth():
    """Checks if topic is allowed. Currently allowed are

    ```
    exchange = "amq.topic"
    ```

    and the routing keys `send.username` and `receive.username`
    """
    username = g.form["username"]
    if g.form["name"] != "amq.topic":
        logger.warning("User %s tried to access exchange %s", username, g.form["name"])
        return "deny"
    if g.form["routing_key"] not in [f"send.{username}", f"receive.{username}"]:
        logger.warning(
            "User %s tried to subscribe to routing_key %s",
            username,
            g.form["routing_key"],
        )
        return "deny"

    return "allow"

user_auth() async

Checks login with username/password

Source code in cattle_grid/gateway/auth.py
@rabbit_blueprint.post("/user")
async def user_auth():
    """Checks login with username/password"""
    username = g.form.get("username")
    user = await user_with_username_password(username, g.form.get("password"))

    if not user:
        logger.warning("Failed login to message broker with username '%s'", username)
        return "deny"

    return "allow"

vhost_auth() async

Authentication for vhosts, currently only “/” is allowed

Source code in cattle_grid/gateway/auth.py
@rabbit_blueprint.post("/vhost")
async def vhost_auth():
    """Authentication for vhosts, currently only "/" is allowed"""
    if g.form["vhost"] != "/":
        logger.warning(
            "User %s tried to access vhost %s", g.form["username"], g.form["vhost"]
        )
        return "deny"
    return "allow"

cattle_grid.gateway.data_types

Action

Bases: str, Enum

Action to be taken by the gateway

Source code in cattle_grid/gateway/data_types.py
class Action(str, Enum):
    """
    Action to be taken by the gateway
    """

    self = 'self'
    send = 'send'
    fetch = 'fetch'
    profile = 'profile'
    options = 'options'
    manage_actor = 'manage_actor'

Action1

Bases: str, Enum

Action taken by the gateway

Source code in cattle_grid/gateway/data_types.py
class Action1(str, Enum):
    """
    Action taken by the gateway
    """

    self = 'self'
    fetch_result = 'fetch_result'
    incoming = 'incoming'
    profile = 'profile'
    options = 'options'

GatewayMessage

Bases: BaseModel

Message send to the gateway then forwarded to cattle_grid

Source code in cattle_grid/gateway/data_types.py
class GatewayMessage(BaseModel):
    """
    Message send to the gateway then forwarded to cattle_grid
    """

    model_config = ConfigDict(
        extra='forbid',
    )
    action: Action
    """
    Action to be taken by the gateway
    """
    actor: str
    """
    actor_id of the actor that is performing the action. Actor must belong to the user
    """
    data: Dict[str, Any]
    """
    Activity to be send.
    """

action: Action instance-attribute

Action to be taken by the gateway

actor: str instance-attribute

actor_id of the actor that is performing the action. Actor must belong to the user

data: Dict[str, Any] instance-attribute

Activity to be send.

GatewayMessageResult

Bases: BaseModel

Message send from the gateway

Source code in cattle_grid/gateway/data_types.py
class GatewayMessageResult(BaseModel):
    """
    Message send from the gateway
    """

    model_config = ConfigDict(
        extra='forbid',
    )
    action: Action1
    """
    Action taken by the gateway
    """
    actor: str
    """
    actor_id of the actor that is receiving the message.
    """
    data: Dict[str, Any]
    """
    Received data.
    """

action: Action1 instance-attribute

Action taken by the gateway

actor: str instance-attribute

actor_id of the actor that is receiving the message.

data: Dict[str, Any] instance-attribute

Received data.

JSON schema

The following is the JSON schema file that is used to generate the models above.

gateway_message.schema.json