第一:
场景:我正在尝试构build一个简单的监控解决scheme,以便监控我现在控制的一百多台机器的某些方面(并且在不久的将来可能会增加)。 我需要能够生成安全报告,例如,给他们打包版本,以certificate最近披露的漏洞已经在y外的机器上进行了修补。
我可以用Ansible等人实时提供这些信息,但是a)不能保证所有的机器都能在任何时候连接,b)pipe理工具可以给我当前的状态,但不一定是我可能需要的历史数据报告。 所以从我的angular度来看,解决scheme就是一个可以存放每个系统logging的数据库。 当一个系统被更新时,我们将一个新的logging放入数据库,指出这个变化,然后我可以稍后再绘制出来。
为此,我们正在使用MySQL数据库。 目前,我们有一个简单的,准系统的MySQL安装,创build一个小的表集,并定义一个非root用户。 MySQL中定义的用户列表是:
select user, host, authentication_string from mysql.user; +-------------+-----------+-------------------------------------------+ | user | host | authentication_string | +-------------+-----------+-------------------------------------------+ | root | localhost | *D971D136A477A4C205AEF706... | | mysql.sys | localhost | *THISISNOTAVALIDPASSWORDT... | | pkg_manager | localhost | *E91158E2E26F343D6639E4BD... | +-------------+-----------+-------------------------------------------+
所以没有空string用户名存在。
问题帐户是pkg_manager帐户。 授予权限是:
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' | +-------------------------------------------------------------------------------------+
pkg_manager帐户连接没有问题,使用命令行如下所示:
[~]$ 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>
但是,我需要允许一个自动化的工具login到数据库(它将拉出一个当前不是最新的系统列表,检查当前在线的系统,然后向它们推送更新并logging每个系统成功更新。)该工具将用Python编写,并且已经下拉了Python 2.1.3连接器。
我们为这个工具构build了一个options.cnf文件,并将其存储在一个受限制的目录中(最初是root:root 0700,目前是:。)通过连接器在python中打开连接的初始testing:
connection = mysql.connector.connect(option_files='/path/to/options.cnf')
导致错误1045,SQLState 28000消息。 (实际上,还有一些其他的东西,主要是指定套接字path,但是这些东西已经被清除了,我们知道它们已经不存在了,因为现在MySQL日志报告了失败的连接尝试。
我们知道这是部分工作的,因为1045错误的全部细节是“拒绝用户pkg_manager'@'localhost'(使用密码:YES)”。 因此它正在读取选项文件,它识别pkg_manager帐户,并且在文件中看到密码条目(如果没有密码input,则消息结尾变为“(使用密码:否)”。
然后,我们尝试使用相同的选项文件来简化问题,并在其中创build一个客户端部分,指定connector_python部分中的所有相同字段。 这也失败了:
mysql --defaults-file="/path/to/options.cnf"
但是,如上所示,我们知道在手动指定命令行上的login信息时,帐户已经工作。
经过许多小时的searchlogin失败的用户体验之后,我们决定尝试一种混合的方法 – 使用–defaults文件进行命令行login,还指定-p强制我们在命令行上input密码:
[~]$ 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>
因此,我们知道在选项conf文件中提供的其余信息是正确的。 简单地运行mysql –print-defaults(确定pathsearch列表中是否有其他选项文件可能会干扰)会导致列出的启动选项为零,因此没有其他选项可以实现。
而在这一点上,我几乎卡住了。 官方MySQL文档明确指出,除了encryption的本地login文件外,您还可以将未encryption的密码存储在选项文件中: http : //dev.mysql.com/doc/refman/5.7/en/password-security-user.html
然而,很显然,这是行不通的。 我已经查看了可以设置的configuration文件variables的列表,我没有看到任何看起来像他们会阻止从选项文件的密码authentication。 我已经把错误日志logging到了3,但是除了单行注释之外没有提供关于连接问题的细节,表明来自'pkg_manager'@'localhost'的连接尝试被拒绝了。
在我忘记之前,这里是选项文件(无密码):
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"
这里是/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
我终于有机会再花几个小时来看问题,并find了解决办法。 正如我所知,这是令人沮丧的简单,但它也违背发布在多个用户论坛,甚至MySQL参考文档的build议。
如果我的密码存储在选项文件的引号中,将无法连接。 当我从密码中删除引号时,它会连接。 在我意识到这一点之前,我最终通过了Python连接器代码,主要是因为我之前尝试删除密码中的引号,但稍微有点不同的问题,然后在脑海中将这两个问题混为一谈。
我在通过Python连接器代码的时候注意到,我可以直接实例化一个选项文件parsing器,所以我试了一下(把path传递给我的选项文件作为参数)。当我这样做的时候,我看到所有的选项,包括密码,通过文件中的任何引号导入parsing器状态。 然而,之后的任何阶段都没有采取步骤去除密码引号(至less是我看到的),所以当连接器用parsing器打开选项文件时,引号被包含并传递给用于身份validation的服务器作为密码的一部分。
我很可能把这个作为一个错误报告给MySQL的开发者,因为所有其他的选项工作正常与报价。