Lambda 関数 + SES を利用して EC2 インスタンスのスクリーンショットをメールアドレスに送信してみた
はじめに
テクニカルサポートの 片方 です。
今回は Lambda 関数 + SES を利用して EC2 インスタンスのスクリーンショットをメールアドレスに送信してみました。
インスタンスに接続できない場合はインスタンスのスクリーンショットをキャプチャして、それをイメージとして表示することができます。このイメージにより、インスタンスのステータスについて可視化されるため、迅速にトラブルシューティングすることができます。
インスタンスの実行中またはクラッシュ後にスクリーンショットを生成できます。イメージは JPG 形式で生成され、100 KB 未満です。スクリーンショットにはデータ転送コストがかかりません。
※ EC2 インスタンスのスクリーンショット例
やってみた
SES については検証済みの E メールアドレスがあることを前提に進めさせていただきます。
以下の順番で実装します。
- 実行ロール作成
- Lambda 関数作成
実行ロール作成
※ 信頼関係
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
※ アタッチするポリシー例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:GetConsoleScreenshot",
"Resource": "arn:aws:ec2:*:*:instance/*"
},
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
適宜修正してください。
Lambda 関数
Python 3.13 で作成しました。
実行ロールでは、既存のロールを使用するを選択し、先ほど作成したロールを指定します。
import boto3
import base64
import os
import email.mime.multipart
import email.mime.text
import email.mime.application
from datetime import datetime
def lambda_handler(event, context):
# 環境変数から設定を取得
instance_id = os.environ.get('INSTANCE_ID')
recipient_email = os.environ.get('RECIPIENT_EMAIL')
sender_email = os.environ.get('SENDER_EMAIL')
aws_region = os.environ.get('AWS_REGION')
# イベントからパラメータを上書き(オプション)
if 'instance_id' in event:
instance_id = event['instance_id']
if 'email' in event:
recipient_email = event['email']
# 必須パラメータの検証
if not instance_id:
return {
'statusCode': 400,
'body': 'Missing required environment variable: INSTANCE_ID'
}
if not recipient_email:
return {
'statusCode': 400,
'body': 'Missing required environment variable: RECIPIENT_EMAIL'
}
if not sender_email:
return {
'statusCode': 400,
'body': 'Missing required environment variable: SENDER_EMAIL'
}
try:
# EC2クライアントを作成
ec2_client = boto3.client('ec2')
# スクリーンショットを取得
response = ec2_client.get_console_screenshot(
InstanceId=instance_id,
WakeUp=True # コンソールをウェイクアップ
)
# Base64エンコードされた画像をデコード
image_data = base64.b64decode(response['ImageData'])
# 現在の日時を取得してファイル名に使用
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
filename = f"ec2-screenshot-{instance_id}-{timestamp}.png"
# SESクライアントを作成
ses_client = boto3.client('ses', region_name=aws_region)
# メールの作成
msg = email.mime.multipart.MIMEMultipart()
msg['Subject'] = f'EC2 Instance {instance_id} Screenshot - {timestamp}'
msg['From'] = sender_email
msg['To'] = recipient_email
# メール本文
body = email.mime.text.MIMEText(
f'EC2インスタンス {instance_id} のスクリーンショットです。\n'
f'取得日時: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n\n'
'自動送信メールです。'
)
msg.attach(body)
# スクリーンショットを添付
attachment = email.mime.application.MIMEApplication(image_data)
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attachment)
# メールを送信
ses_client.send_raw_email(
Source=sender_email,
Destinations=[recipient_email],
RawMessage={'Data': msg.as_string()}
)
print(f"スクリーンショットを {recipient_email} に送信しました")
return {
'statusCode': 200,
'body': f'Screenshot of instance {instance_id} sent to {recipient_email}'
}
except Exception as e:
print(f"エラーが発生しました: {str(e)}")
return {
'statusCode': 500,
'body': f'Error: {str(e)}'
}
環境変数
Lambda 関数の「設定」タブから「環境変数」を選択し、以下の変数を設定します
▽ キー:値
- INSTANCE_ID :i-xxxxxxxxxxxxxx (対象の EC2 インスタンス ID)
- RECIPIENT_EMAIL :your-email@example.com (受信者のメールアドレス)
- SENDER_EMAIL :sender@example.com (SES で検証済みの送信元メールアドレス)
タイムアウト設定
デフォルトのタイムアウト値(3秒)では短すぎるため、延長します。
タイムアウトを「60秒」に設定しました。
これで実施は終了です。お疲れ様でした!
検証してみた
作成した Lambda 関数をテストします。
Lambda 関数側では成功してます。
では EC2 インスタンスのスクリーンショットが設定しているメールアドレスへ添付されているか確認します。
結果、問題なく添付されてました。成功です!
なお、Windows OS でも成功しました。
まとめ
本ブログが誰かの参考になれば幸いです。
参考資料
- 到達できない Amazon EC2 インスタンスのトラブルシューティング - Amazon Elastic Compute Cloud
- EC2 - Boto3 1.38.3 documentation
- SES - Boto3 1.38.3 documentation
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。