** 긴 글, 줄여보면(tldr;)
굳이
mysql root
를 사용하지 말고, 그냥sudo mysql
을 사용하는게 지금 추세인 듯 하다. 적어도 새롭게 만드는 DB 라면, 그냥 이 상태로 사용하는 편이 여러모로 정신건강에 좋을 듯 하다.
이 글은, 원래 다른 글의 일부로 있던 내용이었는데, 그 일부를 떼어 독립(?)시켰고, 주로 다음 글을 참고하여 작성했다.
Authentication from MariaDB 10.4
위 글은, 아래 글이 원문으로 보인다.
MariaDB 는 10.0 부터 인증 방식에 변화를 줬는데, 그게 바로 Unix Socket 방식이다.
이게 뭔 소리냐 하면, mysql 사용자와, 시스템 사용자를 일치시킨다는 의미가 된다.
mysql 내부에는 ‘root’ 라는 사용자가 존재한다. 이 root 는 mysql 이 돌아가고 있는 시스템(리눅스)의 root 와는 전혀 관계가 없다. 시스템 root 가 무소불위 권력을 가진 CEO 라고 한다면, mysql root 는 CIO 라고 할 수 있을까?
여기엔, CEO 가 CIO 에게 필요 시에, 모든 정보를 내놓으라고 할 수 있다는 전제가 깔려있다.
그리고, 그야말로 대형 시스템이라면 모르겠지만, 소규모 서버에서는 이 전제가 아마도 맞다고 본다. (즉, 시스템 root 가 마음만 먹는다면 mysql 의 모든 정보에 접근할 수 있다.)
그렇기에, MariaDB 측에선 이런 방식을 택한게 아니었을까.
어쨌든, 시스템 root 는 mysql root 와 동일인이 된다.
다시 말해서, mysql 사용자는 시스템 사용자와 동일한 ID 를 갖고, 시스템 사용자의 인증을 그대로 따라간다.
시스템에 root 가 있으면 mysql 에도 root 가 있다.
시스템에 mysql 이라는 사용자가 있다면, 역시 mysql 에도 같은 사용자가 있다.
실 사용은 이렇다.
예전, 두 root 가 분리되어 있을 때는, mysql 사용자 root 를 명시하고 로그인했다.
$ mysql -u root -p
Unix Socket 방식은 이렇다.
$ sudo mysql
sudo 로서 root 권한이 있다는 사실만 증명하면, mysql 에선 다른 인증을 하지 않는다.
만약, Unix Socket 을 사용하여, mysql 이라는 사용자로 mysql 에 접근하고 싶다면? 다소 헷갈리는 명령어를 사용해야 한다.
$ sudo -u mysql mysql -u mysql
- sudo -u user : 특정 사용자로 명령을 내리고자 할 때 사용한다.
- mysql : 시스템 사용자 mysql 을 뜻한다. (sudo -u mysql 로, 시스템 사용자 mysql 로 실행 주체를 바꾼다.)
- mysql : /usr/bin/mysql 을 뜻한다.
- -u mysql : mysql 사용자인 ‘mysql’ 을 명시한다.
mysql 이 계속 나오지만, 뜻은 모두 다름을 이해해야 한다.
이렇게, 시스템 ID = mysql ID 를 대응시켜 사용하는 게 현재 추세다.
그럼에도 불구하고 예전처럼 mysql root 를 시스템 root 와 분리하고 싶다면? 즉, mysql_native_password 방식을 사용하고 싶다면?
MariaDB 10.1 까지는 다음 방법으로 해줄 수 있다.
# 10.1 까지 $ sudo mysql_secure_installation ... mysql root 비밀번호 새로 설정. 기타 작업은 모두 Y 로. $ sudo mysql -u root MariaDB [(none)]> use mysql; MariaDB [mysql]> update user set plugin='mysql_native_password' where user='root'; MariaDB [mysql]> flush privileges; MariaDB [mysql]> quit;
10.4 이후는 이런 식이다.
$ sudo mysql -u root MariaDB [(none)]> set password = password("새로운 비밀번호 입력");
set password 를 해주기 전엔, “authentication_string” 이 “Invalid” 로 되어 있어서, 이 인증을 사용할 수가 없게 돼 있었다.
위 명령을 내린 후에도, unix_socket 방식과 mysql_native_password 방식을 그대로 유지할 수 있다.
즉, sudo mysql
로도, mysql -u root -p
로도 모두 접근 가능하다.
User, plugin 등을, 예전 방식으로 확인해보자면, 이런 결과가 나온다.
MariaDB [(none)]> SELECT user,authentication_string,plugin,host FROM mysql.user; +----------+-----------------------+-----------------------+-----------+ | User | authentication_string | plugin | Host | +----------+-----------------------+-----------------------+-----------+ | root | invalid | mysql_native_password | localhost | | mysql | invalid | mysql_native_password | localhost | +----------+-----------------------+-----------------------+-----------+
MariaDB 10.4 에도 mysql.user 테이블이 아직 있긴 있는데, 과거 호환을 위해서만 존재한다고 하고, 이제는 mysql.global_priv 를 써야 한다고 한다.
따라서, 아래와 같은 명령으로 인증 정보등을 확인할 수 있다.
MariaDB [(none)]> select concat(user, '@', host, ' => ', json_detailed(priv)) from mysql.global_priv; .... 중요부분만 발췌.. | root@localhost => { "access": 18446744073709551615, "plugin": "mysql_native_password", "authentication_string": "*4AD47E08DAE2BD4F0977EED5D23DC901359DF617", "auth_or": [ { }, { "plugin": "unix_socket" } ], "password_last_changed": 1562644150 }
두 방식이 모두 설정돼 있음을 볼 수 있긴 한데.. (뒤에 다시 언급하겠지만, mysql_native_password 만 할 수 있게 바꿔도 위 내용은 달라지질 않는다.)
만약, mysql_native_password 만 사용하게끔 하려면? MariaDB 문서에선 이렇게 하라고 한다.
$ sudo mysql -u root MariaDB [(none)]> ALTER USER root@localhost IDENTIFIED VIA mysql_native_password USING PASSWORD("verysecret")
이렇게 되면 sudo mysql
은 사용이 불가능해진다.
하지만 인증 방식을 mysql_native_password 전용으로 바꿔줬다 해도,
MariaDB [(none)]> ALTER USER root@localhost IDENTIFIED VIA mysql_native_password USING PASSWORD("verysecret") MariaDB [(none)]> select concat(user, '@', host, ' => ', json_detailed(priv)) from mysql.global_priv; .... 중요부분만 발췌.. | root@localhost => { "access": 1073741823, "plugin": "mysql_native_password", "authentication_string": "*4AD47E08DAE2BD4F0977EED5D23DC901359DF617", "auth_or": [ { }, { "plugin": "unix_socket" } ], "password_last_changed": 1562649627 }
이렇게, 눈에 보이기엔 바뀐 부분이 없다. 그러나, 어쨌든, sudo mysql
은 불가능해진다.
- 인증을 mysql_native_password 로 바꾸면, Nextcloud 등에서 사용하는 초기 설치 스크립트등을 무난하게 사용할 수 있다.
만약, 다시 두 인증방식을 모두 쓰고 싶다면,
MariaDB [(none)]> alter USER root@localhost IDENTIFIED VIA mysql_native_password USING password('verystrongpassword');
이 명령으로 원상태 복귀가 가능하다.
왜 이렇게(Unix Socket 방식 인증)해야하는 지에 대해, 내용을 읽어봐도 정확하겐 이해가 되지 않는다. 아마도 MariaDB 측은 ‘시스템 관리자 = DB 관리자’라는 정책을 피력하는 듯 하다. 해당 내용이 MariaDB 10.4 문서에 나와있다.
“Using unix_socket means that if you are the system root user, you can login as root@locahost without a password. This technique was pioneered by Otto Kekäläinen in Debian MariaDB packages and has been successfully used in Debian since as early as MariaDB 10.0.”
그렇다는 얘기는, mysql root 를 password 로그인하여 쓰지 말라는 거다. (즉, Unix Socket 방식이 보안에 더 좋다는 얘기.)
SQL 에 대한 이해가 부족해서겠지만, 모든 mysql 사용자를 시스템 사용자와 1:1 대응시키라는 얘기는 아닌 듯 하다. 그렇게 사용하려면 불편한 점이 더 많을텐데..?
아무튼 적어도 root 와 mysql(사용자) 은, 시스템/mysql 을 연동시켜 사용하라는게 MariaDB 10.4 의 골자다.
그러나, 예전방식을 고수하고자 mysql root 를 독립(?)시키면, 다시 말해서 mysql root 에 password 를 할당하면, 또 다른 문제가 발생한다.
이 문제는 우분투 18.04 에서 제공하는 10.1.40 에서 발생하고, MariaDB 저장소에 있는 Deb 꾸러미로 설치하면 발생하지 않는다.
어떤 문제냐 하면..
$ sudo systemctl status mariadb.service ● mariadb.service - MariaDB 10.1.40 database server Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled) Drop-In: /etc/systemd/system/mariadb.service.d └─migrated-from-my.cnf-settings.conf Active: active (running) since Wed 2019-06-26 16:30:38 KST; 1s ago Docs: man:mysqld(8) https://mariadb.com/kb/en/library/systemd/ Process: 6444 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS) Process: 6439 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS) Process: 6398 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= || VAR=`/usr/bin/galera_recovery`; [ $? -eq 0 ] && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=ex Process: 6391 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS) Process: 6373 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS) Main PID: 6408 (mysqld) Status: "Taking your SQL requests now..." Tasks: 26 (limit: 2285) CGroup: /system.slice/mariadb.service └─6408 /usr/sbin/mysqld Jun 26 16:30:38 nthnht mysqld[6408]: Version: '10.1.40-MariaDB-0ubuntu0.18.04.1' socket: '/var/run/mysqld/mysqld.sock' port: 3306 Ubuntu 18.04 Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6443]: Upgrading MySQL tables if necessary. Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6447]: /usr/bin/mysql_upgrade: the '--basedir' option is always ignored Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6447]: Looking for 'mysql' as: /usr/bin/mysql Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6447]: Looking for 'mysqlcheck' as: /usr/bin/mysqlcheck Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6447]: Version check failed. Got the following error when calling the 'mysql' command line client Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6447]: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6447]: FATAL ERROR: Upgrade failed Jun 26 16:30:38 nthnht /etc/mysql/debian-start[6459]: Checking for insecure root accounts. Jun 26 16:30:38 nthnht systemd[1]: Started MariaDB 10.1.40 database server.
이렇게, mariadb service 시작 시에 오류가 발생한다. 오류가 발생해도 작동에는 이상은 없는 듯 하다. 이 오류는 /etc/mysql/debian-start 가 실행되면서 발생하는데, 이 파일은 /etc/mysql/debian.cnf 를 참조하고, 이 파일의 내용은 아래와 같다.
# /etc/mysql/debian.cnf # Automatically generated for Debian scripts. DO NOT TOUCH! [client] host = localhost user = root password = socket = /var/run/mysqld/mysqld.sock [mysql_upgrade] host = localhost user = root password = socket = /var/run/mysqld/mysqld.sock basedir = /usr
debian.cnf 의 권한(소유자는 물론 root)은 600 으로 되어 있어, root 가 아니면 볼 수도 없다. 그렇다곤 해도, 저기에 mysql root 의 암호를 넣게끔 되어 있는 건, 보안 측면에서 최선은 아니라고 생각한다.
Mariadb 기본 설정에선 root password 가 설정되어 있지 않기 때문에 저렇게만 해놔도 아무 문제가 없지만, mysql root pw 를 임의로 할당한 경우엔 위와 같이 오류가 발생할 수 밖에 없다.
이 오류를 해결하려면, [mysql_upgrade] 항목에 있는 password 에 새로 설정한 비밀번호를 넣어주면 된다.
아니면, (해보진 않았지만) [mysql_upgrade] 부분을 모두 주석처리해도 괜찮을 듯 한데.. 업그레이드를 굳이 체크할 필요가 없지 않나?
어차피 이 파일은 root 만 볼 수 있으므로, 보안에 큰 문제가 되지는 않겠으나..
어쨌든 비밀번호를 Hash도 아니고 평문으로 그냥 저장한다는 건 결코 보안 측면에서 권장할만한 일은 아니다.
MariaDB 10.4 에선, 적어도 MariaDB 저장소에서 배포하는 꾸러미에는 이 파일(/etc/mysql/dedian.cnf)이 그냥 비어있다. 즉, debian.cnf 파일은 존재하기는 하되 내용은 없기에, 저런 오류가 발생할 여지가 아예 없다.
그리하여, 결론은! (문두의 tldr; 을 다시 옮겨보자면!)
굳이 mysql root
를 사용하지 말고, 그냥 sudo mysql
을 사용하는게 지금 추세인 듯 하다. 적어도 새롭게 만드는 DB 라면, 그냥 이 상태로 사용하는 편이 여러모로 정신건강에 좋을 듯 하다.
3 thoughts on “MariaDB; 인증(Authentication) 문제.”
Comments are closed.