Gom3rye

팀 프로젝트) Elastalert2를 위한 AWS API Gateway, Lambda, SNS 설정 본문

현대 오토에버 클라우드 스쿨

팀 프로젝트) Elastalert2를 위한 AWS API Gateway, Lambda, SNS 설정

Gom3rye 2025. 11. 11. 09:52
728x90
반응형

ElastAlert2 알림을 API Gateway와 Lambda를 통해 AWS SNS로 전송하기

이번 프로젝트에서는 온프레미스(On-premise) 환경의 ElastAlert 2에서 발생하는 알림을 AWS의 API Gateway를 통해 SNS(Simple Notification Service)로 전송하는 아키텍처를 구축한다.

핵심 아키텍처 및 장점

이 방식은 단순히 알림을 보내는 것을 넘어 다음과 같은 핵심적인 장점을 가진다.

  • 보안 강화: 온프레미스 서버에 Access Key와 같은 장기 AWS 자격증명을 보관할 필요가 없어진다. 대신, 훨씬 안전한 API Key 방식으로 인증하여 자격증명 노출 위험을 원천적으로 차단한다.
  • 유연성 및 확장성: API Gateway에서 요청을 가공하거나, 알림 대상을 SNS에서 Lambda 함수나 다른 AWS 서비스로 쉽게 변경할 수 있다. 이때 ElastAlert의 설정은 변경할 필요 없이 그대로 유지할 수 있어 유연한 확장이 가능하다.
  • 제어 및 모니터링: API Gateway에서 직접 API 호출에 대한 로깅, 모니터링, 사용량 제어(Throttling) 등을 수행할 수 있어, 알림 시스템에 대한 가시성과 제어권을 확보할 수 있다.

이제부터 AWS 리소스를 설정하는 단계부터 시작한다.


1단계: AWS 인프라 설정

A. SNS (Simple Notification Service) 토픽 생성

가장 먼저 알림 메시지를 게시할 SNS 토픽을 생성한다.

📌 SNS(Simple Notification Service)란?

완전관리형 게시/구독(Pub/Sub) 메시징 서비스이다. '토픽'이라는 채널을 생성하고, 해당 토픽으로 메시지를 '게시'하면, 이 토픽을 '구독'하는 모든 대상(이메일, SMS, Lambda 함수 등)에게 메시지가 동시에 전송된다.

  1. AWS Management Console 에 로그인 후, 상단 검색창에서 SNS를 검색하여 Simple Notification Service로 이동한다.
  2. 왼쪽 메뉴에서 **토픽(Topics)**을 클릭하고, '토픽 생성(Create topic)' 버튼을 클릭한다.
  3. 토픽 세부 정보를 설정한다.
    • 유형(Type): **표준(Standard)**을 선택한다. 표준 토픽은 다양한 프로토콜(HTTPS, 이메일, SMS 등)의 구독을 지원하며, 알림 목적에 가장 적합하다. FIFO 토픽은 메시지 순서가 엄격하게 보장되어야 할 때 사용한다. (예 : 이메일)
    • 이름(Name): 토픽을 식별할 수 있는 고유한 이름을 입력한다. (예: elastalertToEmail)
    • 나머지 설정(암호화, 액세스 정책 등)은 기본값으로 두고 '토픽 생성(Create topic)' 버튼을 클릭한다.
  4. 생성이 완료되면 토픽 목록에서 생성된 토픽을 확인할 수 있다. 이후 단계에서 사용해야 하므로 ARN(Amazon Resource Name) 값을 복사해 둔다.
    • arn:aws:sns:ap-northeast-2:815800923450:elastalertToEmail

 

B. Lambda 함수 생성 및 권한 설정

다음으로 API Gateway로부터 요청을 받아 SNS로 메시지를 전달하는 Lambda 함수를 생성한다.

📌 AWS Lambda란?

서버를 프로비저닝하거나 관리할 필요 없이 코드를 실행할 수 있게 해주는 서버리스(Serverless) 컴퓨팅 서비스이다. 이벤트가 발생했을 때만 코드를 실행하고 사용한 컴퓨팅 시간에 대해서만 비용을 지불하므로 효율적이다.

  1. AWS Lambda 콘솔로 이동하여 '함수 생성'을 클릭한다.
    • 옵션: 새로 작성
    • 함수 이름: elastalertHandler (또는 원하는 이름)
    • 런타임: Python 3.13 (또는 최신 버전)
    • 아키텍처: x86_64 (기본값)
  2. 권한 섹션을 확장하고, **'기본 Lambda 권한으로 새 역할 생성'**을 선택한다. 이 설정은 Lambda 함수가 CloudWatch에 로그를 기록할 수 있는 기본 실행 역할을 자동으로 생성해준다.
  3. '함수 생성' 을 클릭한다.
  4. 함수가 생성되면 구성(Configuration) 탭 > 권한(Permissions) 메뉴로 이동하여 방금 생성된 역할 이름을 클릭한다. IAM 콘솔 화면으로 리디렉션된다.
  5. IAM 역할 화면에서 **'권한 추가(Add permissions)' > '정책 연결(Attach policies)'**을 클릭한다.
  6. sns를 검색하여 AmazonSNSFullAccess 정책을 선택하거나, 아래와 같이 SNS 발행(Publish) 권한만 가진 인라인 정책(예 : SNS_Publisher)을 직접 생성하여 연결한다. (보안을 위해 최소 권한 원칙을 따르는 것이 좋다.)
    • 인라인 정책 JSON 예시:
      Resource 값은 앞서 생성한 실제 SNS 토픽의 ARN으로 반드시 변경해야 한다.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "arn:aws:sns:ap-northeast-2:815800923450:elastalertToEmail"
        }
    ]
}

 

 

7. 다시 Lambda 함수 화면으로 돌아와 코드(Code) 탭을 선택하고, lambda_function.py의 내용을 아래 코드로 모두 교체한다.

주의: 코드 내의 SNS_TOPIC_ARN 변수 값을 환경 변수에 설정해야 한다.

import json
import boto3
import os

# boto3 SNS 클라이언트 초기화
sns_client = boto3.client('sns')
# 환경 변수에서 SNS Topic ARN 가져오기
# 하드코딩보다 환경 변수 사용이 훨씬 안전하고 유연합니다.
SNS_TOPIC_ARN = os.environ.get('SNS_TOPIC_ARN')

def lambda_handler(event, context):
    # API Gateway를 통해 전달된 ElastAlert2의 데이터는 'body'에 담겨 있습니다.
    try:
        # event['body']는 문자열이므로 json 객체로 파싱합니다.
        alert_data = json.loads(event.get('body', '{}'))

        # 이메일 제목과 내용 구성
        rule_name = alert_data.get('rule_name', 'N/A')
        subject = f"🚨 ElastAlert 알림 !!!"

        # pre-formatted text로 이쁘게 만듭니다.
        message = f"""
        - 감지된 API : {alert_data.get('API', 'N/A')}
        - 발생 시각: {alert_data.get('@timestamp', 'N/A')}
        - SourceIP : {alert_data.get('sourceIP', 'N/A')}
        - {alert_data.get('result', 'N/A')} 에러
        """

        # SNS Topic으로 메시지 발행
        response = sns_client.publish(
            TopicArn=SNS_TOPIC_ARN,
            Subject=subject,
            Message=message
        )

        print("Message sent to SNS. Message ID: ", response['MessageId'])

        # API Gateway에 성공 응답 반환
        return {
            'statusCode': 200,
            'body': json.dumps({'message': 'Alert successfully sent to SNS!'})
        }

    except Exception as e:
        print(f"Error processing alert: {e}")
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

 

 

8. 환경변수 설정

  • '구성' 탭 > '환경 변수' > **'편집'**을 클릭합니다.
  • **'환경 변수 추가'**를 클릭하고 아래와 같이 입력합니다.
    • 키: SNS_TOPIC_ARN
    • 값: 1단계에서 만든 SNS 주제의 ARN을 복사하여 붙여넣습니다. (ARN은 SNS 주제 상세 페이지에서 확인할 수 있습니다.)
  • **'저장'**을 클릭합니다.

9. 코드 수정 후, 오른쪽 위의 'Deploy' 버튼을 클릭하여 변경 사항을 배포한다.

C. API Gateway 엔드포인트 생성 및 Lambda 연동

마지막으로 외부(ElastAlert)에서 HTTP 요청을 보낼 수 있는 엔드포인트를 생성하고, 이를 Lambda 함수와 연결한다.

📌 Amazon API Gateway란?

어떤 규모에서든 개발자가 API를 손쉽게 생성, 게시, 유지 관리, 모니터링 및 보안할 수 있도록 하는 완전관리형 서비스이다. 애플리케이션의 '관문' 역할을 하여 트래픽 관리, 권한 부여, 모니터링 등의 기능을 수행한다.
이제 Lambda 함수를 실행시킬 HTTP API 엔드포인트를 만듭니다.

  1. API Gateway 콘솔로 이동하여 'API 생성'을 클릭한다.
  2. HTTP API 카드 아래의 '구축' 버튼을 선택한다.
  3. 아래와 같이 API를 설정한다.
    • API 이름: WebHookHandler (또는 원하는 이름)
    • 통합(Integrations) 섹션에서 **'통합 추가(Add integration)'**를 클릭한다.
      • 통합 대상: Lambda
      • Lambda 함수: 위에서 생성한 elastalertHandler 함수를 선택한다.
  4. '다음'을 클릭하여 경로 구성 화면으로 이동하고, 아래와 같이 설정한다.
    • 메서드: POST
    • 리소스 경로: /elastalert
    • 통합 대상: 방금 추가한 Lambda 함수가 선택되어 있는지 확인한다.
  5. '다음'을 두 번 클릭하고, 마지막 검토 화면에서 '생성'을 클릭한다.
  6. API가 생성되면 Stages 메뉴에서 **'호출 URL(Invoke URL)'**을 확인할 수 있다.
  7. 이 호출 URL과 위에서 설정한 리소스 경로(/elastalert)를 조합한 주소가 ElastAlert에서 알림을 보낼 최종 엔드포인트 주소가 된다.

이제 ElastAlert 의 alert 설정에서 url 항목에 이 주소를 입력하면, AWS 자격증명 없이도 안전하고 유연하게 알림을 보낼 수 있다.

728x90
반응형