ER_HOST_NOT_PRIVILEGED - docker container fails to connect to mariadb - mysql

I'm trying to get a docker container to work with mariadb and node.js images. The container will use an existing database in /home/mysql. However, when the container is launched, I'm getting this "failed to connect" error in node.js:
Error: ER_HOST_NOT_PRIVILEGED:
Host '172.18.0.5' is not allowed to connect to this MariaDB server
Here's my docker-compose.yml:
version: '3'
services:
mariadb:
image: mariadb
restart: always
volumes:
- /home/mysql:/var/lib/mysql
user: "mysql"
ports:
- "3306:3306"
watch:
build: .
restart: always
links:
- mariadb:mysql
environment:
- DOCKER_IP=172.18.0.2
depends_on: ['mariadb']
ports:
- "3000:3000"
After reading this thread, I found that mysql is actually running, but it fails to let other services connect:
These are some of the steps I have checked. As you can see, I can log in to the mysql instance:
$ docker exec -it 552aae9ea09c bash
mysql#552aae9ea09c:/$ mysql -u root -p
Enter password: *******
MariaDB [(none)]> SELECT host, user FROM mysql.user;
+-------------+------------------+
| host | user |
+-------------+------------------+
| 127.0.0.1 | root |
| ::1 | root |
| someusername| |
| someusername| root |
| localhost | |
| localhost | dbusername |
| localhost | databasename |
| localhost | root |
+-------------+------------------+
8 rows in set (0.00 sec)
mysql#552aae9ea09c:/$ mysqld --verbose --help | grep bind-address
2017-11-13 17:35:40 139825857279872 [Note] Plugin 'FEEDBACK' is disabled.
--bind-address=name IP address to bind to.
bind-address (No default value)
One thing to note is that even though I've explicitly set the user to mysql in the yml file, these three files in /home/mysql: ib_logfile0,ib_logfile1, ib_buffer_pool are still under the group of systemd-journal-remote, which I suspect has something to do with the connection failure.(reference)

The error you are receiving is caused by the fact that MariaDB thinks you are not authorized to connect to the server. This means that you haven't created a database user for the Node.js app or the grants for that user are incorrect.
A fool-proof way to solve this is to create a separate user for the Node.js application. You can automate this by writing the following SQL into a file and mounting the volume into /docker-entrypoint-initdb.d.
CREATE USER 'my-app-user'#'%' IDENTIFIED BY 'my-app-password';
GRANT ALL ON *.* TO 'my-app-user'#'%';
Change the username and password accordingly and reduce the given privileges from the ALL privilege. You can also change the wildcard hostname % to a specific IP address or hostname.

Simply run this sql query:
GRANT ALL PRIVILEGES ON *.* TO 'root'#'%' IDENTIFIED BY 'password'
(assuming that you are connecting as the root user)

Related

Unable to connect Mysql 8 running on docker with mysql workbench

I have a docker setup that is running Mysql 8.
I am able to access Mysql inside docker container, however, I am unable to connect using Mysql workbench. I have another mysql container but this one is Mysql version 5.7 and I have no issues connecting with that one.
I have tried to allow root user full host access with % in the mysql.user
| root | % |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
I have tried to connect to container using hostnames: localhost, 0.0.0.0, 127.0.0.1
and port 3306 but no luck
I also created a separate user and gave full privilege and still no luck
Below is my Docker compose file
version: '3.5'
services:
database:
build:
context: ./images/mysql
restart: always
command: ['--default-authentication-plugin=mysql_native_password']
environment:
- MYSQL_DATABASE=inim
- MYSQL_USER=inimuser
- MYSQL_PASSWORD=inimpass
- MYSQL_ROOT_PASSWORD=docker
ports:
- "3306:3306"
volumes:
- ./database/data:/var/lib
volumes:
my-datavolume:
my Dockerfile:
FROM mysql:8.0.20
CMD ["mysqld"]
EXPOSE 3306
Below is my Docker PS
b8832d9711b4 docker_inim_db_database "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp docker_inim_db_database_1
I have a similar setup with Mysql 5.7 and it connects fine. Not sure what I am doing wrong here.
You can debug your process by going to the container.
Please run:
$ docker exec docker_inim_db_database_1 /bin/bash
Now you should be in bash of the container.
Then login to mysql bash using:
$ mysql -uroot -p
and type your password or just press Enter if none.
There's two steps in that process:
a) Grant privileges. As root user execute with this substituting 'password' with your current root password :
GRANT ALL PRIVILEGES ON *.* TO 'root'#'%' IDENTIFIED BY 'password';
b) bind to all addresses:
The easiest way is to comment out the line in your my.cnf file:
#bind-address = 127.0.0.1
and restart mysql
service mysql restart
By default it binds only to localhost, but if you comment the line it binds to all interfaces it finds. Commenting out the line is equivalent to bind-address=*.
To check where mysql service has binded execute as root:
netstat -tupan | grep mysql
Update For Ubuntu 16:
Config file is (now)
/etc/mysql/mysql.conf.d/mysqld.cnf
Most of steps above are from answer: https://stackoverflow.com/a/11225588/659077

Unable to connect to MySQL database from vps using localhost

I have two environments: my local machine Mac and linux on VPS. The problem is that I can not connect using localhost to my db from VPS.
On my local machine everything works fine.
Local:
mysql -u root mydb -h 127.0.0.1 --password=password --port=2345 //OK
mysql -u root mydb -h 0.0.0.0 --password=password --port=2345 //OK
mysql -u root mydb -h localhost --password=password --port=2345 //OK
Even using public ip of VPS I'm able to connect to remote db from local machine.
VPS:
mysql -u root mydb -h 127.0.0.1 --password=password --port=2345 //OK
mysql -u root mydb -h 0.0.0.0 --password=password --port=2345 //OK
mysql -u root mydb -h localhost --password=password --port=2345 //KO <-
Error:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
I used the following docker file to create my image.
DockerFile:
FROM mysql:8.0
COPY *.sql /docker-entrypoint-initdb.d/
docker-compose.yaml:
version: '3.7'
services:
ls:
image: ***/db-container:v6 # <-my image
container_name: db-container
restart: always
environment:
MYSQL_DATABASE: 'mydb'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
# <Port exposed> : < MySQL Port running inside container>
- '2345:3306'
expose:
# Opens port 3306 on the container
- '3306'
volumes:
- db-container:/var/lib/mysql
volumes:
db-container:
Query inside container:
mysql> SELECT host, user FROM mysql.user;
+-----------+------------------+
| host | user |
+-----------+------------------+
| % | root |
| % | user |
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
+-----------+------------------+
mysql> SELECT * FROM performance_schema.host_cache;
Empty set (0.02 sec)
"localhost" says to use a socket. But VPS probably allows only TCP/IP connections, not "socket".
I guess on local machine, you are not using docker. However, on vps, you are.
On you local, mysql is installed on the OS itself, hence, it has exposed its socket file at /var/run/mysqld/mysqld.sock. However, on VPS, the socket is inside docker.
The highlight here is the difference between localhost and 127.0.0.1 in reference to mysql. On unix based systems(including mac), localhost connects via socket, while 127.0.0.1 connects via TCP/IP.
Try adding following under docker-compose volumes section. See if it works then.
volumes:
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
There are many different root causes for a connection denied.
Since it is possible to execute queries inside the container, the best course of action is to inspect the performance_schema.host_cache table:
SELECT * FROM performance_schema.host_cache;
It should point more precisely at the problem.
Doc:
https://dev.mysql.com/doc/mysql-perfschema-excerpt/8.0/en/host-cache-table.html

root#localhost password set with Ansible mysql_user module doesn't work

I have the following playbook:
- 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)
The problem is the desired pasword is correctly saved in mysql.user for 127.0.0.1, ::1 and the hostname but not for localhost, i.e.
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 |
+-----------+------------------+-------------------------------------------+
Where *8C52... is the encrypted password:
mysql> select password('foobarbaz');
+-------------------------------------------+
| password('foobarbaz') |
+-------------------------------------------+
| *8C5206E23A3B76002AA6E152691F5C5D7ABC31F9 |
+-------------------------------------------+
Therefore, this fails:
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'
and also if I use sudo, I can connect to mysql as root using any password or none.
To put it another way, this ansible command doesn't do anything, but if I use any other user or host it works.
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
Since Ansible supports Unix domain socket for local connections now, there is pretty elegant way (without initial root user setup and any file config):
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 parameter is available for all Ansible mysql modules (v2.9 | v2.10+)
The cause is this limitation of the Ansible mysql_user module:
Currently, there is only support for the mysql_native_password
encryted password hash module.
You can install MySQL packages with or without specifying a root password.
Installation with root password
With a password, the root#localhost login uses mysql_native_password, which is the password hashing method introduced in MySQL 4.1.1, where passwords are 41 bytes long beginning with a single asterisk, and the password() function generates the hash.
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 |
+-----------+------------------+-------------------------------------------+-----------------------+
Installation without root password
Without a password, root#localhost uses the auth_socket plugin:
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 only works if you're connecting from localhost through a unix_socket. It simply checks if the username making the connection matches the username in the 'user' field, there is no password.
That's why you can do sudo mysql and use any password you like, or none, but doing mysql -u root -p as an unprivileged user will never work, regardless of what password you type.
The Ansible module is currently unable to set a password unless the plugin is mysql_native_password, so you need to set the plugin value correctly first.
There's already a feature request for fixing this.
Solution
Install MySQL with a password, by using the debconf module to supply it in advance (you have to set it twice, once for the confirmation screen). Then install MySQL, save the password to /root/.my.cnf so root user can connect automatically, and use mysql_user to set whatever other logins you need.
- 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
Alternative solution:
sudo mysql -u root -p{{ mysql_root_password }} -e "ALTER USER 'root'#'localhost' IDENTIFIED WITH mysql_native_password BY '{{ mysql_root_password }}'; FLUSH PRIVILEGES;"
It works the first time because root still uses the auth_socket authentication plugin and ignores the password, and for subsequent runs because the password will be correct.
Found the solution, with an explanation on how to debug here: https://www.percona.com/blog/2016/03/16/change-user-password-in-mysql-5-7-with-plugin-auth_socket/

Unable to connect to MySQL on Ubuntu from MySQL Workbench on Windows

I have a Linux VM running Ubuntu 14.04 LTS Server. I have installed MySQL 5.6.26 on it and have added a user by issuing the following commands from the terminal window:
CREATE USER 'sas'#'%' IDENTIFIED BY 'some-password-1234';
GRANT ALL PRIVILEGES ON *.* TO 'sas'#'%' IDENTIFIED BY 'some-password-1234' WITH GRANT OPTION;
FLUSH PRIVILEGES;
I can log into mysql with this user with this command:
mysql -u sas -p
and can see this user listed in mysql.users table by issuing this command:
mysql> select host, user from mysql.user;
which results to the following output:
+-----------+------------------+
| host | user |
+-----------+------------------+
| % | sas |
| 127.0.0.1 | root |
| ::1 | root |
| localhost | debian-sys-maint |
| localhost | root |
| ubuntu | root |
+-----------+------------------+
However, when I try to setup a connection in MySQL Workbench from a Windows box using the credentials of user "sas", I get
"Can't connect to MySQLServer on 10.166.7.16".
This is not a network issue since running tcpdump on the Linux box shows the initiated connection from the Windows box.
What should I be looking out for?
On Debian and Ubuntu, mysqld binds to the lo interface only by default. Go through MySQL's configs and look for a directive that reads bind-address. Change its value to 0.0.0.0 if necessary, restart mysqld and try again.

mysql: connection refused when trying to connect to localhost using remote IP

When I try to connect to a local mysql database using it's remote ip-address I get a access denied. When I try to connect to that same database from an external machine, it works without any problems. When I connect to the local database using localhost, it works perfectly as well. E.g., if the database server has the ip 1.2.3.4 then I get the following results:
# From the db server
mysql -u username -h localhost -p #works perfectly
mysql -u username -h 127.0.0.1 -p #works perfectly
mysql -u username -h 1.2.3.4 -p #Access denied
# From any other machine
mysql -u username -h 1.2.3.4 -p #works perfectly
What can I do to allow local access to my database using its remote ip-address? The OS of the database server is Fedora 15 and the MySQL version is 5.5.23.
Try to edit/add bind-address = 0.0.0.0 to your [mysqld] section of your /etc/mysql/mysql.conf.d/mysqld.cnf file and restart MySQL Service.
I found the solution to my problem myself, but I still don't quite understand why it didn't work:
I granted privileges to that user on the hosts % and localhost:
# Before
+-----------------+------------+
| Host | User |
+-----------------+------------+
| % | username |
| localhost | username |
+-----------------+------------+
With these settings I got the results I showed above. When I granted privileges to that user on host it suddenly did work.
# After
+-----------------+------------+
| Host | User |
+-----------------+------------+
| % | username |
| localhost | username |
| <myIpAddress> | username |
+-----------------+------------+
Apparently % does work for remote connections, but not for local connections.
This particular issue can be caused by host name resolution.
I have resolved it in my particular case by deleting this variable from my my.cnf config file:
skip-name-resolve
Either remark the variable by placing a pound sign # or just delete it from your my.cnf after making sure you back it up, of course.