2019年2月2日の PostgreSQLアンカンファレンス で喋った内容をこちらにも書いておきます。
pg_snakeoil
先月末(28 Jan 2019)に PostgreSQL Announce メーリングリストに、面白そうな拡張モジュールのリリースアナウンスがありました。その名も pg_snakeoil。名前も変(snakeoil=いんちき膏薬、的な意味)ですが、提供する機能が興味をそそります。pg_snakeoil はオープンソースのウイルス対策ソフトClamAV を PostgreSQL から利用できるようにしたものです。
PostgreSQL とウイルス対策ソフト
PostgreSQLは何しろウイルス対策ソフトと相性がよくありません。PostgreSQLはデータディレクトリの中をウイルス対策ソフトがスキャンすると、しばしば競合を起こします。特にファイルの同時オープンに厳しい Windows において顕著です。そしてウイルス対策ソフトは Windowsの場合に特に導入が要請されるものです。そのため、PostgreSQLのデータディレクトリはウイルス対策ソフトの検査対象外に指定しておくというのが、ベストプラクティスになっています。
ところが、そうすると攻撃者にとってPostgreSQLのデータディレクトリが都合の良いファイルの退避地になってしまいます。こうした理由から、PostgreSQLの動作と協調しながら、データディレクトリ内を検査してくれるツールを必要とされていました。
というわけで、pg_snakeoilのアナウンスを見て、まさにこれだと思ったわけです。ところがドキュメントを良く読むと・・・
コレジャナイ
わたしが欲しいのはバックグラウンドで PostgreSQL配下のデータベースクラスタやテーブルスペース内のファイルを、PostgreSQL本体と競合せずに検査してくれる機能です。ところが、pg_snakeoilが提供するのは、引数の文字列やバイナリ列についてウイルスチェックするSQL関数でした。
postgres=# SELECT so_is_infected('Not a virus!');
so_is_infected
----------------
f
(1 row)
postgres=# SELECT so_is_infected('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
so_is_infected
----------------
t
(1 row)
どちらかというと論理レベル、すなわち INSERT、UPDATEされるデータを検査する用途を指向しているようです。とはいえ、前述の希望する機能を作るときのお手本としては有用そうです。
ビルドできない
手元の CentOS7.5 / PG10.6、そして、epelリポジトリから入手した clamav 0.101.1 で実際に使ってみようとしましたら・・・
pg_snakeoil.c: In function 'scan_data':
pg_snakeoil.c:163:93: error: 'CL_SCAN_STDOPT' undeclared (first use in this function)
result.return_code = cl_scanmap_callback(map, &result.virus_name, &result.scanned, engine, CL_SCAN_STDOPT, NULL);
pg_snakeoil.c:163:2: error: too few arguments to function 'cl_scanmap_callback'
result.return_code = cl_scanmap_callback(map, &result.virus_name, &result.scanned, engine, CL_SCAN_STDOPT, NULL);
エラーです。clamAV のバージョンが合っていないようです。しかし、README にはどのバージョンの clamAV をサポートしているかも書いていません。とりあえず、githubで作者にエラー報告をしました。
と、ここまででアンカンファレンス発表の時間です。上記のような話をしました。
「モノがウイルス対策ソフトなのだから、epelで何も考えずに導入される最新版に対応していないのでは困るよね」などと言ったりして。
その後、githubサイトを見ると・・・
速攻直してくれた
すばらしい。無事動作しました。
次は Windowsでのビルド、そしてバックグラウンドでファイルレベル検査に応用することを目指します。