SE-PostgreSQL 8.2.3-1.0 alpha release

追記:ITproさんに取り上げて頂きました
http://itpro.nikkeibp.co.jp/article/NEWS/20070305/263930/

======================================================
Security Enhanced PostgreSQL 8.2.3-1.0 alpha release
======================================================

Security Enhanced PostgreSQL (SE-PostgreSQL) は、PostgreSQL拡張機能で、SELinuxと連携して一元的なセキュリティポリシに基づく細粒度の強制アクセス制御を提供します。このようなSE-PostgreSQLの特徴は、RDBMSをOSと一体化した情報フロー制御の枠組みに組み込むことを可能にし、情報資産を漏えいや改ざんといった脅威から保護します。

細粒度のアクセス制御
SE-PostgreSQLは行レベル/列レベルのアクセス制御を可能にします。
PostgreSQL-ACLは表よりも小さな単位のDBオブジェクトにアクセス制御を提供しないため、SE-PostgreSQLの利用によって、データベース管理者はより柔軟できめ細かいアクセス制御を施すことが可能です。

強制アクセス制御
SE-PostgreSQLの提供するアクセス制御は、特権ユーザを含む全てのDBクライアントから発行された全てのSQLクエリに対して例外なく適用されます。即ち、SE-PostgreSQLはユーザ空間リファレンスモニタとして機能します。

SELinuxとの相互作用
SE-PostgreSQLの提供するアクセス制御は、SELinuxセキュリティポリシーに基づいて意思決定が行われます。また、DBクライアントの権限は、接続元プロセスのセキュリティコンテキストによって決定されます。

(※) 本バージョンのSE-PostgreSQLは、正式なリリースに先立って、オープンソースコミュニティからの要望やバグのレポート等のフィードバックを得るためのものです。従って、未だコードに対する十分な検証が行われていないことに留意の上、ご利用ください。
(※) 本ソフトウェアは、IPA 未踏ソフトウェア創造事業(2006年/下期)の支援を受けて開発が進められています。




[インストール]
SE-PostgreSQLは、SELinuxセットアップ済みの Fedora Core 6 環境にインストールすることができます。

以下のURLからRPMパッケージを取得してください

http://code.google.com/p/sepgsql/downloads/list
selinux-policy-2.4.6-40.sepgsql.noarch.rpm
selinux-policy-targeted-2.4.6-40.sepgsql.noarch.rpm
sepostgresql-8.2.3-0.206a.i386.rpm

最初に、selinux-policy と selinux-policy-targeted パッケージをインストールし、続いて sepostgresql パッケージをインストールします。
sepostgresql パッケージのインストール時に、SE-PostgreSQL用の標準セキュリティポリシーがインストールされます。
また、フロントエンドとして psql コマンドを利用する場合には postgresql及び postgresql-libs パッケージのインストールが別途必要です。

データベースクラスタを初期化するため、以下のコマンドを実行してください。

# /etc/init.d/sepostgresql initdb

/var/lib/sepgsql/data 以下にデータベースクラスタが作成されます。

続いて、SE-PostgreSQL サーバを起動します。(標準の) postgresqlサーバが停止していることを確認し、以下のコマンドを実行してください。

# /etc/init.d/sepostgresql start

データベースクラスタを初期化するのは sepgsql ユーザです。suコマンドで sepgsql ユーザになり、createdbコマンドでデータベースを作成したり、createuserコマンドでデータベースロールを作成することができます。

  [例]
  # su - sepgsql
  $ createuser kaigai
  Shall the new role be a superuser? (y/n) y
  CREATE ROLE
  $ createdb kaigaidb
  CREATE DATABASE
  $
[サンプルSQL/構築用]
CREATE TABLE drink (
    did     integer primary key,
    dname   text,
    dprice  integer,
    dsoft   bool,
    dstock  integer
);

ALTER TABLE drink ALTER dstock
    context = 'user_u:object_r:sepgsql_secret_table_t';

INSERT INTO drink VALUES (1, 'juice', 110, true,  35);
INSERT INTO drink VALUES (2, 'coke',  110, true,  20);
INSERT INTO drink VALUES (3, 'milk',  130, true,   5);
INSERT INTO drink VALUES (4, 'water', 100, true,  10);
INSERT INTO drink VALUES (5, 'beer',  240, false, 15);
INSERT INTO drink VALUES (6, 'wine',  380, false,  0);

UPDATE drink SET security_context =
    'user_u:object_r:sepgsql_table_t:SystemHigh'
    where dsoft = false;

create or replace function drink_stock_exist (integer)
    returns bool
    language 'sql'
    as 'select dstock > 0 from drink where did = $1';

ALTER FUNCTION drink_stock_exist(integer)
    context = 'user_u:object_r:sepgsql_trusted_proc_t';


[サンプルSQL/実行例]
$ id -Z
root:system_r:unconfined_t:SystemLow-SystemHigh
$ psql -q
kaigai=# select sepgsql_getcon();
                 sepgsql_getcon
-------------------------------------------------
 root:system_r:unconfined_t:SystemLow-SystemHigh
(1 row)

kaigai=# select * from drink;
 did | dname | dprice | dsoft | dstock
-----+-------+--------+-------+--------
   1 | juice |    110 | t     |     35
   2 | coke  |    110 | t     |     20
   3 | milk  |    130 | t     |      5
   4 | water |    100 | t     |     10
   5 | beer  |    240 | f     |     15
   6 | wine  |    380 | f     |      0
(6 rows)

## 各タプルのセキュリティコンテキストは、システム列 security_context に
## 格納されています。
kaigai=# select security_context,* from drink;
        security_context         | did | dname | dprice | dsoft | dstock
---------------------------------+-----+-------+--------+-------+--------
 user_u:object_r:sepgsql_table_t |   1 | juice |    110 | t     |     35
 user_u:object_r:sepgsql_table_t |   2 | coke  |    110 | t     |     20
 user_u:object_r:sepgsql_table_t |   3 | milk  |    130 | t     |      5
 user_u:object_r:sepgsql_table_t |   4 | water |    100 | t     |     10
 user_u:object_r:sepgsql_table_t |   5 | beer  |    240 | f     |     15
 user_u:object_r:sepgsql_table_t |   6 | wine  |    380 | f     |      0
(6 rows)

kaigai=#

## 権限を落として実行してみます。
## SystemHigh の2つのタプルが結果セットから除外されました

$ runcon -l s0 -- bash
$ id -Z
root:system_r:unconfined_t
$ psql -q
kaigai=# select sepgsql_getcon();
       sepgsql_getcon
----------------------------
 root:system_r:unconfined_t
(1 row)

kaigai=# select * from drink;
NOTICE:  SELinux: denied { select }
    scontext=root:system_r:unconfined_t 
    tcontext=user_u:object_r:sepgsql_table_t:SystemHigh
    tclass=tuple
NOTICE:  SELinux: denied { select }
    scontext=root:system_r:unconfined_t
    tcontext=user_u:object_r:sepgsql_table_t:SystemHigh
    tclass=tuple
 did | dname | dprice | dsoft | dstock
-----+-------+--------+-------+--------
   1 | juice |    110 | t     |     35
   2 | coke  |    110 | t     |     20
   3 | milk  |    130 | t     |      5
   4 | water |    100 | t     |     10
(4 rows)

kaigai=#
$ exit

## sepgsql_secret_table_t にアクセスできないドメインから接続します。

$ runcon -t initrc_t -- bash
$ id -Z
root:system_r:initrc_t:SystemLow-SystemHigh
$ psql -q
kaigai=# select * from drink;
ERROR:  SELinux: denied { select }
    scontext=root:system_r:initrc_t:SystemLow-SystemHigh
    tcontext=user_u:object_r:sepgsql_secret_table_t
    tclass=column name=dstock

## sepgsql_secret_table_t タイプの dstock 列へのアクセスを行おうとして
## アクセスが拒否されました。
## しかし、Trusted Procedure を利用することによって、信頼された手続きに
## 基づいてのみ dstock 列へのアクセスを許可しています。

kaigai=# select did, dname, dprice, drink_stock_exist(did) from drink;
 did | dname | dprice | drink_stock_exist
-----+-------+--------+-------------------
   1 | juice |    110 | t
   2 | coke  |    110 | t
   3 | milk  |    130 | t
   4 | water |    100 | t
   5 | beer  |    240 | t
   6 | wine  |    380 | f
(6 rows)

kaigai=#

[ヒント]
・ SE-PostgreSQLPostgreSQL には、データベースのフォーマットに互換性はありません。誤って PostgreSQL のデータベースを破壊しないよう注意してください。
・ アクセス拒否ログ/アクセス許可ログは、SELinuxのboolean(条件変数)を用いて制御することができます。sesetboolコマンドで以下のbooleanを設定してください。
sepgsql_enable_auditallow
sepgsql_enable_auditdeny
sepgsql_enable_audittuple
・テスト用に initrc_t を権限の弱いドメインとして定義しています。initrc_tドメインからは DDL 文が使えない他、sepgsql_secret_table_t のテーブル/カラム/タプルにアクセスできません。
・strict-policy向けのセキュリティポリシーは開発中です。α版をご利用の場合、targeted-policyを利用する必要があります。