본문 바로가기
Engineering

AWS CloudTrail & CloudWatch & Lambda를 활용한 리소스 생성, 삭제 추적

by weq155 2024. 4. 25.
반응형

목적 : AWS 계정에 대한 리소스의 생성, 삭제 등에 관한 모니터링 구성

Cloud trail
AWS CloudTrail은 AWS 계정의 운영 및 위험 감사, 거버넌스 및 규정 준수를 활성화하는데 도움을 주는 AWS 서비스
사용자, 역할 또는 AWS 서비스가 수행하는 작업은 Event로 기록됨
이벤트에는 AWS Management Console, AWS Command Line Interface 및 AWS SDK, API에서 수행되는 작업들이 포함

CloudTrail은 세가지 방법으로 Event를 기록한다.
- Event history : Event history는 지난 90일 간 한 AWS 리전의 관리 이벤트에 대해 보기, 검색 및 다운로드가 가능하고, 수정이 불가능한 레코드를 제공, 단일 속성을 필터링해 이벤트를 검색 - 과금 X
- CloudTrail Lake : AWS Cloud Lake는 감사 및 보안 목적으로 AWS의 사용자 및 API 활동을 캡처, 저장, 엑세스 및 분석하기 위한 관리형 데이터 레이크
행기반 JSON 형식의 기존 이벤트를 Apache ORC 형식으로 변환(ORC는 데이터 검색에 최적화된 열기반 스토리지 형식) - 보존 기간에 따라 과금형식이 다름
또한 CloudTrail Lake 이벤트 데이터 스토어와 쿼리에는 사용량에 따라 과금 발생
- Trails(추적) : Trails는 AWS 활동 기록을 캡쳐해 이러한 이벤트를 Amazon S3 버킷에 저장하고, 선택적으로 Amazon CloudWatch Logs 및 Amazon EventBridge로 이벤트를 전송
보안 모니터링 솔루션에 이벤트 입력 가능
Amazon Athena와 타사 솔루션 등으로 로그 검색 및 분석 가능
AWS Organizations를 사용해 단일 AWS 계정 또는 다중 AWS 계정 추적을 생성 - S3 스토리지 요금만 과금

 

 


CloudTrail 생성

AWS Organizations에서 조직을 생성한 경우, 해당 조직의 모든 AWS 계정에 대한 모든 이벤트를 로깅하는 _조직 트레일_ 을 생성할 수 있다.
AWS Console > CloudTrail > Trails > Create trail

생성이 완료되면 S3 스토리지 생성
AWSLogs/Account/CroudTrail/Region/Year/Month/Data/Logs 순으로 저장됨

 


Amazon CloudWatch Logs로 CloudTrail 로그 파일 모니터링

 

CloudWatch 콘솔에서 이벤트 보기

CloudWatch Logs 로그 그룹에 이벤트를 전송하도록 추적을 구성한 후 CloudWatch 콘솔에서 이벤트를 확인할 수 있다. CloudTrail은 일반적으로 API 호출 후 평균 5분 이내에 로그 그룹에 이벤트를 전달.
CloudTrail을 생성할때 CloudWatch에 LogGroup 생성

 

CloudWatch 콘솔에서 이벤트를 보려면

  1. [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)에서 CloudWatch 콘솔을 엽니다.
  2. 왼쪽 탐색 창에서 **로그(Logs)**, **로그 그룹(Log groups)**을 선택합니다.
  3. 추적에 대해 지정한 로그 그룹을 선택
  4. 확인하고자 하는 객체를 선택
  5. 추적이 로깅한 이벤트의 세부 정보를 보려면 이벤트를 선택

아래와 같이 Cloudtrail 로그를 확인 가능

Slack API와 연동

Slack IncommingWebhook을 통해 연동
slack -> 앱추가 -> IncommingWebhook -> 채널 설정 -> 이름, 아이콘 등 지정

 

Lambda Function

Process

  1. CloudTrail에서 CloudWatch로 보낸 Event를 파싱
  2. 지정한 Event에 대해 Slack을 통해 Noti

 

Lambda Function 생성

AWS Console > Lambda > Functions > Create Function
AutoScailing으로 Nodegroup의 인스턴스가 생성, 삭제 되는 경우 Event Name : RunInstances, TerminateInstances
- Author from scratch

CloudWatch Filters 생성

아래와 같이 구독 필터를 생성
AWS Console > CloudWatch > Log Groups > Cloudtrail-log > Subscription filters > Create Lambda subscription filter를 선택하고 생성한 lambda funtion을 선택

이전에 생성한 LambdaFunction을 생성하고 Log Format과 filter pattern 정의
Test pattern을 통해 검증 후 생성

 

유의사항 : Filter pattern은 두 개의 정규식만 사용 가능 추가적으로 정규식에 *만 정상작동?

그래서 이번 테스트에서는 Create&Run과 Delete&Terminate 두가지로 구성

 

filter pattern 구문 https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html)

 

 

예시 : { $.eventName = "Run*" || $.eventName = "Terminate*" }

기존에 CloudWatch 문서에서 제공하는 정규식을 사용했는데 정상작동하지 않음

 

 

아래와 같이 생성이 되면 lambda 이름의 Group이 CloudWatch Log Group이 생성됨

 

그 이후 Lambda funtion을 확인해보면 아래와 같이 연결된 걸 확인할 수 있다.

 

Lambda Function Code

  1. 이전에 생성한 SLACK_WEBHOOK_URL를 환경변수로 등록
  2. Slack으로 Log를 전송하는 코드 구성 (GPT를 이용해 코드 작성)

import json  
import os  
import requests  
import base64  
import gzip# Slack Webhook URL  
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']def lambda_handler(event, context):  
    cw_data = event['awslogs']['data']  
    compressed_payload = base64.b64decode(cw_data)  
    uncompressed_payload = gzip.decompress(compressed_payload)    # SNS 메시지에서 CloudWatch 로그 이벤트를 파싱합니다.  
    eventContent = json.loads(uncompressed_payload)  
    messages = json.loads(eventContent['logEvents'][0]['message'])  
    # 필요한 정보를 추출합니다.  
    event_name = messages['eventName']  
    event_time = messages['eventTime']  
    event_source = messages['eventSource']  
    aws_region = messages['awsRegion']  
    if 'userName' in messages['userIdentity']:  
        user_name = messages['userIdentity']['userName']  
    else:  
        user_name = "알수없음"    # Slack에 보낼 메시지를 생성합니다.  
    slack_message = {  
        'text': '*이벤트가 감지되었습니다* ![:확성기:](https://a.slack-edge.com/production-standard-emoji-assets/14.0/apple-medium/1f4e2.png)',  
        'attachments': [  
            {  
                'color': '#36A64F

',  
                'fields': [  
                    {'title': '이벤트 이름', 'value': event_name, 'short': True},  
                    {'title': '생성 시각', 'value': event_time, 'short': True},  
                    {'title': '이벤트 소스', 'value': event_source, 'short': True},  
                    {'title': '리전', 'value': aws_region, 'short': True},  
                    {'title': '유저', 'value': user_name, 'short': True}  
                ]  
            }  
        ]  
    }    # Slack webhook을 통해 메시지를 전송합니다.  
    response = requests.post(SLACK_WEBHOOK_URL, data=json.dumps(slack_message), headers={'Content-Type': 'application/json'})    # Slack으로부터의 응답을 로깅합니다.  
    print("Response from Slack: ", response.text)    return {  
        'statusCode': 200,  
        'body': json.dumps('Message sent to Slack successfully!')  
    }

 

그러나 아래의 에러 발생

{ "errorMessage": "Unable to import module 'lambda_function': No module named 'requests'", "errorType": "Runtime.ImportModuleError", "requestId": "06e1d6ec-4b1a-4274-b533-57f6a4520e5e", "stackTrace": [] }

 


Lambda 함수용 배포 패키지 생성

python -m venv lambda-env
source lambda-env/bin/activate  # Linux/macOS
lambda-env\Scripts\activate     # Windows
vim lambda_function.py # 파일에 lambda Code 입력
pip install requests
cd $VIRTUAL_ENV/lib/python3.12/site-packages  # Python 버전에 맞게 경로 조정
zip -r9 ${OLDPWD}/function.zip .  # 모든 종속성을 zip 파일에 추가
cd $OLDPWD

zip -g function.zip lambda_function.py  # Lambda 함수 파일 추가

 

 

 

Lambda file upload

  1. 해당 Lambda 함수를 선택
  2. **함수 코드** 섹션에서, Upload from > **.zip 파일 업로드**를 선택
  3. 생성한 function.zip 파일을 업로드

 

Test 성공

반응형