やりたいこと
CloudWatchアラートの発生元アカウントと、ハンドリングアカウントを分けたいと思い、以下の構成を作成します。
Cloudformation
パラメータ
Cloudformationパラメータ | event_source.cfn.yaml | event_target.cfn.yaml | 説明 |
---|---|---|---|
TargetAwsAccountId | ○ | - | TargetアカウントID| |
TargetAwsRegion | ○ | - | TargetのカスタムEventBusのリージョン |
CustomEventBusName | ○(TargetEventBusName) | ○ | TargetのカスタムEventBusのリージョン |
SourceAwsAccountId | - | ○ | SourceアカウントID |
EventNotificationMailAddress | - | ○ | Targetアカウント側からメールを送信するアドレス |
コード
event_source.cfn.yaml
Sourceアカウントで発生したCloudWatchアラートの状態変化( CloudWatch Alarm State Change
) をトリガーとして、Target側のEventBusにイベントを転送します。
転送にはIAMロールが必要なので、それも定義しています。
AWSTemplateFormatVersion: "2010-09-09" Description: EventBus CloudWatch Alert Source Parameters: TargetAwsAccountId: Type: String TargetAwsRegion: Type: String TargetEventBusName: Type: String Resources: EventForwardingRole: Type: AWS::IAM::Role Properties: RoleName: CloudWatchAlertForwarder Description: !Sub Forwarding CloudWatch Alert for EventBus ${TargetAwsAccountId}/${TargetEventBusName} AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: events.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CloudWatchEventBusPut PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - events:PutEvents Resource: - !Sub arn:aws:events:${TargetAwsRegion}:${TargetAwsAccountId}:event-bus/${TargetEventBusName} EventForwardingRule: Type: AWS::Events::Rule Properties: Name: CloudWatchAlertForwardingRule Description: CloudWatch Alert Forwarding Rule EventBusName: default State: ENABLED EventPattern: source: - aws.cloudwatch detail-type: - CloudWatch Alarm State Change Targets: - Id: 1 Arn: !Sub arn:aws:events:${TargetAwsRegion}:${TargetAwsAccountId}:event-bus/${TargetEventBusName} RoleArn: !GetAtt EventForwardingRole.Arn
event_target.cfn.yaml
defaultとは別にカスタムEventBusを作成してイベントを待ち受けます。CloudWatchイベントのアラート状態変化 (CloudWatch Alarm State Change
)を受け取ったらSNS Topic(Email)に情報を転送します。
SNS Topicのポリシーとして events.amazonaws.com
からの sns:Publish
を許可してあげるところが、Management Consoleから操作すると自動で設定されるところなのでハマりがちなポイントです。
AWSTemplateFormatVersion: "2010-09-09" Description: EventBus CloudWatch Alert Target Parameters: SourceAwsAccountId: Type: String CustomEventBusName: Type: String EventNotificationMailAddress: Type: String Resources: EventBus: Type: AWS::Events::EventBus Properties: Name: !Ref CustomEventBusName EventBusPolicy: Type: AWS::Events::EventBusPolicy Properties: EventBusName: !Ref EventBus StatementId: EventFromCloudWatchAlertSource Principal: !Ref SourceAwsAccountId Action: events:PutEvents EventNotificationSNSTopic: Type: AWS::SNS::Topic Properties: DisplayName: CloudWatchAlertSample TopicName: cw_alert_mail_sample Subscription: - Endpoint: !Ref EventNotificationMailAddress Protocol: email EventNotificationSNSTopicPolicy: Type: AWS::SNS::TopicPolicy Properties: Topics: - !Ref EventNotificationSNSTopic PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: sns:Publish Principal: Service: events.amazonaws.com Resource: !Ref EventNotificationSNSTopic EventForwardingSNSRule: Type: AWS::Events::Rule Properties: Name: CloudWatchAlertNotificationRule Description: CloudWatch Alert Forwarding Rule State: ENABLED EventBusName: !Ref EventBus EventPattern: source: - aws.cloudwatch detail-type: - CloudWatch Alarm State Change Targets: - Id: 1 Arn: !Ref EventNotificationSNSTopic
使い方
2つアカウントを用意して、それぞれCloudformationでデプロイします。
Source側のアカウントでCloudWatchのアラームのステータスを変更させると、Target側からSNSでメール通知されます。