はじめに
mysqlでcsvファイルをテーブルにインポートしようとした時に、以下のようなエラーが発生しました。
mysql> LOAD DATA LOCAL INFILE '/tmp/dml/sakura100_info.csv' INTO TABLE `sakura_table` FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 LINES;
ERROR 2068 (HY000): LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.調べると、大事な内容だったので、こちらに記載してみようと思いました。
対処法
my.cnfファイルの中身にlocal_infile=1を設定すると、
bash-5.1# cat /etc/mysql/conf.d/my.cnf
[mysqld]
local_infile=1mysql側でlocal_infileがONとなります。
mysql> SHOW VARIABLES LIKE 'local_infile';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile | ON |
+---------------+-------+
1 row in set (0.01 sec)これでエラーが発生しなくなります。
また、--local-infile=1でmysqlにログインしてからcsvをインポートするとエラーが発生せずにインポートすることができます。
bash-5.1# mysql -u root -p --local-infile=1
mysql> LOAD DATA LOCAL INFILE '/tmp/dml/csv_dta/sakura100_info.csv' INTO TABLE `sakura_table` FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 LINES;
Query OK, 100 rows affected, 15 warnings (0.02 sec)
Records: 100 Deleted: 0 Skipped: 0 Warnings: 15dockerだと以下のように–local-infile=1を設定します。
cat ${SCRIPT_DIR}/../init_season_spot.sql | docker compose -f "$COMPOSE_FILE" exec -T db mysql --local-infile=1 --user=<myuser> --password=<mypassword>local_infileはいったい何のか?
local_infileは「クライアントがサーバーにファイルを送信して取り込むことを許可するかどうか」の有無を決めることができます。
ONにしたらクライアントがサーバーにファイルを送信して取り込むことを許可することになります。
一方で、LOAD DATA INFILE(LOCALなし)で読み込むサーバー側ファイルは、セキュリティの観点からsecure_file_privで指定されたディレクトリ内に限定されています。
- secure_file_privはデフォルトで設定される
- secure_file_privがデフォルトで設定されているときは、その設定されているディレクトリにあるファイルしか読み取れない
mysql> SHOW VARIABLES LIKE 'secure_file_priv';
+------------------+-----------------------+
| Variable_name | Value |
+------------------+-----------------------+
| secure_file_priv | /var/lib/mysql-files/ |
+------------------+-----------------------+これでcsvファイルをLOCALなしで読み込むことができます。
以下のように。
mysql> LOAD DATA INFILE '/var/lib/mysql-files/sakura100_info.csv' INTO TABLE `sakura_table` FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 LINES;
Query OK, 47 rows affected (0.10 sec)
Records: 47 Deleted: 0 Skipped: 0 Warnings: 0いや、このフォルダにあるのは何のメリットがあるの?
このフォルダ以外にファイルを配置するとで外部から読み取れてしまう脆弱性を生むことになります。
このフォルダにある事で直接読み取れる可能性を低くできます。
ですので、local_infileはON(1)に常にしておくことは避けるべきです。
できるだけ、secure_file_privが設定しているフォルダ内にファイル群は配置して、それ以外に配置する場合は、ファイル読込みの時だけlocal_infileをONにするのが良いです。
最後に
とりあえず、読み込ませたいから意味も調べずにlocal_infileをONにすることは避けよう!
参考: https://dev.mysql.com/doc/refman/8.0/ja/security-against-attack.html
