はじめに
EventBridge API Destinationsを使えば、AWSから外部のWebhookに通知できることを知ったため実際にやってみました。
ケースとして、S3のPutイベントをTeamsに送信する環境を、コンソールとCloudFormationの両方で構築してみました。
参考
構成
今回の内容で、以下のものが作られます。
- S3バケット
- EventBridge
- EventBridge Rule
- EventBridge API Destinations
- コンソールの
統合-APIの送信先-[APIの送信先]タブ
から確認可能
- コンソールの
- EventBridge Connection
- コンソールの
統合-APIの送信先-[接続]タブ
から確認可能
- コンソールの
- IAM Role
- Secrets Managerのシークレット
やったこと
コンソール
作成
S3バケット作成
コンソールから作成するだけです。
EventBridgeへの通知が必要なので、設定をオンにする必要があります。
EventBridge Rule作成
Amazon EventBridge > ルール
からルールを作成します。
イベントパターンにS3のObject Created
を指定して、先ほど作成したバケットを指定します。
ターゲットに以下を指定していきます。
- ターゲットタイプ:EventBridge APIの宛先
- API送信先:新しいAPI送信先を作成
- 名前:[任意の名前]
- API送信先エンドポイント:[TeamsのWebhookのURL]
- HTTPメソッド:POST
- 接続:新しい接続を作成
- 接続名:[任意の名前]
- 送信先タイプ:その他
-
認証タイプ:APIキー
-
APIキー
- ヘッダー名:Content-Type
- 値:application/json
- これらがSecret Mnagerで扱われることになります
-
ターゲット入力を設定:入力トランスフォーマー
-
ターゲット入力トランスフォーマー
正常に作成できた後は、対象のS3バケットにファイルを置くと、Teamsに通知が行きます。
CloudFormationを作成する場合は、テンプレートを確認して参考にするのがよいと思います。
削除
ルール作成時に自動で作成されているものがあるので、残らず消す必要があります。
EventBridge Rule
EventBridge API destinations
パス > ルール
から、[APIの送信先]タブを開き、対象の名前を選択して削除します。
EventBridge API Connection
パス > ルール
から、[接続]タブを開き、対象の名前を選択して削除します。
- 「認証を解除」しなくても削除できます。
- Secret Managerからも、ここを削除する際に一緒に削除されます。
IAM Role
自動作成した場合Amazon_EventBridge_Invoke_Api_Destination_{数値列}
で作成されているはずなので、それを指定して削除します。
S3バケット
バケットの中を空にした後、削除してください。
CloudFormation
これまで説明した構成を、CloudFormationで記述すると以下のようになります。
TeamsのWebhookURLをパラメータとして指定できるようにしています。
クリックで表示
AWSTemplateFormatVersion: 2010-09-09
Parameters:
TeamsWebhookUrl:
Type: String
Resources:
TargetBucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketKeyEnabled: false
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
TeamsConnection:
Type: AWS::Events::Connection
Properties:
AuthorizationType: API_KEY
Description: Connection to Teams webhook
AuthParameters:
ApiKeyAuthParameters:
ApiKeyName: "Content-Type"
ApiKeyValue: "application/json"
TeamsDestination:
Type: AWS::Events::ApiDestination
Properties:
ConnectionArn: !GetAtt TeamsConnection.Arn
HttpMethod: POST
InvocationEndpoint: !Ref TeamsWebhookUrl
InvocationRateLimitPerSecond: 10
TeamsRuleRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
Action:
- sts:AssumeRole
Path: '/service-role/'
Policies:
- PolicyName: "Amazon_EventBridge_Invoke_Api_Destination"
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- events:InvokeApiDestination
Resource: !GetAtt TeamsDestination.Arn
TeamsRule:
Type: AWS::Events::Rule
Properties:
State: DISABLED
EventBusName: default
EventPattern:
source:
- aws.s3
detail-type:
- Object Created
detail:
bucket:
name:
- !Ref TargetBucket
Targets:
- Id: teams-destination
Arn: !GetAtt TeamsDestination.Arn
RoleArn: !GetAtt TeamsRuleRole.Arn
InputTransformer:
InputPathsMap:
key: $.detail.object.key
InputTemplate: |-
{
"text":"ファイル **<key>** が置かれました"
}
おわりに
今までSNS->Lambdaを連携してTeamsに通知していましたが、これを使えばLambdaのスクリプトの管理が不要で通知できます。
ですがSecrets Managerを使うため、こちらの構成のほうが利用料がかかります。しかもTeamsが送信先の場合は暗号化する情報がContent-Type:application/json
なので割高感が拭えず、こちらの構成の採用を見送りました。
検討される方はコスト面も忘れずに評価してください。