SELinuxのポリシー・モジュールを自作する~FileContexts編
Muninには最初からTomcatプラグインが含まれているのですが、これよりもMunin.warの方がいろんな情報を取得できるので重宝しています。Munin.warについてはこちらを参考してください。
http://woontai.dip.jp/muninwar/
このMunin.warのセキュリティ・コンテキストは次のようになっています。
system_u:object_r:munin_unconfined_plugin_exec_t:s0
これは /etc/selinux/targeted/contexts/files/file_contexts に次のように定義されているためです。
/usr/share/munin/plugins/.* -- system_u:object_r:munin_unconfined_plugin_exec_t:s0
このファイルにはプラグイン個別に別のタイプが設定されていて、例えばTomcatプラグインは次のように定義されています。
/usr/share/munin/plugins/tomcat_.* -- system_u:object_r:munin_services_plugin_exec_t:s0
Munin.warのプラグイン名は cataline_.* なので、これが適用されません。 munin_unconfined_plugin_exec_t のままでも問題なく動くのですが、なんとなく気持ち悪いので、munin_services_plugin_exec_t に合わせてみようかと思います。セキュリティ・コンテキストを変更する方法として、chcon コマンドがあります。
chcon -t munin_services_plugin_exec_t /usr/share/munin/plugins/catalina_*
けれど、chcon コマンドは一時的なもので、restorecon コマンドを実行したり、autorelabel を実行した場合、上記の file_contexts ファイルに定義されたものに貼り直されてしまいます。なので、セキュリティ・ポリシー・モジュールを作成した方が良いでしょう。
以前のブログ記事でもセキュリティ・ポリシー・モジュールを作成する方法を記述しましたが、今回は別コンテキストへの実行許可ではなく、ファイル・コンテキストの設定のみしたいので、前回作成しなかったfcファイルを作成します。
まず、teファイルを作成します。モジュール名は munin-plugin-catalina にします。requireブロックは不要かと思いましたが、記述しないとコンパイルに失敗するので記述しました。typeとして、今回設定する型を記述します。
module munin-plugin-catalina 1.0;
require {
type munin_services_plugin_t;
}
次に、fcファイルを作成します。
/usr/share/munin/plugins/catalina_.* -- gen_context(system_u:object_r:munin_services_plugin_exec_t,s0)
コンパイルして、インストールします。
make -f /usr/share/selinux/devel/Makefile
semodule -i munin-plugin-catalina.pp
インストールしたポリシーを適用します。
restorecon /usr/share/catalina_*
ls -Z コマンドで適用前と適用後を見比べてみてください。munin_unconfied_plugin_exec_t になっているはずです。
追記
munin.fc の設定や書式については次を参照してください。
ちなみに、fc ファイルは次の書式でも有効です。
/usr/share/munin/plugins/catalina_.* -- system_u:object_r:munin_services_plugin_exec_t:s0
SELinuxのポリシー・モジュールを自作する
audit2allowコマンドを使えば自動生成されるけど、いくつかの問題があるときに何度も実行してマージするのが面倒臭くて、audit.logを見ながらポリシー・モジュールを手書きしてたら、きもいって言われたけど、きもくないのを主張するために書きます。
環境は次の通り。
muninの mysql_ はinnodbの状態とかを収集してくれるプラグインで、実態は mysqladmin extended-status で取得できる情報を収集するものです。これをSELinuxを有効にしてると、次のようなエラーメッセージがログ ( /var/log/munin-node/munin-node.log ) に表示されます(一部のみ)。
2013/05/01-23:40:11 [60227] Error output from mysql_qcache_mem:
2013/05/01-23:40:11 [60227] Couldn't instantiate IPC::ShareLite: Permission denied at /usr/share/perl5/Cache/SharedMemoryBackend.pm line 85.
2013/05/01-23:40:11 [60227] Service 'mysql_qcache_mem' exited with status 13/0.
これはSELinuxがアクセスを不許可にしてるようで、 /var/log/audit/audit.log ファイルにdeniedで出力されています(一部のみ)。
type=AVC msg=audit(1367418934.828:49833): avc: denied { unix_read unix_write } for pid=59897 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm setroubleshoot-serverパッケージがインストールされていれば、/var/log/messages ファイルに ..... run sealert -l xxxxxx みたいなメッセージが出力されてて、sealertコマンドを実行すると、
grep xxxx /var/log/audit/audit.log | audit2allow -M mypol
semodule -i mypol.pp
を実行してねってメッセージが表示されるので、実行すると、ポリシー・ソースファイルのmypol.teファイルとコンパイルされたmypol.ppファイルが作成されて、semodule -i mypol.pp を実行するとSELinuxに新しいポリシーが登録されます。
けれど、上記に貼りつけたログのように、たくさんあるときは一つづつ確認するのが面倒だし、場合によっては、このポリシーをクリアした後、別のポリシーを要求されることもあります。なので、最初からポリシー・ファイルを作成したほうが楽な場合があるのです。
以下、muninのmysql_プラグインが動くためのポリシーを作成します。
ポリシー名はmypolで作成します。
touch mypol.te
ファイルにポリシー名とバージョンを記述します。
module mypol 1.0;
今回はドメインで設定するので、audit.logに書かれたscontextとtcontextの転んで区切った三番目のもの (ドメイン属性) を記述します。上記のログだと munin_services_plugin_tだけなので、これを記述します。
require {
type munin_services_plugin_t;
}
さらにこのrequireのブロック内に、audit.logに書かれたtclassと、denied { xxxx } の括弧内の内容を次の書式で記述します。
class shm { unix_read unix_write };
その後、scontext, tcontextの先ほどの三番目のものとtclassとdenied { xxxx } の括弧内のものを次のように記述します。
allow munin_services_plugin_t munin_services_plugin_t:shm { unix_read unix_write };
今回はscontextとtcontextのものが同じなので、selfで置き換えられます。
allow munin_services_plugin_t self:shm { unix_read unix_write };
結果的に、こうなります。
module mypol 1.0;
require {
type munin_services_plugin_t;
class shm { unix_read unix_write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write };
これは、audit.ogが、アクセス・ドメインが munin_services_plugin_t (scontextに書かれたもの) のプロセスmysql_innodb_bpなど (commに書かれたもの) が munin_services_plugin_t (tcontextに書かれたもの)に対して shmクラス (tclassに書かれたもの) でunix_read, unix_write (deniedの後の括弧に書かれたもの) を実行しようとしたが許可されていない、と言っているのに対する設定です。requireで必要なリソースを列挙し、allowでscontextがtcontextに{xxxx}を実行することを許可する、と定義します。
ポリシー・ファイルを作成したので、これをコンパイルします。
make -f /usr/share/selinux/devel/Makefile
実行すると、mypol.fc, mypol.if, mypol.ppを作成しますが、fc, ifファイルは今のところ不要です。ppファイルがコンパイルされたポリシー・モジュールです。これをSELinuxに適用します。
semodule -i mypol.pp
ここで、私の環境では期待通りに別のSELinuxに却下されたメッセージが出力されました。/var/log/audit/audit.log に次のようなメッセージが出力されてます (全部同じなので、1つだけ)。
type=AVC msg=audit(1367422400.503:58827): avc: denied { associate } for pid=65203 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm
これを見る限り、scontextがtcontextにshmでassociateを実行する許可が必要なようです。そこで、require内のshmにassociateを追加して、allowにassociateを追加します。すなわち、こうなります。
module mypol 1.0;
require {
type munin_services_plugin_t;
class shm { unix_read unix_write associate };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate };
これをコンパイルして、SELinuxに適用します。同じ名前のものを最適用するときは、
semodule -r mypol
semodule -i mypol.pp
で削除・登録をするか、
semodule -i mypol.pp
semodule -R
で再登録して、リロードします。すると、また別のメッセージが出力されます。
type=AVC msg=audit(1367423040.036:60463): avc: denied { read write } for pid=1188 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm
今度は read, write が許可されていないと言っているので、先ほどと同じように、requireのclassとallowに追加します。
module mypol 1.0;
require {
type munin_services_plugin_t;
class shm { unix_read unix_write associate read write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate read write };
これをコンパイルして再登録すると、更に別のメッセージが出力されました。
type=AVC msg=audit(1367423459.872:62107): avc: denied { read write } for pid=2367 comm="mysql_innodb_io" path=2F535953563633363337303639202864656C6574656429 dev=tmpfs ino=229383 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:object_r:tmpfs_t:s0 tclass=file
今度は今までと違うものがtcontextとtclassに出力されました。tmpfs_t が登場したので、require内にtypeを追加します。また、fileのread, writeが却下されてるので、classを追加します。
type tmpfs_t;
class file { read write };
そして、munin_services_plugin_tからこれらに対するアクセスを許可します。
allow munin_services_plugin_t tmpfs_t:file { read write };
結果として、次のようになります。
module mypol 1.0;
require {
type munin_services_plugin_t;
type tmpfs_t;
class shm { unix_read unix_write associate read write };
class file { read write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate read write };
allow munin_services_plugin_t tmpfs_t:file { read write };
これをコンパイルして再登録すると、また別のメッセージが出力されました。
type=AVC msg=audit(1367424118.516:63758): avc: denied { getattr } for pid=3842 comm="mysql_innodb_bp" key=1667461225 scontext=unconfined_u:system_r:munin_services_plugin_t:s0 tcontext=system_u:system_r:munin_services_plugin_t:s0 tclass=shm
今回は munin_services_plugin_t 自身に getattr するのを許可するだけなので、class shm とallow ... self:shm にgetattr を追加するだけです。
module mypol 1.0;
require {
type munin_services_plugin_t;
type tmpfs_t;
class shm { unix_read unix_write associate read write getattr };
class file { read write };
}
allow munin_services_plugin_t self:shm { unix_read unix_write associate read write getattr };
allow munin_services_plugin_t tmpfs_t:file { read write };
これをコンパイルして再登録した所、ようやくメッセージがでなくなり、muninがmysql_ プラグインから値を収集できるようになりました。
このあと、それぞれのファイルのラベル付が正しいかとかをチェックして、不要な設定を極力なくしていく作業がありますが、それは私のSELinux力がもう少し付いてから。
ちなみに、これをするまでに学ばせてもらったのは、こちらの資料です。
http://www.slideshare.net/ishikawa84g/hbstudy-28-selinuxhandson
60-61ページ:/var/log/messages の見方
83-85, 96ページ:/var/log/audit/audit.log の見方
106-110ページ:ポリシーの作成方法
追記
munin_ のラベルを munin_services_plugin_t って書いたけど、最初からそうだったのか、自分でchconしたのか覚えてません。。。
MySQL5.6の初期インストール
5.6から初期パスワードが設定されているらしく、5.5以前でパスワード設定をしてたときは問題なかったのだけれど、まっさらな状態の時にするとこの問題に直面したので、その時参考にしたブログのメモ。
http://d.hatena.ne.jp/akishin999/20130207/1360241401
/root/.mysql_secret
にあるそうです。
なので、こうしちゃいます。
touch ~/.my.cnf
echo [mysql] >> ~/.my.cnf
echo user=root >> ~/.my.cnf
sed -e "s/^#.*: /password=/" /root/.mysql_secret >> ~/.my.cnf
chmod 600 ~/.my.cnf
あと、ポート設定に、こちらを参考にしました。
http://ysweb.blogspot.jp/2008/07/sed.html
http://d.hatena.ne.jp/rx7/20110310/p1
sed -i "/^:OUTPUT ACCEPT/a -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT" /etc/sysconfig/iptables
CentOSだと"-i"オプションができるけど、他でも使えるかどうかは怪しいらしい。
一度MySQLにログインしてパスワード変更しないと、リクエストを一切受け付けてくれないんだけど、最初のパスワード変更はスクリプト化できないのだろうか・・・
java-ja.dddに参加しました
GREEさん、ありがとう!と書けと言われました。
それは冗談として、会場、水、ビール、食料(オードブル、ピザ)を無償提供してくれたので、とても有難かったです。人多すぎて、私は何も食べられなかったのですが。
ドメイン駆動って、業務の言葉で語るものだと思っています。うちではT字形ERで業務に出てくる言葉の関係性を整理して、実装ERに落としこむというのをやっています。議論するときはすべて、この図に対して行います。
実装はすぐにコードを書くこともありますが、予めクラス図で関係を書き、アクティビティ図でやりたいことを書きます。これを元にコードを書いて、アクティビティとメソッドがイコールになっていない場合は、やりたいことが理解できていないことであるし、イコールならば読めるコードになっている証拠です。増田さんのsetterを書かないっていうのはよく理解できて、「この値を変更する」のではなく、オブジェクトの状態が変わることに対して名前をつけるべきなんですよね。
Job Arranger for Zabbixの変数について
ちょこちょこ触っているのですが、最初に少し悩んだので、変数についてまとめます。
- ジョブアイコンの中で設定できる変数はジョブ変数といい、そのジョブの中でしか利用できない
- 変数アイコンで設定したものはジョブネット変数といい、ジョブネットとそのジョブネットから呼ばれたジョブネット内で利用できる(環境変数扱い)
- ジョブアイコン内でジョブネット変数を参照するには
変数名:VARIABLE_NAME
値:$VARIBLE_NAME
というジョブ変数を追加する - ジョブアイコン内でジョブネット変数を書き換えられない
- ジョブネット変数を書き換えるには、計算アイコンを利用する
- 計算アイコンの計算式はexprコマンドで実行されるので、exprを書く必要はないが、ジョブアイコン内で整数計算を実行したい場合はexprコマンドを指定する必要がある
- Job Arranger側で用意したジョブコントローラ変数は普通の環境変数として利用できる
サンプル1: 自分で定義したジョブ変数とジョブコントローラ変数
ENV-1でVAL1を定義して、JOB-1, CAL-1で計算していますが、JOB-1は参照しているだけなので、値は変わりません。このジョブネット終了時のVAL1の値は2です。
サンプル2: Job Arrangerで定義しているジョブコントローラ変数
なので、ファイル存在有無によって分岐させたいときは自分で定義したジョブコントローラ変数ではなく、Job Arrangerが定義したものを使います。ここでは終了コードをセットしているJOB_EXIT_CDを利用しています。
自分で定義したジョブコントローラ変数はループ回数や、サブ・ジョブネットに引き渡すために利用することになると思います。
2.0系のZabbixに対してJob Arranger for Zabbixからジョブ結果を送信する構成
Job Arranger for Zabbixがオープンソースで公開されました。
http://www.fitechforce.co.jp/zabbix/job-controller/
これはジョブスケジューラで、ユーザや実行対象ホストの管理にZabbixを利用するというものです。実行結果はZabbixのZabbix Senderという機能を利用して、Zabbixに報告します。これを書いてる時点でバージョンは1.2で、基本的なことはだいたいできます。けれど、対象とするZabbixは1.8系であり、すでに2.0系で運用しているなら、両方を参照するのは面倒です。ジョブスケジューラの結果を2.0系に送信する構成についてまとめます。 それぞれのインストール方法については省略します。ソースコードおよびrpmパッケージは下記URL先で入手できます。
https://oss-support.fitechforce.co.jp/redmine/projects/job-arranger-for-zabbix/repository
環境
- OS: CentOS 6.2
- Job Manager for Zabbix: 1.0
- DB: MySQL 5.5.29
- メインZabbix: 2.0.5
- ローカルマシン: Windows7 SP1 64bit
構成
Zabbixサーバ
- Zabbix Server 2.0.xをインストール
Job Arrangerサーバ
- Zabbix Server 1.8.xをインストール
- 実行サーバをホストとして登録しておきます(Job Arranger Agentがインストールされたホスト名を管理するのに利用します)
- zabbix_senderで書き換えるアイテムを予め登録しておきます(アイテムのタイプはZabbixトラッパーです)
- Job Arranger Serverをインストール
実行サーバ
- Zabbix Agentをインストール
- zabbix_serverは2.0.xでは別パッケージですが、1.8.xではZabbix Agentに同梱されているのでインストールします
- Zabbix Agent自体は利用しないので、起動の必要はありません
- Job Arranger Agentをインストール
- ServerにJob Arrangerサーバを指定します
- Job Arranger Managerからデフォルトで10055ポートで送信されるので、Firewallを設定します
ローカルマシン
- Job Arranger Managerをインストール
- ODBCの設定をしますが、MySQL5.5.xを利用している場合、ODBC 5.2.xが対応していないため、5.1.xのものを利用します
http://dev.mysql.com/downloads/connector/odbc/5.1.html#downloads
また、Job Arranger Managerは32bit用であるため、コントロールパネルではなく次のコマンドを実行して設定します
%WINDOWS_HOME%\SysWOW64\odbcad32.exe
- ODBCの設定をしますが、MySQL5.5.xを利用している場合、ODBC 5.2.xが対応していないため、5.1.xのものを利用します
- Job Arranger Managerでジョブを作成
- ログインはJob Arrangerサーバで動作するZabbixで管理しているユーザ/パスワードです
- ジョブネットを作成する際、拡張ジョブのzabbix_senderを利用せず、ジョブを利用して、実行欄に次のコマンドを記述します
zabbix_sender -z <ZabbixサーバのIP/ホスト名> -p 10051 -s <Zabbixサーバで管理するホスト名> -k <アイテム・キー> -o <送信する値>
もっとうまい方法があると思いますが、まだまだ勉強中です。
サーバの管理方法によっては、zabbix_senderにホスト名などを記述するよりも、設定ファイルを作成したほうがいいかもしれません。zabbix_agent.confにServer, ServerActive, Hostnameを設定して、ジョブネットで実行するコマンドを次のように帰るとよいでしょう。
zabbix_sender -c <zabbix_agent.confのパス> -k <アイテム・キー> -o <送信する値>
G*ワークショップZ Mar 2013に参加しました。
http://jggug.doorkeeper.jp/events/3007
今回はGradleハンズオンでした。うちのプロジェクトでは出来るだけ自動化!を目指してて、Jenkins+Gradleでテストやデプロイから各自の開発環境構築(クラスパスの設定)までをやっているのですが、私は使う方メインで、他の人が作ってくれたやつに軽く手をいれる程度なので、Gradleスキルを忘れてしまわないようにするために参加しました。
@bikisukeさんのLTの内容は通ってきたと思う。WTPは使ってないけど、IDEはeclipseを利用しています。GroovyConsoleとテキストエディタを用いて書いて、Jenkinsで動かして確認しています。eclipseプロジェクトの参照ライブラリを刷新するためにGradleでクラスパス・ファイルを作り直す処理をしていますが、これはbatファイル経由で実行しています。コマンドラインですね。@literaliceさんのLTで出たWrapper、Jenkinsでは便利だけど、自分の環境のクラスパス・ファイルを作り直すときに時々失敗したりするので、ちょっと苦手な印象もあります。いや、便利なんですけどね(同じバージョンのwrapperを差し替えた時にうまく動かない時があったり。そんな時はwrapperやcacheを削除。あと、バージョン上がった時にgradle.propertiesの指定バージョンを書き換えるのを忘れて、数分悩んだこともあったり)。
メインのハンズオンはあまり手を動かしてないような・・・聞きながら色々試したりはしましたが。資料はこちら。PDFはあとは修正されるらしい。これだけの資料を用意してもらえると、今日来れなかった他のメンバーと共有しやすいので、ありがたいです。
https://github.com/nobusue/GradleHandson
勉強会の最初にJGGUGの説明がありました。"Z"はDBなのか週末ヒロインなのか、どちらなんだろうと思ってたら、"2"のことらしい。JGGUGのサイト、全然更新されないと思っていたら、Facebookでグループを作っていたそうです。参加申請すれば、メンバーの誰かが承認してくれるって言われたので登録したら、数秒後、すぐに承認されました。BOT疑惑・・・次回は4/19で、Grails on CloudFoundryハンズオン。
http://www.facebook.com/groups/jggug/