125 lines
6.3 KiB
Markdown
125 lines
6.3 KiB
Markdown
# PAM Authenticator
|
|
|
|
Pluggable authentication module (PAM) is a general purpose authentication API.
|
|
An application using PAM can authenticate a user without knowledge about the
|
|
underlying authentication implementation. The actual authentication scheme is
|
|
defined in the operating system PAM config (e.g. `/etc/pam.d/`), and can be
|
|
quite elaborate. MaxScale supports a very limited form of the PAM protocol,
|
|
which this document details.
|
|
|
|
## Configuration
|
|
|
|
The MaxScale PAM modules themselves have no configuration. All that is required
|
|
is to change the listener and backend authenticator modules to `PAMAuth` and
|
|
`PAMBackendAuth`, respectively.
|
|
|
|
```
|
|
[Read-Write-Listener]
|
|
type=listener
|
|
address=::
|
|
service=Read-Write-Service
|
|
protocol=MariaDBClient
|
|
authenticator=PAMAuth
|
|
|
|
[Master-Server]
|
|
type=server
|
|
address=123.456.789.10
|
|
port=12345
|
|
protocol=MariaDBBackend
|
|
authenticator=PAMBackendAuth
|
|
```
|
|
|
|
The PAM authenticator fetches user entries with `plugin='pam'` from
|
|
the `mysql.user` table of a backend. The user accounts also need to have either
|
|
the global SELECT-privilege or a database or a table-level privilege. The PAM
|
|
service name of a user is read from the `authetication_string`-column. The
|
|
matching PAM service in the operating system PAM config is used for
|
|
authenticating the user. If the `authetication_string` for a user is empty,
|
|
the fallback service `mysql` is used. If a username@host-combination matches
|
|
multiple rows, they will all be attempted until authentication succeeds or all
|
|
services fail.
|
|
|
|
PAM service configuration is out of the scope of this document, see
|
|
[The Linux-PAM System Administrators' Guide
|
|
](http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html) for more
|
|
information. A simple service definition used for testing this module is below.
|
|
|
|
```
|
|
auth required pam_unix.so
|
|
account required pam_unix.so
|
|
```
|
|
|
|
## Anonymous user mapping
|
|
|
|
The MaxScale PAM authenticator supports a limited version of [user
|
|
mapping](https://mariadb.com/kb/en/library/user-and-group-mapping-with-pam/). It requires
|
|
less configuration but is also less accurate than the server authentication. Anonymous
|
|
mapping is enabled in MaxScale if the following user exists:
|
|
- Empty username (e.g. `''@'%'` or `''@'myhost.com'`)
|
|
- `plugin = 'pam'`
|
|
- Proxy grant is on (The query `SHOW GRANTS FOR user@host;` returns at least one row with
|
|
`GRANT PROXY ON ...`)
|
|
|
|
When the authenticator detects such users, anonymous account mapping is enabled for the
|
|
hosts of the anonymous users. To verify this, enable the info log (`log_info=1` in
|
|
MaxScale config file) and look for messages such as "Found 2 anonymous PAM user(s) ..."
|
|
and "Added anonymous PAM user ..." during MaxScale startup.
|
|
|
|
When mapping is on, the MaxScale PAM authenticator does not require client accounts to
|
|
exist in the `mysql.user`-table received from the backend. MaxScale only requires that the
|
|
hostname of the incoming client matches the host field of one of the anonymous users
|
|
(comparison performed using `LIKE`). If a match is found, MaxScale attempts to
|
|
authenticate the client to the local machine with the username and password supplied. The
|
|
PAM service used for authentication is read from the `authentication_string`-field of the
|
|
anonymous user. If authentication was successful, MaxScale then uses the username and
|
|
password to log to the backends. If the client host matches multiple anonymous hosts,
|
|
authentication is attempted with all of their PAM services until one succeeds or all fail.
|
|
|
|
Anonymous mapping is only attempted if the client username is not found in the
|
|
`mysql.user`-table as explained in [Configuration](#configuration). This means,
|
|
that if a user is found and the authentication fails, anonymous authentication
|
|
is not attempted even when it could use a different PAM service with a different
|
|
outcome.
|
|
|
|
Setting up PAM group mapping for the MariaDB server is a more involved process as the
|
|
server requires details on which Unix user or group is mapped to which MariaDB user. See
|
|
[this guide](https://mariadb.com/kb/en/library/configuring-pam-authentication-and-user-mapping-with-unix-authentication/)
|
|
for more details. Performing all the steps in the guide also on the MaxScale machine is
|
|
not required, as the MaxScale PAM plugin only checks that the client host matches an
|
|
anonymous user and that the client (with the username and password it provided) can log
|
|
into the local PAM configuration. If using normal password authentication, simply
|
|
generating the Unix user and password should be enough.
|
|
|
|
## Implementation details and limitations
|
|
|
|
The general PAM authentication scheme is difficult for a proxy such as MaxScale.
|
|
An application using the PAM interface needs to define a *conversation function*
|
|
to allow the OS PAM modules to communicate with the client, possibly exchanging
|
|
multiple messages. This works when a client logs in to a normal server, but not
|
|
with MaxScale since it needs to autonomously log into multiple backends. For
|
|
MaxScale to successfully log into the servers, the messages and answers need to
|
|
be predefined. This requirement denies the use of more exotic schemes such as
|
|
one-time passwords or two-factor authentication.
|
|
|
|
The MaxScale PAM authentication module only supports a
|
|
simple password exchange. On the client side, the authentication begins with
|
|
MaxScale sending an AuthSwitchRequest packet. In addition to the command, the
|
|
packet contains the client plugin name `dialog`, a message type byte `4` and the
|
|
message `Password: `. In the next packet, the client should send the password,
|
|
which MaxScale will forward to the PAM API running on the local machine. If the
|
|
password is correct, an OK packet is sent to the client. If the local PAM API asks
|
|
for additional credentials as is typical in two-factor authentication schemes,
|
|
authentication fails. Informational messages such as password expiration
|
|
notifications are allowed. These are simply printed to the log.
|
|
|
|
On the backend side, MaxScale expects the servers to act as MaxScale did towards
|
|
the client. The servers should send an AuthSwitchRequest packet as defined
|
|
above, MaxScale responds with the password received by the client authenticator
|
|
and finally backend replies with OK. Informational messages from backends are
|
|
only printed to the info-log.
|
|
|
|
## Building the module
|
|
|
|
The PAM authenticator modules require the PAM and SQLite3 development
|
|
libraries (libpam0g-dev and sqlite3-dev on Ubuntu).
|