Password management
MySQL Passwords in ProxySQL
ProxySQL是一个感知协议代理
ProxySQL是根据流量负载来路由连接的,所以连接到ProxySQL的客户端是不能通过目的主机组的认证的,因此ProxySQL需要对客户端进行验证
所以,ProxySQL需要和用户密码相关的信息:足够通过认证的信息
ProxySQL还需要与后端建立连接的信息,来对当前的连接做change_user
三层机构的配置体系同样适用于用户信息的配置.
ProxySQL存储用户信息到mysql_users表:
- MySQL_Authentication()是负责存储用户runtime状态信息的对象
- main.mysql_users缓存内存配置
- disk.mysql_users持久化用户配置
不管是在内存还是磁盘,mysql_users都将认真信息存储在username和password列中。
Password formats
mysql_users.password中的密码用两种存储形式,不管在内存还是磁盘都是一样的:
- 明文文本
- hash加密
明文密码简单易读,如果数据库和配置文件都保存在访问受限的目录,还是可以的。hash加密的密码和MySQL server存储在mysql.user.password的密码有相同的格式。
ProxySQL会把以*开头的密码当作经过hash加密的密码。
Hashed passwords and authentication
在MySQL和ProxySQL中,密码是这样被hash的:SHA1(SHA1('clear_password'))
把一个hash密码转换为明文是根本不可能的
当客户端连接到ProxySQL时,是能通过hash密码进行认证的。
在这第一次客户端认证的过程中,ProxySQL能够获取经过一层加密的密码:SHA1('clear_password')。这个密码是被存储在runtime的,通过它ProxySQL就能够连接后端的mysql server。
How to input new passwords
ProxySQL admin接口没有PASSWORD()函数,也就是说:
- 密码就是以他们插入的形式存储,明文或者是被hash过的
- 当从admin输入密码的时候,他获取到的不可能是一个从明文经过加密的hash密码(但是你能在MySQL server上执行select password('password')并复制粘贴这个结果)
Variable admin-hash_passwords
为了支持hash密码加密,从ProxySQL v1.2.3开始引入了一个全局的布尔变量admin-hash_passwords,这个变量默认是启用的
当admin-hash_passwords=true时,只有在LOAD MYSQL USERS TO RUNTIME时密码会被自动加密。mysql_users表中的密码是不会被自动hash的。
但是,在mysql_users表中,密码是很容易被hash的,不管是缓存在内存中,还是持久化到磁盘。其实,从runtime状态复制就好了,比如执行LOAD MYSQL USERS TO RUNTIME后在SAVE MYSQL USERS FROM RUNTIME,然后在SAVE MYSQL USERS TO DISK
如下:
1 Admin> SELECT * FROM mysql_users; 2 Empty set (0.00 sec) 3 4 Admin> INSERT INTO mysql_users(username,password) VALUES ('user1','password1'), ('user2','password2'); 5 Query OK, 2 rows affected (0.00 sec) 6 7 Admin> SELECT username,password FROM mysql_users; 8 +----------+-----------+ 9 | username | password | 10 +----------+-----------+ 11 | user1 | password1 | 12 | user2 | password2 | 13 +----------+-----------+ 14 2 rows in set (0.00 sec) 15 16 Admin> LOAD MYSQL USERS TO RUNTIME; 17 Query OK, 0 rows affected (0.00 sec) 18 19 Admin> SELECT username,password FROM mysql_users; 20 +----------+-----------+ 21 | username | password | 22 +----------+-----------+ 23 | user1 | password1 | 24 | user2 | password2 | 25 +----------+-----------+ 26 2 rows in set (0.00 sec)
上面这一步,runtime的密码是被hash了的,但是mysql_users表中的任然没有被hash,为了是mysql_users表中的也hash:
1 Admin> SAVE MYSQL USERS FROM RUNTIME; 2 Query OK, 0 rows affected (0.00 sec) 3 4 Admin> SELECT username,password FROM mysql_users; 5 +----------+-------------------------------------------+ 6 | username | password | 7 +----------+-------------------------------------------+ 8 | user1 | *668425423DB5193AF921380129F465A6425216D0 | 9 | user2 | *DC52755F3C09F5923046BD42AFA76BD1D80DF2E9 | 10 +----------+-------------------------------------------+ 11 2 rows in set (0.00 sec)
然后我们就可以将他保存到磁盘:SAVE MYSQL USERS TO DISK
备注:
admin-hash_passwords是一个admin-变量,不是一个mysql-变量,这是因为他影响了admin的行为
这个细节很重要,因为你需要执行的是LOAD ADMIN VARIABLES TO RUNTIME,而不是LOAD MYSQL VARIABLES TO RUNTIME。