bash_historyを時刻を出してログに出したいということで、
セキュリティというか監査的に需要がありまして対応いたしました。
なんでjenkinsかというと可視化と自動化的な需要があったためです。
(脆弱性の対応で何回もビルドすることになりましたがjenkinsジョブになってるので埋もれた情報もなくて便利でした)
jenkinsさんのジョブは以下のような感じです。
単にパラメータつきのシェルの実行です。
# !/bin/bash
topdir="${HOME}/rpmbuild"
rpmdir="${topdir}/RPMS/x86_64"
if [ -f ${HOME}/.rpmmacros ];then
echo "%_topdir ${topdir}" > "${HOME}/.rpmmacros"
echo "%_signature gpg" >> "${HOME}/.rpmmacros"
echo "%_gpg_name D279****" >> "${HOME}/.rpmmacros"
fi
if [ -d ${HOME}/rpmbuild ];then
mv ${HOME}/rpmbuild{,.`date +%Y%m%d.%H%M`}
mkdir -p ${HOME}/rpmbuild/SRPM
fi
case "${TARGET}" in
*.src.rpm) rpm -Uvh "${TARGET}"
cp -p ${topdir}/SPECS/bash.spec{,.org}
sed -i 's/make "CFLAGS=$CFLAGS -fwrapv" "CPPFLAGS=-D_GNU_SOURCE -DRECYCLES_PIDS `getconf LFS_CFLAGS`"/make "CFLAGS=$CFLAGS -fwrapv" "CPPFLAGS=-D_GNU_SOURCE -DRECYCLES_PIDS `getconf LFS_CFLAGS` -DSYSLOG_HISTORY"/g' ${topdir}/SPECS/bash.spec
sed -i 's/Release: 15%{?dist}.2/Release: 15%{?dist}_5.2_hoge_4/g' ${topdir}/SPECS/bash.spec
sed -i '78s/^$/\n/g' ${topdir}/SPECS/bash.spec
sed -i '79s/^$/Patch134: bash-syslog_facirity.patch\n/g' ${topdir}/SPECS/bash.spec
sed -i '149s/^$/%patch134 -p1\n/g' ${topdir}/SPECS/bash.spec
cd ${HOME}/rpmbuild/SOURCES/
tar xzf bash-4.1.tar.gz
cp -rp bash-4.1{,.org}
sed -i 's/# define SYSLOG_FACILITY LOG_USER/# define SYSLOG_FACILITY LOG_LOCAL6/g' ${HOME}/rpmbuild/SOURCES/bash-4.1/config-top.h
sed -i 's!(SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line)!(SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, line)!g' ${HOME}/rpmbuild/SOURCES/bash-4.1/bashhist.c
sed -i 's!(SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc)!(SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, trunc)!g' ${HOME}/rpmbuild/SOURCES/bash-4.1/bashhist.c
diff -crN bash-4.1.org bash-4.1 > ${HOME}/rpmbuild/SOURCES/bash-syslog_facirity.patch
rpmbuild -ba ${topdir}/SPECS/bash.spec
;;
*) echo 'environment variable TARGET must be set.'; exit 1;;
esac
TARGETにしたパラメータは以下です。
http://vault.centos.org/6.5/updates/Source/SPackages/bash-4.1.2-15.el6_5.2.src.rpm
${HOME}
は/var/lib/jenkins
です。
ソースRPM落として入れて
ソースアーカイブ解凍して
sedしてパッチ作って
作ったパッチあてられるようにspecファイルsedして
ビルドする
という流れになっております。
diffでディレクトリまるごとパッチ作るオプションは-crNだったことを調べて知りました。
パッチは敢えて載せると以下のような感じです。
# cat bash-syslog_facirity.patch
diff -crN bash-4.1.org/bashhist.c bash-4.1/bashhist.c
*** bash-4.1.org/bashhist.c 2009-08-15 04:33:02.000000000 +0900
--- bash-4.1/bashhist.c 2014-09-29 10:19:48.611631770 +0900
***************
*** 705,716 ****
char trunc[SYSLOG_MAXLEN];
if (strlen(line) < SYSLOG_MAXLEN)
! syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line);
else
{
strncpy (trunc, line, SYSLOG_MAXLEN);
trunc[SYSLOG_MAXLEN - 1] = '\0';
! syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc);
}
}
#endif
--- 705,716 ----
char trunc[SYSLOG_MAXLEN];
if (strlen(line) < SYSLOG_MAXLEN)
! syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, current_user.uid, line);
else
{
strncpy (trunc, line, SYSLOG_MAXLEN);
trunc[SYSLOG_MAXLEN - 1] = '\0';
! syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d PPID=%d SID=%d User=%s UID=%d CMD=%s", getpid(), getppid(), getsid(getpid()), current_user,user_name, current_user.uid, trunc);
}
}
#endif
diff -crN bash-4.1.org/config-top.h bash-4.1/config-top.h
*** bash-4.1.org/config-top.h 2009-12-23 05:29:39.000000000 +0900
--- bash-4.1/config-top.h 2014-09-29 10:13:15.201961360 +0900
***************
*** 103,109 ****
bash_add_history() to be sent to syslog(). */
/* #define SYSLOG_HISTORY */
#if defined (SYSLOG_HISTORY)
! # define SYSLOG_FACILITY LOG_USER
# define SYSLOG_LEVEL LOG_INFO
#endif
--- 103,109 ----
bash_add_history() to be sent to syslog(). */
/* #define SYSLOG_HISTORY */
#if defined (SYSLOG_HISTORY)
! # define SYSLOG_FACILITY LOG_LOCAL6
# define SYSLOG_LEVEL LOG_INFO
#endif
ログフォーマットは以下URLを参考に親プロセスIDとSUしたPID等を載せるように変えました。(監査的な追いやすさの需要のためです)
the syslog recorded history history - C - C Program Develop
ファシリティがlocal6にかえてあります。rsyslog.conf
で以下のようにする想定です。
*.info;mail.none;authpriv.none;cron.none;local6.none /var/log/messages
# bash_history log
local6.* /var/log/bash_history
別途yumのupdate対象からbashをはずす必要はあると思います。(yum-updatesd
有効な場合はyum.conf
でexclude=bash*
するとか)
Chef(yum)で入れるときに、options "--disablerepo=base,updates"
を入れる必要がありました。他リポジトリのパッケージでupdateされない対策です。他にはChefでレシピ流す時のrun_listの順序内でカスタムリポジトリを入れるレシピを先頭にしないとリポジトリが無いと判断されてinstallやupgradeされないという現象が起こりえます。
RPMSign
というプラグインつかってgpg署名してカスタムyumリポジトリにscpしたりしてます。
gpg鍵とパスフレーズをシステム設定で設定しといて、
ジョブでは鍵選んでコマンドラインオプションのとこに署名するパッケージのフルパス書く(ワイルドカード可)感じです。
あとはscpするのとリポジトリのメタデータの差分作るジョブは別とか、
改ざん対策等でtd-agentでログサーバに内部ELB介して転送してcronで1日一回s3に送ってたりしますが、超長くなるので省略します。
jenkinsさんは自動的にいろいろしてくれるし暗黙の手順がなくなるので便利ですね。いろいろ勉強になりました。
jenkinsのことを社内の開発の方に教えていただきました。ありがとうございました。
では読んでいただいてありがとうございました。