EventBridge+LambdaによるAMI作成通知を実装するCloudFormationテンプレートを作成しました。
今回参考にさせていただいた記事
AMIの作成時間が知りたかったのでSNS Topicで通知させてみた
CloudFormationテンプレートによる実装概要
CloudFormationテンプレートでスタックを作成すると下記のような構成が出来上がります。
CloudTrailについてはCloudFormationテンプレートに含んでいませんので別途有効化が必要となります。
この構成は下記のCloudFormationテンプレートで構築しています。
- AMI作成時のSNS通知用CloudFormationテンプレート(notify-sns-createimage.yml)
- CloudTrail有効化を前提
- SNSの通知先指定メールアドレス宛に届く確認メールは別途対応前提
AMI作成時のSNS通知用CloudFormationテンプレート(notify-sns-createimage.yml)
AMI作成時にCreateImageというAWS API Call が呼び出されたときにEventBridge経由にてSNS通知(Email)するものです。Lambdaでは下記の処理を行います。
- AMI作成時にSNS通知
メールフォーマット
件名:
Start CreateImage (対象インスタンスID(対象AMI名))
本文:
Start CreateImage
Region:対象リージョン
InstanceID:対象インスタンスID
AMI Name:対象AMI名
AMI ID:対象AMI ID
AMI作成時のSNS通知用CloudFormationテンプレート(notify-sns-createimage.yml)の内容は下記となります。
CloudFormationスタック作成時に入力が必要となるパラメータを説明します。
- EventName :Event名(初期値:notify-sns-createimage_event)
- FunctionName:Lambda関数名(初期値:notify-sns-createimage)
- RoleName : Lambda関数で利用するIAMロール名(初期値:notify-sns-createimage)
- SNSSubscriptionEmail : SNSのエンドポイント(送信先メールアドレス) (初期値:xxxx@example.com)
- 必ず受信可能なメールアドレスに変更してください
- SNSTopicName : SNS Topic名(初期値:notify-sns-createimage_event)
notify-sns-createimage.yml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
RoleName:
Type: String
Default: notify-sns-createimage
FunctionName:
Type: String
Default: notify-sns-createimage
EventName:
Type: String
Default: notify-sns-createimage_event
SNSTopicName:
Type: String
Default: notify-sns-createimage
SNSSubscriptionEmail:
Type: String
Default: xxxx@example.com
Resources:
LambdaRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub '${RoleName}'
AssumeRolePolicyDocument:
Statement:
- Action:
- 'sts:AssumeRole'
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Version: 2012-10-17
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaExecute'
Path: /
Lambda:
Type: 'AWS::Lambda::Function'
DependsOn: LambdaRole
Properties:
Code:
ZipFile: |
import os
import boto3
def lambda_handler(event, context):
awsRegion = event['detail']['awsRegion']
name = event['detail']['requestParameters']['name']
instanceId = event['detail']['requestParameters']['instanceId']
imageId = event['detail']['responseElements']['imageId']
client = boto3.client('sns')
sns_response = client.publish(
TopicArn= os.environ['SNS_TopicName'] ,
Message=('Start CreateImage\n\nRegion:'
+ awsRegion
+ '\nInstanceID:'
+ instanceId
+ '\nAMI Name:'
+ name
+ '\nAMI ID:'
+ imageId
+ '\n\n'),
Subject= 'Start CreateImage (' + instanceId + '(' + name + '))'
)
return sns_response
Description: SNS notification when CreateImage is executed
FunctionName: !Sub ${FunctionName}
Handler: index.lambda_handler
MemorySize: 128
Role: !GetAtt LambdaRole.Arn
Runtime: python3.6
Timeout: 300
Environment:
Variables:
'AWS_ACCOUNT': !Sub ${AWS::AccountId}
'SNS_TopicName': !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${SNSTopicName}
Tags:
- Key: Name
Value: !Sub ${RoleName}
- Key: CloudformationArn
Value: !Ref 'AWS::StackId'
NotifyMailSNSTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Sub ${SNSTopicName}
TopicName: !Sub ${SNSTopicName}
Subscription:
- Endpoint: !Sub ${SNSSubscriptionEmail}
Protocol: email
NotifyMailSNSPolicy:
Type: AWS::SNS::TopicPolicy
DependsOn: NotifyMailSNSTopic
Properties:
PolicyDocument:
Id: MyTopicPolicy
Version: '2012-10-17'
Statement:
- Sid: NotifyMailSNSPolicy
Effect: Allow
Principal:
AWS: !GetAtt LambdaRole.Arn
Action:
- sns:Publish
Resource: !Ref NotifyMailSNSTopic
Topics:
- !Ref NotifyMailSNSTopic
Rule:
Type: 'AWS::Events::Rule'
Properties:
Description: !Sub ${EventName}
Name: !Sub ${EventName}
EventPattern:
source:
- "aws.ec2"
detail-type:
- "AWS API Call via CloudTrail"
detail:
eventSource:
- "ec2.amazonaws.com"
eventName:
- "CreateImage"
State: "ENABLED"
Targets:
- Arn: !GetAtt
- Lambda
- Arn
Id: lambda
LambdaEvent:
Type: 'AWS::Lambda::Permission'
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: !Ref Lambda
Principal: events.amazonaws.com
SourceArn: !GetAtt
- Rule
- Arn