| =============================================== |
| RAPI authentication and authorization using PAM |
| =============================================== |
| |
| .. contents:: :depth: 4 |
| |
| This design document describes a way of :doc:`rapi` authentication |
| and authorization refactoring by using the pluggable authentication |
| modules (PAM). |
| |
| Current State |
| ============= |
| |
| Currently :doc:`rapi` supports authentication using *basic auth* over |
| https protocol. The users are stored in a file (usually |
| ``/var/lib/ganeti/rapi/users``) and have either read or write rights. |
| Please read :ref:`rapi-users` for more details. |
| |
| .. _motivation: |
| |
| Motivation |
| ========== |
| |
| During GanetiCon 2015 the following features were requested by the |
| community: |
| |
| - Support for different authentication methods; |
| - Granular access to different RAPI command subsets; |
| - Granular access to different target instances. |
| |
| The last two statements may be desired when an administrator wants to |
| provide some restricted cluster or instance management rights for users. |
| |
| Proposed Implementation |
| ======================= |
| |
| Ganeti RAPI will use PAM for *authentication* and *account* |
| (authorization) purposes. ``ganeti-basic`` PAM module performing |
| *authentication* and *account* based on the contents of |
| ``ganeti/rapi/users`` file will be distributed with Ganeti. Ganeti rapi |
| will interact with PAM using ``ganeti-rapi`` service name. The default |
| configuration for ``ganeti-rapi`` PAM service will just use |
| ``ganeti-basic`` module. |
| |
| A good documentation on client-server PAM model is available |
| at http://www.linux-pam.org/pre/doc/current-draft.txt. |
| |
| Authentication Specific Details |
| ------------------------------- |
| |
| In case of *basic auth* over http, the username and password will |
| be extracted as they are presented in the |
| :ref:`standard form <basic-protocol>`. Note, that independent from |
| authentication method, all interactions will be performed via https |
| protocol. |
| |
| In case of another authentication method, additional user's credintials |
| (e.g. request signature) should be provided in |
| ``Ganeti-RAPI-Credential`` field. The field should be encoded using |
| base64 algorithm as for the *basic auth* over http. |
| |
| Ganeti will copy the username to ``PAM_USER`` field of a ``pam_handler`` |
| and the contents of ``Ganeti-RAPI-Credential`` http header fielf to |
| ``PAM_AUTHTOK`` field of a ``pam_handler``. |
| |
| User's password will be send as a reply to each request made by |
| *conversation function* with ``PAM_PROMPT_ECHO_OFF`` message constant. |
| Other requests will be just ignored. |
| |
| Authorization Specific Details |
| ------------------------------ |
| |
| Ganeti will pass several parameters that might be useful for the |
| *authorization* phase to the modules via the private PAM environmental |
| variables (using ``pam_setenv``) |
| |
| GANETI_RAPI_URI |
| The requested URI. |
| GANETI_REQUEST_BODY |
| The body of a request if any or an empty string otherwise. |
| GANETI_REQUEST_METHOD |
| The method of an http request (GET, PUT, POST or DELETE). |
| GANETI_RESOURCE_ACCESS |
| The comma-separated access handlers of a resource if provided in |
| rlib2 or empty string otherwise. |
| |
| One More Time About the Goals |
| ============================= |
| |
| Support for Different Authentication Methods |
| -------------------------------------------- |
| |
| The proposed solution allows to use signatures of any kind instead of |
| user password or in addition to it. It allows an administrator to |
| support more complex and secure authentication schemes than just a basic |
| authentication over http. |
| |
| Granular Access to Different Command Subsets |
| -------------------------------------------- |
| |
| This functionality can be implemented just by writing more complex |
| authorization module that will permit or deny execution of some command |
| based on the environment variables passed and some additional config |
| file. |
| |
| Granular Access to Different Target Instances |
| --------------------------------------------- |
| |
| For such kind of authorization, a PAM module may be implemented as |
| well. The main difference is that for complex access rights maintaining |
| the module will have to store users rights and lists of owned objects |
| on some kind of dynamic database instead of simple static config file. |
| |
| Switching Between the Old and the New Implementations |
| ----------------------------------------------------- |
| |
| As the changes introduced should be backwards compatible, a new |
| ganeti-rapi daemon run-time option ``--enable_pam_rapi`` will be |
| introduced. |
| |
| Other Changes |
| ============= |
| |
| As writing PAM module is an universal solution for the authorization |
| problem, sometimes such flexibility is not necessary or not |
| available because of disabled PAM. In that case it is still possible |
| to provide granular access to the RAPI. |
| |
| For that purpose ``RAPI-Auth:username`` will be added to the reason |
| trail just before sending a job for a further processing. That will |
| allow to configure a filter that will reject job subsets initiated |
| by some specific user i.e. add a user to a blacklist. See |
| :doc:`design-optables` for more information about job filters. |
| |
| Additionally, we propose to introduce a new |
| :ref:`filter predicate <filter-predicates>`, ``username`` that will |
| contain the authenticated user's login and thus will make it possible to |
| define an allowed user set for each operation. |