悪いことをすると、即通報されるやさしくない世界（Linux）を構築してみた＜前編＞

前編では、vimエディタで「私が思う悪いこと」をすると、通報されるやさしくない世界の創り方を紹介します。
(ここでは、通報＝ログ出力としますが、適宜アクションは変更できます。)

**2018/09/29 更新：
編集が加わった時のみログ記録されるようにするため、以下の修正をしました。
・vimでファイルオープンした際にファイルのハッシュ値を環境変数へ保存
・ファイルオープン時のハッシュ値が編集後のハッシュ値と異なる場合のみ通報**

# 材料
- vimエディタの設定ファイル(/etc/vimrc)
- シェルスクリプト

# 私が思う悪いこと
- history ファイルを編集する
    - コマンド履歴を編集するのは「過ちを闇に葬る」悪いこと
- ログファイルを編集する
    - ログファイルを編集するのは「事実を改ざんする」悪いこと

# やさしくない世界の創り方
### 1. vimエディタにトラップを仕込む
vimエディタの設定ファイル（/etc/vimrc）の末尾に下の設定を追加します。
これで、**ファイル編集時にシェルスクリプト（watchvim.sh）が実行されるようになります**。
引数として、編集しているファイル名（\<afile\>）とファイルのハッシュ値（\$PREHASH）、ユーザー名（\$USER）を渡します。


```:/etc/vimrc
augroup watchvim
autocmd!
autocmd BufRead * silent :let $PREHASH = system('md5sum ' . expand('%:p') . ' | awk "{print \$1}"')
autocmd BufWritePost * silent !/etc/vimrc.d/watchvim.sh <afile> $PREHASH $USER
augroup END
```

また、ユーザーがviエディタを使用する場合に備え、viのエイリアスとしてシンタックス・ハイライトをオフにしたvimを登録します。
（**vimエディタを使っていることを気付かせないためだけでなく、シンタックス・ハイライトを使用したくないユーザーへ配慮するため**です）

```bash:/etc/profile.d/force_vim.sh
# Force users to use vim instead of vi

alias vi="vim -c ':syntax off'"
```

### 2. 特定のファイルが編集された時にログ出力するシェルスクリプトを仕込む
まずは、配置場所を作ります

```
mkdir /etc/vimrc.d 
```

下のシェルスクリプト（watchvim.sh）と設定ファイル（watchvim.conf）を /etc/vimrc.d/ に配置します。

``` bash:/etc/vimrc.d/watchvim.sh
#!/bin/bash

PROGNAME=$(basename $0)
PROGDIR=$(dirname $0)
CONFPATH="$PROGDIR/${PROGNAME%.*}.conf"
VERSION="1.1"

usage() {
    echo "
Usage:
    $PROGNAME [FILE] [FILEHASH] [USER]

Description:
    $PROGNAMEは、vimで編集されたファイルの名前をログ出力するためのシェルスクリプトです。
    /etc/vimrcから呼び出されることを想定しています。
    同一ディレクトリに配置される${PROGNAME%.*}.confに記載されたファイル一覧を監視対象とします。

    /etc/vimrcにおける使用例： 
    autocmd BufRead * silent :let $PREHASH = system('md5sum ' . expand('%:p') . ' | awk \"{print \$1}\"')
    autocmd BufWritePost,FileWritePost * silent !/etc/vimrc.d/$PROGNAME <afile> \$PREHASH \$USER

Options:
    --help, -h      ヘルプを表示
    --version, -v   バージョン情報を表示"
    exit 1
}

for OPT in "$@"
do
    case "$OPT" in
        '-h'|'--help' )
            usage
            exit 1
            ;;
        '-v'|'--version' )
            echo $VERSION
            exit 1
            ;;
        -* )
            echo "$PROGNAME: illegal option -- '$(echo $1 | sed 's/^-*//')'" 1>&2
            exit 1
            ;;
        *)
            if [[ ! -z "$1" ]] && [[ ! "$1" =~ ^-+ ]]; then
                param+=( "$1" )
                shift 1
            fi
        ;;
    esac
done

if [ ${#param[@]} -ne 3 ]; then
    echo "$PROGNAME: 3 arguments is required." 1>&2
    echo "Try '$PROGNAME --help' for more information." 1>&2
    exit 1
fi

if [ ! -e $CONFPATH ]; then
    echo -e "# Created by $PROGNAME
# This is the $PROGNAME configuration file.
# $PROGNAME watches only the files you specify below and logger who edits them
# when they are edited with Vim." > $CONFPATH 2>&1
fi

set -f
for FILEPATH in `grep -v "^#" $CONFPATH`;
do
    EDITFILE=`readlink -f ${param[0]}`
    if [[ $EDITFILE == $FILEPATH ]]; then
        EXHASH=`md5sum $EDITFILE | awk '{ print $1 }'`
        if [ ${param[1]} != $EXHASH ]; then
            logger -p local0.warning -t "$PROGNAME" "$EDITFILE has been edited by ${param[2]}."
        fi
        break
    fi
done
set +f
```


```:/etc/vimrc.d/watchvim.conf
# Created by watchvim.sh
# This is the watchvim.sh configuration file.
# watchvim.sh watches only the files you specify with absolute path below and logger who edits them.
# when they are edited with Vim.
/var/log/*
*bash_history
```

どのユーザーからも実行できるようにパミッションを変更します。

```
chmod 755 /etc/vimrc.d/watchvim.sh

chmod 644 /etc/vimrc.d/watchvim.conf
```

以上で、仕込みは完了です。

# 悪いことをしてみた
- history ファイルを編集してみた

```
[badman@notkind ~]$ vim /home/badman/.bash_history
```

（誤ってファイル消したちゃったから、rmコマンドの履歴削除っと・・・）

```:/var/log/messages
Sep 25 14:51:45 notkind watchvim.sh: /home/badman/.bash_history has been edited by badman.
```

ばっちりログに残ります。

- ログファイルを編集してみた

```
[badman@notkind ~]$ sudo vim /var/log/yum.log
```

（yumで勝手にパッケージ追加したから、ログを改ざんしておこう・・）

```:/var/log/messages
Sep 25 14:54:33 notkind watchvim.sh: /var/log/yum.log has been edited by badman.
```

これも、ばっちりログに残ります。
やさしくない世界の実現が確実に近づいてきましたね。

# あとがき
設定ファイル（watchvim.conf）にファイル名を書き込めば、自由に監視対象を設定できます。ワイルドカードも使用できます。
興味があれば、使用してみてください。

~~※仕様で、何も編集していない場合でもvimエディタで「:w」を実行すると、編集したと判断してしまうので注意してください・・・。~~
**※2018/09/29 更新で、編集が加わった時のみ通報されるように修正**

後編では、シェルスクリプトを利用した変更検知の仕組みを紹介します。
vimエディタだろうがsedコマンドだろうが、編集したらとにかく検知する仕組みなのでやさしくない世界に磨きがかかることと思います。

**最後まで、ご愛読いただきましてありがとうございました。
やさしくない世界の創り方を募集しておりますので、おすすめの作り方があれば是非教えてください！**