Patch Manager 本番・検証環境で時間を分けて自動パッチ適用をしてみた

# はじめに

AWS Systems Manager に、Patch Manager と呼ばれる自動パッチ適用を提供してくれる機能があります。AWS 上はもちろん、オンプレミス側のマシンも含めたパッチ適用の自動化と管理ができます。なお、Patch Manager は、パッチファイルそのものを提供してくれるものでは**ありません**。rpm や Windows Update で利用するパッチファイルは、OS が参照している先から利用します。通常はインターネットで公開されている Amazon Linux の Repository などから取得する考え方になります。

今回の記事は、「本番環境」と「検証環境」の 2 環境が 1 AWS アカウントにあるときに、先に「検証環境」に適用して、一定時間後に「本番環境」に適用する手順を確認します。いきなり「本番環境」に適用してしまって問題を発生させたくないので、安全をみて「検証環境」から先にパッチ適用をします。



# 本番・検証環境用の BaseLine を用意

本番環境と検証環境で、対象とするパッチ基準をそれぞれ用意したいので、Baseline を 2 つ作成します。

初めて Patch Manager を開くと、以下のような画面になります。Start with an overview を押します。

![image-20230728190826156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/16f879db-1ffa-6805-9731-b3c5c867a7eb.png)



Create patch baseline を押します。

![image-20230728191142198.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/28df417f-a3be-39ee-4da3-075ea6c84b4a.png)



適当に名前を付与します。

```
Prod-AmazonLinux2-Baseline
```

![image-20230728191400769.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/2106183b-48ac-613e-0946-ead8f5e17129.png)



AWS から提供されている `AWS-AmazonLinux2DefaultPatchBaseline` と同じ指定をします。OS のセキュリティに関するアップデートを行う指定です。アプリケーションは対象外しています。

**<u>本番環境ではセキュリティパッチが出てから、7 日後のものを対象にしています。検証環境の場合は 2 日後に指定することで、環境ごとの時間差を作り出します。</u>**

![image-20230728191933668.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c25fba46-260a-9b75-d354-a128bafe8914.png)



デフォルトのまま Create を押します。

![image-20230728192242445.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/eaf37a3c-bb2a-6770-ae3c-d3b74a12db94.png)



作成されました。検証環境用の Baseline を作成するため、Create patch baseline を押します。

![image-20230728192336725.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/6df1bdf9-7d11-7904-5a84-9377b8443548.png)



適当に名前を指定します。

```
Staging-AmazonLinux2-Baseline
```

![image-20230728192515240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/ff2308d9-ed63-a7b4-e15e-a72355f22f2a.png)



検証環境用なので、**<u>セキュリティパッチが公開されてから 2 日後以降のものを対象にします。本番が 7 日後で、検証が 2 日後にすることで、5 日間の猶予が生れる設定です。</u>**

![image-20230728192748750.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/b6afbff1-4f9d-cb44-7169-5a416830fb52.png)



このまま Create を押します。

![image-20230728192242445.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c9bcc349-4219-7b27-fed8-a4e89c25941f.png)



本番・検証環境の両方の Baseline が出来ました。

![image-20230728193036780.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/83dcd12d-f3b1-8b6e-b217-8dc078c3a4ce.png)



# Fleet Manager に自動登録する

Patch Manager で EC2 インスタンスを管理するために、Fleet Manager 上に登録する必要があります。色々方法はありますが、便利に登録できる Default Host Management を使っていきます。

![image-20230728195209153.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/694a93cd-cfe8-14a9-f263-a1a5bd07b903.png)



IAM Role を Document にしたがって指定します。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/managed-instances-default-host-management.html

![image-20230728195533173.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/56ed2c1e-a649-b4aa-6d9a-e26d37f0c1cf.png)



# EC2 インスタンスを準備

EC2 インスタンスを準備します。今回は、EC2 インスタンスに付与する Tag を使って、本番環境と検証環境を区別してパッチを当てていきます。

少し古い Amazon Linix2 の AMI を利用

```
amzn2-ami-kernel-5.10-hvm-2.0.20230207.0-x86_64-gp2
```



本番環境には、`env` `prod` という値を付与しています。 

```
prod-al2
```

![image-20230728194505976.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/981c9ae4-2f8b-3eb1-c5d7-e3ecb955f0fd.png)



検証環境には、`env` `staging` という値を付与しています。 

```
staging-al2
```

![image-20230728194451114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e0f96d7d-aa13-944f-4f0d-4c0576132cd8.png)



SSH でログインし、2 つの EC2 インスタンス上で ssm agent を最新化しておきます。

```
# Install RPM package (一応IMDSv2を使う様にしている)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
REGION_NAME=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//')
sudo yum install -y https://s3.${REGION_NAME}.amazonaws.com/amazon-ssm-${REGION_NAME}/latest/linux_amd64/amazon-ssm-agent.rpm

# Restart SSM agent
sudo systemctl restart amazon-ssm-agent
```



この結果、Fleet Manager に自動登録されました。

![image-20230728200244462.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c8bc71db-9295-2482-ac05-cfafdb677dd8.png)





# QuickSetup を実行

Systems Manager の Quick Setup からパッチ適用を行っていきます。

![image-20230728152932173.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3e98a430-3e9e-53df-df0e-f7e8711e4104.png)



本番環境の Patch Policy を指定していきます

- パッチ適用を 1 日ごとに実行する cron の設定をします。
  - scan : cron(0 16 ? * * *) : 日本時間 午前 1 時 00 分
  - install : cron(5 16 ? * * *) : 日本時間 午前 1 時 05 分
- Scan のタイミングと、Install のタイミングは時間差を設定しないと動きませんでした。
- 設定が完了したらすぐに実行する (Wait to scan targets until first CRON Interval をオフにする)

![image-20230729155409399.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/2ad5da5a-2961-9f46-404d-f3230658ce6a.png)



OS ごとに、どの Baseline を利用するか選択できます。今回は、Amazon Linux 2 で本番環境用の Baseline を用意したので、それを指定します。パッチが出てから 7 日後のものを対象のインストールします。 (検証環境は 2 日後が対象)

![image-20230729124812237.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/25f146f4-1113-4ff7-d775-3361a311cb47.png)



パッチ適用の対象を指定する方法はいくつかあります。今回は、「Specify node tag」で指定します。

- All managed nodes : すべての仮想マシンを対象
- Specify the resouce group : 別途指定するリソースグループを対象
- Specify node tag : EC2 インスタンスに紐づけた Tag を使って指定
- Manual : 手動で指定

![image-20230729125047221.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/19063059-130f-d8d0-dd50-4d22b1067a7c.png)



あとはデフォルトのまま Create を押します。

![image-20230729125244766.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/15d4ce8a-5f2e-369c-8076-79e01d194d93.png)



Patch Policy が作成されました

![image-20230729125343361.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4ed98fa3-a390-caaa-4c85-377d94c433c5.png)



同様に、検証環境用の Quick Setup を作成します。

![image-20230729130745685.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/213b1ec1-661d-06dd-c162-0218fcdb46d9.png)



Patch Manager で Create

![image-20230729130841575.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a4ea794f-52e9-d492-bde0-2803dff51954.png)



適当に、検証環境用の指定を入れます。

```
staging-patch-policy
```

![image-20230729155550187.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e3cb3396-edda-e572-4bb2-93cd93986220.png)



2 つの Quick Setup が作成されました。

![image-20230729131128439.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/708db48e-7b45-dbff-6351-bbd476ee0a89.png)





# アップデート状況を確認

指定した時間の後に、アップデート状況を確認します。まず、Quick Setup の画面上で、Compliant となっていることがわかります。

![image-20230729155820717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f5467002-2f71-7b56-c89f-9eb8b2ab21cc.png)



どの EC2 インスタンスに、どのパッケージがインストールされているかを Fleet Manager の Node (仮想マシンの管理単位) から確認できます。本番環境用の仮想マシンの詳細画面を開きます。

![image-20230729160041864.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/71a0ef17-2a57-e0b6-c3d3-293914adc5c4.png)



仮想マシン全体でインストールされたパッチの総数がわかります。また、左側のメニューから Patches を選択して詳細を確認します。

![image-20230729160533660.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/27486e1e-3fe8-b3f7-e1a9-aca731d37ad6.png)



いつ、何の名前のパッケージがインストールされたか確認できます。この例では、Kernel (`kernel.x86_64:0:5.10.184-175.749.amzn2`) がインストールされたことがわかります。

![image-20230729160832357.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/5af63839-3569-9fd7-1345-7ea632c40e9e.png)



実際に OS の中でも確認してみましょう。Patch Manager 実行前の yum history はこんな感じになっています。

```
[ec2-user@ip-10-0-30-106 ~]$ sudo yum history list all
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
ID     | Login user               | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
     2 | EC2 ... <ec2-user>       | 2023-07-28 11:00 | Update         |    1 EE
     1 | System <unset>           | 2023-07-28 10:58 | I, O, U        |   53
history list
```



また、Patch Manager 実行前の `yum update` はこんな感じにインストール対象が表示されています。

```
[ec2-user@ip-10-0-30-106 ~]$ sudo yum update
Dependencies Resolved

========================================================================================================================
 Package                        Arch       Version                                     Repository                  Size
========================================================================================================================
Installing:
 kernel                         x86_64     5.10.184-175.749.amzn2                      amzn2extra-kernel-5.10      33 M
Updating:
 awscli                         noarch     1.18.147-1.amzn2.0.2                        amzn2-core                 2.1 M
 cloud-init                     noarch     19.3-46.amzn2.0.1                           amzn2-core                 927 k
 cpio                           x86_64     2.12-11.amzn2                               amzn2-core                 256 k
 curl                           x86_64     8.0.1-1.amzn2.0.1                           amzn2-core                 400 k
 dbus                           x86_64     1:1.10.24-7.amzn2.0.3                       amzn2-core                 245 k
 dbus-libs                      x86_64     1:1.10.24-7.amzn2.0.3                       amzn2-core                 167 k
 ec2-hibinit-agent              noarch     1.0.2-4.amzn2                               amzn2-core                  14 k
 glibc                          x86_64     2.26-63.amzn2                               amzn2-core                 3.3 M
 glibc-all-langpacks            x86_64     2.26-63.amzn2                               amzn2-core                 7.0 M
 glibc-common                   x86_64     2.26-63.amzn2                               amzn2-core                 774 k
 glibc-locale-source            x86_64     2.26-63.amzn2                               amzn2-core                 3.2 M
 glibc-minimal-langpack         x86_64     2.26-63.amzn2                               amzn2-core                  33 k
 hibagent                       noarch     1.1.0-6.amzn2                               amzn2-core                  18 k
 iputils                        x86_64     20180629-11.amzn2.1.20160308                amzn2-core                 147 k
 kpatch-runtime                 noarch     0.9.4-8.amzn2                               amzn2-core                  28 k
 libcap                         x86_64     2.54-1.amzn2.0.2                            amzn2-core                  73 k
 libcrypt                       x86_64     2.26-63.amzn2                               amzn2-core                  53 k
 libcurl                        x86_64     8.0.1-1.amzn2.0.1                           amzn2-core                 346 k
 libfastjson                    x86_64     0.99.4-3.amzn2.0.1                          amzn2-core                  27 k
 libicu                         x86_64     50.2-4.amzn2.0.1                            amzn2-core                 6.8 M
 libssh2                        x86_64     1.4.3-12.amzn2.2.4                          amzn2-core                 136 k
 libtiff                        x86_64     4.0.3-35.amzn2.0.8                          amzn2-core                 174 k
 libwebp                        x86_64     0.3.0-10.amzn2.0.2                          amzn2-core                 170 k
 libxml2                        x86_64     2.9.1-6.amzn2.5.8                           amzn2-core                 661 k
 libxml2-python                 x86_64     2.9.1-6.amzn2.5.8                           amzn2-core                 246 k
 mariadb-libs                   x86_64     1:5.5.68-1.amzn2.0.1                        amzn2-core                 767 k
 microcode_ctl                  x86_64     2:2.1-47.amzn2.0.15                         amzn2-core                 589 k
 mtr                            x86_64     2:0.92-2.amzn2.0.1                          amzn2-core                  89 k
 net-tools                      x86_64     2.0-0.22.20131004git.amzn2.0.3              amzn2-core                 304 k
 openssh                        x86_64     7.4p1-22.amzn2.0.2                          amzn2-core                 507 k
 openssh-clients                x86_64     7.4p1-22.amzn2.0.2                          amzn2-core                 650 k
 openssh-server                 x86_64     7.4p1-22.amzn2.0.2                          amzn2-core                 457 k
 openssl                        x86_64     1:1.0.2k-24.amzn2.0.7                       amzn2-core                 497 k
 openssl-libs                   x86_64     1:1.0.2k-24.amzn2.0.7                       amzn2-core                 1.2 M
 pcre                           x86_64     8.32-17.amzn2.0.3                           amzn2-core                 430 k
 python-babel                   noarch     0.9.6-8.amzn2.0.2                           amzn2-core                 1.4 M
 python-ipaddress               noarch     1.0.16-2.amzn2.0.2                          amzn2-core                  35 k
 python-requests                noarch     2.6.0-10.amzn2.0.1                          amzn2-core                  95 k
 python2-botocore               noarch     1.18.6-1.amzn2.0.3                          amzn2-core                 4.4 M
 python2-rpm                    x86_64     4.11.3-48.amzn2.0.3                         amzn2-core                  85 k
 python2-rsa                    noarch     3.4.1-1.amzn2.0.4                           amzn2-core                  67 k
 python2-setuptools             noarch     41.2.0-4.amzn2.0.3                          amzn2-core                 658 k
 python3                        x86_64     3.7.16-1.amzn2.0.2                          amzn2-core                  72 k
 python3-libs                   x86_64     3.7.16-1.amzn2.0.2                          amzn2-core                 9.8 M
 python3-pip                    noarch     20.2.2-1.amzn2.0.4                          amzn2-core                 2.0 M
 rpm                            x86_64     4.11.3-48.amzn2.0.3                         amzn2-core                 1.2 M
 rpm-build-libs                 x86_64     4.11.3-48.amzn2.0.3                         amzn2-core                 107 k
 rpm-libs                       x86_64     4.11.3-48.amzn2.0.3                         amzn2-core                 277 k
 rpm-plugin-systemd-inhibit     x86_64     4.11.3-48.amzn2.0.3                         amzn2-core                  48 k
 rsync                          x86_64     3.1.2-11.amzn2.0.2                          amzn2-core                 407 k
 rsyslog                        x86_64     8.24.0-57.amzn2.2.0.2                       amzn2-core                 619 k
 screen                         x86_64     4.1.0-0.27.20120314git3c2946.amzn2.0.1      amzn2-core                 549 k
 tcpdump                        x86_64     14:4.9.2-4.amzn2.1.0.1                      amzn2-core                 424 k
 tzdata                         noarch     2023c-1.amzn2.0.1                           amzn2-core                 482 k
 yajl                           x86_64     2.0.4-4.amzn2.0.2                           amzn2-core                  40 k

Transaction Summary
========================================================================================================================
Install   1 Package
Upgrade  55 Packages
```



Patch Manager 実行後は、ID 3 の履歴が追加されていました。

```
[ec2-user@ip-10-0-30-106 ~]$ sudo yum history list all
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
ID     | Login user               | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
     3 | System <unset>           | 2023-07-29 04:31 | Install        |    1
     2 | EC2 ... <ec2-user>       | 2023-07-28 11:00 | Update         |    1 EE
     1 | System <unset>           | 2023-07-28 10:58 | I, O, U        |   53
history list
```


ID 3 の履歴を確認すると、`kernel-5.10.184-175.749.amzn2.x86_64` がインストールされていることがわかります。なお、**今回は Baseline にアプリケーションを含めていないので、awscli などのアプリケーションは更新されません。**

```
[ec2-user@ip-10-0-30-106 ~]$ sudo yum history info 3
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Transaction ID : 3
Begin time     : Sat Jul 29 04:31:05 2023
Begin rpmdb    : 454:e482a4bf131b72b83497373b5941b4df9eb7d346
End time       :            04:31:15 2023 (10 seconds)
End rpmdb      : 455:c7de75e59060e3f3bac8dcd41658b5c5e63bddaf
User           : System <unset>
Return-Code    : Success
Transaction performed with:
    Installed     rpm-4.11.3-48.amzn2.0.2.x86_64 installed
    Installed     yum-3.4.3-158.amzn2.0.6.noarch installed
Packages Altered:
    Install kernel-5.10.184-175.749.amzn2.x86_64 @amzn2extra-kernel-5.10
history info
```



なお、Patch Manager の Dashboard 上でも、準拠状況の一覧がわかります。

![image-20230729161619323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/bdf968ea-93a9-f23b-da49-7329df364fc1.png)



# 検証を通じてわかったこと

- Patch Manager のサポート OS
  - https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/patch-manager-prerequisites.html
- Patch Policy の作成は、Patch Manager の画面ではなく、Quick Setup のメニューから行う
- Patch が非準拠になったら通知する設定を入れると、失敗時に気が付いて良い
  - https://cloud5.jp/patchmanager-sns-notification/
- 再起動を有効にして、2 つの Web サーバーで冗長化を組んでいる時、片方ずつ適用するためには、Step Functions との併用がかんがえられる
  - https://dev.classmethod.jp/articles/stepfunctions-jobnet/





# 参考 URL

https://dev.classmethod.jp/articles/patching-env-using-maintenance-windows/

https://dev.classmethod.jp/articles/aws-patch-management-with-patch-policy-made-easy/