blazar/doc/source/admin/usage-enforcement.rst
Radosław Piliszek 83f805eb72 Improve ExternalServiceFilter
Apply my comments from the original patch [1] and add unit tests.

[1] https://review.opendev.org/c/openstack/blazar/+/781917

Change-Id: I116aad6677423aedb5dda48f06b36afc32819ba8
2022-09-15 09:32:43 +00:00

161 lines
5.2 KiB
ReStructuredText

=================
Usage Enforcement
=================
Synopsis
========
Usage enforcement and lease constraints can be implemented by operators via
custom usage enforcement filters or an external service.
Description
===========
Usage enforcement filters are called on ``lease_create``, ``lease_update`` and
``on_end`` operations. The filters check whether or not lease values or
allocation criteria pass admin defined thresholds. There are currently two
filters provided out-of-the-box. ``MaxLeaseDurationFilter`` restricts the
duration of leases. ``ExternalServiceFilter`` calls a third-party service for
implementing policies using a URL configured in ``blazar.conf``.
Options
=======
All filters are a subclass of the BaseFilter class located in
``blazar/enforcement/filter/base_filter.py``. Custom filters must implement
methods for ``check_create``, ``check_update``, and ``on_end``. The
``MaxLeaseDurationFilter`` is a good example to follow. Filters are enabled in
``blazar.conf`` under the ``[enforcement]`` group. For example, enabling the
``MaxLeaseDurationFilter`` to limit lease durations to only one day would work
as follows:
.. sourcecode:: console
[enforcement]
enabled_filters = MaxLeaseDurationFilter
max_lease_duration = 86400
..
Do note that filter config options follow filter names - the prefix is always
the snake case of the filter name (``MaxLeaseDurationFilter`` becomes
``max_lease_duration``; in this case it is special that there is nothing
beyond the prefix but there is also ``max_lease_duration_exempt_project_ids``).
MaxLeaseDurationFilter
----------------------
This filter simply examines the lease ``start_date`` and ``end_date``
attributes and rejects the lease if its duration exceeds a threshold. It
supports two configuration options:
* ``max_lease_duration``
* ``max_lease_duration_exempt_project_ids``
See the :doc:`../configuration/blazar-conf` page for a description of these
options.
ExternalServiceFilter
---------------------
This filter delegates the decision for each API to an external HTTP service.
The service must use token-based authentication, accepting (or ignoring)
the static token sent by Blazar in the ``X-Auth-Token`` header.
The following endpoints should be implemented:
* ``POST /check-create``
* ``POST /check-update``
* ``POST /on-end``
The exact URLs can be overridden and not all have to be used (although
we imagine a proper implementation requires at least both checks unless
lease updates are disabled in the first place).
The external service should return ``204 No Content`` if the parameters meet
defined criteria and ``403 Forbidden`` if not. The service may send a JSON
body response with the ``403 Forbidden`` reply, including the rejection
reasoning in the field named ``message`` as in:
.. sourcecode:: json
{
"message": "You shall not pass!"
}
An example of data the external service will receive in a request body (do note
all dates and times are encoded as strings following the ISO8601 standard that
is expected in JSON to represent dates and times):
* Request example:
.. sourcecode:: json
{
"context": {
"user_id": "c631173e-dec0-4bb7-a0c3-f7711153c06c",
"project_id": "a0b86a98-b0d3-43cb-948e-00689182efd4",
"auth_url": "https://api.example.com:5000/v3",
"region_name": "RegionOne"
},
"current_lease": {
"start_date": "2020-05-13T00:00:00.012345+02:00",
"end_time": "2020-05-14T23:59:00.012345+02:00",
"reservations": [
{
"resource_type": "physical:host",
"min": 1,
"max": 2,
"hypervisor_properties": "[]",
"resource_properties": "[\"==\", \"$availability_zone\", \"az1\"]",
"allocations": [
{
"id": "1",
"hypervisor_hostname": "32af5a7a-e7a3-4883-a643-828e3f63bf54",
"extra": {
"availability_zone": "az1"
}
}
]
}
]
},
"lease": {
"start_date": "2020-05-13T00:00:00.012345+02:00",
"end_time": "2020-05-14T23:59:00.012345+02:00",
"reservations": [
{
"resource_type": "physical:host",
"min": 2,
"max": 3,
"hypervisor_properties": "[]",
"resource_properties": "[\"==\", \"$availability_zone\", \"az1\"]",
"allocations": [
{
"id": "1",
"hypervisor_hostname": "32af5a7a-e7a3-4883-a643-828e3f63bf54",
"extra": {
"availability_zone": "az1"
}
},
{
"id": "2",
"hypervisor_hostname": "af69aabd-8386-4053-a6dd-1a983787bd7f",
"extra": {
"availability_zone": "az1"
}
}
]
}
]
}
}
The ``current_lease`` field is present only in ``check-update`` requests and
describes the existing lease. In both checks the ``lease`` field describes
the new lease. In ``on-end``, the ``lease`` field describes the lease that
has just ended.
There is no guarantee on the delivery of the ``on-end`` event and it should be
considered an optimisation rather than a reliable mechanism.