본문 바로가기

기타

[AWS] AWS CloudWatch 경보를 Slack으로 보내는 방법_ver2

728x90

AWS CloudWatch 경보를 Slack으로 보내는 방법

시스템 구성

이미지 출처 : https://medium.com/analytics-vidhya/generate-slack-notifications-for-aws-cloudwatch-alarms-e46b68540133

1. Amazon SNS

1-1. 주제 생성

- 이름 : cloudwatch-notification

1-2 구독

메일 확인

1-3 메시지 게시(메시지 발송 테스트)

2. Slack webhooks url 생성

slack webhooks(incoming webhooks) 생성 방법 - https://sangchul.kr/784

#cluodwatchalert
https://hooks.slack.com/services/T018562TM6A/T017ZZ55YUV/wE5gd1fbfjNgxUeLqPUDMTbLR

3. Key Management Service (KMS)

slack 주소 암호화

aws --profile testprofile --region ap-northeast-2 kms create-key

aws --profile testprofile --region ap-northeast-2 \
 kms create-alias --alias-name "alias/slackkey" \
 --target-key-id "b6c5abab-1212-3434-5656-8bdfe1657878"
aws --profile testprofile --region ap-northeast-2 \
 kms encrypt --key-id "alias/slackkey" \
 --plaintext "hooks.slack.com/services/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"

4. AWS Lambda

AWS 콘솔에서 Lambda > 함수 > 함수 생성 > 블루프린트 > cloudwatch-alarm-to-slack-python > 환경 변수 값 입력

- 블루프린트 : cloudwatch-alarm-to-slack-python

환경 변수

- slackChannel : test
- kmsEncryptedHookUrl :  test

lambda  환경 변수 편집

 - 키:값 생성

 kmsEncryptedHookUrl : hooks.slack.com/services/T017/ABAB/nJg51JAITZ0Z0 (webhook URL)

  slackChannel : #channel (채널명)

5. Identity and Access Management(IAM)

IAM 권한 추가

- CloudWatchReadOnlyAccess

- AWSLambdaBasicExecutionRole-xxxx

- kms-lambda-cloudwatch-notification

kms-lambda-cloudwatch-notification

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1443036478000",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:ap-northeast-2:123456789:key/d3s3ceb5-cc9b-4a25-b123-11d86gr346ce4"
            ]
        }
    ]
}

6. cloudwatch 경고 설정

 

7. Slack 메시지

8. 기타(메시지 포맷 편집)

lambda > lambda_function > slack_message 편집

import boto3
import json
import logging
import os

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


# The base-64 encoded, encrypted key (CiphertextBlob) stored in the kmsEncryptedHookUrl environment variable
ENCRYPTED_HOOK_URL = os.environ['kmsEncryptedHookUrl']
# The Slack channel to send a message to stored in the slackChannel environment variable
SLACK_CHANNEL = os.environ['slackChannel']

HOOK_URL = "https://" + boto3.client('kms').decrypt(
    CiphertextBlob=b64decode(ENCRYPTED_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):
    logger.info("Event: " + str(event))
    message = json.loads(event['Records'][0]['Sns']['Message'])
    logger.info("Message: " + str(message))

    alarm_name = message['AlarmName']
    #old_state = message['OldStateValue']
    new_state = message['NewStateValue']
    reason = message['NewStateReason']

    username = 'CloudWatch'
    color = '#00e200'
    
    if new_state == 'ALARM':
        color = '#ff0000'
    
    slack_message = {
        'channel': SLACK_CHANNEL,
        'username': username,
        'pretext': "%s: state - %s" % (alarm_name, new_state),
        'color': color,
        'text': "%s state is now %s: %s" % (alarm_name, new_state, reason)
    }

    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)

728x90