★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

F.40. sepgsql

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

警告

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

F.40.1. 概要

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

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

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

F.40.2. インストール

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

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のセットアップを行わねばなりません。

このモジュールをビルドするには、PostgreSQLのconfigureコマンドに--with-selinuxオプションを追加してください。 これは、ビルド時にlibselinux-develパッケージがインストールされている事を確認します。

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

以下にsepgsql関数およびセキュリティラベルと共にデータベースクラスタを初期化する手順を示します。 インストール先に応じて、適宜パス名を読み替えるようにしてください。

$ export PGDATA=/path/to/data/directory
$ initdb
$ vi $PGDATA/postgresql.conf

  この行を
    #shared_preload_libraries = ''                # (change requires restart)

  以下に変更
    shared_preload_libraries = 'sepgsql'          # (change requires restart)
$ for DBNAME in template0 template1 postgres; do
    postgres --single -F -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 type db_blobs
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 36 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 37 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 38 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 39 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 40 has invalid object type db_language

これらのメッセージは無害ですので無視してください。

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

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

SELinuxの性質上、sepgsqlのリグレッションテストを実行するには、いくつかの追加的な設定が必要で、そのうちの幾つかはrootで実行する必要があります。 リグレッションテストは通常のmake checkmake installcheckコマンドで実行する事はできません。 必要な設定を行い、テスト用スクリプトを手動で実行する必要があります。 このテストはPostgreSQLビルドツリーのcontrib/sepgsqlディレクトリで実行する必要があります。 しかしビルドツリーを必要とする一方、このテストはインストールされたサーバに対して実行する必要があります。 これは、make checkではなく、make installcheckによく似ています。

最初に、F.40.2に従ってsepgsqlをデータベースにセットアップします。 使用するOS上のユーザは、認証無しでデータベース特権ユーザとして接続できる必要があることに留意してください。

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

$ cd .../contrib/sepgsql
$ make -f /usr/share/selinux/devel/Makefile
$ sudo semodule -u sepgsql-regtest.pp
$ sudo semodule -l | grep sepgsql
sepgsql-regtest 1.07

次に、sepgsql_regression_test_modeを有効化してください。 安全のため、デフォルトではsepgsql-regtestに含まれる全てのルールが有効化されている訳ではありません。 sepgsql_regression_test_modeパラメータはリグレッションテストを起動するために必要となる幾つかのルールを有効にします。 setseboolコマンドによって有効化する事ができます。

$ sudo setsebool sepgsql_regression_test_mode on
$ getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on

次に、シェルがunconfined_tドメインで動作している事を確認して下さい。

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

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

最後に、リグレッションテストのスクリプトを実行します。

$ ./test_sepgsql

このスクリプトは全ての設定ステップが正常に行われていることを確認し、その後、sepgsqlモジュールに対するリグレッションテストを実行します。

テストの実行後はsepgsql_regression_test_modeパラメータを無効化する事をお勧めします。

$ sudo setsebool sepgsql_regression_test_mode off

sepgsql-regtestポリシーをアンロードする際は、以下のコマンドを実行してください。

$ sudo semodule -r sepgsql-regtest

F.40.4. GUCパラメータ

sepgsql.permissive (boolean)

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

このパラメータがonの場合、たとえSELinuxがエンフォーシングモードで動作していたとしても、sepgsql関数はパーミッシブモードで動作します。 このパラメータは主としてテストの目的に有用です。

sepgsql.debug_audit (boolean)

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

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

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

F.40.5. 機能

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

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

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

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

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

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

参照された全てのカラムに対して列レベルの権限チェックが行われます。 SELECT構文で読み出されるカラムに対してだけでなく、他のDML構文で参照されているカラムに対してもdb_column:select権限がチェックされます。 また、UPDATEINSERTによって操作の対象となっているカラムに対しても、db_column:updatedb_column:insert権限がそれぞれチェックされます。

以下の例を見てください

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

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

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

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

利用者がクエリの一部として、あるいは近道インタフェースを用いた呼び出しによって関数を実行しようとするとき、db_procedure:{execute}権限がチェックされます。 関数がトラステッドプロシージャである場合、関数がトラステッドプロシージャのエントリーポイントとして振る舞う事ができるかどうかを検査するためにdb_procedure:{entrypoint}権限がチェックされます。

あらゆるスキーマオブジェクトにアクセスするためには、それらを含むスキーマに対するdb_schema:search権限が必要です。 あるスキーマオブジェクトがスキーマ修飾無しに参照された場合、この権限を与えられていないスキーマは探索されません(あたかも利用者がスキーマに対するUSAGE権限を有していないかのように振る舞います)。 明示的なスキーマ修飾があり、このスキーマに対して利用者が要求された権限を有していない場合、エラーが発生します。

クライアントは全ての被参照テーブル・カラムに対して参照の権限を有している必要があります。それらがビューに由来し、展開されたものであっても同様です。これにより、テーブルの内容がどのような方法によって参照されるかに関係なく、一貫したアクセス制御ルールを適用する事ができます。

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

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

オブジェクトの作成、変更、削除やセキュリティラベルの変更など、SELinuxは各オブジェクトに共通の操作を制御するためのパーミッションを何個か定義しています。 また、特定のスキーマに対する名前の追加や削除など、いくつかのオブジェクトにはそれ固有の操作を制御するための特別なパーミッションも定義されています。

新しいデータベースオブジェクトの作成にはcreate権限が必要です。 SELinuxは利用者のセキュリティラベルと新しいオブジェクトに付与される事になるセキュリティラベルの対に基づいて、この権限を許可、あるいは拒否します。 いくつかの場合では、追加的な権限チェックが行われます。

  • CREATE DATABASEは、複製元またはテンプレートのデータベースに対するgetattr権限を要求します。

  • スキーマオブジェクトの作成は、それを含むスキーマに対してadd_name権限を要求します。

  • テーブルの作成は同時に、それがあたかも独立したオブジェクトであるかのように、個々のテーブル列を作成する権限を要求します。

  • LEAKPROOF属性を持った関数の作成はinstall権限を要求します。(これはまた、既存の関数にLEAKPROOF属性を設定する時にも要求されます)

DROP構文の実行時、削除されるオブジェクトに対してdrop権限がチェックされます。 CASCADEにより間接的に削除されるオブジェクトに対してもチェックは行われます。 特定のスキーマに含まれるオブジェクト(テーブル、ビュー、シーケンスや関数)の削除に際しては、スキーマに対するremove_name権限も併せてチェックされます。

ALTER構文の実行時、テーブルに対するインデックスやトリガなど別オブジェクトに従属するもの(これらは代わりに親オブジェクトに対する権限がチェックされる)を除き、setattrがチェックされます。 いくつかの場合では、追加的な権限チェックが行われます。

  • オブジェクトを新しいスキーマに移動させるには、古いスキーマに対してremove_name権限が、新しいスキーマに対してadd_name権限が必要です。

  • 関数に対するLEAKPROOF属性の設定はinstall権限を要求します。

  • SECURITY LABELコマンドの実行時、ラベル付けされるオブジェクトの古いラベルに対してsetattr権限とrelabelfrom権限が、入力された新しいラベルに対してrelabelto権限がチェックされます。 (複数のラベルプロバイダがインストールされており、利用者がSELinuxの管理下にないラベルを設定しようとした場合、setattr権限だけがチェックされるべきです。しかし実装上の制約により、現在はこれをチェックしていません。)

F.40.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.40.5.5. 動的ドメイン遷移

セキュリティポリシーによって許可されている場合、SELinuxの動的ドメイン遷移機能を用いて、利用者のラベルを新しいものに切り替える事ができます。 利用者のドメインはsetcurrent権限および、古いドメインから新しいドメインに遷移するためのdyntransition権限を有している必要があります。

利用者に自身のラベル、すなわち権限を切り替える事を可能にする動的ドメイン遷移は、システムによる自動切り替え(トラステッドプロシージャの場合)に比べて慎重に取り扱う必要があります。 dyntransition権限は元々のドメインよりも小さな権限セットを持つドメインに切り替える場合にのみ安全であると考えられます。 例えば、

regression=# select sepgsql_getcon();
                    sepgsql_getcon
-------------------------------------------------------
 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4');
 sepgsql_setcon
----------------
 t
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023');
ERROR:  SELinux: security policy violation

上記の例では、広いMCSレンジc1.c1023から狭いMCSレンジc1.c4への遷移は許可されているものの、その逆は禁止されています。

動的ドメイン遷移とトラステッドプロシージャの組み合わせは、典型的なコネクションプーラのライフサイクルに適合する興味深い利用法を提供します。 たとえコネクションプーリングソフトウェアが大半のSQLの実行を許可されていない場合でも、トラステッドプロシージャの内側からsepgsql_setcon()関数を用いて利用者のセキュリティラベルを切り替える事ができます。(トラステッドプロシージャは利用者のセキュリティラベルを切り替えるための認証情報を要求すべきです。) この後、現在のセッションはコネクションプーラの権限ではなく、対象となる利用者の権限で動作する事になります。 また、sepgsql_setcon()NULL引数を与えて(適切な権限チェックを行う)トラステッドプロシージャから再び呼び出す事で、コネクションプーラは後でセキュリティラベルを元に戻す事ができます。 ここでのポイントは、トラステッドプロシージャだけが実際に有効なセキュリティラベルを変更する権限を持っており、正しい認証情報が与えられた場合にのみそれを実行するという事です。 言うまでもなく、安全な操作のためには、権限のないアクセスから認証情報を保持するテーブルや関数定義などを保護しなければなりません。

F.40.5.6. その他

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

F.40.6. sepgsql関数

表 F.29に利用可能な関数を示します。

表F.29 sepgsql関数

関数

説明

sepgsql_getcon () → text

利用者のドメイン、つまり、現在の利用者ラベルを返却します。

sepgsql_setcon ( text ) → boolean

セキュリティポリシーで許可されている場合、現在のセッションの利用者ドメインを新しいドメインへと切り替えます。 NULLを引数に取る事も可能で、その場合、元々の利用者ドメインへの遷移を意味します。

sepgsql_mcstrans_in ( text ) → text

mcstransデーモンが動作している場合、入力されたMLS/MCSレンジを修飾フォーマットから直接フォーマットに変換します。

sepgsql_mcstrans_out ( text ) → text

mcstransデーモンが動作している場合、入力されたMLS/MCSレンジを直接フォーマットから修飾フォーマットに変換します。

sepgsql_restorecon ( text ) → boolean

現在のデータベース内のすべてのオブジェクトに対して初期セキュリティラベルを割り当てます。 引数はNULLもしくはシステムの標準に代わる定義ファイルの名前です。


F.40.7. 制限事項

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

実装上の制約により、いくつかのDDL操作はパーミッションをチェックしません。

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

実装上の制約により、DCL操作はパーミッションをチェックしません。

行レベルアクセス制御

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

隠れチャネル

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

F.40.8. 外部リソース

SE-PostgreSQL Introduction

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

SELinux User's and Administrator's Guide

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

Fedora SELinux FAQ

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

F.40.9. 作者

KaiGai Kohei