構成管理対象なサーバーが、ツール以外で変更されたのを確認する(Puppet corrective_change)

サーバーの設定変更を構成管理ツールで行うとき、ツール以外で変更されると（誰かがエディターで直接変更など）、結構大変だったりします。**構成管理ツールで、サーバー設定がデグるのが怖いので、構成管理ツール以外で変更されていないことをチェックするのが意外と重要です**。

Puppet4.6.0から、前回Puppetで変更してから今回Puppetを実行した間に、Puppet以外で変更されているかどうか確認できるようになったので、試してみました。

# 確認できる場所

実行時ログではなく、reportsファイルに出力されます。デフォルトでは、/opt/puppetlabs/puppet/cache/reports/サーバー名/の下にレポートが出力されています。**Puppet実行ごとにレポートファイルができるので、直近の結果は一番新しいファイルをチェックする必要があります。**なお、レポートをマスターサーバーに送る設定にしている場合、マスターサーバーにもレポートファイルがあります。

```
[root@6bce16e83e4b /]# ls -lR /opt/puppetlabs/puppet/cache/reports/
/opt/puppetlabs/puppet/cache/reports/:
total 4
drwxr-x--- 2 root root 4096 Aug 26 04:51 6bce16e83e4b

/opt/puppetlabs/puppet/cache/reports/6bce16e83e4b:
total 192
-rw-r----- 1 root root 7575 Aug 26 02:58 201608260258.yaml
-rw-r----- 1 root root 6145 Aug 26 02:59 201608260259.yaml
-rw-r----- 1 root root 7329 Aug 26 03:00 201608260300.yaml
...
```

誰かが変更している場合、レポートファイルのcorrective_changeがtrueになります。
Puppet以外で変更されていない場合、corrective_changeがfalseです。

```
corrective_change: true
```

# 誰かが変更している場合のレポート結果例

例として、Puppetで設定管理している/tmp/hello_puppet.txtを、直接エディターで変更した後に、Puppetの実行したときのレポート結果です。Puppet実行ごとにレポートファイルができるため、/opt/puppetlabs/puppet/cache/reports/にある一番新しいファイルをcatしています。
（レポートが長いので抜粋です。#右側は説明用に追記した文です。）

```
[root@6bce16e83e4b /]# find /opt/puppetlabs/puppet/cache/reports/ -type f | xargs ls -l --time-style=long-iso | sort -k 6,7 | tail -1 | cut -d ' ' -f 8-8 | xargs cat
--- !ruby/object:Puppet::Transaction::Report
metrics:
  resources: !ruby/object:Puppet::Util::Metric
    name: resources
    label: Resources
    values:
    - - total
      - Total
      - 8
    - - skipped
      - Skipped
      - 0
    - - failed
      - Failed
      - 0
    - - failed_to_restart
      - Failed to restart
      - 0
    - - restarted
      - Restarted
      - 0
    - - changed
      - Changed
      - 0
    - - out_of_sync
      - Out of sync
      - 1
    - - scheduled
      - Scheduled
      - 0
    - - corrective_change
      - Corrective change
      - 1 # Puppet以外で変更されているリソースの数
# 中略
resource_statuses:
  File[/tmp/hello_puppet.txt]: !ruby/object:Puppet::Resource::Status
    title: "/tmp/hello_puppet.txt"
    file: "/file.pp"
    line: 1
    resource: File[/tmp/hello_puppet.txt]
    resource_type: File
    containment_path:
    - Stage[main]
    - Main
    - File[/tmp/hello_puppet.txt]
    evaluation_time: 0.016081488
    tags:
    - file
    - class
    time: '2016-08-26T04:47:03.011544781+00:00'
    failed: false
    changed: false
    out_of_sync: true
    skipped: false
    change_count: 0
    out_of_sync_count: 1
    events:
    - !ruby/object:Puppet::Transaction::Event
      audited: false
      property: content
      previous_value: "{md5}a630ec71439b539ba2754031dd61f4bd"
      desired_value: "{md5}4cdb039380c678cac7863cebc1606bea"
      historical_value:
      message: current_value {md5}a630ec71439b539ba2754031dd61f4bd, should be {md5}4cdb039380c678cac7863cebc1606bea
        (noop)
      name: :content_changed
      status: noop
      time: 2016-08-26 04:47:03.018419317 +00:00
      redacted:
      corrective_change: true
    corrective_change: true # /tmp/hello_puppet.txtがPuppet以外で変更されている
# 中略
# レポートの一番最後
corrective_change: true # Puppet以外で変更されているリソースがある
```

変更されたリソースを確認する場合、grepした方がよいかもです。(レポートの表示順は、Puppetバージョンで変わるかもしれません。)

```
[root@6bce16e83e4b /]# find /opt/puppetlabs/puppet/cache/reports/ -type f | xargs ls -l --time-style=long-iso | sort -k 6,7 | tail -1 | cut -d ' ' -f 8-8 | xargs grep -e 'corrective_change: true' -e 'resource:'
    resource: File[/tmp/hello_puppet.txt]
      corrective_change: true # この行のすぐ上のリソースが手で変更されたリソース
    corrective_change: true
    resource: Schedule[puppet]
    resource: Schedule[hourly]
    resource: Schedule[daily]
    resource: Schedule[weekly]
    resource: Schedule[monthly]
    resource: Schedule[never]
    resource: Filebucket[puppet]
corrective_change: true
```

こういう場合、前回Puppet実行時から今回実行した間に、**Puppet以外で変更されているので差分を入念にチェックする必要があります**。

# Puppetでしか変更していない場合のレポート結果例

参考までに、Puppetのマニフェストを更新した場合に、差分が発生する場合のレポート結果です。corrective_changeがfalseなので、Puppet以外で変更されていないことがわかります。

```
[root@6bce16e83e4b /]# find /opt/puppetlabs/puppet/cache/reports/ -type f | xargs ls -l --time-style=long-iso | sort -k 6,7 | tail -1 | cut -d ' ' -f 8-8 | xargs cat
--- !ruby/object:Puppet::Transaction::Report
metrics:
  resources: !ruby/object:Puppet::Util::Metric
    name: resources
    label: Resources
    values:
    - - total
      - Total
      - 8
    - - skipped
      - Skipped
      - 0
    - - failed
      - Failed
      - 0
    - - failed_to_restart
      - Failed to restart
      - 0
    - - restarted
      - Restarted
      - 0
    - - changed
      - Changed
      - 1
    - - out_of_sync
      - Out of sync
      - 1
    - - scheduled
      - Scheduled
      - 0
    - - corrective_change
      - Corrective change
      - 0
# 中略
resource_statuses:
  File[/tmp/hello_puppet.txt]: !ruby/object:Puppet::Resource::Status
    title: "/tmp/hello_puppet.txt"
    file: "/file.pp"
    line: 1
    resource: File[/tmp/hello_puppet.txt]
    resource_type: File
    containment_path:
    - Stage[main]
    - Main
    - File[/tmp/hello_puppet.txt]
    evaluation_time: 0.048850239
    tags:
    - file
    - class
    time: '2016-08-26T04:51:17.097576288+00:00'
    failed: false
    changed: true
    out_of_sync: true
    skipped: false
    change_count: 1
    out_of_sync_count: 1
    events:
    - !ruby/object:Puppet::Transaction::Event
      audited: false
      property: content
      previous_value: "{md5}4cdb039380c678cac7863cebc1606bea"
      desired_value: "{md5}8e03c9189653240eb4b5f9ba187e12c9"
      historical_value:
      message: content changed '{md5}4cdb039380c678cac7863cebc1606bea' to '{md5}8e03c9189653240eb4b5f9ba187e12c9'
      name: :content_changed
      status: success
      time: 2016-08-26 04:51:17.106767383 +00:00
      redacted:
      corrective_change: false
    corrective_change: false
# 中略
corrective_change: false
```

```
[root@6bce16e83e4b /]# find /opt/puppetlabs/puppet/cache/reports/ -type f | xargs ls -l --time-style=long-iso | sort -k 6,7 | tail -1 | cut -d ' ' -f 8-8 | xargs grep -e 'corrective_change: true' -e 'resource:'
    resource: File[/tmp/hello_puppet.txt]
    resource: Schedule[puppet]
    resource: Schedule[hourly]
    resource: Schedule[daily]
    resource: Schedule[weekly]
    resource: Schedule[monthly]
    resource: Schedule[never]
    resource: Filebucket[puppet]
```

# 試した感想

オープンソース版だと、レポートを見るのにちょっとコツがいりますが、今までの差分をひたすらチェックするよりは楽になったかと思います。Puppet Enterpriseの管理コンソールとかであればもう少しみやすいかもしれないですが、オープンソース版だとレポート確認がちょっと大変です。できれば、実行時ログの方にも、表示されるとうれしいのですが。。。

# 試した環境

- CentOS Linux release 7.2.1511 (Core)
- Puppet 4.6.1