この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
吉川@広島です。
【新機能】WorkSpacesのログインイベントのトラッキングが可能になりました | DevelopersIO
案件でこちらの機能を使用する機会があったため、共有したいと思います。
大まかな構成は上記記事を踏襲していますが、差分は以下になります。
- CDKで構築する
- SNSからの通知先をメールではなくAWS Chatbot(Slack)とする
- Lambdaコードの言語はPythonではなくNode.js(TypeScript)とする
AWS Chatbotの下準備
CloudWatch AlarmをAWS ChatbotからSlack通知する仕組みをCDKで作ってみた | DevelopersIO
こちらの「AWS Chatbot の Workspace Configuration を GUI から作成」の手順を実施します。
CDKコード
cdkコマンドでプロジェクトを生成します。
npx aws-cdk init --language typescript
// bin/cdk.ts
#!/usr/bin/env node
import 'source-map-support/register'
import * as cdk from '@aws-cdk/core'
import { CdkStack } from '../lib/cdk-stack'
const app = new cdk.App()
new CdkStack(app, 'workspaces-alarm-stack', {
slackWorkspaceId: 'xxxxxxxxx', // SlackワークスペースID
slackChannelId: 'xxxxxxxxx', // SlackチャンネルID
})
// lib/cdk-stack.ts
import * as cdk from '@aws-cdk/core'
import * as sns from '@aws-cdk/aws-sns'
import * as iam from '@aws-cdk/aws-iam'
import * as chatbot from '@aws-cdk/aws-chatbot'
import * as lambda from '@aws-cdk/aws-lambda'
import * as events from '@aws-cdk/aws-events'
import * as eventsTargets from '@aws-cdk/aws-events-targets'
export interface MyProps {
readonly slackChannelId: string
readonly slackWorkspaceId: string
}
export class CdkStack extends cdk.Stack {
constructor(
scope: cdk.Construct,
id: string,
props?: cdk.StackProps & MyProps
) {
super(scope, id, props)
/**
* SNS
*/
const topic = new sns.Topic(this, 'topic')
topic.addToResourcePolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['SNS:Publish'],
principals: [new iam.ServicePrincipal('events.amazonaws.com')],
resources: [topic.topicArn],
})
)
/**
* Chatbot
*/
const chatbotRole = new iam.Role(this, 'chatbot-role', {
assumedBy: new iam.ServicePrincipal('sns.amazonaws.com'),
})
chatbotRole.addToPolicy(
new iam.PolicyStatement({
resources: ['*'],
actions: ['cloudwatch:*'],
})
)
new chatbot.CfnSlackChannelConfiguration(this, 'slack-channel-config', {
configurationName: 'slack-channel-config',
iamRoleArn: chatbotRole.roleArn,
slackChannelId: props!.slackChannelId,
slackWorkspaceId: props!.slackWorkspaceId,
snsTopicArns: [topic.topicArn],
loggingLevel: 'ERROR',
})
/**
* Lambda
*/
const fn = new lambda.Function(this, 'fn', {
runtime: lambda.Runtime.NODEJS_14_X,
code: lambda.Code.fromAsset('/path/to/dist'), // Bundle後のLambdaコードのPATHを指定
handler: 'index.handler',
environment: {
SNS_TOPIC_ARN: topic.topicArn,
},
})
topic.grantPublish(fn)
/**
* CloudWatch Events
*/
new events.Rule(this, 'rule', {
eventPattern: {
source: ['aws.workspaces'],
detailType: ['WorkSpaces Access'],
},
targets: [new eventsTargets.LambdaFunction(fn)],
})
}
}
Lambdaコード
CloudWatch Eventsをトリガーとして起動するLambdaコードを書きます。せっかくなので
- TypeScriptで書いて
- AWS SDK v3を使って
- esbuildでバンドル
という感じでいきます。
npm i -S @aws-sdk/client-sns
npm i -D esbuild @types/node
SNSにPublishするだけのシンプルなLambda関数です。
import { PublishCommand, SNSClient } from '@aws-sdk/client-sns'
export const handler = (event: unknown) => {
console.log(JSON.stringify(event))
const snsClient = new SNSClient({})
snsClient.send(
new PublishCommand({
TopicArn: process.env.SNS_TOPIC_ARN!,
Message: JSON.stringify(event, null, 2),
Subject: 'WorkSpaces Access Notification',
})
)
}
npx esbuild src/index.ts --platform=node --target=node14 --bundle --outfile=dist/index.js
動作確認
以上の設定でデプロイ後、AWS WorkSpacesのインスタンスにログインすると通知が来ることを確認できました。