Primeiro:
- Estamos executando o MySQL 5.7.13.
- OS é o Red Hat Enterprise Linux 7.2.
- O problema foi descoberto usando o Python / Connector 2.1.3
- O sistema não está associado ao domínio (ainda.)
- Todos os pacotes MySQL instalados a partir dos próprios repositórios yum do MySQL!
O cenário: Eu estou tentando construir uma solução de monitoramento simples para manter abas em alguns aspectos de um conjunto de atualmente cerca de uma centena de máquinas sob meu controle (e provavelmente aumentando em número num futuro próximo); Eu sou obrigado a produzir relatórios para segurança, por exemplo, dando-lhes versões de pacotes para provar que as vulnerabilidades divulgadas recentemente foram corrigidas em x de máquinas.
Eu poderia extrair essa informação em tempo real com Ansible et al, mas a) não há garantia de que todas as máquinas serão conectadas a qualquer momento eb) ferramentas de gerenciamento podem me fornecer status atual, mas não necessariamente dados históricos que Eu posso precisar relatar. Então a solução da minha perspectiva é um banco de dados que pode abrigar registros para cada sistema; Quando um sistema é atualizado, lançamos um novo registro no banco de dados, indicando a mudança, e depois eu posso desenhar isso mais tarde.
Para isso, estamos usando um banco de dados MySQL. Atualmente, temos uma instalação simples e simples do MySQL com um pequeno conjunto de tabelas criado e um único usuário não root definido. A lista de usuários, conforme definida no MySQL, é:
select user, host, authentication_string from mysql.user;
+-------------+-----------+-------------------------------------------+
| user | host | authentication_string |
+-------------+-----------+-------------------------------------------+
| root | localhost | *D971D136A477A4C205AEF706... |
| mysql.sys | localhost | *THISISNOTAVALIDPASSWORDT... |
| pkg_manager | localhost | *E91158E2E26F343D6639E4BD... |
+-------------+-----------+-------------------------------------------+
Portanto, não há nomes de usuário de string vazios presentes.
A conta do problema em questão é a conta pkg_manager. Conceder permissões sobre isso:
mysql> show grants for 'pkg_manager'@'localhost';
+-------------------------------------------------------------------------------------+
| Grants for pkg_manager@localhost |
+-------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'pkg_manager'@'localhost' |
| GRANT SELECT, INSERT ON 'panopticon'.'package' TO 'pkg_manager'@'localhost' |
| GRANT SELECT, INSERT ON 'panopticon'.'package_history' TO 'pkg_manager'@'localhost' |
+-------------------------------------------------------------------------------------+
A conta pkg_manager conecta-se sem problemas, usando uma linha de comando como:
[~]$ mysql -u pkg_manager -p --database=panopticon
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.13 MySQL Community Server (GPL)
Copyright (c) 2000, 2016, 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>
No entanto, preciso permitir que uma ferramenta automatizada faça login no banco de dados (ela estará puxando uma lista de sistemas que não estão atualizados no momento, verificando quais deles estão atualmente on-line e enviando atualizações para eles e gravar cada atualização bem sucedida.) A ferramenta será escrita em Python, e eu puxei para baixo o conector do Python 2.1.3.
Criamos um arquivo options.cnf para a ferramenta e o armazenamos em um diretório restrito (inicialmente root: root 0700, atualmente um:. Testes iniciais de abertura de uma conexão em python através do conector com:
connection = mysql.connector.connect(option_files='/path/to/options.cnf')
resultou em um erro 1045, mensagem SQLState 28000. (Na verdade, houve algumas outras coisas primeiro, principalmente envolvendo a especificação do caminho do soquete. Essas, no entanto, são esclarecidas e sabemos que elas estão fora do caminho, porque agora o log do MySQL está relatando as tentativas de conexão com falha.)
Sabemos que isso está funcionando parcialmente, porque os detalhes completos do erro 1045 são "Acesso negado ao usuário 'pkg_manager' @ 'localhost' (usando a senha: YES)". Então está lendo o arquivo de opções, ele está identificando a conta pkg_manager, e está vendo a entrada da senha no arquivo (se não houver nenhuma entrada de senha presente, o final da mensagem se torna "(usando senha: NO)".
Em seguida, tentamos simplificar o problema usando o mesmo arquivo de opções e criando uma seção do cliente, especificando todos os mesmos campos que estão presentes na seção connector_python. Isso também falhou:
mysql --defaults-file="/path/to/options.cnf"
No entanto, sabíamos que a conta funcionava ao especificar manualmente as informações de login na linha de comando, conforme demonstrado acima.
Após muitas horas pesquisando experiências de usuários com falhas de login, decidimos tentar uma abordagem híbrida - login de linha de comando usando o arquivo --defaults, mas também especificando -p para nos forçar a inserir a senha na linha de comando:
[~]$ mysql --defaults-file="/etc/pkg_manager/db_info/options.cnf" -p
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
...
mysql>
Portanto, sabemos que o restante das informações fornecidas no arquivo conf de opções está correto. Simplesmente executando mysql --print-defaults (para determinar se existem outros arquivos de opções na lista de busca de caminho que possam interferir) resulta em zero opções de inicialização listadas, então não há outras opções para atrapalhar.
E neste momento, estou praticamente preso. A documentação oficial do MySQL declara explicitamente que você pode armazenar senhas não criptografadas em um arquivo de opções, além do arquivo de login local criptografado:
link
No entanto, claramente, não está funcionando. Examinei a lista de variáveis de arquivos de configuração que podem ser configuradas e não vejo nenhuma que pareça impedir a senha auth de um arquivo de opções. Transformei o registro de erros em até 3, mas nenhum detalhe foi apresentado sobre problemas de conexão além de uma única nota de linha indicando que uma tentativa de conexão de 'pkg_manager' @ 'localhost' foi rejeitada.
Antes que eu esqueça, aqui está o arquivo de opções (sans password):
1 # Options file for pkg_manager, easy way to "securely" store database login info.
2 [connector_python]
3 user="pkg_manager"
4 password="*********"
5 database="panopticon"
6 host="localhost"
7 unix_socket="/var/lib/mysql/mysql.sock"
8
9 [client]
10 user="pkg_manager"
11 password="*********"
12 database="panopticon"
13 host="localhost"
14 socket="/var/lib/mysql/mysql.sock"
E aqui está o arquivo /etc/my.cnf:
1 # For advice on how to change settings please see
2 # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
3
4 [mysqld]
5 #
6 # Remove leading # and set to the amount of RAM for the most important data
7 # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
8 # innodb_buffer_pool_size = 128M
9 #
10 # Remove leading # to turn on a very important data integrity option: logging
11 # changes to the binary log between backups.
12 # log_bin
13 #
14 # Remove leading # to set options mainly useful for reporting servers.
15 # The server defaults are faster for transactions and fast SELECTs.
16 # Adjust sizes as needed, experiment to find the optimal values.
17 # join_buffer_size = 128M
18 # sort_buffer_size = 2M
19 # read_rnd_buffer_size = 2M
20 datadir=/data/panopticon
21 socket=/var/lib/mysql/mysql.sock
22
23 skip-networking
24
25 # Disabling symbolic-links is recommended to prevent assorted security risks
26 symbolic-links=0
27
28 log-error=/var/log/mysqld.log
29 log_error_verbosity=3
30 general-log=1
31 general_log_file=/var/log/mysql_general.log
32 pid-file=/var/run/mysqld/mysqld.pid