Aurora DBに接続したユーザー情報をSlackに通知する
序論
皆さんは本番環境のデータベースに誰が入っているかしっかり記録していますか?
当たり前のことですが、本番環境のデータベースに誰が接続しているのかわからない状態というのはあまりよろしくありません。
誰がいつデータベースにアクセスしたか記録することは、監査上重要です。
今回はKiro[1]の力を借りてデータベースにアクセスがあったらSlackへ通知するAWS SAM[2]サーバーレスアプリケーションを構築してみましたのでご紹介いたします。
対象読者
- Aurora MySQL/PostgreSQLを使っている
- DBへの接続情報を記録する必要がある
- AWS SAMの基本的な知識がある
- Goの知識がある(LambdaはGoで実装しています)
構成概要
仕組みは単純でユーザーがデータベースに接続したらログをCloudWatch Logsへ出力させ、サブスクリプションフィルターでLambdaにログを転送します。
ログを受け取ったLambdaはログの中身をSlack通知へ適するように整形し、接続ログを転送しています。
Aurora ログ出力手順
Aurora側でCloudWatch Logsへログを出力させる場合、パラメータグループで出力するログの種類について事前にフィルタリングすることが望ましいです。ログ量が増えるとCloudWatch Logsのコストやログを確認する運用の負荷が増してしまうので適切にログを出力するようにします。
パラメータグループの設定
Auroraならパラメータグループの設定から行なえますが、SQLからでも設定変更できます。
-- MySQL の場合
SET GLOBAL general_log = 'ON';
SET GLOBAL log_output = 'FILE';
-- PostgreSQL の場合
SET log_connections = on;
Aurora構築時にログエクスポート設定を有効化すれば、CloudWatch Logsに以下のようなログが出力されます。
# MySQL
2025-09-23T09:34:39.173138Z 176 Connect test28@10.0.140.132 on mysql using TCP/IP
# PostgreSQL
2025-09-23 10:49:18 UTC:10.0.136.99(48800):yuta@postgres:[4914]:LOG: connection authorized: user=yuta database=postgres application_name=psql SSL enabled (protocol=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384, bits=256)
このログメッセージをそのままSlackに送信すると視認性が悪いので、AWS SAMでログを整形するサーバーレスアプリケーションを実装しました。
AWS SAM実装
テンプレートの全体像は以下のリポジトリにMySQL、PostgreSQLそれぞれ分けて作ってあります。
- MySQL
- PostgreSQL
単にコードを載せて終わりですと味気ないので実装で工夫した点についていくつか説明いたします。
システムユーザーの除外
Aurora MySQL/PostgreSQLはシステムユーザーの定期的な接続情報がCloudWatch Logsに記録され、そのログもSlackへ通知させてしまうと大量に通知され運用しづらくなります。
# MySQL
2025-09-23T11:12:31.939073Z 665 Connect rdsadmin@localhost on using Socket
# PostgreSQL
2025-09-23 10:49:01 UTC:10.0.136.99(53898):[unknown]@[unknown]:[4897]:LOG: connection received: host=10.0.136.99 port=53898
これらのログをCloudWatch Logsへ出力させないようにするのはAWSの仕様上難しそう[3]でしたので、アプリケーション側で回避できるようにシステムユーザーを除外して不要なログを通知させないようにしました。
- MySQL
- PostgreSQL
JST変換
CloudWatch Logsに出力されたログのタイムスタンプはUTC表記になっており、データベースのタイムゾーンを変更してもJSTのタイムスタンプで出力できません。
CloudWatch LogsのタイムスタンプはJSTでもログのタイムスタンプはUTC
ログを受け取ってLambdaのなかでタイムスタンプをUTCからJST表記に変更することで時刻の認識違いを防ぐようにしてます。
- MySQL
- PostgreSQL
デプロイ
SAMテンプレートの内容はLambdaと付随するIAMロールの作成くらいで基本的にGitHubにあげている内容をそのまま流用できます。
一通りコードを書き終えたらビルドしてデプロイしていきます。
# ビルド
$ make build
sam build
Starting Build use cache
Valid cache found, copying previously built resources for following functions (MysqlConnectAuditFunction)
Build Succeeded
Built Artifacts : .aws-sam\build
Built Template : .aws-sam\build\template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
# デプロイ
$ make deploy
sam deploy --guided
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Found
Reading default arguments : Success
Setting default arguments for 'sam deploy'
=========================================
Stack Name [mysql-connect-audit]:
AWS Region [ap-northeast-1]:
Parameter SlackWebhookUrl: # SlackのIncoming Webhookで生成したWebhook URLを入力する
Parameter AuroraClusterIdentifier [handson-db-mysql]: # Auroraクラスター名を入力する
Parameter CloudWatchLogGroupName [/aws/rds/cluster/handson-db-mysql/general]: # Cloudwatch Logグループ名を入力する
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [Y/n]:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CloudFormation outputs from deployed stack
Successfully created/updated stack - mysql-connect-audit in ap-northeast-1
Slack通知確認
実際にAuroraへログインしてSlackに通知されるか確認します。MySQLにユーザーが接続したらCloudwatch Logに接続情報が記録されます。
appdbにtest28ユーザーが接続した
このログを先のサーバーレスアプリケーションでSlackへ以下のように通知させてみました。
PostgreSQLも同様に通知できました。
所感
Auroraへのユーザー接続情報をSlackへ通知することで誰がいつデータベースへアクセスしたか監査できるサーバーレスアプリケーションを実装してみました。
ログをCloudwatch Logに出してもリアルタイムですぐに確認することは難しいのでSlackへ通知できる仕組みを実装することで統制がとれるようになりますので、参考になりましたら幸いです。
参考文献
Discussion