🐡

RDSのエラーログをslackに通知する仕組みを作成してみる

2023/03/22に公開

今回作成する構成

cloud watchのエラーログを検知するとslackにエラーが発生したことを通知する仕組みを作成する

とりあえず今回の本筋でないELB-ECS-RDSはcloudformationで作成する

下記リポジトリーからコードをダウンロードして、cloudformationで起動してみてください!
https://github.com/hirosi1900day/inspection-ecs-cloudformation-

cloud watchログに移動して, RDSのエラーログにlambdaにログを送信するサブスクリプションを作成する

  • cloud watch RDSエラーログの部分でサブスクリプションを作成する

  • lambdaを作成しておく

  • lambdaの発火条件としてrdsのエラーログをlambdaの発火条件にする

  • cloudwatch rdsのエラーログのサブスクリプションにlambdaが追加されたことを確認(ここから追加しても良い)

lambdaを実装する

  • slackのhook urlをWEB_HOOK_URLの環境変数をセットする

  • slackにpostするコードを実装する

import boto3
import json
import logging
import os

from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError


SLACK_CHANNEL = os.environ['SLACK_CHANEL']

HOOK_URL = os.environ['WEB_HOOK_URL']

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def lambda_handler(event, context):
    
    slack_message = {
        'channel': SLACK_CHANNEL,
        'attachments':  [{
            'title': 'DBでエラーが発生しました',
            'text': 'DBでエラーが発生しました'    
        }]
    }

    req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
    
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted to %s", slack_message['channel'])
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)

実行してみる

見事実行されました!

WEB_HOOK_URLを暗号化

  • kmsでカスタムキーを作成

kmsにlambdaからのアクセスを許可するために、lambdaのロールにアクセス許可を追加

  • lambdaの環境変数を暗号化


    暗号化されたことを確認する

  • lambdaの実装変更

import boto3
import json
import logging
import os

from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError


SLACK_CHANNEL = os.environ['SLACK_CHANEL']

ENCRYPTED_WEB_HOOK_URL = os.environ['WEB_HOOK_URL']

# 下記の行で複合化する
HOOK_URL = boto3.client('kms').decrypt(
        CiphertextBlob=b64decode(ENCRYPTED_WEB_HOOK_URL),
        EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']}
    )['Plaintext'].decode('utf-8')
    
logger = logging.getLogger()
logger.setLevel(logging.INFO)


def lambda_handler(event, context):
    print('DECRYPTED : {}'.format(HOOK_URL))
    slack_message = {
        'channel': SLACK_CHANNEL,
        'attachments':  [{
            'title': 'DBでエラーが発生しました',
            'text': 'DBでエラーが発生しました'    
        }]
    }

    req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
    
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted to %s", slack_message['channel'])
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)
  • 通知できました!!!

Discussion