Amazon Web Services ブログ
Systems Manager Automation Runbook でスクリプトを活用する
お客様は今まで、 AWS Systems Manager Automationドキュメントを使用して、AWS Lambda 関数の呼び出しや Amazon Machine Image (AMI) のコピーなど、AWS インフラストラクチャで実行する一連のアクションを定義してきました。これらのドキュメントは現在 Runbook と呼ばれており、簡単に使用でき、かつ強力です。 aws:executeScript アクションを使用すると、Python と PowerShell を Runbook に直接埋め込むことができます。
aws:executeScript
アクションにより、次のことが可能になります。
- ロジックを格納するためだけに Amazon Elastic Compute Cloud (Amazon EC2) インスタンスなどのリソース – これらは追加で、ネットワーク、AWS Identity and Access Management (IAM)、セキュリティなどの構成が必要になる場合がありますね- を立ち上げる必要がなくなります。
- ループ、文字列、JSON、エラー処理などのプログラミング ロジックをフルで使用できます。
- 開発者がすでに慣れている構文を使用して、SDK および PowerShell コマンドレットの呼び出しができます。
このブログポストでは、AWS Config の 自動修復アクション の一部としてこのアクションを使用する方法の例をいくつか紹介します。まず、aws:executeScript
を使用してリソースの情報を取得し、次に Slack と統合し情報を Slack チャネルに送信します。
ソリューションの概要
このブログポストでは、AWS Config の encrypted-volumes ルールを使用します。このルールは、Amazon Elastic Block Store (Amazon EBS) ボリュームをモニターし、暗号化されていないボリュームを見つけます。 暗号化されていないボリュームが見つかると、ルールによって自動修復アクションがトリガーされ、Automation Runbook にてボリュームに関する情報を収集し、情報をSlack チャネルに送信します。これにより、Slack チャネルをモニターしている運用管理者または開発者チームは、問題のあるリソースに対して対応することができます。
注: コードを再利用しやすいように、異なるステップとして作成しています。必要に応じて、両ステップを 1 つのステップに統合して構いません。
プロセスは次のとおりです。
- AWS Config は
encrypted-volumes
ルールを実行して、暗号化されていない EBS ボリュームを見つけます。 - 暗号化されていない EBS ボリュームごとに、AWS Config は Systems Manager Automation Runbook を実行する自動修復アクションを呼び出します。
- Runbook は
aws:executeScript
を使用して、EBS ボリュームに関する情報を取得します。 - Runbook は
aws:executeScript
を使用して次のことを行います。- Slack URL とチャネル情報を含む AWS Secrets Manager シークレットを取得します。
- 情報を Slack チャネルに投稿します。
前提
このチュートリアルを完了するには、次のものが必要です。
Slack との統合
Slack との統合については、この手順に従って Slack Incoming Webhook を追加します。情報を送信するためのSlack チャネルを選び、https://hooks.slack.com/workflows/… のプレフィックスが付いた URL を取得します。Slack チャネルと URL は後に使用します。
AWS Config との統合
AWS Config を有効にします。 [記録するリソースタイプ] で、すべてのリソースを記録しているか、少なくともEC2:Instance と EC2:Volume が含まれていることを確認してください。これらの設定は、encrypted-volumes
ルールが機能するために必要です。詳細については、AWS Config 開発者ガイドの AWS Config の使用開始 を参照してください。
AWS Secrets Manager でシークレットを作成する
作成した Slack URL は機密情報と見なされるため、AWS Secrets Manager に保存します。
- AWS Secrets Manager コンソールにサインインし、[新しいシークレットを保存] を選択します。
- シークレットの種類には、[その他のシークレット] を選択します。
- [プレーンテキスト] タブで、以下を貼り付けます。
TheSlackUrl
とTheSlackChannel
を “前提” の章で構成した値に置き換えてから、[次へ] をクリックします。 - [シークレットの名前] には、
SlackInfo
と入力します。 - 他のページは、すべてのデフォルトのままとします。
- 後でシークレットの ARN を使用するため、[シークレット] でシークレットの名前を選択し、[シークレットの ARN] の下にある値をコピーします。
CloudFormation テンプレートを使ってスタックを作成する
次に、EncryptedVolsToSlack.yaml から CloudFormation テンプレートをダウンロードし、コンピューター上に保存します。
- AWS CloudFormation コンソールで、[スタック]、[スタックの作成]、[新しいリソースを使用 (標準)] の順に選択します。
- [スタックの作成] ページで、[テンプレートファイルのアップロード] を選択し、保存した YAML ファイルを選択してから、[次へ] をクリックします。
- [スタックの詳細を指定] ページで:
- [スタックの名前]には、
UnencryptedVolToSlackStack
と入力します。 - [パラメータ] の [SlackSecretARN] で、SlackInfo シークレット ARN の値を入力します。
- 既にIAM ロールを持っている場合はその名前を[ExistingRoleName] に入力します。そうでない場合は、このフィールドを空白のままにします。
- [スタックの名前]には、
- [次へ] をクリックします。
- 次のページで、[次へ] をクリックします。
- [レビュー] ページで、[承認します] チェックボックスをオンにしてから、[スタックの作成] をクリックします。
数分後、ページを更新し、スタックのステータスが CREATE_COMPLETE になっていることを確認してください。 AWS Config は、新しく作成されたencrypted-volumes
ルールを実行します。これには数分かかる場合があります。
注: CloudFormation テンプレートで使用される IAM ロールは、アカウント内のすべてのリソース (Resource: ‘*’) で ec2:DescribeVolumes および ec2:DescribeInstances アクションを許可します。あくまでも一例です。組織のセキュリティーポリシーに従って、適切に制限してください。
AWS Config ルールを確認する
- AWS Config コンソールで、[ルール] を選択します。
- UnencryptedVolToSlackStackrule を選択します。これは、CloudFormation スタックで構成されたルールです。
- [対象範囲内のリソース] の下にある [非準拠] を選択して、暗号化されていない EBS ボリュームのリストを表示します。
暗号化されていない EBS ボリュームがある場合には、自動修復の後 (つまり、スタックによって作成された Automation Runbook が実行された後) 、 [ステータス] の下に [アクションが正常に実行されました] という文字が表示されます。表示されていない場合は、ページを更新してください。
AWS Systems Manager Automation Runbook を確認する
次に、Systems Manager で作成されたリソースを見てみましょう。
- AWS Systems Manager コンソールで、[ドキュメント] を選択します。
- [自己所有] タブを選択し、UnencryptedVolToSlackStack* のプレフィックスが付いた Automation Runbook を選択します。これは CloudFormation テンプレートによって作成されたものです。
- [コンテンツ] タブで、
aws:executeScript
アクションを呼び出す 2 つのステップを含む、Automation ドキュメントのコンテンツを確認できます。これらを詳細に調べてみましょう。
EBS ボリュームに関する情報を取得します:
- name: extractInfo
action: 'aws:executeScript'
outputs:
- Name: ebsInfoMsg
Selector: $.Payload.message
Type: String
inputs:
Runtime: python3.6
Handler: script_handler
Script: |-
import json
import boto3
def script_handler(events, context):
ec2 = boto3.client('ec2')
response = ec2.describe_volumes(
Filters=[
{
'Name': 'volume-id',
'Values': [
events['ebsVolumeId']
],
}
],
)
state = response['Volumes'][0]['State']
iops = 'N/A'
if 'Iops' in response['Volumes'][0]:
iops = response['Volumes'][0]['Iops']
volumeType = response['Volumes'][0]['VolumeType']
attachments = response['Volumes'][0]['Attachments']
ec2Attached = "No EC2 attached"
if attachments:
ec2Attached = attachments[0]['InstanceId']
theMsg = 'Account {} - Unencrypted Volume {} found! ' \
'[type:{} state:{} Iops:{} EC2-attached:{}' \
.format(events['accountId'], events['ebsVolumeId'],volumeType,state,iops,ec2Attached)
return {'message': theMsg }
InputPayload:
ebsVolumeId: '{{ResourceId}}'
accountId: '{{global:ACCOUNT_ID}}'
description: Gather information for the resource
以下の3つの部分に注目してください。
Inputs
セクションでは、実行する Python スクリプトを指定しています。このスクリプトは、ec2.describe_volumes
呼び出しを実行して、EBS ボリュームに関する情報を取得します。InputPayload
セクションは、Python スクリプトで使用する変数を宣言しています。この変数は、AWS Lambda 関数ハンドラーのイベント引数を介して Python スクリプト内でアクセスできます。ebsVolumeId
は、AWS Config ルールによって Automation ドキュメントに渡される引数ResourceId
で初期化されます。accountId
は、実行時に使用できるグローバル Automation システム変数 である ACCOUNT_ID で初期化されます。
Outputs
セクションは変数ebsInfoMsg
を宣言し、$.Payload.message
で初期化します。Payload
変数には、Python スクリプトが返す JSON オブジェクト (つまり、return {‘message’: theMsg} ) が設定されます。したがって、ebsInfoMsg
にはtheMsg
の値が設定されます。
メッセージを Slack チャネルに投稿します:
- name: publishToSlack
action: 'aws:executeScript'
inputs:
Runtime: python3.6
Handler: script_handler
Script: |-
import json
import urllib
from botocore.exceptions import ClientError
import boto3
def script_handler(events, context):
slack_secret_arn = events['SlackSecretARN']
slack_info = json.loads(get_slack_secret(slack_secret_arn))
slack_message = {
'channel': slack_info["channel"],
'Content': events['theMsgToSend']
}
data = json.dumps(slack_message).encode('utf-8')
req = urllib.request.Request(slack_info["URL"], data)
try:
response = urllib.request.urlopen(req)
the_page = response.read()
except HTTPError as e:
print('Request failed: {} {}'.format(e.code, e.reason))
except URLError as e:
print('Server connection failed: {}'.format(e.reason))
return {"msg": 'Message posted to Slack Channel {}'.format(slack_message['channel'])}
def get_slack_secret(secret_arn):
………
InputPayload:
theMsgToSend: '{{extractInfo.ebsInfoMsg}}'
SlackSecretARN: !Ref SlackSecretARN
description: Send message to Slack channel
この 2 つ目のアクションには、2 つの重要なセクションがあります。
inputs
セクションは、実行する Python スクリプトを指定しています。今回は、Slack チャネルとメッセージを含む JSON ペイロードをポストすることにより、Slack チャネルに通知を送信します。inputPayload
セクションは、Python スクリプトに渡す 2 つの変数を初期化しています。変数は、AWS Lambda 関数ハンドラーのイベント引数を介して Python スクリプト内でアクセスできます。theMsgToSend
は、前のステップextractInfo
で宣言されたebsInfoMsg
変数の値を保持します。- CloudFormation テンプレートで宣言されたパラメーター
SlackSecretARN
は、通知の送信先となる Slack チャネルと URL を取得するために使用されます。
Automation 実行結果を確認する
Automation の実行中にエラーが発生した場合、実行されたアクションの結果をチェックできます。
- AWS Systems Manager コンソールで[自動化] を選択すると、実行されたすべての Automation Runbook のリストを確認できます。
- Runbook の名前は
UnencryptedVolToSlackStack*
で始まります。詳細を表示するには、その実行の 1 つを選択します。
実行の詳細ページで、2 つのステップが正常に実行されたかどうかを確認できます。 1 つのステップでエラーが発生した場合は、失敗した処理のステップ ID を選択して確認します。
クリーンナップ
このチュートリアルで作成した AWS リソースを削除するには、CloudFormation コンソールで [スタック] を選択します。作成したスタック (たとえば、UnencryptedVolToSlackStack) を選択し、[削除] を選択してから、確認画面で[スタックの削除] を選択します。
テンプレートを複数の AWS リージョンにデプロイした場合、スタックによって作成された IAM ロールは、それを作成したスタックによってのみ削除されることに注意してください。このため、IAM ロールを作成したスタックが削除されていることを最後に確認し、不完全にリソースが残らないように気をつけてください。
結論
このブログポストでは、Systems Manager Automation Runbook で aws:executeScript
を使用して Python コードのブロックを実行する 2 つの方法を紹介しました。EC2 インスタンスなどの追加のリソースをプロビジョニングすることなしに、使い慣れた AWS SDK for Python コマンドを使用して準拠していないリソースの情報を収集し、標準の Python ロジックを使用してサードパーティのツールと統合しました。
今回は、スクリプトを AWS Config で実行しましたが、AWS Service Catalog や Amazon EventBridge などの他の AWS サービスを介して Automation Runbook を実行することもできます(訳注:他に AWS Systems Manager OpsCenter や AWS Systems Manager Incident Manager を介しても実行可能です)。また、スタンドアロンの Automation Runbook を実行することもできます。 EC2 および EBS リソースへのアクセスを許可するポリシーを含む IAM ロールを使用して、CloudFormation テンプレートにてインフラストラクチャを簡単にセットアップできます。このロールは、組織のニーズに合わせて調整可能です。
Systems Manager と AWS Config は、すべての主要な AWS リージョンで利用できます。詳細については、AWS Systems Manager ユーザーガイドの スクリプトを実行するランブックを作成する と、AWS Config 開発者ガイドの AWS Config ルールによる非準拠の AWS リソースの修復 を参照してください。
著者について
Melina Schweizer は、AWS のシニアスペシャリストソリューションアーキテクトビルダーです。彼女は、お客様のビジネス成果を促進するためのシンプルで効果的なソリューションの作成に取り組んでいます。余暇には、ピアノを弾いたり、ガーデニングをしたり、家族と一緒に休暇を楽しんだりしています。
翻訳は SA 石橋が担当しました。原文はこちら。