26 novembro 2017

Autenticação externa via PAM no MySQL Enterprise e Oracle Linux 7.4

O MySQL Enterprise Edition suporta um método de autenticação que permite que o MySQL Server use o PAM (Pluggable Authentication Modules) para autenticar usuários do MySQL.
O PAM pode ser visto como um subsistema do Linux e macOS que provê uma interface padronizada para autenticação. Ou seja, os aplicativos podem usar a interface do PAM para confirmar usuários e senhas. Pode-se configurar o PAM para vários métodos de autenticação, incluindo usuários e senhas armazenados localmente no próprio SO ou buscá-los remotamente em um diretório LDAP.
Com o plugin authentication_pam habilitado, o MySQL server vai delegar a autenticação dos usuários para o PAM. Você pode, por exemplo, usar os usuários/senhas do Sistema Operacional para fazer login no MySQL. Outro exemplo, se o SO e o PAM estiverem integrados a um serviço de identidade e autenticação, tais como Open LDAP ou Active Directory, o MySQL pode usar os usuários/senhas a partir destes serviços.

O plugin authentication_pam também tem suporte a usuários 'proxy'. Esta funcionalidade permite que o DBA mapeie as permissões de um usuário MySQL para um grupo definido externamente. Por exemplo, supondo que exista no diretório LDAP um grupo 'developers' contendo vários usuários, o DBA pode criar um único usuário 'developer' no MySQL com as devidas permissões e mapeá-lo com o grupo 'developers' do diretório LDAP (1 para n). Desta forma, o time de segurança que mantém o diretório LDAP pode adicionar, remover, alterar senhas dos desenvolvedores que vão acessar o MySQL sem que o DBA precise tocar no banco de dados.
Nota: se você quiser configurar o MySQL para conectar-se diretamente a um serviço de identidade e autenticação LDAP sem configurar o PAM e o Sistema Operacional, pode usar o plugin authentication_ldap, também disponível no MySQL Enterprise Edition. O MySQL Enterprise é um software comercial e sua licença para uso em produção deve ser adquirida junto à Oracle. Porém, você pode utilizá-lo em ambiente não-produtivo por 30 dias.
Abaixo veremos como configurar o plugin authentication_pam no Oracle Linux 7.4. Os passos são bastante similares para outras distribuições Linux e macOS. Consulte a documentação para mais detalhes.

Passo 1: habilitar o plugin authentication_pam no MySQL

Acidione ao arquivo my.cnf:
[mysqld]
plugin-load-add=authentication_pam.so
Reinicie o MySQL:
systemctl restart mysqld
Confirme se o plugin está ativo:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%pam%';
+--------------------+---------------+
| PLUGIN_NAME        | PLUGIN_STATUS |
+--------------------+---------------+
| authentication_pam | ACTIVE        |
+--------------------+---------------+
1 row in set (0.00 sec)

Passo 2: criar um módulo mysql no PAM

Crie um novo serviço mysql no PAM. Basta criar um arquivo com nome mysql no diretório de configuração do PAM (normalmente /etc/pam.d):
vi /etc/pam.d/mysql
#
# PAM-1.0 configuration file for the 'mysql' service
#
auth       include   password-auth
account    include   password-auth
O que fizemos ao usar o include foi repassar autenticação para outro serviço password-auth já definido no PAM. Se quiser ver em detalhes como está configurado, basta visualizar o conteúdo do arquivo /etc/pam.d/password-auth.
cat /etc/pam.d/password-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faildelay.so delay=2000000
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so
account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so
password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so
session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
Note que este arquivo foi gerado automaticamente pela ferramenta authconfig. Uma maneira usual de integrar o Sistema Operacional a diferentes serviços de identidade e autenticação (LDAP, Activer Directory, etc.) é usar o System Security Services Daemon (SSSD).

Passo 3: garantir permissões do processo mysqld ao arquivo de usuários do SO

Em alguns Sistemas Operacionais, tal como o Oracle Linux 7.4, é usado o arquivo /etc/shadow para manter informações de acesso os usuários. O processo mysqld vai precisar de permissões de acesso a este arquivo para funcionar corretamente com o PAM.
Uma maneira de dar tais permissões é:
  1. criar um grupo shadow;
  2. dar permissões ao grupo para acessar /etc/shadow;
  3. adicionar o usuário que vai rodar o processo mysqld (por padrão, o usuário mysql);
  4. reiniciar o processo mysqld.
Execute os seguintes comandos:
groupadd shadow
chgrp shadow /etc/shadow
chmod g+r /etc/shadow
gpasswd -a mysql shadow
systemctl restart mysqld
Neste ponto, a autenticação externa via PAM já deve estar funcionando.

Passo 4: mapear usuários do MySQL para autenticação externa

Opcão 1: mapeamento 1 para 1

Você pode mapear um usuário MySQL para um usuário externo. O usuário do MySQL vai definir os privilégios enquanto que a senha para login estará definida fora do MySQL.
Teste 1 para 1 Para testar a autenticação externa, criaremos um usuário myuser no Sistema Operacional e o mapearemos para um usuário no MySQL. O usuário do SO vai definir a senha enquanto que o usuário no MySQL vai definir quais dados terá acesso.
  1. Crie o usuário myuser no Sistema Operacional e dê uma senha:
adduser myuser
passwd myuser
  1. (opcional) Verifique se foi criado com sucesso com:
# su - myuser
$ id
uid=1001(myuser) gid=1001(myuser) groups=1001(myuser) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$ exit
logout
#
  1. No MySQL, crie um usuário mapeando as permissões para o usuário myuser:
CREATE USER 'myuser'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql';
GRANT SELECT ON *.* TO 'myuser'@'localhost';
Neste exemplo demos apenas permissões de SELECT ao usuário myuser.
  1. Teste o acesso ao MySQL usando a senha que você definiu para o usuário myuser no SO:
# mysql -umyuser -p --enable-cleartext-plugin
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.20-enterprise-commercial-advanced MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
  1. Você pode verificar as informações do usuário autenticado com:
SELECT USER(), CURRENT_USER(), @@proxy_user;
+------------------+------------------+--------------+
| USER()           | CURRENT_USER()   | @@proxy_user |
+------------------+------------------+--------------+
| myuser@localhost | myuser@localhost | NULL         |
+------------------+------------------+--------------+
1 row in set (0.00 sec)
  1. Ao final dos testes, remova os usuários do MySQL e do SO:
DROP USER 'myuser'@'localhost';
userdel -r myuser

Opção 2: mapeamento 1 para n (grupos de usuários)

Você pode mapear um usuário MySQL para um grupo de usuários. O usuário do MySQL vai definir os privilégios e estará ligado a um grupo de usuários. Desta forma, os dados de quem serão os usuários pertencentes ao grupo e suas respectivas senhas estarão definidas e mantidos fora do MySQL.
Teste 1 para n Para testar a autenticação externa, criaremos no Sistema Operacional um grupo myusers contendo os usuários myuser1 e myuser2. Depois mapearemos o grupo myusers para um usuário MySQL priv_myusers.
  1. No Sistema Operacional, crie o grupo myusers com os usuários myuser1 e myuser2:
groupadd myusers
adduser myuser1
passwd myuser1
gpasswd -a myuser1 myusers
adduser myuser2
passwd myuser2
gpasswd -a myuser2 myusers
  1. No MySQL, garanta que não existe um usuário anônimo:
SELECT user, host FROM mysql.user WHERE user='';
Empty set (0.00 sec)
  1. No MySQL, crie um usuário proxy padrão ''@'' que irá mapear os usuários externos (PAM) para usuários internos (MySQL):
CREATE USER ''@'' IDENTIFIED WITH authentication_pam AS 'mysql, myusers=priv_myusers';
  1. No MySQL, crie um usuário priv_myusers, mapeando as permissões para o grupo myusers:
CREATE USER 'priv_myusers'@'localhost' IDENTIFIED BY 'SecretPass1!';
GRANT PROXY ON 'priv_myusers'@'localhost' TO ''@'';
GRANT SELECT ON *.* TO 'priv_myusers'@'localhost';
Neste exemplo demos apenas permissões de SELECT no MySQL.
  1. Teste o acesso ao MySQL usando a senha que você definiu para o usuário myuser1 no SO:
# mysql -umyuser1 -p --enable-cleartext-plugin
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.20-enterprise-commercial-advanced MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
  1. Você pode verificar as informações do usuário autenticado com:
SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+------------------------+--------------+
| USER()            | CURRENT_USER()         | @@proxy_user |
+-------------------+------------------------+--------------+
| myuser1@localhost | priv_myusers@localhost | ''@''        |
+-------------------+------------------------+--------------+
1 row in set (0.00 sec)

  1. Teste também o acesso ao MySQL com o usuário myuser2:
# mysql -umyuser2 -p --enable-cleartext-plugin
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.20-enterprise-commercial-advanced MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+------------------------+--------------+
| USER()            | CURRENT_USER()         | @@proxy_user |
+-------------------+------------------------+--------------+
| myuser2@localhost | priv_myusers@localhost | ''@''        |
+-------------------+------------------------+--------------+
1 row in set (0.01 sec)
  1. Ao final dos testes, remova os usuários do MySQL e do SO:
DROP USER 'priv_myusers'@'localhost';
DROP USER ''@'';
userdel -r myuser1
userdel -r myuser2

Conclusão

O recurso de Autenticação Externa do MySQL Enterprise Edition permite gerenciar usuários e senhas fora do MySQL. É um recurso que pode facilitar a implantação de políticas de segurança, principalmente as que exigem gerenciamento de identidades por administradores que não sejam os DBAs.

Referências

  1. Manual de referência do MySQL 5.7 - Authentication Plugins

Nenhum comentário: