GA

2024/03/08

Rocky Linux 8とMySQLでcoreファイルが見つからない

TL;DR


—core-file も ulimit -c unlimited も設定してるのにcoredumpが見つからない…と思ったら変わっていたらしい。


$ less /usr/mysql/8.0.36/data/error.log

..

2024-03-08T07:36:23Z UTC - mysqld got signal 11 ;

<secret>
/usr/mysql/8.0.36/bin/mysqld(do_command(THD*)+0x15b) [0xde00bb]
/usr/mysql/8.0.36/bin/mysqld() [0xf391b8]
/usr/mysql/8.0.36/bin/mysqld() [0x2576814]
/lib64/libpthread.so.0(+0x81da) [0x7fa868e941da]
/lib64/libc.so.6(clone+0x43) [0x7fa867236e73]

Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (7fa80438de80): SHOW CREATE TABLE sys.metrics
Connection ID (thread ID): 14
Status: NOT_KILLED

The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
Writing a core file

Writing a core file と言ってるくせに、datadirにない。

$ ll /usr/mysql/8.0.36/data/core*
ls: cannot access '/usr/mysql/8.0.36/data/core*': No such file or directory

journalctl を見たらなんかスタックトレース ( gdb の thread apply all bt と同じように全スレッドぶん) が載ってる…こんなの前にはなかったはず…そして俺はスタックトレースじゃなくてcoreファイルが欲しいんだ…!

$ sudo journalctl --since=today | less
..
Mar 08 07:36:45 yoku0825-sandbox systemd-coredump[2500410]: Process 2453404 (mysqld) of user 1001 dumped core.

                                                            Stack trace of thread 2453453:
                                                            #0  0x00007fa868e9ba85 pthread_kill (libpthread.so.0)
                                                            #1  0x0000000000f4913c handle_fatal_signal (mysqld)
                                                            #2  0x00007fa868e9ed40 __restore_rt (libpthread.so.0)
..

と思ってググったらあっという間に冒頭のブログに出会った。

systemd-coredump環境で暮らす - 赤帽エンジニアブログ

$ sudo coredumpctl list
TIME                            PID   UID   GID SIG COREFILE  EXE
Thu 2024-03-07 02:41:14 GMT  2433147  1001  1001  11 present   /usr/mysql/8.0.36/bin/mysqld
Thu 2024-03-07 04:00:05 GMT  2441380  1001  1001   5 present   /usr/mysql/8.0.36/bin/mysqld
Fri 2024-03-08 07:36:45 GMT  2453404  1001  1001  11 present   /usr/mysql/8.0.36/bin/mysqld

coredumpctl dump .. でスタックトレースが出て「違う、俺はコアファイルが欲しいんだ」って気になったけど特に気にしなくて良くてちゃんとoutputに出力されてた。

$ sudo coredumpctl dump -1 --output ./core.2433147
           PID: 2453404 (mysqld)
           UID: 1001 (yoku0825)
           GID: 1001 (yoku0825)
        Signal: 11 (SEGV)
     Timestamp: Fri 2024-03-08 07:36:23 GMT (50min ago)
  Command Line: /usr/mysql/8.0.36/bin/mysqld --basedir=/usr/mysql/8.0.36 --datadir=/usr/mysql/8.0.36/data --plugin-dir=/usr/mysql/8.0.36/lib/plugin --server-id=1080 --default-authentication-plugin=mysql_native_password --mysqlx=off --early-plugin-load=keyring_file.so --default-time-zone=+00:00 --loose-rpl-semi-sync-source-enabled=ON --loose-innodb-ddl-threads=1 --log-error=error.log --pid-file=/usr/mysql/8.0.36/data/mysql.pid --socket=/usr/mysql/8.0.36/data/mysql.sock --port=64080
    Executable: /usr/mysql/8.0.36/bin/mysqld
 Control Group: /
         Slice: -.slice
       Boot ID: 64f2b36cc0ba43cea4f50ea42cae833f
    Machine ID: f0891c4bddbf4944abc3c0e87e12fe9c
      Hostname: yoku0825-sandbox
       Storage: /var/lib/systemd/coredump/core.mysqld.1001.64f2b36cc0ba43cea4f50ea42cae833f.2453404.1709883383000000.lz4
       Message: Process 2453404 (mysqld) of user 1001 dumped core.

..

dumpで吐き出させたあとはいつも通りgdbで見られる。 coredumpctl debug -1 でも良さそう(sudo噛ませると .gdbinit 読んでくれなくてちょっと見づらい)

$ gdb ../bin/mysqld core.2433147
or
$ sudo coredumpctl debug -1
           PID: 2453404 (mysqld)
           UID: 1001 (yoku0825)
           GID: 1001 (yoku0825)
        Signal: 11 (SEGV)
     Timestamp: Fri 2024-03-08 07:36:23 GMT (53min ago)
  Command Line: /usr/mysql/8.0.36/bin/mysqld --basedir=/usr/mysql/8.0.36 --datadir=/usr/mysql/8.0.36/data --plugin-dir=/usr/mysql/8.0.36/lib/plugin --server-id=1080 --default-authentication-plugin=mysql_native_password --mysqlx=off --early-plugin-load=keyring_file.so --default-time-zone=+00:00 --loose-rpl-semi-sync-source-enabled=ON --loose-innodb-ddl-threads=1 --log-error=error.log --pid-file=/usr/mysql/8.0.36/data/mysql.pid --socket=/usr/mysql/8.0.36/data/mysql.sock --port=64080
    Executable: /usr/mysql/8.0.36/bin/mysqld
 Control Group: /
         Slice: -.slice
       Boot ID: 64f2b36cc0ba43cea4f50ea42cae833f
    Machine ID: f0891c4bddbf4944abc3c0e87e12fe9c
      Hostname: yoku0825-sandbox
       Storage: /var/lib/systemd/coredump/core.mysqld.1001.64f2b36cc0ba43cea4f50ea42cae833f.2453404.1709883383000000.lz4
       Message: Process 2453404 (mysqld) of user 1001 dumped core.

..
### これもしばらくスタックトレース吐いたあと止まるけどそのうちgdbが始まる

coredumpctl infoだと圧縮されたコアファイルのパスも吐いてくれるので、lz4catとかでもなんとかなった

$ sudo coredumpctl info -1
           PID: 2453404 (mysqld)
           UID: 1001 (yoku0825)
           GID: 1001 (yoku0825)
        Signal: 11 (SEGV)
     Timestamp: Fri 2024-03-08 07:36:23 GMT (54min ago)
  Command Line: /usr/mysql/8.0.36/bin/mysqld --basedir=/usr/mysql/8.0.36 --datadir=/usr/mysql/8.0.36/data --plugin-dir=/usr/mysql/8.0.36/lib/plugin --server-id=1080 --default-authentication-plugin=mysql_na>
    Executable: /usr/mysql/8.0.36/bin/mysqld
 Control Group: /
         Slice: -.slice
       Boot ID: 64f2b36cc0ba43cea4f50ea42cae833f
    Machine ID: f0891c4bddbf4944abc3c0e87e12fe9c
      Hostname: yoku0825-sandbox
       Storage: /var/lib/systemd/coredump/core.mysqld.1001.64f2b36cc0ba43cea4f50ea42cae833f.2453404.1709883383000000.lz4         <----- ここ
       Message: Process 2453404 (mysqld) of user 1001 dumped core.

..

昔 abrtd にコアファイルを消し去られる事案があってそれかなあと思っていたら RHEL8では非推奨 になっていたんですね。

OSが変わったことを感じる…。

​

2024/03/07

replicate_wild_ignore_table="mysql.%" で CREATE USERやGRANTがignoreされる理由

TL;DR

  • 体感としては知ってたけどレプリケーションフィルタには対応するコードがなくてもんにょりしていた
  • sql/rpl_filter.cc じゃなくて sql/auth/sql_user_table.cc に埋まっていやがった

ドキュメントには、

ただし、通常はこの情報を間接的に更新するステートメント (GRANT、REVOKE、およびトリガー、ストアドルーチン、およびビューを操作するステートメント) は、ステートメントベースレプリケーションを使用してレプリカにレプリケートされます。

MySQL :: MySQL 8.0 リファレンスマニュアル :: 17.5.1.22 mysql システムスキーマのレプリケーション

Table-level replication filters are only applied to tables that are explicitly mentioned and operated on in the query. They do not apply to tables that are implicitly updated by the query. For example, a GRANT statement, which updates the mysql.user system table but does not mention that table, is not affected by a filter that specifies mysql.% as the wildcard pattern.

https://dev.mysql.com/doc/refman/8.0/en/replication-options-replica.html#option_mysqld_replicate-wild-ignore-table

(日本語版にはこの表記がなかった…)

しかもご丁寧に回避方法まで

If you need to filter out GRANT statements or other administrative statements, a possible workaround is to use the —replicate-ignore-db filter. This filter operates on the default database that is currently in effect, as determined by the USE statement.

https://dev.mysql.com/doc/refman/8.0/en/replication-options-replica.html#option_mysqld_replicate-wild-ignore-table

と、あたかもCREATE USERもGRANTもフィルターに引っかからずにステートメントベースのルールでだけ評価されそうなことを言っているのに、現実には replicate_wild_ignore_table=mysql.% でフィルタされてしまう。

実験。

### Sourceになる
mysqlsh -- dba deploySandboxInstance 3306 --password=testpass

### 比較のためにreplicate_ignore_db=mysqlを設定したMySQL
mysqlsh -- dba deploySandboxInstance 3307 --password=testpass --mysqldOptions="replicate-ignore-db=mysql"

### 本丸のreplicate_wild_ignore_table=mysql.%を設定したMySQL
mysqlsh -- dba deploySandboxInstance 3308 --password=testpass --mysqldOptions="replicate-wild-ignore-table=mysql.%"

ソースにCREATE USER/GRANTでレプリケーション用アカウントを作る。ここまではフツー。

mysqlsh root:testpass@localhost:3306 --sql

CREATE USER replicate IDENTIFIED BY 'replication';
GRANT REPLICATION SLAVE ON *.* TO replicate;

3307のインスタンスと3308のインスタンスでそれぞれレプリケーションを組む。 source_ssl=1 にしているのはcaching_sha2_passwordのエラー避け ( 日々の覚書: MySQL 8.0のcaching_sha2_password + 非SSL接続が転ける )
別に GET_SOURCE_PUBLIC_KEY=1 でもいい。

mysqlsh root:testpass@localhost:3307 --sql

CHANGE REPLICATION SOURCE TO source_host = '127.0.0.1', source_port = 3306, source_user = 'replicate', source_password = 'replication', source_ssl = 1;
START REPLICA;

---

mysqlsh root:testpass@localhost:3308 --sql

CHANGE REPLICATION SOURCE TO source_host = '127.0.0.1', source_port = 3306, source_user = 'replicate', source_password = 'replication', source_ssl = 1;
START REPLICA;

source_log_pos を指定していないのでソースに残っている先頭のバイナリログのpos=1からレプリケーションするので、本来 CREATE USERとGRANTはレプリカでも実行されてアカウントが作成されるはず。

それぞれのインスタンスでSHOW GRANTSしてみると、

for port in 3306 3307 3308 ; do
  mysqlsh root:testpass@localhost:$port --sql -e "SHOW GRANTS FOR replicate"
done

Grants for replicate@%
GRANT REPLICATION SLAVE ON *.* TO `replicate`@`%`    ### 3306, replication source

Grants for replicate@%
GRANT REPLICATION SLAVE ON *.* TO `replicate`@`%`    ### 3307, replicate_ignore_db=mysql だけどCREATE USERもGRANTも `USE` しない状態でやっているのでフィルターされない

ERROR: 1141 (42000) at line 1: There is no such grant defined for user 'replicate' on host '%'   ### 3308のreplicate_wild_ignore_tablesだとフィルターされてCREATEもGRANTも実行されない

コードを見る限りたぶんMySQLのバグじゃなくてドキュメントが間違ってるんだと思う。

https://github.com/mysql/mysql-server/blob/mysql-8.0.36/sql/auth/sql_user_table.cc#L1975-L1990

​

2024/03/05

MySQLのCHECKSUM TABLEは特別なことをせずに愚直に行を全部読んでチェックサムを取っている

TL;DR

  • タイトルが全て
  • インデックスの情報は考慮しないのでインデックスが違ってもチェックサムは一致する
  • 最終的に行ごとのチェックサムを合計しているので行の順番が違ってもチェックサムは一致する

CHECKSUM TABLE は不思議なちからでテーブルのチェックサムを計算しているかのように思えるかも知れないがさにあらず。
実に地味に1行1フィールドずつ読んでチェックサムを取っている。

https://github.com/mysql/mysql-server/blob/mysql-8.0.36/sql/sql_table.cc#L18745-L18904

ということは、データ型が同じ扱いになるやつや行の順番には関係がないので CHECKSUM TABLE が通ることがある…?

  • PKあり vs PKなし、データ型いっしょ、行の順番違う

    • CHECKSUMいっしょ
mysql80 40> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `num` bigint unsigned NOT NULL AUTO_INCREMENT,
  `val` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`num`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql80 40> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `num` bigint unsigned NOT NULL,
  `val` varchar(32) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql80 40> SELECT * FROM t1;
+-----+------+
| num | val  |
+-----+------+
|   1 | one  |
|   2 | two  |
+-----+------+
2 rows in set (0.00 sec)

mysql80 40> SELECT * FROM t2;
+-----+------+
| num | val  |
+-----+------+
|   2 | two  |
|   1 | one  |
+-----+------+
2 rows in set (0.00 sec)

mysql80 40> CHECKSUM TABLE t1, t2;
+-------+------------+
| Table | Checksum   |
+-------+------------+
| d1.t1 | 4082666774 |
| d1.t2 | 4082666774 |
+-------+------------+
2 rows in set (0.00 sec)
  • varchar vs char, 行の順番一緒

    • 違うのになる
mysql80 40> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `val` varchar(32) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql80 40> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `val` char(32) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql80 40> CHECKSUM TABLE t1, t2;
+-------+------------+
| Table | Checksum   |
+-------+------------+
| d1.t1 | 1816645479 |
| d1.t2 | 2736998372 |
+-------+------------+
2 rows in set (0.00 sec)
  • varchar(32) vs varchar(255), 行の順番一緒

    • 同じのになる
mysql80 40> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `val` varchar(32) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql80 40> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `val` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql80 40> CHECKSUM TABLE t1, t2;
+-------+------------+
| Table | Checksum   |
+-------+------------+
| d1.t1 | 1816645479 |
| d1.t2 | 1816645479 |
+-------+------------+
2 rows in set (0.00 sec)

あなたの知らない CHECKSUM TABLE の世界

​

2024/02/09

GRANTでデータベース名にワイルドカードを指定することとpartial revokesと

TL;DR

  • partial_revokes が有効な状態だと GRANT ALL ON 'd%'.* TO .. みたいなデータベースワイルドカードの構文が効かない
In privilege assignments, enabling partial_revokes causes MySQL to interpret occurrences of unescaped _ and % SQL wildcard characters in schema names as literal characters, just as if they had been escaped as \_ and \%. Because this changes how MySQL interprets privileges, it may be advisable to avoid unescaped wildcard characters in privilege assignments for installations where partial_revokes may be enabled.

In addition, use of _ and % as wildcard characters in grants is deprecated as of MySQL 8.0.35, and you should expect support for them to be removed in a future version of MySQL.

https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_partial_revokes


ドキュメントに書いてある以外に地味な罠があったし、そもそもこのpartial_revokesの制限を知らずに知らずに時間を溶かしたのでメモ。。

CREATE USER yoku0825;
GRANT ALL ON `d%`.* TO yoku0825;  -- シングルクォートでなくてバッククォート

mysql80 9> SHOW GRANTS;
+--------------------------------------------------+
| Grants for yoku0825@%                            |
+--------------------------------------------------+
| GRANT USAGE ON *.* TO `yoku0825`@`%`             |
| GRANT ALL PRIVILEGES ON `d%`.* TO `yoku0825`@`%` |
+--------------------------------------------------+
2 rows in set (0.00 sec)

mysql80 9> CREATE DATABASE d11;   -- d%` にマッチするから
Query OK, 1 row affected (0.00 sec)

mysql80 9> CREATE DATABASE d15;   -- d% にマッチするから
Query OK, 1 row affected (0.01 sec)

mysql80 9> CREATE DATABASE newdb;  -- d% にマッチしないから
ERROR 1044 (42000): Access denied for user 'yoku0825'@'%' to database 'newdb'

SET GLOBAL partial_revokes = ON;

mysql80 11> CREATE DATABASE d17;   -- d% が文字列リテラルとして解釈されるから
ERROR 1044 (42000): Access denied for user 'yoku0825'@'%' to database 'd17'

mysql80 11> DROP DATABASE d11;  -- !?
Query OK, 0 rows affected (0.00 sec)

mysql80 11> CREATE TABLE d15.t1 (num int);  -- !?
Query OK, 0 rows affected (0.01 sec)

このデータベースのワイルドカード指定が8.0.35から非推奨だから、この一貫性のない挙動が直ってくれる気はしない…。


【2024/02/09 15:21】

他の環境(8.0.32 + partial_revokes)だと既存のスキーマに対する操作もちゃんと拒否された(一貫性がある)

違いがわからぬ。。。


【2024/02/09 17:41】

my.cnfにpartial_revokes足してmysqldを再起動したらちゃんと一貫性のある動作になった。安心。

​


2024/01/23

mysql_ssl_rsa_setupがopensslコマンドを実行しているだけっぽいので見てみた

TL;DR

実行してるのは以下。


cd $datadir

echo "basicConstraints=CA:TRUE" > cav3.ext

echo "basicConstraints=CA:FALSE" > certv3.ext

openssl version
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout ca-key.pem -subj /CN=MySQL_Server_8.0.36_Auto_Generated_CA_Certificate -out ca-req.pem
openssl rsa -in ca-key.pem -out ca-key.pem
openssl x509 -sha256 -days 3650 -extfile cav3.ext -set_serial 1 -req -in ca-req.pem -signkey ca-key.pem -out ca.pem
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -subj /CN=MySQL_Server_8.0.36_Auto_Generated_Server_Certificate -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -sha256 -days 3650 -extfile certv3.ext -set_serial 2 -req -in server-req.pem -CA ca.pem -CAkey ca-key.pem -out server-cert.pem
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem -subj /CN=MySQL_Server_8.0.36_Auto_Generated_Client_Certificate -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -sha256 -days 3650 -extfile certv3.ext -set_serial 3 -req -in client-req.pem -CA ca.pem -CAkey ca-key.pem -out client-cert.pem
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem

mysql_ssl_rsa_setup がなんか openssl コマンドをそのまま投げている気がしたので strace で雑に拾い上げてみた。

https://github.com/mysql/mysql-server/blob/mysql-8.0.36/client/mysql_ssl_rsa_setup.cc#L270-L271

execveのやつだけ拾い上げてみる。

[yoku0825@yoku0825-sandbox ~]$ strace -f -s 1000 -e execve /usr/mysql/8.0.36/bin/mysql_ssl_rsa_setup --datadir=/tmp/rsa 2>&1 1>/dev/null | grep openssl
[pid 346515] execve("/bin/sh", ["sh", "-c", "openssl version > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346516] execve("/usr/bin/openssl", ["openssl", "version"], 0x55eb7da66760 /* 45 vars */) = 0
[pid 346517] execve("/bin/sh", ["sh", "-c", "openssl req -newkey rsa:2048 -days 3650 -nodes -keyout ca-key.pem -subj /CN=MySQL_Server_8.0.36_Auto_Generated_CA_Certificate -out ca-req.pem && openssl rsa -in ca-key.pem -out ca-key.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346518] execve("/usr/bin/openssl", ["openssl", "req", "-newkey", "rsa:2048", "-days", "3650", "-nodes", "-keyout", "ca-key.pem", "-subj", "/CN=MySQL_Server_8.0.36_Auto_Generated_CA_Certificate", "-out", "ca-req.pem"], 0x557bb10a9760 /* 45 vars */) = 0
[pid 346519] execve("/usr/bin/openssl", ["openssl", "rsa", "-in", "ca-key.pem", "-out", "ca-key.pem"], 0x557bb10ba9b0 /* 45 vars */) = 0
[pid 346520] execve("/bin/sh", ["sh", "-c", "openssl x509 -sha256 -days 3650 -extfile cav3.ext -set_serial 1 -req -in ca-req.pem -signkey ca-key.pem -out ca.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346521] execve("/usr/bin/openssl", ["openssl", "x509", "-sha256", "-days", "3650", "-extfile", "cav3.ext", "-set_serial", "1", "-req", "-in", "ca-req.pem", "-signkey", "ca-key.pem", "-out", "ca.pem"], 0x562d199db760 /* 45 vars */) = 0
[pid 346522] execve("/bin/sh", ["sh", "-c", "openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -subj /CN=MySQL_Server_8.0.36_Auto_Generated_Server_Certificate -out server-req.pem && openssl rsa -in server-key.pem -out server-key.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346523] execve("/usr/bin/openssl", ["openssl", "req", "-newkey", "rsa:2048", "-days", "3650", "-nodes", "-keyout", "server-key.pem", "-subj", "/CN=MySQL_Server_8.0.36_Auto_Generated_Server_Certificate", "-out", "server-req.pem"], 0x55882da28760 /* 45 vars */) = 0
[pid 346524] execve("/usr/bin/openssl", ["openssl", "rsa", "-in", "server-key.pem", "-out", "server-key.pem"], 0x55882da398d0 /* 45 vars */) = 0
[pid 346525] execve("/bin/sh", ["sh", "-c", "openssl x509 -sha256 -days 3650 -extfile certv3.ext -set_serial 2 -req -in server-req.pem -CA ca.pem -CAkey ca-key.pem -out server-cert.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346526] execve("/usr/bin/openssl", ["openssl", "x509", "-sha256", "-days", "3650", "-extfile", "certv3.ext", "-set_serial", "2", "-req", "-in", "server-req.pem", "-CA", "ca.pem", "-CAkey", "ca-key.pem", "-out", "server-cert.pem"], 0x5577023de760 /* 45 vars */) = 0
[pid 346527] execve("/bin/sh", ["sh", "-c", "openssl req -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem -subj /CN=MySQL_Server_8.0.36_Auto_Generated_Client_Certificate -out client-req.pem && openssl rsa -in client-key.pem -out client-key.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346528] execve("/usr/bin/openssl", ["openssl", "req", "-newkey", "rsa:2048", "-days", "3650", "-nodes", "-keyout", "client-key.pem", "-subj", "/CN=MySQL_Server_8.0.36_Auto_Generated_Client_Certificate", "-out", "client-req.pem"], 0x56301ba4e760 /* 45 vars */) = 0
[pid 346529] execve("/usr/bin/openssl", ["openssl", "rsa", "-in", "client-key.pem", "-out", "client-key.pem"], 0x56301ba5f8d0 /* 45 vars */) = 0
[pid 346530] execve("/bin/sh", ["sh", "-c", "openssl x509 -sha256 -days 3650 -extfile certv3.ext -set_serial 3 -req -in client-req.pem -CA ca.pem -CAkey ca-key.pem -out client-cert.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346531] execve("/usr/bin/openssl", ["openssl", "x509", "-sha256", "-days", "3650", "-extfile", "certv3.ext", "-set_serial", "3", "-req", "-in", "client-req.pem", "-CA", "ca.pem", "-CAkey", "ca-key.pem", "-out", "client-cert.pem"], 0x5562dd1f4760 /* 45 vars */) = 0
[pid 346532] execve("/bin/sh", ["sh", "-c", "openssl verify -CAfile ca.pem server-cert.pem client-cert.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346533] execve("/usr/bin/openssl", ["openssl", "verify", "-CAfile", "ca.pem", "server-cert.pem", "client-cert.pem"], 0x562abf4f7760 /* 45 vars */) = 0
[pid 346534] execve("/bin/sh", ["sh", "-c", "openssl genrsa  -out private_key.pem 2048 > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346535] execve("/usr/bin/openssl", ["openssl", "genrsa", "-out", "private_key.pem", "2048"], 0x55ed169cb760 /* 45 vars */) = 0
[pid 346536] execve("/bin/sh", ["sh", "-c", "openssl rsa -in private_key.pem -pubout -out public_key.pem > /dev/null 2>&1"], 0x7fffd3ff2930 /* 46 vars */) = 0
[pid 346537] execve("/usr/bin/openssl", ["openssl", "rsa", "-in", "private_key.pem", "-pubout", "-out", "public_key.pem"], 0x5593c3a5e760 /* 45 vars */) = 0

ここからコマンドだけを引っこ抜いた ( && の部分は成功したから openssl が引数の方の execve に載っていたのでリストしてある ) のが冒頭のテキスト。
echo コマンドまでは使っていなかったけど、このファイルが無いと当然 -extfile の指定で転けるので平文だしechoで作ってみた。

https://github.com/mysql/mysql-server/blob/mysql-8.0.36/client/mysql_ssl_rsa_setup.cc#L317-L321

流石に mysqld の auto_generate_certs の方はここまで雑な作りではなかった。

https://github.com/mysql/mysql-server/blob/824e2b4064053f7daf17d7f3f84b7a3ed92e5fb4/sql/auth/sql_authentication.cc#L5912-L5990

ちなみに mysql_ssl_rsa_setup は8.0.34で非推奨だそうです。
https://dev.mysql.com/doc/refman/8.0/en/mysql-ssl-rsa-setup.html

​

2024/01/20

keyring_fileを消したり戻したりしながら確かめてみる

ただ思いついたことを順番に実行したメモ。


1. keyring_fileを食った状態でt1を作る。

2. keyring_fileをコピーして消す

3. t2を作る -> エラーログなし

4. mysqldを停止してkeyring_fileを戻す

5. mysqldを起動する

6. t1もt2も読める

7. keyring_fileをコピーして消してmysqld再起動

8. t1, t2は読めない -> 起動時のエラーログに出る

9. t3を作る

10. mysqld再起動

11. t3を作った時点でkeyring_fileが変わっているのでt1, t2は読めない、t3だけが読める状態


```
2024-01-20T14:29:22.972253Z 1 [ERROR] [MY-012664] [InnoDB] Failed to decrypt encryption information, please check whether key file has been changed!
2024-01-20T14:29:22.972297Z 1 [ERROR] [MY-012226] [InnoDB] Encryption information in datafile: ./d1/t1.ibd can't be decrypted, please confirm that keyring is loaded.
2024-01-20T14:29:22.972780Z 1 [ERROR] [MY-012664] [InnoDB] Failed to decrypt encryption information, please check whether key file has been changed!
2024-01-20T14:29:22.972795Z 1 [ERROR] [MY-012226] [InnoDB] Encryption information in datafile: ./d1/t2.ibd can't be decrypted, please confirm that keyring is loaded.
```

12. mysqldを止めてt3を作ったkeyring_fileを消してt2までの時点のkeyring_fileを戻して起動

13. t1, t2は読めるけどt3が読めない状態で起動

14. t3のことは忘れて、keyring_fileをコピーして消してmysqld再起動 -> 当然t1, t2が読めない状態で起動

15. keyring_fileを戻してt4を作る

16. mysqld再起動

17. t1, t2は読めない、t4だけが読める



keyring_fileを食わせて起動したらさっさと消してしまってマスターキーのローテーションの時だけ戻せば…とか雑なことを考えたけど、その間に暗号化テーブルを作られたら簡単に詰む