132 lines
4.5 KiB
ReStructuredText
132 lines
4.5 KiB
ReStructuredText
:title: Tenant Scoped REST API
|
|
|
|
.. _tenant-scoped-rest-api:
|
|
|
|
Tenant Scoped REST API
|
|
======================
|
|
|
|
Users can perform some privileged actions at the tenant level through protected
|
|
endpoints of the REST API, if these endpoints are activated.
|
|
|
|
The supported actions are **autohold**, **enqueue/enqueue-ref**,
|
|
**dequeue/dequeue-ref** and **promote**. These are similar to the ones available
|
|
through Zuul's CLI.
|
|
|
|
The protected endpoints require a bearer token, passed to Zuul Web Server as the
|
|
**Authorization** header of the request. The token and this workflow follow the
|
|
JWT standard as established in this `RFC <https://tools.ietf.org/html/rfc7519>`_.
|
|
|
|
Important Security Considerations
|
|
---------------------------------
|
|
|
|
Anybody with a valid token can perform privileged actions exposed
|
|
through the REST API. Furthermore revoking tokens, especially when manually
|
|
issued, is not trivial.
|
|
|
|
As a mitigation, tokens should be generated with a short time to
|
|
live, like 10 minutes or less. If the token contains authorization Information
|
|
(see the ``zuul.admin`` claim below), it should be generated with as little a scope
|
|
as possible (one tenant only) to reduce the surface of attack should the
|
|
token be compromised.
|
|
|
|
Exposing administration tasks can impact build results (dequeue-ing buildsets),
|
|
and pose potential resources problems with Nodepool if the ``autohold`` feature
|
|
is abused, leading to a significant number of nodes remaining in "hold" state for
|
|
extended periods of time. As always, "with great power comes great responsibility"
|
|
and tokens should be handed over with discernment.
|
|
|
|
Configuration
|
|
-------------
|
|
|
|
To enable tenant-scoped access to privileged actions, see the Zuul Web Server
|
|
component's section.
|
|
|
|
To set access rules for a tenant, see :ref:`the documentation about tenant
|
|
definition <admin_rule_definition>`.
|
|
|
|
Most of the time, only one authenticator will be needed in Zuul's configuration;
|
|
namely the configuration matching a third party identity provider service like
|
|
dex, auth0, keycloak or others. It can be useful however to add another
|
|
authenticator similar to this one:
|
|
|
|
.. code-block:: ini
|
|
|
|
[auth zuul_operator]
|
|
driver=HS256
|
|
allow_authz_override=true
|
|
realm=zuul.example.com
|
|
client_id=zuul.example.com
|
|
issuer_id=zuul_operator
|
|
secret=exampleSecret
|
|
|
|
With such an authenticator, a Zuul operator can use Zuul's CLI to
|
|
issue tokens overriding a tenant's access rules if need
|
|
be. A user can then use these tokens with Zuul's CLI to perform protected actions
|
|
on a tenant temporarily, without having to modify a tenant's access rules.
|
|
|
|
.. _jwt-format:
|
|
|
|
JWT Format
|
|
----------
|
|
|
|
Zuul can consume JWTs with the following minimal set of claims:
|
|
|
|
.. code-block:: javascript
|
|
|
|
{
|
|
'iss': 'jwt_provider',
|
|
'aud': 'my_zuul_deployment',
|
|
'exp': 1234567890,
|
|
'iat': 1234556780,
|
|
'sub': 'alice'
|
|
}
|
|
|
|
* **iss** is the issuer of the token. It can be used to filter
|
|
Identity Providers.
|
|
* **aud**, as the intended audience, is usually the client id as registered on
|
|
the Identity Provider.
|
|
* **exp** is the token's expiry timestamp.
|
|
* **iat** is the token's date of issuance timestamp.
|
|
* **sub** is the default, unique identifier of the user.
|
|
|
|
JWTs can be extended arbitrarily with other claims. Zuul however can look for a
|
|
specific **zuul** claim, if the ``allow_authz_override`` option was set to True
|
|
in the authenticator's configuration. This claim has the following format:
|
|
|
|
.. code-block:: javascript
|
|
|
|
{
|
|
'zuul': {
|
|
'admin': ['tenant-one', 'tenant-two']
|
|
}
|
|
}
|
|
|
|
The **admin** field is a list of tenants on which the token's bearer is granted
|
|
the right to perform privileged actions.
|
|
|
|
Manually Generating a JWT
|
|
-------------------------
|
|
|
|
An operator can generate a JWT by using the settings of a configured authenticator
|
|
in ``zuul.conf``.
|
|
|
|
For example, in Python, and for an authenticator using the ``HS256`` algorithm:
|
|
|
|
.. code-block:: python
|
|
|
|
>>> import jwt
|
|
>>> import time
|
|
>>> jwt.encode({'sub': 'user1',
|
|
'iss': <issuer_id>,
|
|
'aud': <client_id>,
|
|
'iat': time.time(),
|
|
'exp': time.time() + 300,
|
|
'zuul': {
|
|
'admin': ['tenant-one']
|
|
}
|
|
}, <secret>, algorithm='HS256')
|
|
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ6dXVsIjp7ImFkbWluIjpbInRlbmFudC1vbmUiXX0sInN1YiI6InZlbmttYW4iLCJpc3MiOiJtYW51YWwiLCJleHAiOjE1NjAzNTQxOTcuMTg5NzIyLCJpYXQiOjE1NjAzNTM4OTcuMTg5NzIxLCJhdWQiOiJ6dXVsIn0.Qqb-ANmYv8slNUVSqjCJDL8HlH9L7nnLtLU2HBGzQJk'
|
|
|
|
Online resources like https://jwt.io are also available to generate, decode and
|
|
debug JWTs.
|