RBACでDB管理者ロールを定義する(前編)

RHEL6もβが公開とかで、そろそろRBACが真っ当に使えるようなSELinuxの標準ポリシーが出てきそうな今日この頃。先んじて設定方法をまとめておく。

一応、標準ではwebコンテンツ管理者ロールというのが入っているが、私の興味分野的にアレなので、DB管理者ロールを定義して、特定のユーザがDB管理者ロールの時にだけDB起動/再起動などを行えるようにしたい。

まず、ポリシーモジュールを書く。
既にアップストリームに統合済みのポリシーも含まれているので、後々のFedoraではconflictする事もあるやと。その場合は、適宜重複分を削ってほしい。

policy_module(dbadm, 1.1.0)

########################################
#
# Declarations
#

## <desc>
## <p>
## Allow dbadm to manage files in users home directories
## </p>
## </desc>
gen_tunable(dbadm_manage_user_files, false)

## <desc>
## <p>
## Allow dbadm to read files in users home directories
## </p>
## </desc>
gen_tunable(dbadm_read_user_files, false)

role dbadm_r;

userdom_base_user_template(dbadm)


########################################
#
# database admin local policy
#

allow dbadm_t self:capability { dac_override dac_read_search sys_ptrace };

files_dontaudit_search_all_dirs(dbadm_t)
files_manage_generic_locks(dbadm_t)
files_list_var(dbadm_t)

selinux_get_enforce_mode(dbadm_t)

logging_send_syslog_msg(dbadm_t)

userdom_dontaudit_search_user_home_dirs(dbadm_t)

tunable_policy(`dbadm_manage_user_files',`
        userdom_manage_user_home_content_files(dbadm_t)
        userdom_read_user_tmp_files(dbadm_t)
        userdom_write_user_tmp_files(dbadm_t)
')

tunable_policy(`dbadm_read_user_files',`
        userdom_read_user_home_content_files(dbadm_t)
        userdom_read_user_tmp_files(dbadm_t)
')

optional_policy(`
        mysql_admin(dbadm_t, dbadm_r)
')

optional_policy(`
        postgresql_admin(dbadm_t, dbadm_r)
')

optional_policy(`
        staff_role_change_to(dbadm_r)
')

#
# Hotfix in type_transition rules and permissions to execute
# system defined procedures.
# (memo: this fix was already upstreamed at Mon Apr 12 2010)
#
gen_require(`
        class db_database all_db_database_perms;
        class db_table all_db_table_perms;
        class db_procedure all_db_procedure_perms;
        class db_column all_db_column_perms;
        class db_tuple all_db_tuple_perms;
        class db_blob all_db_blob_perms;

        attribute sepgsql_admin_type;
        attribute sepgsql_database_type;
        type sepgsql_db_t;
        type sepgsql_table_t;
        type sepgsql_proc_exec_t;
        type sepgsql_blob_t;
')
type_transition sepgsql_admin_type sepgsql_admin_type:db_database sepgsql_db_t;
type_transition sepgsql_admin_type sepgsql_database_type:db_table sepgsql_table_t;
type_transition sepgsql_admin_type sepgsql_database_type:db_procedure sepgsql_proc_exec_t;
type_transition sepgsql_admin_type sepgsql_database_type:db_blob sepgsql_blob_t;

allow sepgsql_admin_type sepgsql_proc_exec_t:db_procedure execute;

これをビルドしてインストール

$ vi dbadm.te
$ make -f /usr/share/selinux/devel/Makefile dbadm.pp
find: `~.doc': No such file or directory
Compiling targeted dbadm module
/usr/bin/checkmodule:  loading policy configuration from tmp/dbadm.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule:  writing binary representation (version 10) to tmp/dbadm.mod
Creating targeted dbadm.pp policy package
rm tmp/dbadm.mod tmp/dbadm.mod.fc
$ su
Password:
# semodule -i dbadm.pp
# semodule -l | grep dbadm
dbadm   1.1.0

OK。これで下準備は終わり。
後々のFedora/RedHatELのアップデートでは、この辺の下準備は必要なくなると思う。

次いで、SELinuxユーザとロールとの関連付けを行う。
SELinuxユーザというのは、UNIXユーザとロールに対してN:Mの対応付けを行うための抽象的な識別子で、あるロールの組(例:foo_r var_r baz_r)に対してUNIXユーザ(例:hoge monu)を対応させる場合に、1個のSELinuxユーザを定義してfoo_r var_r baz_rを紐付け、そこにhogeとmonuを関連付けてやる。

ここでは、sepgsql_uというSELinuxユーザを作成し、staff_r/dbadm_r/system_rを紐付けている。

  • Rオプション以外はひとまず"おまじない"だと思ってほしい。
# semanage user -a -R "staff_r dbadm_r system_r" -P user \
             -r s0-s0:c0.c1023 -L s0-s0:c0.c1023 sepgsql_u

次に、sepgsqlというUNIXユーザを、先ほど定義したsepgsql_uに関連付ける。

# semanage login -a -s sepgsql_u -r s0-s0:c0.c1023 sepgsql

最後に、sepgsql_uユーザがログイン時に利用するロールを指定する設定ファイルをコピーする。
今回の場合は、staff_uと全く同じなので編集の必要はなし。

# cp /etc/selinux/targeted/contexts/users/staff_u \
     /etc/selinux/targeted/contexts/users/sepgsql_u

では、sepgsqlユーザでログインしてみよう。

[root@masu ~]# ssh sepgsql@localhost
sepgsql@localhost's password:
Last login: Sat Apr 24 11:32:56 2010 from localhost
[sepgsql@masu ~]$ id -Z
sepgsql_u:staff_r:staff_t:s0-s0:c0.c1023

OK、sepgsqlでログインすると、SELinuxユーザはsepgsql_uで、ロール/ドメインはstaff_rになっている。

続いて、sepostgresqlデーモンを起動/停止するためのsudoを設定する。

echo "sepgsql ALL=(ALL) ROLE=dbadm_r TYPE=dbadm_t NOPASSWD:/sbin/service" >> /etc/sudoers

ROLE= とか TYPE= はSELinux用の拡張で、sudoする時にロールやドメインを切り替える。この場合、dbadm_r/dbadm_tに切り替える。

では、sepostgresqlを初期化/起動してみる。

[sepgsql@masu ~]$ sudo service sepostgresql initdb
Initializing database:                                 [  OK  ]
[sepgsql@masu ~]$ sudo service sepostgresql start
Starting sepostgresql service:                         [  OK  ]
[sepgsql@masu ~]$ ps -AZ | grep sepostgres
sepgsql_u:system_r:postgresql_t:s0-s0:c0.c1023 19695 ? 00:00:01 sepostgres
sepgsql_u:system_r:postgresql_t:s0-s0:c0.c1023 19697 ? 00:00:00 sepostgres
sepgsql_u:system_r:postgresql_t:s0-s0:c0.c1023 19698 ? 00:00:00 sepostgres
sepgsql_u:system_r:postgresql_t:s0-s0:c0.c1023 19699 ? 00:00:00 sepostgres
sepgsql_u:system_r:postgresql_t:s0-s0:c0.c1023 19700 ? 00:00:00 sepostgres
sepgsql_u:system_r:postgresql_t:s0-s0:c0.c1023 19701 ? 00:00:00 sepostgres

OK、無事に起動しているのがわかる。

定義済み boolean の設定しだいでは、dbadm_u ロールにはユニークな権限を持たせることができる。その辺の解説はまた後日。