F.38. sepgsql

sepgsqlは、SELinuxのセキュリティポリシーに基づいた、ラベルベースの強制アクセス制御(MAC; Mandatory Access Control)機能を提供するモジュールです。

警告

現在の実装にはいくつかの重要な制限事項があり、そのため、全ての操作に対して強制アクセス制御を適用するわけではありません。 詳細は 項F.38.6 をご覧ください。

F.38.1. 概要

このモジュールは、PostgreSQLが標準で提供しているものに加えて、SELinuxと統合されたアクセス制御のレイヤーを追加します。 SELinuxの視点からは、このモジュールがPostgreSQLをユーザ空間オブジェクトマネージャとして機能することを可能にします。 すなわち、DMLクエリによる個々のテーブルや関数へのアクセスは、オペレーティングシステムのセキュリティポリシーによってチェックされます。 このチェックは、PostgreSQLによる通常のパーミッションに対して、追加的に実施されます。

SELinuxにおけるアクセス制御の意思決定は、system_u:object_r:sepgsql_table_t:s0のような書式を持ったセキュリティラベルと呼ばれる文字列を用いて行われます。 個々のアクセス制御の意思決定には、2種類のラベルが利用されます。 すなわち、ある操作を行おうとする主体(サブジェクト)のラベルと、その操作の対象となるオブジェクトのラベルです。 これらのラベルはあらゆる種類のオブジェクトに対して適用されるため、(このモジュールを用いる事で)データベースに格納されたオブジェクトに対するアクセス制御は、他の一般的なオブジェクト(例: ファイル)に対するものと同一の基準に従って意思決定される事になります。 このデザインは、情報資産を格納する方法とは独立に、一元管理されたセキュリティポリシーによって情報資産を保護することを意図しています。

SECURITY LABELを用いてデータベースオブジェクトにセキュリティラベルを設定することができます。

F.38.2. インストール

このモジュールはSELinuxが有効なLinuxカーネル 2.6.28 以上で動作します。その他のプラットフォーム上では利用する事はできません。 加えて、libselinux 2.0.101以上、selinux-policy 3.9.13以上(ディストリビューションによっては、必要なルールを古いバージョンのポリシーにバックポートしているか可能性があります)が必要で、--with-selinuxオプションによって明示的に有効化しなければいけません。

sestatusコマンドを用いてSELinuxの状態を確認することができます。

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted

SELinuxが無効化されている、あるいはインストールされていない場合、このモジュールのインストールの前に、SELinuxのセットアップを行わねばなりません。

このモジュールを利用するには、shared_preload_libraries パラメータに sepgsql を追記する必要があります。これ以外の方法で ロードされた場合、このモジュールは機能しません。 このモジュールのロード後、各データベースに対してsepgsql.sqlを 実行し、セキュリティラベル管理のための関数のインストールや、初期セキュリティ ラベルの設定を行うべきです。

以下の手順では、/usr/local/pgsqlディレクトリ以下にPostgreSQLのインストールが行われ、/path/to/database以下にデータベースクラスタが構築されているものとします。 インストール先に応じて、適宜パスを読み替えるようにして下さい。

$ export PGDATA=/path/to/database
$ initdb
$ vi $PGDATA/postgresql.conf
$ for DBNAME in template0 template1 postgres; do
  postgres --single -F -O -c exit_on_error=true $DBNAME \
      < /usr/local/pgsql/share/contrib/sepgsql.sql > /dev/null
  done

インストール手順が正常に終了したら、通常通り、サーバを起動することができます。

特定のバージョンのlibselinuxselinux-policyの 組み合わせによっては、以下のメッセージが出力されるかもしれません。

/etc/selinux/targeted/contexts/sepgsql_contexts:  line 33 has invalid object ty

このメッセージは無害なものであり、無視しても構いません。

F.38.3. リグレッションテスト

SELinuxの性質上、このモジュールのリグレッションテストを実行するには、追加的なサーバ設定が何点か必要となります。

最初に、項F.38.2に従ってsepgsqlのインストールを行ってください。このリグレッションテストはSE-Linuxが動作しているシステム上で実行されることを意図しています。また、OS上のユーザはスーパーユーザとして認証なしでデータベースに接続できなければいけません。

次に、リグレッションテスト用のポリシーパッケージのビルドとインストールを行ってください。sepgsql-regtest.ppはリグレッションテストの実行に必要な一連のルールを含む特別な目的のポリシーパッケージです。 ポリシーのソースファイル(sepgsql-regtest.te)から、通常はmakeコマンドによってビルドする事ができます。 この時、インストール先システムにおいて、適切なMakefileの位置を指定する必要があります。以下の例で示されているパスは一例です。 ビルドが完了したら、semoduleを用いてこのポリシーパッケージをインストールする事ができます。このコマンドは、指定されたポリシーパッケージをリンクし、カーネル空間にロードする役割を果たします。 インストールが正常終了したら、semodule -lにより有効なパッケージの一覧としてsepgsql-regtestが表示されるはずです。

$ make -C ./contrib/sepgsql -f /usr/share/selinux/devel/Makefile
$ su
# semodule -u ./contrib/sepgsql/sepgsql-regtest.pp
# semodule -l
    :
sepgsql-regtest 1.03
    :

三番目に、SELinuxのブーリアン設定sepgsql_regression_test_modeを有効化してください。 安全のため、デフォルトではsepgsql-regtest.ppに含まれる全てのルールが有効化されている訳ではありません。 sepgsql_regression_test_modeはリグレッションテストを起動するための幾つかのルールに関連付けされており、setseboolコマンドによって有効化する事ができます。

$ su
# setsebool sepgsql_regression_test_mode on
# getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on

最後に、unconfined_tドメインからリグレッションテストを起動します。

idコマンドを使って現在のドメインを確認する事ができます。 以下のように、シェルプロセスがunconfined_tドメインで動作している事を確認してください。

$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

利用者の動作ドメインを設定する方法について、必要であれば、詳細は項F.38.7をご覧ください。

pg_regressコマンドがpsqlコマンドの起動に失敗するようであれば、psqlコマンドが正しくbin_tタイプにラベル付けされている事を確かめた方が良いでしょう。 そうでなければ、多くの場合、restoreconコマンドを用いる事でPostgreSQLのインストール先ディレクトリ配下のセキュリティラベルを修正する事ができるでしょう。

$ restorecon -R /usr/local/pgsql/

F.38.4. GUCパラメータ

sepgsql.permissive (boolean)

このパラメータにより、オペレーティングシステムの設定に関わらず、SE-PostgreSQLをパーミッシブモードで動作させる事ができます。デフォルトの設定値はoffです。 postgresql.conf内、およびサーバ起動時のコマンドラインでのみ、このパラメータを設定する事ができます。

このパラメータがonの場合、たとえオペレーティングシステムがエンフォーシングモードで動作していたとしても、SE-PostgreSQLはパーミッシブモードで動作します。 このパラメータは主としてテストの目的に有用です。

sepgsql.debug_audit (boolean)

このパラメータにより、セキュリティポリシーの設定とは無関係に監査ログを出力する事が可能になります。 デフォルト値はoff(セキュリティポリシーの設定に従う)です。

SELinuxのセキュリティポリシーには、特定のアクセスを監査ログに記録するか否かを制御するルールも存在します。 デフォルトでは、ポリシーに違反したアクセスを記録し、それ以外はログに記録されません。

システムのポリシーとは無関係に、このパラメータは全ての監査ログの出力を強制します。

F.38.5. 機能

F.38.5.1. 制御されるオブジェクトの種類

SELinuxのセキュリティモデルでは、全てのアクセス制御 ルールは動作主体(サブジェクト; 典型的にはデータベースクライアント)と 対象オブジェクト間の関係として記述し、これらはセキュリティラベルによって 識別されます。 ラベル付けされていないオブジェクトに対するアクセスが発生した場合、 そのオブジェクトはあたかもunlabeled_tタイプが割り当てられて いるかのように振舞います。

現在のsepgsqlでは、スキーマ、テーブル、カラム、シーケンス、ビューおよび関数に対するラベル付けがサポートされています。 sepgsqlの利用時には、これらのデータベースオブジェクトに対して、その生成時に自動的にセキュリティラベルが割り当てられます。 このラベルはデフォルトセキュリティラベルと呼ばれ、作成者のラベルと親関係にあたるオブジェクトのラベルに基づいて、システムのセキュリティポリシーが決定します。

新しいデータベースオブジェクトのラベルは、タイプ遷移と呼ばれる異なったラベルを設定するための特別なルールがセキュリティポリシーに設定されている場合を除き、親関係にあるオブジェクトのラベルを引き継ぎます。 スキーマの親オブジェクトはデータベースであり、カラムはその属するテーブルが、テーブル、シーケンス、ビュー、および関数はその属するスキーマが親オブジェクトという事になります。

F.38.5.2. DMLパーミッション

テーブルに対しては、構文の種類に応じてdb_table:selectdb_table:insertdb_table:updateあるいはdb_table:delete権限が全ての被参照テーブルに対してチェックされます。 加えて、WHERE句やRETURNING句で参照されるカラム、又はUPDATEの際のデータ元として利用されるカラムの属するテーブルに対してdb_table:select権限もチェックされます。

UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;

この場合、t1.aWHERE句の中で参照されているため、利用者はdb_table:update権限に加えて、db_table:select権限を有していなければいけません。 さらに、参照されているカラムに対しては列レベルのパーミッションがチェックされます。

ビューを通しての参照であっても、利用者は参照する全てのテーブルとカラムに対するアクセスを許可されている必要があります。 これにより、テーブルがどのような方法によりアクセスされるかを問わず、一貫したアクセス制御のルールを適用する事ができます。

カラムに対しては、SELECT構文で読み出されるカラムに対してだけでなく、他のDML構文で参照されるカラムに対してもdb_column:select権限がチェックされます。

言うまでもなく、UPDATE構文やINSERT構文によって更新されるカラムに対しては、db_column:update権限、もしくはdb_column:insert権限がチェックされます。

UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;

この場合、更新されるt1.xに対してdb_column:update権限が、更新と同時に参照されるt1.yに対してはdb_column:{select update}権限が、そして、WHERE句で参照されるだけのt1.zにはdb_column:select権限がチェックされます。 また、テーブルレベルではdb_table:{select update}権限がチェックされます。

SELECT構文を用いてシーケンスを参照する場合、db_sequence:get_valueがチェックされます。 しかし、現在のところlastval()など関連する関数の実行時にはパーミッションチェックを行わない事に留意してください。

ビューに対してはdb_view:expand権限がチェックされ、次いで、ビューから展開されたオブジェクトに対するパーミッションが個別にチェックされます。

関数に対してdb_procedure:{execute}権限が定義されていますが、現バージョンではチェックされません。

データベーススーパーユーザに対して、標準のデータベース権限システムはDMLを用いたシステムカタログの更新と、TOASTテーブルの参照および更新を許していますが、sepgsqlが有効なとき、これらの操作は禁止されます。

F.38.5.3. DDLパーミッション

SECURITY LABELコマンドの実行時、ラベル付けされるオブジェクトの古いラベルに対してsetattr権限とrelabelfrom権限が、入力された新しいラベルに対してrelabelto権限がチェックされます。

複数のラベルプロバイダがインストールされており、利用者がSELinuxの管理下にないセキュリティラベルを設定しようとした場合、setattr権限だけがチェックされるべきです。しかし実装上の制約により、現在はこれをチェックしていません。

F.38.5.4. トラステッド プロシジャ

トラステッド・プロシジャはSECURITY DEFINER関数やSet-UIDコマンドに似て います。通常、機密データに対する高度にコントロールされたアクセス手段を 提供する目的で、SELinuxは利用者のものとは異なる セキュリティラベルで信頼済みのコードを実行するための機能を持っています。 関数がトラステッド・プロシジャとして振舞うかどうかは、関数のセキュリティ ラベルおよびオペレーティングシステムのセキュリティポリシーに従って 決まります。 例えば:

postgres=# CREATE TABLE customer (
               cid     int primary key,
               cname   text,
               credit  text
           );
CREATE TABLE
postgres=# SECURITY LABEL ON COLUMN customer.credit
               IS 'system_u:object_r:sepgsql_secret_table_t:s0';
SECURITY LABEL
postgres=# CREATE FUNCTION show_credit(int) RETURNS text
             AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
                        FROM customer WHERE cid = $1'
           LANGUAGE sql;
CREATE FUNCTION
postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
               IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
SECURITY LABEL

これらの操作は管理権限を持つ利用者で行ってください。

postgres=# SELECT * FROM customer;
ERROR:  SELinux: security policy violation
postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
 cid | cname  |     show_credit
-----+--------+---------------------
   1 | taro   | 1111-2222-3333-xxxx
   2 | hanako | 5555-6666-7777-xxxx
(2 rows)

この場合、一般の利用者はcustomer.creditを直接参照することはできませんが、トラステッド・プロシジャであるshow_creditを用いる事で、一部の桁がマスクされた顧客のクレジットカード番号をプリントする事が可能になります。

F.38.5.5. その他

ロードされたモジュールは、セキュリティポリシーの適用を容易にバイパスできるため、LOADコマンドの実行は全面的に禁止されています。

F.38.6. 制限事項

ユーザ空間アクセスベクタ・キャッシュ

まだsepgsqlはユーザ空間アクセスベクタ・キャッシュをサポートしていません。この機能はパフォーマンスを改善するでしょう。

Data Definition Language (DDL) パーミッション

実装上の制約により、DDLパーミッションはチェックされていません。

Data Control Language (DCL) パーミッション

実装上の制約により、DCLパーミッションはチェックされていません。

Row-level access control

PostgreSQLは行レベルアクセス制御をサポートしていません。 したがって、sepgsqlも同様です。

隠れチャネル

たとえ利用者が参照を許可されていないオブジェクトであっても、sepgsqlはその存在を隠すことを意図していません。 例えば、我々があるオブジェクトの内容を参照する事ができなくても、主キーの競合や外部キー違反、その他の方法によって不可視なオブジェクトが存在する事を推測できます。 "最高機密"テーブルの存在を隠すことは不可能であり、その内容を秘匿することだけを意図しています。

F.38.7. 外部リソース

SE-PostgreSQL Introduction

このwikiページでは、概要、セキュリティ・デザイン、アーキテクチャ、管理、および将来の機能について紹介しています。

Fedora SELinux User Guide

このドキュメントはSELinuxシステム管理に対する広範な知識を提供しています。 主としてFedoraを対象としていますが、それに限ったものではありません。

Fedora SELinux FAQ

このドキュメントはSELinuxに関するよくある質問と回答(FAQ)です。 主としてFedoraを対象としていますが、それに限ったものではありません。

F.38.8. 著者

KaiGai Kohei