BLOB機能のサポート

PostgreSQLには、データベースにファイルの内容をそのまま格納したい時に便利なBLOB(Binary Large Object)という機能がある。

ネイティブPostgreSQLには、特にBLOBに対するアクセス制御機能が備わっていないために、重要なデータを保持する場合には注意が必要である。が、それは置いておいてww

SE-PostgreSQLでは、DBMSを経由した情報フローを管理するという観点から、当然BLOBに対するアクセス制御を行う必要がある。つまり、BLOBへのread/wrtieにアクセス制御を行う必要がある。これ自体は全く難しい話ではなく、フックを一つ入れれば済むだけの話である。

頭痛のタネになったのが、サーバー側の lo_import()関数と、lo_export()関数。

Oid lo_import(text <em>filename</em>)
int32 lo_export(Oid <em>loid</em>, text <em>filename</em>)

lo_import()関数は、filenameで指定されたファイルをサーバ側のファイルシステム上で検索し、それをBLOBとしてDBに叩き込む。
lo_export()関数は、loidで指定されたBLOBを、filenameとして指定されたサーバ側ファイルシステム上のファイルとして書き込む。

このファイル入出力を行うのは SE-PostgreSQLサーバプロセスであり、クライアントプロセスではない。
ファイルに対するアクセス制御も、SE-PostgreSQLサーバプロセス <--> ファイル間でOSがフックして行われる。このため、クライアントプロセスの権限に関係なくSE-PostgreSQLサーバプロセスの書き出した物として扱われる。

ここで私の採った方法は、blob:{import export}というアクセスベクタを新たに追加したというもの。ここでのポイントは、import/exportの対象が SE-PostgreSQL のサーバプロセスであること。

つまり、以下のようなデータフローを記述できるようになる。

SE-PostgreSQL     blob:read   Binary Large
Client Process <------------- Object (BLOG)
   |
   |  blob:export          SE-PostgreSQL   file:write   Exported
   +---------------------> Server Process ------------>   Files

SE-PostgreSQLは最初に、BLOB→Clientのread権限をチェックし、次にClient→Serverのexport権限をチェックする。
そして、Server→Fileのfile:write権限がOSによって行われ、lo_export()の処理が行われる。

ここでの考え方は、lo_export()の処理では一旦クライアントがBLOBのデータを参照し、それをサーバに転送する。そして、サーバがそれをファイルに書き出すというもの。
あくまでも、ファイルとのI/Oを行っている主体はサーバプロセスであるので矛盾は生じない。