検証・本番環境を考慮した EC2インスタンスへのパッチ適用環境を作ってみる【SSMステートマネージャ編】

2021.06.19

はじめに

img

上図のように インスタンスの タグを使って パッチを当てる/当てないパッチ内容 をコントロールできるようなパッチ当て環境を実装してみます。

今回は Systems Manager(SSM) Patch Manager および State Manager を活用します。

前提条件

今回は Amazon Linux 2 のインスタンス群からなる検証/本番環境を前提として話を進めます。

また、検証環境/本番環境がアカウント分離されているかどうかは問いません。

実現したい環境

  • 原則、全インスタンスを 重要パッチを適用させている状態 としたい (AutoScaling Group から起動されるインスタンスも含む)
  • 定期的にパッチが当たるようにしたい
  • 事前にどのパッチが当たるかを判断するために、「スキャンのみ」も実施できるようにしたい
  • 検証環境/本番環境でパッチ内容を変えたい(例: タイミングをずらす)

設計

インスタンスの タグ を使って パッチを当てる/当てないパッチ内容 をコントロールします。 具体的には以下の 2種類のタグを使って、インスタンスを分類してみます。

Patch Group タグ PatchAssociationTask タグ 分類
STG SCAN 検証環境のインスタンス。パッチスキャンのみ
STG INSTALL 検証環境のインスタンス。パッチ当てを行う
PRD SCAN 本番環境のインスタンス。パッチスキャンのみ
PRD INSTALL 本番環境のインスタンス。パッチ当てを行う

この分類に応じた 「Patch Manager ベースライン」「State Manager 関連付け」設計を行います。

Patch Manager ベースライン

Patch Manager ベースライン(以降 単に "ベースライン") は 「どのような内容でパッチを適用するか定義したもの」です。

img

画像: 【AWS Systems Manager】パッチマネージャーの パッチベースライン と パッチグループ の概念を勉強する | DevelopersIO

今回は Amazon Linux 2 の STG用 ベースライン および PRD用 ベースライン を作成して、 検証環境インスタンス、本番環境インスタンスでパッチ内容を分けるように設定します。

STG用 ベースライン PRD用 ベースライン
名前 STG-AL2Baseline PRD-AL2Baseline
パッチグループ Patch Group=STG Patch Group=PRD
承認ルール#1 Security/Critical/リリース後 1日 Security/Critical/リリース後 31日
承認ルール#2 Security/Important/リリース後 1日 Security/Important/リリース後 31日

2つのベースラインの主な違い「承認ルール」です。 STGベースラインの方がより早く(1ヶ月)新しいパッチが当たるようになっています。

State Manager 関連付け

State Manager 関連付け(以降 単に "関連付け")を使って、 インスタンスに対してSSMドキュメント実行をスケジュールできます。

関連付けられたタイミングでインスタンスへ SSMドキュメント実行できる点が State Manager の特徴です。 例えば「ASGで生成されたインスタンスも例外なくパッチ適用させたい」 場合には State Manager が活かせます。

パッチ適用を行う SSMドキュメントは AWS-RunPatchBaseline です。 AWS-RunPatchBaseline の主なパラメータは以下 2つ。

  • RebootOption=Reboot/NoReboot … パッチ適用後に再起動するか、しないか
  • Operation=Scan/Install … スキャンのみ行うか、インストールまで行うか

よって、以下のように スキャン用の関連付けと インストール用の関連付けを 作成すれば良さそうです。

スキャン用 関連付け インストール用 関連付け
名前 patch-association-scan patch-association-install
ターゲット PatchAssociationTask=SCAN PatchAssociationTask=INSTALL
Operationパラメータ Scan Install

設計まとめ

img

改めて 実現したい環境と、その解決案をまとめます

  • 原則、全インスタンスを 重要パッチを適用させている状態 としたい (ASGインスタンスも含む)
    • → State Manager 関連付けを活用
  • 定期的にパッチが当たるようにしたい
    • → State Manager 関連付けを活用
  • 事前にどのようなパッチが当たるかを判断するために、「スキャンのみ」も実施できるようにしたい
    • → SCAN用関連付け、INSTALL用関連付けを作成。 PatchAssociationTask タグで分類できるようにする
  • 検証環境/本番環境でパッチ適用タイミングをずらいしたい
    • → STG用ベースライン、PRD用ベースラインを作成。 Patch Group タグで分類できるようにする

構築

Patch Manager ベースライン

以下のような CloudFormation テンプレートを作成して、展開しました。 Patch Manager ベースラインを 2つ展開します。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  # --- PatchBaseline(STG)
  BaseLineNameSTG:
    Type: String
    Default: STG-AL2Baseline
  PatchGroupSTG:
    Type: String
    Default: STG
  ApproveAfterDaysSTG:
    Type: Number
    Default: 1

  # --- PatchBaseline(PRD)
  BaseLineNamePRD:
    Type: String
    Default: PRD-AL2Baseline
  PatchGroupPRD:
    Type: String
    Default: PRD
  ApproveAfterDaysPRD:
    Type: Number
    Default: 31

Resources:
  # --- PatchBaseline(STG)
  STGBaseline:
    Type: AWS::SSM::PatchBaseline
    Properties: 
      Name: !Ref BaseLineNameSTG
      OperatingSystem: AMAZON_LINUX_2
      PatchGroups: 
        - !Ref PatchGroupSTG
      ApprovalRules:
        PatchRules:
          - ApproveAfterDays: !Ref ApproveAfterDaysSTG
            ComplianceLevel: CRITICAL
            EnableNonSecurity: false
            PatchFilterGroup: 
              PatchFilters:
                - Key: CLASSIFICATION
                  Values: [Security]
                - Key: SEVERITY
                  Values: [Critical]
          - ApproveAfterDays: !Ref ApproveAfterDaysSTG
            ComplianceLevel: HIGH
            EnableNonSecurity: false
            PatchFilterGroup: 
              PatchFilters:
                - Key: CLASSIFICATION
                  Values: [Security]
                - Key: SEVERITY
                  Values: [Important]

  # --- PatchBaseline(PRD)
  PRDBaseline:
    Type: AWS::SSM::PatchBaseline
    Properties: 
      Name: !Ref BaseLineNamePRD
      OperatingSystem: AMAZON_LINUX_2
      PatchGroups: 
        - !Ref PatchGroupPRD
      ApprovalRules:
        PatchRules:
          - ApproveAfterDays: !Ref ApproveAfterDaysPRD
            ComplianceLevel: CRITICAL
            EnableNonSecurity: false
            PatchFilterGroup: 
              PatchFilters:
                - Key: CLASSIFICATION
                  Values: [Security]
                - Key: SEVERITY
                  Values: [Critical]
          - ApproveAfterDays: !Ref ApproveAfterDaysPRD
            ComplianceLevel: HIGH
            EnableNonSecurity: false
            PatchFilterGroup: 
              PatchFilters:
                - Key: CLASSIFICATION
                  Values: [Security]
                - Key: SEVERITY
                  Values: [Important]

▼ (参考) STG用ベースライン

img

▼ (参考) PRD用ベースライン

img

State Manager 関連付け

同じように CloudFormation テンプレートを作成して、展開しました。 State Manager 関連付けを 2つ展開します。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  OutputS3BucketName:
    Type: String
  ScheduleExpression:
    Type: String
    Default: "cron(00 17 * * ? *)"
  WaitForSuccessTimeoutSeconds:
    Type: Number
    Default: 1800
  TargetKey:
    Type: String
    Default: PatchAssociationTask

  # --- Association(Scan)
  AssociationNameScan:
    Type: String
    Default: patch-association-scan
  TargetValueScan:
    Type: String
    Default: SCAN
  OutputS3KeyPrefixScan:
    Type: String
    Default: "patch/association/scan/"

  # --- Association(Install)
  AssociationNameInstall:
    Type: String
    Default: patch-association-install
  TargetValueInstall:
    Type: String
    Default: INSTALL
  OutputS3KeyPrefixInstall:
    Type: String
    Default: "patch/association/install/"

Resources:
  # --- Association(Scan)
  AssociationScan:
    Type: AWS::SSM::Association
    Properties: 
      AssociationName: !Ref AssociationNameScan
      Name: AWS-RunPatchBaseline
      Targets: 
        - Key: !Sub "tag:${TargetKey}"
          Values: 
            - !Ref TargetValueScan
      Parameters: 
        Operation: [Scan]
        RebootOption: [NoReboot]
      OutputLocation: 
        S3Location: 
          OutputS3BucketName: !Ref OutputS3BucketName
          OutputS3KeyPrefix: !Ref OutputS3KeyPrefixScan
      ScheduleExpression: !Ref ScheduleExpression
      WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds

  # --- Association(Install)
  AssociationInstall:
    Type: AWS::SSM::Association
    Properties: 
      AssociationName: !Ref AssociationNameInstall
      Name: AWS-RunPatchBaseline
      Targets: 
        - Key: !Sub "tag:${TargetKey}"
          Values: 
            - !Ref TargetValueInstall
      Parameters: 
        Operation: [Install]
        RebootOption: [NoReboot]
      OutputLocation: 
        S3Location: 
          OutputS3BucketName: !Ref OutputS3BucketName
          OutputS3KeyPrefix: !Ref OutputS3KeyPrefixInstall
      ScheduleExpression: !Ref ScheduleExpression
      WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds

SSMドキュメントの実行ログを S3バケットへ格納する設定を入れています。 S3バケットへ格納しない場合は、 Run Command のコンソールから実行ログ(24,000文字まで)を確認できます。 AWS-RunPatchBaseline の実行ログは多いため、ほぼ 24,000文字以降のログが省略されます。 証跡を残すためにも S3へ保存しましょう。

▼ (参考) SCAN用関連付け

img

img

img

▼ (参考) INSTALL用関連付け

img

img

img

確認

STG環境インスタンスへ「スキャン」を行う

以下のようなタグ情報を付与したEC2インスタンスを作成しました。

img

しばらくして確認すると SCAN用 関連付け のリソースに登録されていました。タスク実行も成功しています。

img

Run Command の実行ログも コンソールで確認。さらに S3バケットへ格納されていることを確認できました。

img

PRD環境インスタンスへ「パッチ当て」を行う

次に以下 タグ情報を付与したEC2インスタンスを作成してみます。

img

しばらくして確認すると INSTALL用 関連付け のリソースへの登録を確認、タスク実行も成功していました。

img

Run Command の実行ログも コンソールで確認。さらに S3バケットへ格納されていることを確認できました。

img

おわりに

以上、検証環境/本番環境でパッチ適用タイミングをずらした環境の一例でした。 EC2インスタンスへのタグ付け作業は タグエディタで実施すると一括操作できて便利です。

次回は SSMメンテナンスウィンドウを使って同じようなパッチ適用環境を作ってみます。

参考