我有以下剧本:
- hosts: myserver
vars:
mysql_root_password: foobarbaz
[...]
tasks:
[...]
- name: update mysql root password for all root accounts
mysql_user: name=root host={{ item }} password={{ mysql_root_password }} priv=*.*:ALL,GRANT
with_items:
- "{{ ansible_hostname }}"
- 127.0.0.1
- ::1
- "localhost"
become: true
tags: mysql
[...]
# I've ommitted the tasks to install the mysql packages,
# store the password in /root/.my.cnf and restart the server)
问题是所需的密码正确保存在mysql.user中127.0.0.1,:: 1和主机名但不是 for localhost,即
mysql> select host,user,authentication_string from user;
+-----------+------------------+-------------------------------------------+
| host | user | authentication_string |
+-----------+------------------+-------------------------------------------+
| localhost | root | |
| localhost | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | debian-sys-maint | *DA57FEBA9C5C5119186DB8834C7B83216E450117 |
| ubuntu | root | *8C5206E23A3B76002AA6E152691F5C5D7ABC31F9 |
| 127.0.0.1 | root | *8C5206E23A3B76002AA6E152691F5C5D7ABC31F9 |
| ::1 | root | *8C5206E23A3B76002AA6E152691F5C5D7ABC31F9 |
+-----------+------------------+-------------------------------------------+
其中* 8C52 ...是加密密码:
mysql> select password('foobarbaz');
+-------------------------------------------+
| password('foobarbaz') |
+-------------------------------------------+
| *8C5206E23A3B76002AA6E152691F5C5D7ABC31F9 |
+-------------------------------------------+
因此,这失败了:
william@ubuntu:/etc/mysql$ mysql -u root --password=foobarbaz
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
如果我使用sudo,我可以使用任何密码或无连接以root身份连接到mysql。
换句话说,这个ansible命令没有做任何事情,但是如果我使用任何其他用户或主机它可以工作。
ansible myserver -m mysql_user -a "name=root host=localhost password=foobarbaz priv=*.*:ALL,GRANT" -b
myserver | SUCCESS => {
"changed": true,
"user": "root"
}
MySQL:Ver 14.14 Distrib 5.7.15
Ubuntu 16.04.1 LTS
Ansible 2.1.2.0
答案 0 :(得分:5)
由于Ansible现在支持用于本地连接的Unix域套接字,因此存在一种非常优雅的方法(无需初始root用户设置和任何文件配置):
tasks:
# assume that pymysql and mysql-server (with default config) are installed before this task
- name: add user to mysql server
mysql_user:
# you can get socket path from /etc/mysql/mysql.conf.d/mysqld.cnf
login_unix_socket: /var/run/mysqld/mysqld.sock # default path
name: username
password: user_password
priv: "database.*:ALL" # not sure about dot, colon and asterisk, so I used quotes here
become: yes
login_unix_socket
参数可用于所有Ansible mysql modules
答案 1 :(得分:3)
原因是Ansible mysql_user module:
的这种限制目前,只支持mysql_native_password 加密密码哈希模块。
您可以在指定或未指定root密码的情况下安装MySQL软件包。
使用root密码安装
使用密码,root @ localhost登录使用mysql_native_password,password hashing method introduced in MySQL 4.1.1,其中密码长度为41个字节,以单个星号开头,password()
函数生成哈希值。
mysql> select host,user,authentication_string,plugin from mysql.user;
+-----------+------------------+-------------------------------------------+-----------------------+
| host | user | authentication_string | plugin |
+-----------+------------------+-------------------------------------------+-----------------------+
| localhost | root | *9B500343BC52E2911172EB52AE5CF4847604C6E5 | mysql_native_password |
| localhost | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password |
| localhost | debian-sys-maint | *DA57FEBA9C5C5119186DB8834C7B83216E450117 | mysql_native_password |
+-----------+------------------+-------------------------------------------+-----------------------+
没有root密码的安装
没有密码,root @ localhost使用auth_socket
插件:
mysql> select host,user,authentication_string,plugin from mysql.user;
+-----------+------------------+-------------------------------------------+-----------------------+
| host | user | authentication_string | plugin |
+-----------+------------------+-------------------------------------------+-----------------------+
| localhost | root | | auth_socket |
| localhost | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password |
| localhost | debian-sys-maint | *DA57FEBA9C5C5119186DB8834C7B83216E450117 | mysql_native_password |
+-----------+------------------+-------------------------------------------+-----------------------+
auth_socket
仅在您从localhost通过unix_socket连接时才有效。它只会检查连接的用户名是否与“用户”字段中的用户名匹配,没有密码。
这就是为什么你可以sudo mysql
使用你喜欢的任何密码,或者不使用任何密码,但无论你输入什么密码,以mysql -u root -p
作为无特权用户都无法工作。
Ansible模块目前无法设置密码,除非插件是mysql_native_password,因此您需要先正确设置插件值。
已经有feature request来修复此问题。
<强>解决方案强>
使用密码安装MySQL ,使用debconf module提前提供(您必须设置两次,一次用于确认屏幕)。然后安装MySQL,将密码保存到/root/.my.cnf
,以便root用户可以自动连接,并使用mysql_user设置您需要的其他任何登录。
- hosts: myserver
vars:
mysql_root_password: foobarbaz
tasks:
- name: Specify MySQL root password before installing
# without this, auth_socket will be used for root@localhost, and we won't be able to set the password
debconf: name='mysql-server' question='mysql-server/root_password' value='{{mysql_root_password | quote}}' vtype='password'
become: true
- name: Confirm MySQL root password before installing
debconf: name='mysql-server' question='mysql-server/root_password_again' value='{{mysql_root_password | quote}}' vtype='password'
become: true
- name: Install MySQL server
apt: name={{ item }} state=present
with_items:
- mysql-server
- python-mysqldb
become: true
- name: Start MySQL
service: name=mysql state=started
become: true
- name: create /root/.my.cnf (from template) with password credentials
template: src=/etc/ansible/templates/root/.my.cnf dest=/root/.my.cnf owner=root mode=0600
become: true
- name: update mysql root password for all root accounts
mysql_user: name=root host={{ item }} password={{ mysql_root_password }} sql_log_bin=yes priv=*.*:ALL,GRANT
with_items:
- "{{ ansible_hostname }}"
- 127.0.0.1
- ::1
- "localhost"
become: true
答案 2 :(得分:2)
替代解决方案:
sudo mysql -u root -p{{ mysql_root_password }} -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '{{ mysql_root_password }}'; FLUSH PRIVILEGES;"
它首次运行,因为root仍然使用auth_socket
身份验证插件并忽略密码,并且后续运行因为密码是正确的。
找到解决方案,并在此解释如何调试:https://www.percona.com/blog/2016/03/16/change-user-password-in-mysql-5-7-with-plugin-auth_socket/