BLOG

Amazon Security Lake의 효과적인 로그 분석과 쿼리 자동화를 위한 GenAI 구현하기 (Amazon Bedrock, RAG)
작성일: 2024-06-14

Amazon Security Lake 서비스 파트너 자격을 취득한 유일한 MSP!

 

메가존클라우드 홈페이지 테크 블로그에 게시되어 있는 Amazon Security Lake와 관련한 콘텐츠를 보셨나요?

 

Amazon Security Lake 서비스는 AWS의 Native SIEM(Security Information and Event Management) Service로 AWS의 다양한 로그들을 간단하게 수집하고 동일한 포맷(OCSF)으로 변환 할 수 있습니다. 메가존클라우드에서는 2023년 10월에 한국 최초로 Security Lake Service Partner자격을 취득하면서, 기술 전문성을 기반으로 다양한 고객사분들께 소개해드리고 있습니다.

 

Amazon Security Lake는 AWS의 Native Log를 수집하기 좋은 서비스이나, 실제 고객사분들께서 어려워하는 부분이 이 로그를 어떻게 분석을 할 것인가에 대한 것입니다. 최근 화두가 되고 있는 GenAI 서비스를 활용하여 이 로그를 분석하는데 도움을 줄 수 있는 Architecture를 구현 및 테스트하고, AWS Summit Seoul 2024 메가존 클라우드 부스에서 시연을 준비한 과정을 본 콘텐츠로 공유드리고자 합니다.

 

높은 성능의 GenAI 구성을 위한 AWS 서비스와 기술

 

올해 초 AWS Tech Blog에 Amazon SageMaker와 Amazon Bedrock을 이용하여 Amazon Security Lake의 데이터를 활용할 수 있는 게시글이 업로드가 된 것을 확인했습니다. 해당 AWS Tech Blog에서는 Security Lake를 통해 한 곳으로 모아진 OCSF 포맷의 로그들을 LLM 모델을 활용하여 분석하고, 이를 통해 보다 효율적으로 위협을 탐지하고 대응에 대해서 더 빠르게 추적할 수 있도록 솔루션을 구성하는 것을 보여줍니다. 흥미로운 내용이었으며, 실제 구현을 통해 원하는 성능이 나오게 된다면, 충분히 기업 내부에서 활용하고 유용한 도구가 될 것이라고 생각했습니다.

 

그래서, 저희 메가존클라우드 CTC(Cloud Technology Center)에서 해당 블로그를 참고하여 직접 구현하고, 성능에 대한 테스트 및 고도화를 진행했습니다. 데모 구성 내용을 알아보기 전 관련 서비스 및 기술에 대해 알아보겠습니다.

 

Amazon Bedrock과 Amazon SageMaker

 

Amazon Bedrock과 Amazon SageMaker는 둘 다 AWS에서 제공하는 머신 러닝(ML) 및 인공지능 서비스를 위한 플랫폼이라는 공통점이 있으나, 그 목적과 기능 면에서 다소 차이가 있습니다.

 

Amazon Bedrock은 선도적인 AI 기업들의 고성능 기초 모델(Foundation Models, FM)을 통합하여 제공하는 완전 관리형 서비스입니다. 사용자는 Amazon Bedrock을 사용하여 다양한 대규모 AI 모델을 쉽게 테스트하고 평가할 수 있으며, 필요에 맞게 모델을 선택하고, Fine Tuning 및 RAG(Retrieval Augmented Generation)와 같은 기술로 개인화하여 사용할 수 있습니다. 특히 다양한 LLM 모델을 제공하며, 사용자의 데이터를 안전하게 관리하고 보호하는 데 중점을 둡니다.

 

Amazon SageMaker는 전체 ML워크플로우를 지원하며, 사용자가 더 빠르고 쉽게 ML 모델을 개발할 수 있도록 설계되었습니다. 다시 말하자면 데이터 준비부터 모델 훈련, 튜닝, 배포까지의 모든 ML 워크로드를 수행하면서 시각적으로 관리할 수 있는 통합 플랫폼을 제공합니다.

 

두 서비스 모두 AWS의 ML 및 AI 서비스 생태계의 핵심이며, 사용자가 복잡한 인프라 관리에 신경쓰지 않고 AI 및 ML 본연의 기능을 효과적으로 구현할 수 있도록 지원합니다. 그러나 Amazon Bedrock은 주로 LLM기반의 대규모 생성형 AI 모델의 적용에 초점을 맞추며, Amazon SageMaker는 더 광범위한 ML 워크플로우를 지원하여 개발자가 다양한 워크로드의 머신러닝 프로젝트를 보다 세밀하게 제어하고 최적화할 수 있게 합니다. 이 데모에서는 Amazon Bedrock와 Amazon SageMaker가 결합하여 보안 데이터에 대한 깊이 있는 분석과 빠른 반응 속도를 가능하게 합니다.

 

Foundation Models (Anthropic Claude – Haiku, Sonnet, Opus)

 

데모를 위한 기초 모델로는 Antropic Claude 3.0의 3가지 모델인 Haiku, Sonnet, Opus 모델로 테스트를 진행하였습니다. Amazon Bedrock이 지원하는 다양한 LLM 모델 중에서 한국어를 지원하는 3가지 모델을 선택하여 테스트를 진행하였습니다.

각 모델별 특징으로는 다음과 같습니다.

 

1. Haiku는 Claude 모델 중 가장 작습니다. 효율성과 빠른 응답 시간의 관점에서 최적화되었습니다. 기본적인 언어 이해, 간단한 콘텐츠 생성, 빠른 응답 작업에 적합하며, 상대적으로 제한된 리소스에서도 사용이 가능합니다. 비용 측면에서 다른 Claude 모델에 비해 경쟁력이 있습니다. 계산 요구가 적고 처리 속도가 빨라서 예산이 제한된 애플리케이션이나 비즈니스를 위해 설계되었습니다. 소규모 비즈니스, 스타트업 또는 개인 개발자가 고객 지원 챗봇, 간단한 콘텐츠 생성, 가벼운 언어 처리 작업에 활용할 수 있습니다.

 

2. Sonnet은 중간 크기의 모델로, 성능과 자원 소비 간의 균형을 제공합니다. Haiku보다 더 방대한 데이터로 훈련하여, 향상된 언어 이해 및 생성 기능을 제공합니다. 더 복잡한 콘텐츠 생성, 더 나은 맥락 이해, 보다 세밀한 언어 작업 처리가 가능합니다. Haiku보다 높은 금액이지만, 향상된 기능을 반영하며 비용 대비 성능이 최적화되어 있습니다. 중간 수준의 비용으로, 더 발전된 언어 모델이 필요하지만 많은 비용을 투자하기 어려운 비즈니스에 적합합니다. 그래서 중소기업, 기술 회사, 더 정교한 언어 처리가 필요한 서비스에 적당하며 고급 고객 지원, 콘텐츠 생성, 마케팅 자동화, 상호작용 AI 애플리케이션에 활용할 수 있습니다. 다재다능하고 비용 대비 성능 비율이 좋으며, 다양한 애플리케이션에 적합한 모델입니다.

 

3. Opus는 Claude 시리즈 중 가장 크고 강력한 모델로 포괄적이고 다양한 데이터를 사용하여 최첨단 언어 이해 및 생성 능력을 제공합니다. 특히 고급 콘텐츠 생성, 깊이 있는 맥락 이해, 복잡하고 세밀한 작업 처리 가능, 대규모 애플리케이션 지원, 상세한 콘텐츠 생성, 광범위한 마케팅 및 판매 자동화, 연구 개발 등에 사용됩니다. 그러나 광범위한 훈련과 고급 기능으로 인해 Claude 모델 중 가장 높은 비용이 필요합니다. 그렇기 때문에, 대기업 및 최첨단 AI 솔루션이 필요한 조직에 적합합니다.

 

요약하자면, Haiku는 기본 작업을 위한 저비용/고효율의 AI 솔루션이 필요한 비즈니스에 이상적입니다. Sonnet은 성능과 비용의 균형을 맞추어, 합리적인 예산 내에서 기본 이상의 기능이 필요한 비즈니스에 적합합니다. 그리고, Opus는 최고 수준의 AI 기능이 필요하고 고급 애플리케이션을 위해 프리미엄 성능에 투자할 준비가 된 조직을 대상으로 합니다. 이처럼 Claude 시리즈의 각 모델은 특정 요구 사항과 예산 제약에 따라 선택할 수 있도록 설계되어, 다양한 비즈니스 필요를 충족할 수 있습니다.

 

Text2SQL

 

Text2SQL(Text-To-SQL)은 사용자가 자연어로 입력한 질문을 SQL(Structured Query Language) 쿼리로 자동 변환하는 기술입니다. 이 기술은 데이터 베이스에서 정보를 추출하기 위해 널리 사용되는 SQL과 결합되어 일반적인 언어로 질문할 수 있게 해주고, 시스템은 이를 적절한 SQL 쿼리로 변환하여 필요한 데이터를 찾아낼 수 있습니다.

 

특히, 데이터베이스 관리가 복잡하거나 기술 지식이 부족한 사용자들에게 유용하며, 복잡한 쿼리 구문을 직접 작성할 필요 없이 평소 사용하는 언어로 질문함으로써 필요한 정보에 접근할 수 있습니다. 이러한 접근 방식은 비기술적인 보안 전문가가 보안 로그 데이터를 쉽게 분석하고 원하는 정보를 추출하는 등 보안 분야에서도 유용하게 활용될 수 있습니다. 이는 데이터베이스 사용의 진입 장벽을 낮추고, 데이터 중심의 의사 결정을 보다 빠르고 효율적으로 수행할 수 있도록 지원하기 때문에, 비즈니스 분석, 고객 서비스 관리, 보안 모니터링 등 다양한 분야에서 다양하게 활용할 수 있을 것입니다.

 

아키텍처

 

다음으로 이러한 AWS 서비스와 기술 등을 활용하여 메가존클라우드에서 실제 구성 및 테스트한 내용을 살펴보겠습니다.

 

 

Amazon Security Lake with GenAI 아키텍처

 

데모를 진행할 때 저희는 AWS 블로그에서 안내하는 아키텍처를 기반으로 필요한 서비스만 구성했습니다. 우선 Amazon Security Lake가 활성화된 Account와 GenAI를 구성할 Account를 분리하여 Amazon SageMaker와 Amazon Bedrock을 활성화하였습니다.

 

구체적으로, AWS GenAI for Security Lake Account에는 Amazon SageMaker와 Amazon Bedrock을 활용하여 GenAI 모델을 구성했습니다. 이 계정에서는 SageMaker VPC와 SageMaker 도메인을 설정하였으며, Amazon Sagemaker Instance를 구성했습니다. 그리고, Amazon Athena를 통해 데이터를 분석할 수 있도록 했으며, 최종적으로 분석 결과는 Amazon S3에 저장되도록 구성하였습니다.

 

아쉽게도 Amazon Bedrock이 서울 리전을 지원하고 있지 않아 전체 서비스들을 버지니아 북부에 구축을 진행했습니다. 또한, Amazon Security Lake는 클라우드, 서버, 데이터베이스 등 많은 로그를 통합 수집하기 때문에, 모든 로그를 대상으로 테스트하기에는 많은 리소스와 제약이 있어 일부 클라우드 로그인 VPC Flow Logs와 CloudTrail Logs 대상으로만 구성하여 현실적인 환경에서 테스트를 진행하였습니다.

Amazon SageMaker 아키텍처

 

SageMaker 구성 흐름

 

AWS 환경 구축 진행 후 Amazon SageMaker에서 Notebook Instance를 구성하였으며, Amazon SageMaker의 구조의 기본 로직은 사용할 테이블 및 데이터 정보 기반 템플릿 작성, 작성한 템플릿 기반 LLM 호출 및 결과 출력, 출력 쿼리 검증, 분석 결과 설명 순서로 구성을 진행하였습니다.

 

SageMaker의 주요 모듈은 다음과 같으며, 세부적으로 살펴보겠습니다.
※아래 코드는 최종 구성한 사항으로, 테스트 진행 과정에서의 코드와는 다소 차이가 있을 수 있습니다.

 

table_info_call_athena: 사용 테이블 및 데이터 정보 추출
● create_query_prompt: 기본 템플릿 구성 정의
task_define_template: 상세 task 정의 템플릿 (create_query_template의 기본 구성 내용과 결합)
query_validation_with_record: 추출 쿼리 검증 모듈

 

1. 사용할 테이블 및 데이터 정보 기반 템플릿 작성

 

먼저, 사용자의 자연어를 입력받는 것으로 시작하게 됩니다. 그 후 사용자의 자연어를 입력받아 사용할 테이블 및 데이터 정보를 추출하고, 이를 기반으로 프롬프트 템플릿을 작성합니다. 프롬프트 템플릿에서는 테이블 및 데이터 정보뿐만 아니라 실무에서 사용되는 비지니스 로직이 담겨있기 때문에, Amazon Bedrock 모델의 정확도를 높일 수 있습니다.

 

# 테이블 및 데이터 정보 추출 및 Prompt 템플릿 선언
table_name = 'cloudtrail_table'
table_info = slm.table_info_call_athena(table_name=table_name, info_type='structure')
prompt = slm.create_query_prompt(table_info=table_info, query_k=query_k, user_input=user_input, retrieve_few_shots=global)

 

#DB 테이블 정보 추출
def table_info_call_athena(info_type=None):
    table_name = 'cloudtrail_table'
    if info_type == 'structure':
        return spt.cloudtrail_table_info

 

#테이블 정보 및 사용자의 질의를 바탕으로 쿼리 생성 및 프롬프트 템플릿 정의
def create_query_prompt(table_info=None, sample_log=None, query_k=None, user_input=None):
    template = spt.task_define_template(table_info=table_info, sample_log=sample_log, query_k=query_k)
    prompt = f"""
        System: {template}
        Human: {user_input}
        Assistant:
    """
    return prompt

...


def task_define_template(table_info=None, sample_log=None, query_k=None):
        task_define_template = f""" 
            You are the chief security officer in charge of in-house security control. 
            You are in charge of analyzing AWS SecurityLake data.
            Your role is to convert natural language requests into valid SQL queries.
            <table_info>
            {table_info}
            </table_info>
            <table_info></table_info> contains database schema and 3 sample rows from the table. 
            Generate a query using only the columns that exist in the database schema provided for the table information.
            The DB table name is “{table_name}”.
            Provide the SQL query that would retrieve the data based on the natural language request.
            Always limit a query to a maximum of {query_k} results.
            If you think the question is not related to database, Answer "요청한 작업은 수행할 수 없는 작업입니다".
        """

2. 작성한 템플릿 기반 LLM 호출 및 결과 출력

 

프롬프트 템플릿 기반으로 Claude 모델을 호출하고 결과를 출력합니다. 사용자의 선호나 비즈니스 환경에 맞게 Anthropic Claude 모델을 선택할 수 있으며, 이는 Amazon Bedrock의 개방성을 엿볼 수 있습니다.

 

 

# 프롬프트 템플릿 기반 Claude 모델 호출 및 결과 출력
return_text, boto3_bedrock = slm.query_invoke_model(model_name=model_name, prompt=st.session_state.prompt_session, max_token=None)

# 출력 결과에서 쿼리만 추출
model_query = slm.query_extract(return_text=return_text)

 

3. 출력 쿼리 검증

 

생성된 쿼리는 실제 데이터베이스에서 실행됩니다. 쿼리 실행이 성공하면 결과가 검증되며, 실행이 실패하면 쿼리가 재생성됩니다. ‘query_validation_with_record’ 함수는 쿼리의 실행 및 검증 루프를 활용해서 쿼리의 정확도를 높입니다. 완성도 높은 LLM 모델을 지원하는 Amazon Bedrock이지만 여러 요구에 완벽한 답변을 제공하기는 간혹 어려울 수도 있습니다. 그래서, 검증 로직을 활용하여 전체적인 시스템의 완성도를 높였습니다.

 

 

# 쿼리 검증
query_result, st.session_state.prompt_session, valid_log, query_id = slm.query_validation_with_record(
    valid_roop=valid_roop, model_query=model_query, retrieve_few_shots=globals()['retrieve_few_shots'], 
    table_info=table_info, query_k=query_k, session_log=st.session_state.prompt_session, model_name=model_name,
    user_input=user_input, table_name=table_name, boto3_bedrock=boto3_bedrock, max_tokens=max_tokens, query_mode=query_mode)

 

 

def query_validation_with_record(valid_roop=None, model_query=None, db_conn=None, model_name=None,
                                 table_info=None, sample_log=None, query_k=None, session_log=None,
                                 user_input=None, table_name=None, boto3_bedrock=None, max_tokens=None, query_mode=None,
                                 retrieve_few_shots=None):
    query_result = None
    valid_model_query = ''
    valid_log = []

    for roop in range(valid_roop):
        if query_result is None:
            try:
                query_result = query_execute_with_athena(query=model_query)
                if query_result.shape[0] < 1:
                    print('NO DATA')
                    raise Exception('No data')
                else:
                    print('EXECUTE SUCCESS')
                    break
            except Exception as e:
                query_result = None
                valid_model_query += f'\n\nAssistant : {model_query}'
                valid_model_query += '\n\nHuman: An error occurs in the query you created. Please re-create the query with appropriate syntax.'
                prompt = query_valid_prompt(table_info=table_info, sample_log=sample_log, query_k=query_k, user_input=user_input, 
                                            valid_model_query=valid_model_query, table_name=table_name, query_mode=query_mode)
                return_text = query_invoke_model(prompt=prompt, boto3_bedrock=boto3_bedrock, max_tokens=max_tokens)
                model_query = query_extract(return_text=return_text)
                print(return_text)
    else:
        query_result = None

    return query_result

4. 분석 결과 출력

 

LLM이 생성한 쿼리를 어떤 근거로 생성했는지 세부적으로 파악하기 위해 분석 결과에 대해 출력되도록 하였으며, 이는 사용자의 높은 만족도와 쿼리 이해도를 높이기 위해 시스템적인 접근으로 구성하였습니다.

 

analysis_prompt = st.session_state.prompt_session
PaS_analysis = spt.result_analysis_template()
analysis_prompt += f'\n\nHuman: {PaS_analysis} \nAssistant: '
message, msg = analysis_model(prompt=analysis_prompt, boto3_bedrock=boto3_bedrock, max_tokens=4096)

 

def result_analysis_template(table_info=None, query=None, result=None):
    result_analysis_template = """
    마지막으로 생성한 쿼리와 마지막으로 생성한 쿼리의 결과를 기반으로 어떤 논리적 근거로 마지막 쿼리를 생성했는지 설명해 주세요.
    계획을 세우고 단계별로 문제를 해결해 봅시다.
    """
    return result_analysis_template

 

#결과 분석 모델 호출
def analysis_model(prompt=None, boto3_bedrock=None, max_tokens=None, log_f=None):
    prompt_config = {
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": max_tokens,
        "messages": [
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                ],
            }
        ],
    }

    body = json.dumps(prompt_config)
    modelId = "anthropic.claude-3-sonnet-20240229-v1:0"
    accept = "application/json"
    contentType = "application/json"

    response = boto3_bedrock.invoke_model_with_response_stream(body=body, modelId=modelId, accept=accept, contentType=contentType)
    msg = response.get("body")

    return msg

 

5. 결과 반환

 

쿼리가 검증되고 성공적으로 실행된다면, 결과가 사용자에게 반환되도록 합니다.

 

사용자 Question에 따른 Answer Return

 

위와 같이 Amazon SageMaker 구성을 완료한 후 실제 질문과 답변에 대한 정확도 등에 대해 테스트를 진행하였습니다. 테스트 시에는 일반적인 질문(‘최근 일주일 중 API Call이 가장 많이 발생한 Source IP를 알려줘.’, ‘root 계정을 사용한 로그 내역 알려줘.’ 등) 뿐만 아니라, 실제 보안 위협 분석이 가능한지를 판단하기 위해 실제 Port Scan 및 Credential 탈취 시나리오와 관련한 로그를 미리 발생시켜 탐지에 대한 질문도 진행했습니다. 보안 로그에 대해 다양한 질의를 했으며, 테스트 진행 시 Latency와 쿼리 정확도를 가장 우선시하였습니다.

테스트 결과

 

초기에는 Amazon SageMaker에 zero-shot learning 기법으로 구성하였습니다. 일반적인 질의문과 Port Scan과 Credential 탈취 시나리오와 관련한 위협 탐지를 위한 질의를 진행하였으며, 다음과 같은 결과 값이 도출되었습니다.

 

사용자 Question(VPC Flow Logs 관련)에 따른 Failed Result

 

사용자 Question(VPC Flow Logs관련)에 따른 Failed Result

 

테스트 결과, 위의 내용처럼 zero-shot으로 진행 시 LLM 모델이 정확한 Text2SQL 생성을 하지 못하였습니다.

이러한 결과는 Amazon Security Lake는 JSON 데이터를 포함하는 OCSF(Open Cybersecurity Schema Framework) 로그를 데이터셋으로 활용하며, 쿼리 실행의 기반이 되는 데이터셋이 JSON 형태일 때 생성 쿼리 자체의 복잡도가 높아 쿼리 생성의 한계가 있었던 것으로 추측하였습니다. 또한, OCSF 스키마에 대한 정보 등이 부족하여 쿼리 생성이 정확하지 않았던 것으로 판단하였습니다.

 

 

1차 고도화 – Few-Shot Learning

 

 

이러한 문제를 해결하기 위해 JSON 데이터를 포함하는 로그에서 JSON 부분을 분리하여 별도의 데이터 셋을 구성하였으며, 이를 바탕으로 새로운 환경에서 테스트를 진행하였습니다. 내부 데이터 소스에 근거하여 정확성 높은 응답 제공하는 Few-Shot Learning 기법을 적용하였으며, 질의문과 함께 SQL 쿼리를 보조하는 Query Assistant를 구성하여 테스트를 다시 진행하였습니다.

 

사용자 Question(VPC Flow Logs관련)에 따른 Succeed Result

 

사용자 Question(CloudTrail Logs관련)에 따른 Succeed Result

 

위의 사진과 같이 개선 후에는 질문 의도에 적합한 답변 결과가 나온 것을 확인하였습니다. 개선한 구성 방식에서 조금 더 정확한 결과를 확인하기 위해 다양한 질의 리스트로 다수의 질의와 함께 기초 모델(Haiku, Sonnet, Opus)에 대한 테스트를 진행하였습니다. 그 결과로는 기초 모델 중에서는 Sonnet이 가장 정확도 높은 답변을 하였으며, 약 40%의 정확도의 결과가 도출되었습니다. 이는 초기 구성 방식에 비해 상당한 향상이 있지만, 여전히 개선이 필요한 부분입니다.

 

 

2차 고도화 – RAG(Retrieval Augmented Generation, 검색 증강 생성)

 

 

위와 같이 테스트 및 1차 고도화를 진행한 후, 2차 고도화 진행했습니다. 2차 고도화 과정에서 테스트 결과가 상당히 향상되었으며, 정확도가 크게 높아진 것을 확인할 수 있었습니다. 이러한 개선을 통해 AWS Summit Seoul 2024 메가존클라우드 부스에서 데모를 시연하기로 결정했습니다.

 

2차 고도화는 크게 두가지로 이루어졌습니다. Few-Shot Learning 데이터를 추가하고, RAG(Retrieval Augmented Generation)를 구성하며, 일부 프롬프트를 수정했습니다. 먼저, Few-Shot Learning을 위해 데이터를 추가를 진행하였고, 테스트 진행 시 Few-Shot Learning에 사용된 데이터의 S3 버킷 이름이 쿼리에 사용되는 등 실제 할루시네이션(Hallucination)이 발생했습니다.(할루시네이션은 LLM이 존재하지 않거나 논리적으로 일치하지 않는 내용으로 답변하는 현상으로, 이는 AI 모델의 낮은 성능을 나타냅니다.) 이러한 문제를 해결하고, 더 정확하고 신뢰할 수 있는 응답을 생성하기 위해 RAG(Retrieval Augmented Generation)로 구현하여 고도화를 진행했습니다. 세부적으로 RAG로 구현한 내용과 AWS Summit Seoul 2024에서 진행한 데모에 대해 살펴보도록 하겠습니다.

 

인공지능(AI) 분야에서 정보를 생성하고 검색하는 과정을 결합한 기술입니다. 이 방법은 언어 모델이 더 정확하고 유용한 응답을 생성할 수 있도록 외부 데이터 소스에서 관련 정보를 검색한 후, 이를 사용하여 텍스트를 생성합니다. RAG의 작동 방식은 크게 사용자의 질문 처리 → 정보 검색 → 답변 생성으로 이루어져 있습니다. 자세히 설명하자면, 사용자가 질문이나 요청을 입력하면 이 입력값을 임베딩 벡터로 변환하여 유사한 문서를 검색합니다. 이후 LLM이 검색된 문서의 내용을 바탕으로 최종 응답을 생성합니다. 이 단계에서는 검색된 정보와 언어 모델의 지식(훈련 데이터)을 결합하여 더 정확한 응답을 생성합니다.

 

RAG는 정보 검색과 생성의 강점을 결합하여 더 정확하고 유용한 텍스트를 생성하는 기술입니다. 이를 통해 GenAI 모델의 성능을 크게 향상시킬 수 있으며, 다양한 애플리케이션에서 활용될 수 있습니다. RAG는 주로 인덱싱(임베딩)과 검색 및 생성 두가지로 이루어져있습니다. 인덱싱은 데이터를 소스에서 수집하고 인덱싱하기 위한 파이프라인이며, 검색 및 생성은 사용자 쿼리를 기반으로 인덱스에서 관련 데이터를 검색한 후 이를 모델에 전달하여 답변을 생성합니다.

 

RAG 인덱싱 과정으로는 다음 그림과 같습니다. RAG의 장점은 모델 외부 데이터를 활용하여 언어 모델의 응답 정확성을 크게 향상시킵니다. 그리고 최신 정보를 실시간으로 검색하여 응답에 반영할 수 있기 때문에 모델 자체의 한계를 넘어 외부 지식을 활용함으로써 더 풍부한 정보를 제공할 수 있습니다.

 

 

[RAG 인덱싱 과정]

 

 

여러 데이터를 로드한 후 큰 텍스트를 작은 세그먼트로 분할하는 과정인 Data Chunking을 진행 합니다. 그 후 청크된 데이터를 인코딩하는 과정(Embedding)이 진행된 후 분할된 데이터를 검색할 수 있도록 Vector Database에 저장됩니다.

 

사용자가 입력한 질문의 임베딩과 유사한 데이터를 Vector Database에서 검색하여 LLM에 제공합니다. LLM이 더 효율적인 답변을 할 수 있도록 합니다. 아래의 RAG 다이어그램을 보면 더 잘 이해할 수 있습니다.

 

 

 

RAG 다이어그램

 

금번 데모 진행 시 Amazon Security Lake에서 저장된 로그에서 자주 사용되는 질문 및 해당 질문에 대한 정답 쿼리를 미리 구성하여 Vector Database를 생성하였으며, 아래와 같이 RAG를 구현하여 사용자가 입력하는 질문과 의미적으로 가장 비슷한 질문 쿼리를 참고해 결과를 출력할 수 있도록 구성하였습니다.

#RAG 구현
chunking_dataset = pickle.load(open(os_path+'/pickle_dir/chunking_dataset.pkl', 'rb'))
corpus_embeddings = pickle.load(open(os_path+'/pickle_dir/corpus_embeddings.pkl', 'rb'))
query_list = pickle.load(open(os_path+'/pickle_dir/query_list.pkl', 'rb'))

# HuggingFace 한국어 임베딩 모델 로드
embeddings = SentenceTransformer("jhgan/ko-sroberta-multitask") 
# FAISS 엔진을 활용한 Similarity Search(IndexFlatIP : Cosine Similarity)
index = faiss.IndexIDMap(faiss.IndexFlatIP(768)) 
# question embedding과 인덱스를 연결
index.add_with_ids(corpus_embeddings, np.array(range(0, corpus_embeddings.shape[0]))) 

# 한국어 임베딩 모델을 활용해 user_input에 대한 encoding 작업
query_vector = embeddings.encode([user_input])
# 유저의 질문과 유사한 쿼리 인덱스 리스트 출력
top_k = index.search(query_vector, few_shot_k) 
docs = [chunking_dataset[_id] for _id in top_k[1].tolist()[0]]

# 유사도 검색 결과 가장 유사한 질문에 대한 정답쿼리를 prompt template에 구성
for doc, idx in zip(docs, top_k[1][0].tolist()):
temp_str = f"Human: {doc}\nAssistant: {query_list[idx]}\n\n"

 

 

print(chunking_dataset) # 문장 단위로 분할

['MFA를 비활성화한 관리 콘설 로그인이 있었나요?',
"'root' 계정 사용한 로그가 있나요?",
'어제 몇번의 로그인 시도가 있었습니까?',
'최근 일주일간 가장 많이 로그인한 IAM User를 알려주세요',
'AWS 콘솔에 로그인한 IP 중 54.216.116.106 이 아닌 IP를 알려주세요.',
'최근 일주일 동안 가장 많이 발생된 API Call이 무엇입니까?',
'최근 한달동안 error가 가장 많이 발생된 행위(API Call)가 무엇입니까?',
'최근 1일간 AWS KMS 이벤트 기록을 알려주세요',
'이틀 전 API 호출이 제일 많았던 IP를 알려주세요',
'어제 API 호출이 가장 많이 이루어진 시간대는 언제인가요?',
'KMS 등으로 가장 많이 복호화 요청이 있었던 서비스/사용자는?',
'EC2 인스턴스, RDS 인스턴스 의 기동, 중지, 삭제 등 확인이 가능한가요?',
'특정 보안 그룹의 규칙이 추가되거나 제거된 이벤트 확인이 가능한가요??',
'AWS 리소스에 대한 태그 변경 분도 확인이 가능한가요?',
'최근 일주일 동안 api call 을 발생시킨 횟수가 많은 순으로 IP를 리스팅 해주고 리스트 상위 5개 IP에서 발생한 API call 들을 IP별로 보여줘',
'Security Group 변경된 로그가 있나요?',
'AWS Management Console 인증 실패에 대한 로그가 있나요?',
"arn:aws:iam::551508107696:user/DemoUser' 가 로그인할 때 MFA를 사용했습니까?",
'Amazon RDS 인스턴스에 대한 스냅샷 복원 이벤트를 추적할 수 있나요?',
'지난 24시간 동안 API 호출이 실패한 경우를 리스팅 해주고 errorCode와 errorMessage 항목들을 보여줘',
'CMK가 키로테이션 된 일자를 알고 싶습니다.',
'새벽에 접속한 사람 있어??']

 

 

print(corpus_embeddings) # 임베딩

tensor([[-5.3411e-03, -7.4023e-02, 3.7926e-01, ..., -7.2996e-04,
-1.6781e-01, -1.9504e-01],
[ 3.5060e-02, -2.2566e-01, 4.5334e-01, ..., -2.9150e-01,
-1.2969e-01, 1.0309e-01],
[-4.2866e-01, -6.3441e-01, 5.5720e-01, ..., -9.3364e-02,
6.0054e-02, -6.7089e-01],
...,
[-9.8832e-01, 6.1827e-01, 3.7764e-02, ..., -2.4416e-01,
5.9593e-02, 1.0958e-01],
[-2.9902e-01, -1.5139e-01, 1.4176e-01, ..., 1.6358e-02,
8.6800e-01, -7.1446e-01],
[-2.9451e-01, -4.9310e-01, 9.2341e-01, ..., 6.7432e-02,
-3.1949e-01, -1.7224e-01]])

 

 

print(q_list)

['SELECT * \nFROM \n ""amazon_security_lake_glue_db_ap_northeast_2"".""security_lake_genai""\nWHERE\n eventday >=
'SELECT\n *\nFROM \n ""amazon_security_lake_glue_db_ap_northeast_2"".""security_lake_genai""\nWHERE\n eventday
'SELECT COUNT(activity_name) activity_name_count\nFROM ""amazon_security_lake_glue_db_ap_northeast_2"".""security_lake_
'SELECT user_uuid, COUNT(actor_user_uuid) user_uuid_count, COUNT(activity_name) activity_name_count\nFROM ""amazon_secu
'SELECT src_endpoint_ip, COUNT(src_endpoint_ip) src_endpoint_ip_count\nFROM ""amazon_security_lake_glue_db_ap_northeast
'SELECT api_operation, api_service_name, eventday, COUNT(api_operation) as api_count\nFROM ""amazon_security_lake_glue_
'SELECT api_operation, api_service_name, eventday, COUNT(api_operation) as api_count\nFROM ""amazon_security_lake_glue_
'SELECT api_operation, COUNT(activity_name) activity_name_count\nFROM ""amazon_security_lake_glue_db_ap_northeast_2""."
'SELECT src_endpoint_ip, COUNT(src_endpoint_ip) src_endpoint_ip_count\nFROM ""amazon_security_lake_glue_db_ap_northeast
'SELECT \n CAST(CONCAT(CAST(DATE(""time"") AS VARCHAR), \' \', CAST(HOUR(""time"") AS VARCHAR), \':00\') AS TIMESTAM
'WITH \n role_tbl AS(\n -- assumerole_table\n SELECT actor_invoked_by as actor, COUNT(actor_invoked_by
'SELECT\n api_operation\n , count(api_operation) AS operation_count\nFROM \n ""amazon_security_lake_glue_db_ap
'SELECT\n api_operation\n , count(api_operation) AS operation_count\nFROM \n ""amazon_security_lake_glue_db_ap
'SELECT\n api_operation\n , count(api_operation) AS operation_count\nFROM \n ""amazon_security_lake_glue_db_ap
'WITH ip_list_table AS (\n SELECT\n src_endpoint_ip\n , COUNT(src_endpoint_ip) AS ip_count\n FROM \
'SELECT\n *\nFROM \n ""amazon_security_lake_glue_db_ap_northeast_2"".""security_lake_genai""\nWHERE \n eventda
'SELECT\n *\nFROM \n ""amazon_security_lake_glue_db_ap_northeast_2"".""security_lake_genai""\nWHERE\n eventday
"SELECT * \nFROM security_lake_genai\nWHERE actor_user_uuid ='arn:aws:iam::551508107696:user/DemoUser' AND mfa= true\nO
'SELECT\n *\nFROM \n ""amazon_security_lake_glue_db_ap_northeast_2"".""security_lake_genai""\nWHERE \n eventda
'SELECT\n api_operation\n , api_response_error\n , api_response_message\n , api_service_name\nFROM \n ""
'SELECT\n api_operation\n , eventday\n , resources_uid\nFROM \n ""amazon_security_lake_glue_db_ap_northeast
]

 

이와 같이 Security Lake와 GenAI를 결합하여 로그 데이터를 분석하고 SQL 쿼리를 생성하는 전체 과정을 알아보았으며, 최종적으로 RAG 모델을 추가하여 LLM의 안정성과 정확성을 높였습니다.

최종 결과

 

이렇게 구성한 데모 환경을 Web으로 구성하여 AWS Summit Seoul 2024 메가존클라우드 부스에서 시연하였습니다. 시연 내용은 아래에서 확인할 수 있습니다.

 

 

 

 

 

 

 

 

고객 환경과 요구사항을 위한 추가적인 제안

 

 

지금까지 Amazon Security Lake로 수집된 로그들을 Amazon Bedrock과 Amazon Sagemaker를 통해 보안 로그에 대한 접근과 분석을 조금 더 용이할 수 있도록 구성한 내용을 함께 살펴보았습니다. 실제 데모 환경 구성 과 테스트를 통해 보안 로그 분석이 한층 더 수월해진 것을 확인할 수 있었으나, 이번 데모 테스트는 제한된 환경에서 진행된 것으로 몇 가지 아쉬운 부분이 있었습니다. 그렇기 때문에, 향후 추가적인 고도화 작업이 반드시 필요할 것입니다. 아래는 데모 테스트를 진행하면서 이후에 추가적으로 고려해야 할 사항들을 정리한 내용입니다.

 

먼저, 이번 테스트는 데이터베이스 내 단일 테이블을 대상으로 단순 조회 및 집계 쿼리 생성을 수행하였습니다. 그러나 실제 운영 환경에서는 여러 개의 테이블을 사용하여 결과를 도출해야 하는 경우가 많습니다. 특히 Security Lake에는 다양한 보안 로그가 통합되어 저장되기 때문에, 각 로그의 연관관계 분석 시 룰셋 등을 정의하여 추가적인 학습 및 튜닝을 진행해야 합니다. 이 과정에서 쿼리의 복잡도가 증가하며, 다중 조인 쿼리(multiple join query)에 대한 성능 검증이 필요하기 때문에, 다양한 테이블을 활용한 쿼리 구성과 그에 따른 성능 최적화 방안을 고려해야 합니다.

 

또한, 자연어를 기반으로 쿼리를 생성하는 과정에서 프롬프트 템플릿을 구성할 때 자연어에 대한 구체적인 가이드를 작성하는 것이 중요합니다. 예를 들어, 질의문에 ‘트래픽’과 관련한 질의를 했을 경우, 실제 사용자의 의도는 ‘네트워크 로그의 수’와 관련한 내용이지만, LLM은 ‘로그의 용량’과 관련한 데이터를 찾는 등의 문제가 발생할 수 있습니다. 이러한 문제를 방지하기 위해 의미는 동일하지만 표현이 다른 단어들에 대한 명확한 지침을 마련하여 일관된 쿼리 생성을 도모해야 합니다.

 

마지막으로, LLM을 통해 결과를 출력할 때 설명이 함께 출력되거나 그렇지 않은 경우가 있어 출력 포맷이 항상 일관되지 않을 수 있습니다. 이를 해결하기 위해 다수의 테스트를 수행하여 출력 결과의 일관성을 확보하고, 분석 결과의 신뢰성을 높일 수 있습니다.

 

이러한 고려 사항들은 보안 전문가 및 AI/ML 전문가가 본 데모를 실제 운영 환경에 적용할 때 필수적으로 검토해야 할 요소들입니다. 이러한 요소들을 충분히 검토하고 반영하여 시스템을 고도화하면 보다 안정적이고 효율적인 보안 데이터 분석 환경을 구축할 수 있을 것입니다.

 

 

메가존클라우드와 함께하는 Amazon Security Lake with GenAI

 

 

이렇게 OCSF로 공통된 형식으로 통합하여 저장하는 Amazon Security Lake와 GenAI를 활용하면, 보안 로그 검색과 각 로그의 연관 관계 분석을 단일 프롬프트에서 진행할 수 있습니다. 이는 보안 담당자 및 데이터 사이언티스트들에게 많은 노력과 리소스를 절약할 수 있는 기회를 제공할 것입니다.

 

이 블로그가 보안 데이터 분석에 관심 있는 기술자 및 데이터 과학자들에게 유용한 정보를 제공하여 복잡한 보안 데이터셋에서도 유용한 인사이트를 추출하는 데 도움이 되기를 바랍니다. 메가존클라우드는 사용자들이 안전하고 효율적인 클라우드 환경을 구축할 수 있도록 지속적으로 연구하고 혁신할 것입니다.

 

메가존클라우드는 해당 데모 환경을 지속적으로 연구하고 개발하여 보안 위협을 효과적으로 탐지하고 대응할 수 있도록 고도화를 진행할 예정입니다.또한, 기업별 환경과 요구사항에 맞춘 세부적인 맞춤형 솔루션을 제공할 수 있도록 노력할 것입니다. Amazon Security Lake Service Partner로서 최고 수준의 서비스와 기술력을 제공하기 위해 최선을 다하고 있으며, Amazon Security Lake에 관심 있으신 고객분들께서는 언제든지 연락주시기 바랍니다.

 

 

📧Contact: megazonecloud-asl@mz.co.kr

 

 

 

[참고 자료]

[https://aws.amazon.com/ko/blogs/security/generate-ai-powered-insights-for-amazon-security-lake-using-amazon-sagemaker-studio-and-amazon-bedrock/] AWS Blog
[https://www.megazone.com/amazon_security_lake_231012/] AWS Service Partner 취득
[https://www.megazone.com/techblog_awssecuritylake_ocsfv1-1_240514/] OCSF 1.1 및 1.2 소개
[https://python.langchain.com/v0.2/docs/introduction/ ] LangChain

Written by 메가존클라우드 Cloud Technology Center