【2024年7月19日に発生したWindowsサーバー障害に関する記事】AWS ナレッジセンターに公開された手順のうち AWS Systems Manager を利用する手順の確認をしました

記事タイトルとURLをコピーする

本記事は 2024年7月21日 時点での公開情報に基づいた検証内容となります。
今後 AWS の公式情報に変更があった場合、常に AWS 公式情報を優先します。

みなさん、こんにちは。 AWS CLI が好きなテクニカルサポート課の市野です。

2024年7月19日に発生した CrowdStrike Falcon のエージェントファイル csagent.sys の不具合に起因した Windows サーバーの障害について、AWS re:Post に具体的な回復手順の公開がされました。

repost.aws

昨日、弊社荒川が「Use the manual recovery method」セクション以降の手動による回復手順の検証を行い、ブログ記事として公開していますが、本記事では「Use the AWS Systems Manager automation runbook」セクションに記載されている AWS Systems Manager Runbook による自動復旧の手順を検証しました。

blog.serverworks.co.jp

なお、AWSSupport- ではじまる AWS Systems Manager Runbook となりますので、先日、ブログで紹介しました AWS SAW(AWS Support Automation Workflows)の扱いとなります。

blog.serverworks.co.jp

手順概要(AWS re:Post 記事からの抜粋)

Note: The AWSSupport-StartEC2RescueWorkflow Systems Manager automation runbook stops your instance. If your instance uses instance store volumes, then use the manual recovery method.

Before you start the AWSSupport-StartEC2RescueWorkflow runbook, make sure that your AWS Identify and Access Management (IAM) user or role has the required permissions. For more information, see the Required IAM permissions section of AWSSupport-StartEC2RescueWorkflow. You must also add kms:CreateGrant permission to the IAM role.

To use AWSSupport-StartEC2RescueWorkflow to automate recovery, open the runbook on the Systems Manager console, and select the AWS Region and instances you need to recover. If your EBS root volume is encrypted, then set AllowEncryptedVolume to True.

This workflow launches a temporary EC2 instance (helper instance) in a virtual private cloud (VPC). The launched instance is automatically associated with the default security group of the VPC. The default security group must allow outbound HTTPS (port 443) communication to both Amazon S3 and Systems Manager endpoints. This ensures that the instance can reach the required AWS services to complete the configured workflow tasks. The instance mounts the root volume of the selected instances, and runs the following command to delete the affected file:

get-childitem -path "$env:EC2RESCUE_OFFLINE_DRIVE\Windows\System32\drivers\CrowdStrike\" -Include C-00000291*.sys -Recurse | foreach { $_.Delete()}

To verify the content of the Base64 OfflineScript payload from the preceding command, run the following command:

PS C:\Windows\system32> [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("REPLACE_WITH_BASE64_HERE"))

(当方での和訳)

注意: AWSSupport-StartEC2RescueWorkflow Systems Manager 自動化ランブックはインスタンスを停止します。インスタンスがインスタンスストアボリュームを使用している場合は、手動リカバリ方法を使用してください。

AWSSupport-StartEC2RescueWorkflow ランブックを開始する前に、AWS 識別およびアクセス管理 (IAM) ユーザーまたはロールに必要な権限があることを確認してください。詳細については、AWSSupport-StartEC2RescueWorkflow の「必要な IAM 権限」セクションを参照してください。また、IAM ロールに kms:CreateGrant 権限を追加する必要があります。

AWSSupport-StartEC2RescueWorkflow を使用してリカバリを自動化するには、Systems Manager コンソールでランブックを開き、リカバリする必要がある AWS リージョンとインスタンスを選択します。EBS ルートボリュームが暗号化されている場合は、AllowEncryptedVolume を True に設定します。

このワークフローは、仮想プライベートクラウド (VPC) で一時的な EC2 インスタンス (ヘルパーインスタンス) を起動します。起動されたインスタンスは、VPC のデフォルトのセキュリティグループに自動的に関連付けられます。デフォルトのセキュリティグループは、Amazon S3 と Systems Manager エンドポイントの両方へのアウトバウンド HTTPS (ポート 443) 通信を許可する必要があります。これにより、インスタンスは設定されたワークフロータスクを完了するために必要な AWS サービスにアクセスできます。インスタンスは、選択したインスタンスのルートボリュームをマウントし、次のコマンドを実行して影響を受けるファイルを削除します。

get-childitem -path "$env:EC2RESCUE_OFFLINE_DRIVE\Windows\System32\drivers\CrowdStrike\" -Include C-00000291*.sys -Recurse | foreach { $_.Delete()}

先のコマンドでBase64 OfflineScriptペイロードの内容を確認するには、以下のコマンドを実行する:

PS C:\Windows\system32> [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("REPLACE_WITH_BASE64_HERE"))

前提

  • 対象のインスタンスがAWS Marketplace で提供されている AMI から起動したインスタンスでないこと
  • 対象のインスタンスが停止状態でないこと(停止状態の場合は「Use the manual recovery method」セクション以降の手動による回復が必要となります)
  • 該当の Systems Manager Runbook の実行を AmazonSSMAutomationRole ロール相当以上の権限で実行すること
  • 対象のインスタンスはマネージドノードとして認識されていなくても構わない

事前準備

今回の事象は、%windir%\system32\drivers\CrowdStrike\ ディレクトリにある C-00000291*.sys という命名規則のファイルを削除して再起動を実行することで対処が可能と公式の案内がされています。

そのため、該当のファイルを模したものをあらかじめ検証用のインスタンスへ作成しておきます。
また、類似の他のファイルへの影響がないことも確認するために、C-00000290*.sysC-00000292*.sys となるファイルも作成しておきました。

その上で、AWS re:Post 記事で案内されている AWSSupport-StartEC2RescueWorkflow を用いることで該当のファイルが削除された状態のインスタンスへ修復ができているかの確認を行います。

検証

1. 実行コマンドの base64 化

AWSSupport-StartEC2RescueWorkflow の公式ドキュメントに解説のある通り get-childitem -path "$env:EC2RESCUE_OFFLINE_DRIVE\Windows\System32\drivers\CrowdStrike\" -Include C-00000291*.sys -Recurse | foreach { $_.Delete()} コマンドレットをレスキューインスタンスで実行する必要があります。

AWSSupport-StartEC2RescueWorkflow 実行時のパラメータのうち OfflineScript に対し実行したいコマンドを指定しますが、この時 base64 化してある必要があります。

ドキュメントでは、powershell または bash を利用する方法がありますが、ここでは CloudShell で実行してみます。

echo 'get-childitem -path "$env:EC2RESCUE_OFFLINE_DRIVE\Windows\System32\drivers\CrowdStrike\" -Include C-00000291*.sys -Recurse | foreach { $_.Delete()}' | base64

上記の要領でコマンドを実行すると、以下のように返却されます。

Z2V0LWNoaWxkaXRlbSAtcGF0aCAiJGVudjpFQzJSRVNDVUVfT0ZGTElORV9EUklWRVxXaW5kb3dzXFN5c3RlbTMyXGRyaXZlcnNcQ3Jvd2RTdHJpa2VcIiAtSW5jbHVkZSBDLTAwMDAwMjkxKi5zeXMgLVJlY3Vyc2UgfCBmb3JlYWNoIHsgJF8uRGVsZXRlKCl9Cg==

2. 作成した base64 文字列の妥当性の確認

以下の要領でデコードを実行し返却される値が、元のコマンド文字列であることを確認します。

echo "Z2V0LWNoaWxkaXRlbSAtcGF0aCAiJGVudjpFQzJSRVNDVUVfT0ZGTElORV9EUklWRVxXaW5kb3dzXFN5c3RlbTMyXGRyaXZlcnNcQ3Jvd2RTdHJpa2VcIiAtSW5jbHVkZSBDLTAwMDAwMjkxKi5zeXMgLVJlY3Vyc2UgfCBmb3JlYWNoIHsgJF8uRGVsZXRlKCl9Cg==" | base64 -d

上記の要領でコマンドを実行すると、以下のように返却されます。
実行したいコマンドと同じ文字列が返却されていることを確認します。

get-childitem -path "$env:EC2RESCUE_OFFLINE_DRIVE\Windows\System32\drivers\CrowdStrike\" -Include C-00000291*.sys -Recurse | foreach { $_.Delete()}

3. オートメーション ランブックの実行

  1. AWS Systems ManagerAutomationExecute へ進みます。
  2. Automatino runbook として AWSSupport-StartEC2RescueWorkflow を検索します。
  3. 検索の結果見つかった AWSSupport-StartEC2RescueWorkflow ランブックのリンクをクリックし、オートメーション詳細画面へ移動します。
  4. 「オートメーションを実行する」ボタンをクリックします。
  5. 検証では Simple execution を選択しました。(要件に応じて適宜選択ください)
  6. 対象のインスタンスを選択します。
    プルダウンより「Show managed instances only」で絞り込み、「Show all instances」ですべてのインスタンスを表示することが可能です。
  7. OfflineScript 欄に、<1>で base64 化したコマンドを入力します。
    また、その他の項目は以下となります。適宜オプション項目を設定しページ下部の「Execute」ボタンをクリックすると、ランブックが実行されます。
    1. AutomationAssumeRole:オプション項目/該当の Runbook を実行するための IAM ロールとなります。未指定の場合、コンソールを操作している IAM エンティティの権限で実行されます。
    2. EC2RescueInstanceType:オプション項目/起動するレスキューインスタンスのインスタンスタイプを指定可能です。
    3. SubnetId:オプション項目/レスキューインスタンスが起動するサブネットの ID を入力可能です。デフォルトでは修復対象のインスタンスと同じサブネットでレスキューインスタンスが起動します。
    4. S3BucketName:オプション項目/トラブルシューティングログを指定の S3 バケットへアップロードすることが可能です。
    5. S3Prefix:オプション項目/トラブルシューティングログをアップロードする場合の接頭辞を指定可能です。
    6. AMIPrefix:オプション項目/バックアップ用の AMI に付与される接頭辞を指定可能です。
    7. CreatePreEC2RescueBackup:オプション項目/OfflineScript を実行する前に AMI を作成することが可能です。
    8. CreatePostEC2RescueBackup:オプション項目/OfflineScript を実行する後に AMI を作成することが可能です。
    9. UniqueId:オプション項目/該当のワークフローの一意の識別子を指定可能です。
    10. HelperInstanceProfileName:オプション項目/起動するレスキューインスタンスに既存の IAM ロールを付与することが可能です。
    11. AllowEncryptedVolume:オプション項目/修復対象のインスタンスが EBS 暗号化ルートボリュームである場合、True を選択する必要があります。
    12. AssociatePublicIpAddress:オプション項目/起動するレスキューインスタンスにパブリック IP アドレスを割り当てることが可能です。
    13. HelperInstanceSecurityGroupId:オプション項目/起動するレスキューインスタンスにセキュリティグループを指定可能です。指定しない場合、VPC のデフォルトのセキュリティグループが使用されます。
  8. CloudWatch アラームを設定し、自動化の制御(アラームでオートメーションの停止)を行うことが可能です。
  9. 実行するランブックにタグを設定可能です。

実行結果

AWS マネジメントコンソール上では、Overall status が Success となっていれば、Runbook の実行は正常に完了しています。

また、この状態で修復対象のインスタンスへアクセスすると、目的の C-00000291*.sys のみを削除できていることがわかります。

おまけ - CLI での実行

今回の処理を CLI で実行することを考えた場合、以下のようなスクリプトで実行が可能かと考えられます。
なお、スクリプトのパラメータ部分の組み立てに不安がある場合は、検証の<3>の手順の最下部にある「AWS CLI command and shareable execution link」セクション部分を展開し「Execution platform」プルダウンより「CLI command for Linux/Unix/OS X」を選択することで取得が可能です。

なお、上記の方法で取得できるサンプルの CLI コマンドは、オプション項目で、かつ、デフォルト値のないものは [""] のように挿入されていますが(例:"AutomationAssumeRole":[""] )この状態ではエラーが発生しましたので、入力しないパラメータは適宜取り除く必要がありました。

aws ssm start-automation-execution \
  --document-name "AWSSupport-StartEC2RescueWorkflow" \
  --document-version "\$DEFAULT" \
  --parameters '{ "InstanceId":["i-xxxxxxxxxxxxxxxx"],"OfflineScript":["Z2V0LWNoaWxkaXRlbSAtcGF0aCAiJGVudjpFQzJSRVNDVUVfT0ZGTElORV9EUklWRVxXaW5kb3dzXFN5c3RlbTMyXGRyaXZlcnNcQ3Jvd2RTdHJpa2VcIiAtSW5jbHVkZSBDLTAwMDAwMjkxKi5zeXMgLVJlY3Vyc2UgfCBmb3JlYWNoIHsgJF8uRGVsZXRlKCl9Cg=="],"EC2RescueInstanceType":["t3.medium"],"SubnetId":["SelectedInstanceSubnet"],"S3Prefix":["AWSSupport-EC2Rescue"],"AMIPrefix":["AWSSupport-EC2Rescue"],"CreatePreEC2RescueBackup":["False"],"CreatePostEC2RescueBackup":["False"],"UniqueId":["{{ automation:EXECUTION_ID }}"],"AllowEncryptedVolume":["True"],"AssociatePublicIpAddress":["True"]}' \
  --region ap-northeast-1

おわりに

冒頭の前提ではさらっと流してしまっているのですが、公式ドキュメントにも修復対象のインスタンスがマネージドノードである必要性についての言及がなく、手元の環境でも試してみましたが、フリートマネージャーでマネージドノードとして表示されないインスタンスに対して実行をしても、問題なく対象のファイルの削除ができました。

その背景については、実施中の挙動を確認した結果から、修復対象のインスタンスがマネージドノードとなっていなくても、レスキューインスタンスとして起動されるインスタンスに AmazonSSMManagedInstanceCore をはじめとする必要な IAM ロールが付与され、レスキューインスタンスに対して runCommand が実施されている点にあるかと考えられます。

AWS re:Post の案内では、ec2 describe-instance-status サブコマンドを用いてインスタンスステータスチェックに失敗しているインスタンスの抽出、およびインスタンス ID の取得を行なっています。
今回の検証では、ステータスが impaired となる状態までは再現できなかったため説明を省いていますが、該当の確認と対象インスタンス ID のリスト化を行い、AWSSupport-StartEC2RescueWorkflow ランブックを用いて自動化した修正対応を検討することもできるかと思います。

本記事がどなたかのお役に立てば幸いです。

ではまた。

市野 和明 (記事一覧)

マネージドサービス部・AWS サポート課

お客様から寄せられたご質問や技術検証を通じて得られた気づきを投稿していきます。

情シスだった前職までの経験で、UI がコロコロ変わる AWS においては GUI で手順を残していると画面構成が変わってしまって後々まごつくことが多かった経験から、極力変わりにくい AWS CLI での記事が多めです。

X(Twitter):@kazzpapa3(AWS Community Builder)