AWS System Managerでセキュリティパッチを自動的にあてるときの注意点

セキュリティや脆弱性はいつでもエンジニアを悩ませる問題の一つです。

**Amazon System Manger**の機能を組み合わせると自動的にセキュリティパッチをインストールさせることができます。今回、仕事で使うことがあったので概要やハマりどころをまとめてみました。

## System ManagerのPatch ManagerとMaintenanceWindowを組み合わせてできること
- 自動的にあてたいパッチのレベルを指定できる
- 適用対象のインスタンスをグループ化できる。
- グループ内で、１インスタンスずつインストールさせたり、半分づつインストールさせることができる(blue green的な)
- メンテナンス時間を指定できる
- S3やCloudWatchLogsにログを出力できるし、SNSで結果を通知することもできる

## 注意点・ハマりどころ

### 挙動について
- パッチのあたったインスタンスは強制的に再起動がかかります
- IAMのRoleの内容を変更したらssm-agentをリスタートしないとうまく動いてくれない。

### マネジメントコンソールについて
- Amazon EC2のマネジメントコンソールからから見れるSystems ManagerとAWS Systems Manager専用のマネジメントコンソールがあるので注意。マニュアルは基本的に後者を前提として書かれている印象。なので初めての人は前者で試したほうがいいかも。
- ただし、後者(AWS System Mangerの専用コンソール)のほうが見やすくて操作しやすい。でも、一個でも自分でPatch Baselineを作らないとPatch ManagerからBaselineを確認できなかったり、言葉の表記がマニュアルと異なっていたりで慣れないと難しい。逆にこっちの専用コンソールからじゃないとできないこともある。結局私は両方見比べながらやりました。
- マネジメントコンソールでは、パッチを充てた日付がバグってて、いつ、何を充てたのかがわからない（EC2も専用のコンソールも両方）。

### ドキュメントについて
- 日本語と英語でドキュメントの内容が随分違うページがあるので注意が必要。基本英語のドキュメントを見たほうが良い。
- SystemManager自体が複数の機能の組み合わせによって様々なワークロードを実現できるため、英語のドキュメントを見ていたとしても、結局いろんなページを飛び飛びに見ないといけないことがある。見落としによってうまく動かないこともあるので注意が必要。

## 用語集
新しい単語・概念が多く分かりにくかったので簡単にまとめてみました。

### Amazon System Manager(SSM)
EC2のインスタンスに対して自動的に任意のコマンドを実行させたり、定期実行させたり、コンプライアンスの状態を確認したりする機能を提供しているサービス。

### Managed Instance
`amazon-ssm-agent`がインストールされ、`AmazonEC2RoleforSSM`のポリシーを持っているインスタンス。System Managerで今現在、管理ができるインスタンスのこと。

### Maintenance Window
System Managerの１機能で、cronやcronに近い書式を使って、特定のRun Commandを任意の日時に実行できるようにするもの。

### Patch Baseline
いつ、どんな種類のパッチを適用するかをまとめたルールみたいなもの。パッチをあてる基準。OSごとに作成できる。

### Patch Manager
Patch Baselineを作成・編集・削除する管理機能。

### RunCommand
直接EC2インスタンスにSSHログインしなくても、ssm-agentを使ってSysmtemMangerから任意のコマンドを実行できる機能。`Document`と呼ばれる、コマンドを実行する手順や条件などが書かれたものを実行する模様。パッチを適用する際には`AWS-RunPatchBaseline`というドキュメントを指定する。

### System Manager Agent(amazon-ssm-agent)
SystemManagerを使って管理をしたいEC2インスタンスにインストールされるエージェントソフトウェア。
場合によってはyumでもインストールできる。具体的なインストール方法は後述。
これが定期的(5分間隔?)に実行されることでSystemMangerにインスタンスの情報を送ったり、SystemManagerから命令されたコマンドを実行したりするみたい。


## おおまかな導入手順
1. Amazon Linuxのバージョンを確認(2015.09, 2015.03 or later)
2. IAMとかRoleの作成・設定(IAMはオペーレーターに、Roleは主に監視対象のインスタンスと、RunCommandに）
3. SSM Agentを対象端末にインストールする
4. PatchBaselineの作成、また事前に用意されているPatchBaselineの確認(自動的にあてたいパッチのレベルとか種類の設定・確認)
5. メンテナンスウィンドウの作成
6. それにひもづくターゲットの作成
7. メンテナンスウィンドウで実行するタスク(RunCommand)の作成

１から３まで動作に必要な条件となっています。詳しくは[こちら](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up.html#systems-manager-prereqs)。

## 各手順の説明

### IAM/Roleを作成する

ざっくり以下の４つが必要です。

対象 | Policy
:--|:--|
自分のIAM| AmazonSSMFullAccess
パッチ適用対象のインスタンス| AmazonEC2RoleforSSM
メンテナンスウィンドウを使ってパッチをあてるタスク(RunComannd)に割り当てるポリシー|AmazonSSMMaintenanceWindowRole
SNSで通知する場合(任意)|AmazonSNSFullAccess

まずはパッチのタスクを作成したりメンテナンスウィンドウを作成するために自分のIAMに**AmazonSSMFullAccess**を含む権限が必要ですのでご確認ください。

そして次にパッチをインストールさせるEC2のインスタンスには**AmazonEC2RoleforSSM**というポリシーが必要になります。

ちなみに新しくRoleを作るわけではなく、既存のRoleに上記のRoleを割り当てる場合、`ssm.amazonaws.com`をTrust Entitiesに追加しないとダメなようですので注意してください。大事なことなのですが、ドキュメントにはさらっと書いてあって読み飛ばしてしまい、しばらくエージェントがちゃんと動いてくれませんでした。

>This procedure created a new role from a pre-existing IAM policy or managed policy. If you choose to create a role from a custom policy, you must add ssm.amazonaws.com as a trusted entity to your role (after you create it). 

https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-access.html

さらに、ポリシーとかロールを変えたらssmエージェントも再起動しないと言うこと聞いてくれないので注意してください。

また、メンテナンスウィンドウを使う場合、タスク作成時に＊＊AmazonSSMMaintenanceWindowRole**を持つRoleを指定する必要がありますので、事前に作成しておいてください。
https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-maintenance-perm-console.html

またMaintenanceWindowを使ってタスクの実行ステータスをSNSで通知する場合は、別途**AmazonSNSFullAccess** を持ったRoleが必要になりますの作成しておいてください。その場合、このRoleには下記のような信頼関係を持たせないとダメなようですのでお気をつけください。

```json
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Sid":"",
         "Effect":"Allow",
         "Principal":{
            "Service":[
               "ec2.amazonaws.com",
               "ssm.amazonaws.com",
               "sns.amazonaws.com"
            ]
         },
         "Action":"sts:AssumeRole"
      }
   ]
}
```

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-maintenance-perm-console.html

### エージェントをインストールする
[マニュアル](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-manual-agent-install.html#agent-install-al)では

```
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
```

みたいなことをやる必要があるようですが、yumで入れらるかなと思ってやってみたらできました。

```
sudo yum install amazon-ssm-agent
```

インストールしたらエージェントの起動も忘れずに。ちなみにchkconfigしなくても、勝手に起動してくれるようです。
エージェントの操作はこんな感じでできます。

```
#　再起動するとき
sudo restart amazon-ssm-agent

# 止めるとき
sudo stop amazon-ssm-agent

# 状態を確認したいとき
sudo status amazon-ssm-agent
```

エージェントが起動すると`/var/log/amazon/ssm/amazon-ssm-agent.log`というログファイルが作成されて、動作を確認することができます。

```
$ tail -f /var/log/amazon/ssm/amazon-ssm-agent.log
2018-03-08 11:13:32 INFO [instanceID=i-xxxxxxxx] [HealthCheck] HealthCheck reporting agent health.
2018-03-08 11:14:19 INFO [instanceID=i-xxxxxxxx] [LongRunningPluginsManager] There are no long running plugins currently getting executed - skipping their healthcheck
2018-03-08 11:18:32 INFO [instanceID=i-xxxxxxxx] [HealthCheck] HealthCheck reporting agent health.
2018-03-08 11:19:44 INFO [instanceID=i-xxxxxxxx] [MessagingDeliveryService] [Association] Schedule manager refreshed with 0 associations, 0 new assocations associated
```

### Patch Baselineの作成、または確認
どんな種類のパッチを適用するかのルールですが、最初からAmazonが各OS毎のデフォルトのBaselineを用意してくれています(Amazon Linux, Redhat Enterprise Linux, Ubuntu, Suse, Windows)。

Amazon Linux向けのものとしては下記のものが用意されています。

<img width="893" alt="approval_rules (1).png" src="https://qiita-image-store.s3.amazonaws.com/0/237077/6349e92f-c9c5-edbe-dadf-f9c5f91d57ba.png">

`Product`ではAmazonLinuxのバージョンが指定できますが、ここでは全てのバージョンが指定されています`Classification`はパッチの種類でSecurityやBugfixのほかにEnhancementやRecommendedなどがあるようです。`Severity`は重要度でCritical, Important, Medium, Lowがあります。さらに`Auto Approval Delay`ではそのパッチが承認されて配布されてから何日たってからインストールするかを設定することができるようです。

この機能がある理由は、対象となるソフトウェアによってすぐにあてたほうが良いパッチと、検証してからあてたほうが良いパッチがあるからだと思われます。例えばゼロデイ攻撃の観点などから`Critical`のような緊急度の高いパッチは早めにあてる必要がありますし、そうでないものに関してはパッチをあてる前に動作検証が必要な場合もあります。Patch Managerを使えば、柔軟なパッチ充て戦略を取ることができます。

もしデフォルトで提供されているPath Baselineで問題なければ新しくBaselineを作成する必要はありません。

### Patch Groupの作成と割り当て

どのPatch Baselineを使うかが決まったら今度はその適用範囲を決める必要があります。Patch Mangerでは"Patch Group"というタグをインスタンスに貼って実現しています。

Patch Groupを割り当てたら、適用すべきBaselineにも「このPatch Groupに対して適用します」ということを教えてあげる必要があります。分かりにくいのでキャプチャーで説明します。

これはEC2のPatch Baselineのメニューをクリックしたときの画面です。最初から用意されているBaselineが確認できると思います。Amazon LinuxのBaselineにチェックをつけて`Actions`ボタンを押下し、さらに`Modify Patch Groups`をクリックしてください。
<img width="1227" alt="modify_patch_group (1).png" src="https://qiita-image-store.s3.amazonaws.com/0/237077/d48f6a7c-0eda-0d09-16f7-a2e1cce931bf.png">

するとこんな画面が出るので、`PatchGroups`のところに、適用させたいグループ名を入力してください。
![pg.png](https://qiita-image-store.s3.amazonaws.com/0/237077/eb93a15c-644a-eb28-4156-238af4313409.png)

### Maintenance Windowの作成

メンテナンスウィンドウは、メンテナンスウィンドウそのもののと、実行するタスク、実行対象となるターゲットの３つの要素で構成されています。

名前 | 機能
:---|:---
メンテナンスウィンドウ| 実行するタイミングの設定。主にcron。
タスク| 実体はRunCommand。実行内容の指定と、通知やログの出力先の設定。
ターゲット| 実行するインスタンスの指定。

パッチグループを作っているにもかかわらず、ここでも対象を指定しないといけないので注意が必要です。マニュアルでは「間違ったパッチがあたらないように」って書いてあった気がします。

タスクの作成で注意すべきところは実行するDocumentとして"AWS-RunPatchBaseline"を指定することと、適切な実行Roleを指定することです。その他ここでは実行するインスタンスを半分ずつ実行するなどの指定ができたり、実行ログの出力先を指定したり、SNSの通知設定ができることです。

SNSの通知設定についてはちょっと分かりにくかったので別途ご紹介できればと思います。

### テストと実行、通知に関して
Maintenance Windowは時間にならないと実行されません。でも今すぐちゃんと動いているかを確認したい場合があります。その場合はMaintenance Windowではなく`Run Command`で実行してみてください。

やり方はMaintenance Windowのタスクの作成方法と全く一緒です。ただし、パッチインストール後は強制的に再起動がかかるので本番で運用しているインスタンスなどでは注意が必要です。`Command Parameter`という設定項目で`operation`を`install`ではなく`scan`にしておけば、どんなパッチがあるかを調べるだけなので動作確認としては使えると思います。

## 全体像
![スライド1.png](https://qiita-image-store.s3.amazonaws.com/0/237077/ec300be0-884f-e588-ce56-8790cfd64be9.png)
Maintenance WindowがTaskとTargetで構成されていることや、割り当てるRoleの違いなどが
分かりにくかったので図にしてみました。

参考になれば幸いです。