본문 바로가기

Cloud

[AWS] 웹 방화벽(Web Application Firewall, WAF) 로깅 구성 - 3

저번 포스팅 글에서 Athena 설정 까지 완료는 되었지만 문제가 있다..

원하는 값을 추출하여 확인하는 작업까지는 많이 수월하지만..

매일 확인이 필요한 담당자로써는 자동으로 쿼리문을 실행하여 결과만을 보여주는 작업이 필요하다고 느낀다.

 

그래서 이번 글에서는 Lambda를 이용하여 Athena 쿼리를 매일 실행해주는 작업을 진행하고자 한다.

 

#AWS Lambda

Lambda란 서버를 프로비저닝하거나 관리하지 않고도 코드를 실행할 수 있는 컴퓨팅 서비스이다.

이 서비스를 사용한다면 매일 로그인하지 않고 Athena 서비스를 이용하여 쿼리문 실행이 가능하다.

#Lambda 함수 생성

 

스케쥴링 작업을 실행하기 위해 우선 함수 생성을 진행한다. 런타임 언어는 Python을 진행하였지만 다른 언어를 사용하고 싶은 경우 변경도 가능하다.

 

함수 생성이 완료되었으면 EventBridge를 통해 스케쥴링 작업 설정이 필요하다.

EventBridge에서는 예약 표현식을 지정해야 약속된 시간에 코드가 실행되도록 설정할 수 있으며 적용 전 cron 명령어가 어떤 역할을 하는 명령어인지 학습이 필요하다.

트리거 생성을 성공적으로 마무리하였다면 이제 동작 코드단계 작성해야 Lambda 설정이 모두 완료된다.

 

#Lambda 코드 예시

아래 코드는 이전 글에서 Athena 쿼리문을 실행 시 필요한 코드를 예시로 한다.

좀더 코드에 대한 가공이 필요한 경우 AWS 공식 문서를 참고하여 본인의 입맛에 맞게 코드 작성을 진행하면 된다.

 

import time
import boto3
import datetime

#조회 일자 (전일,금일)
yesterday = datetime.datetime.now() + datetime.timedelta(days=-1)
nowday = datetime.datetime.now()
dt_yesterday = str(yesterday.date())
dt_now = str(nowday.date())

query = """
select to_iso8601(from_unixtime(timestamp / 1000)) as time_ISO_8601,
terminatingruletype as Rule_Type,
terminating_reason_detail.terminatingrule.ruleid as Block_Reason,
action as Action,
httprequest.clientip as Source_IP,
httprequest.country as Country,
httprequest.uri as URI,
terminatingrulematchdetails as Match_Reason,
httprequest.args as Args,
httprequest.httpMethod as HttpMethod,
responsecodesent as response,
httprequest.headers as Header
from "데이터베이스명"."테이블명"
cross join unnest(coalesce(waf_full_log_kor.rulegrouplist, ARRAY[NULL])) as t(terminating_reason_detail)
where (terminating_reason_detail.terminatingrule.ruleid != '' or action ='BLOCK') and date_format(from_unixtime(timestamp / 1000),'%Y-%m-%d') between '{0}' and '{1}'
""".format(dt_yesterday,dt_now)

output='WAF log S3 경로'

def lambda_handler(event, context):
    client = boto3.client('athena')

    # Execution
    response = client.start_query_execution(
        QueryString=query,
        QueryExecutionContext={
            'Database': '데이터베이스명'
        },
        ResultConfiguration={
            'OutputLocation': output,
        }
    )
    return response
    return