Sentry의 AI Agent Monitoring을 통해 5개 에이전트로 구성된 AWS 보안 스캐너의 토큰 폭발 현상을 포착하다
요약
CrewAI와 Amazon Bedrock Nova Pro를 활용하여 AWS 보안 설정을 스캔하는 5개의 전문 AI 에이전트 시스템을 구축한 사례입니다. Sentry의 AI Agent Monitoring을 통해 멀티 에이전트 환경에서 발생하는 토큰 폭발 현상을 포착하고 계측하는 방법을 다룹니다.
핵심 포인트
- CrewAI 기반의 5개 전문 에이전트로 AWS 보안 태세 자동화
- Amazon Bedrock Nova Pro를 LLM으로 사용하여 보안 스캔 수행
- Sentry를 활용한 멀티 에이전트 시스템의 토큰 사용량 및 성능 모니터링
- 실제 AWS 리소스를 대상으로 한 CIS 벤치마크 매핑 및 위험 점수 산정
이 게시물은 Sentry가 지원하는 DEV's Summer Bug Smash: Clear the Lineup에 제출된 것입니다.
프로젝트 개요
저는 **AWS 보안 태세 에이전트 (AWS Security Posture Agent)**를 구축했습니다. 이는 보안 설정 오류를 스캔하고, 발견된 사항을 CIS 벤치마크에 매핑하며, 위험 점수를 산정하고, 복사하여 붙여넣을 수 있는 수정 명령어를 생성하는 5개의 전문 AI 에이전트입니다.
이 에이전트들은 Amazon Bedrock Nova Pro를 LLM (Large Language Model)으로 사용하여 CrewAI 위에서 순차적으로 실행됩니다:
1. ResourceDiscovery → EC2, S3, Lambda, IAM, SG, API GW, DynamoDB 인벤토리 작성
2. SecurityScanner → 열린 포트, 퍼블릭 버킷, 관리자 역할, 보안에 취약한 설정 탐색
3. ComplianceChecker → CIS AWS Foundations Benchmark에 매핑
...
각 에이전트는 90개의 IAM 역할, 14개의 S3 버킷, 9개의 보안 그룹(Security Groups), 7개의 Lambda 함수가 있는 실제 계정을 대상으로 실제 AWS API 호출을 수행하는 커스텀 boto3 도구를 가지고 있습니다. 테스트 데이터가 아닌 실제 탐지 결과입니다.
GitHub logo simplynadaf / aws-security-posture-agent
CrewAI + Amazon Bedrock을 사용하여 AWS 계정의 보안 설정 오류를 스캔하고, Sentry AI Agent Monitoring으로 계측된 멀티 에이전트 AI 시스템입니다. 5개의 전문 에이전트가 리소스를 발견하고, 보안을 분석하며, CIS 벤치마크에 매핑하고, 위험 점수를 산정하며, 수정 명령어를 생성합니다.
AWS Security Posture Agent
5개의 AI 에이전트가 AWS 계정을 스캔합니다. 설정 오류를 찾고, 위험 점수를 매기며, 수정 명령어를 받으세요.
빠른 시작 (Quick Start) | 아키텍처 (Architecture) | 스크린샷 (Screenshots) | 성능 수정 (Performance Fix)
문제 (The Problem)
대부분의 AWS 계정은 보안 부채 (security debt)를 조용히 쌓아갑니다. 테스트를 위해 열어둔 SSH 포트, 암호화되지 않은 S3 버킷, 아무도 생성한 기억이 없는 전체 관리자 권한 (full admin access)의 IAM 역할 등이 그것입니다. 수동 감사 (manual audits)는 놓치는 부분이 생기기 마련이며, AWS Config 규칙은 비용이 발생합니다. SecurityHub는 너무 많은 알림 (noisy)을 보냅니다.
이 에이전트는 60초 내에 귀하의 계정을 스캔하여 실제 문제를 찾아내고, 이를 CIS 벤치마크 (CIS benchmarks)에 매핑하며, 위험 점수를 산출하고, 각 문제를 해결하기 위한 정확한 AWS CLI 명령어를 제공합니다.
탐지 내용 (What It Finds)
실제 AWS 계정 (90개의 IAM 역할, 14개의 S3 버킷, 9개의 보안 그룹, 7개의 Lambda 함수)에서 실행한 결과:
97개의 보안 탐지 결과 (security findings)
├── CRITICAL: 0.0.0.0/0으로부터의 개방된 SSH/RDP, MFA가 없는 IAM 사용자
├── HIGH: 관리자 역할 (admin roles), 암호화되지 않은 EBS, 퍼블릭 액세스 차단 누락
...
…
데모 (Demo)
제 AWS 계정을 대상으로 실행 중인 전체 스캔 영상입니다. 스캔 부분은 4배속으로 재생되었으며, 결과 설명 부분은 정상 속도입니다:
버그 수정 또는 성능 개선 (Bug Fix or Performance Improvement)
SecurityScanner 에이전트는 다른 모든 에이전트가 평균 5~10초가 걸리는 동안 22.6초가 소요되었습니다. 각 에이전트의 실행 내부에서 어떤 일이 일어나고 있는지에 대한 가시성 (visibility)이 없었다면, 저는 Bedrock의 지연 시간 (latency) 탓으로 돌리고 그냥 넘어갔을 것입니다.
근본 원인: 제가 만든 IAMAnalyzer 도구가 계정에서 90개의 모든 IAM 역할(서비스 연결 역할(service-linked roles)을 필터링한 후 59개)을 가져와서, 이를 27KB 크기의 JSON 블롭 (JSON blob)으로 직렬화(serializing)한 뒤, 그 전체 페이로드 (payload)를 도구 출력값으로서 LLM에 전달하고 있었습니다. 이로 인해 컨텍스트 윈도우 (context window)가 과부하되었습니다. CrewAI의 내부 재시도 로직 (retry logic)이 작동하면서, 훨씬 더 많은 컨텍스트를 포함한 두 번째 시도에서 토큰을 낭비하게 되었습니다.
도구 하나. 잘못된 기본값. 파이프라인 전체가 고통받았습니다.
코드 (Code)
수정 사항이 포함된 PR:
GitHub logo fix: IAM 분석 페이지네이션 적용 및 토큰 예산 가드 추가 #1
**simplynadaf**가 2026년 7월 20일에 게시함
원인 (What)
IAMAnalyzer 도구가 계정 내의 모든 역할(Role)을 하나씩 가져오고 있었으며(총 90개, 서비스 연결 역할(service-linked roles) 필터링 후 59개), 그 전체 상세 정보를 단일 JSON 블롭(blob)에 쏟아부었습니다. 이 블롭의 크기는 26,980자에 달했습니다. LLM이 이를 처리하지 못해 과부하(choke)가 걸렸고, CrewAI는 작업을 재시도했으며, 결과적으로 SecurityScanner 에이전트가 실행되는 동안 다른 모든 에이전트가 5~10초 내에 완료된 반면 이 에이전트는 22.6초가 소요되었습니다.
발견 방법 (How I found it)
각 에이전트와 도구에 Sentry 스팬(span)을 추가했습니다. 트레이스 워터폴(trace waterfall)을 통해 원인이 명확히 드러났습니다. SecurityScanner가 다른 모든 것보다 두 배나 넓었습니다. 도구 스팬(tool spans)을 상세 분석한 결과, 다른 도구들이 약 4,000자인 것에 비해 iam_analyzer의 result_length_chars는 26,980으로 나타났습니다.
출력량이 7배나 불균형했습니다. 그것이 문제였습니다.
변경 사항 (What I changed)
iam_analyzer.py에서 세 가지를 변경했습니다:
- 역할을 페이지네이션(paginate)하고
RoleLastUsed날짜별로 정렬하여, 가장 활발하게 사용되는 상위 20개 역할만 분석하도록 했습니다. 나머지는 몇 달 동안 아무도 건드리지 않은 오래된 역할들입니다. - 31개의 서비스 연결 역할(service-linked roles)을 사전에 건너뜁니다 (어차피 수정할 수 없으며, 이를 감사하는 것은 노이즈에 불과합니다).
- 마지막에 토큰 예산 가드(Token budget guard)를 추가했습니다: JSON 출력이 4,000자를 초과하면
role_summary를 이름과 정책 목록(policy lists)만 남기고 축소(trim)합니다.
수치 (Numbers)
- 도구 출력: 26,980자에서 15,532자로 감소 (42% 감소)
- SecurityScanner: 22.6초에서 17.8초로 감소 (21% 빨라짐, 더 이상의 LLM 재시도 없음)
- IAM API 호출: 59회에서 20회로 감소
- 전체 파이프라인: 62초에서 57.7초로 감소
- 탐지 결과(Findings): 여전히 27개. 상위 20개의 가장 활발한 역할에 모든 문제적 역할(AdminRole, Bedrock-Lambda-Role 등 모두 활발히 사용됨)이 포함되어 있으므로 탐지 범위(coverage) 손실은 없습니다.
핵심적인 변경 사항은 src/security_posture/tools/iam_analyzer.py에 있습니다. 변경 전후를 비교하면 다음과 같습니다.
변경 전 (버그 발생):
# 페이지네이션 제한 없이 모든 역할을 가져옴
roles = iam.list_roles(MaxItems=100)
role_details = []
...
이 코드는 90개의 역할(role)이 있는 계정에 대해 26,980자의 JSON을 생성합니다. LLM은 이를 처리하지 못하고 막혀버립니다.
변경 후 (수정 완료):
# 수정: 페이지네이션을 적용하고 관련성 순으로 정렬
all_roles = []
paginator = iam.get_paginator("list_roles")
...
여기에 마지막으로 토큰 예산 가드(token budget guard)를 추가했습니다:
# 토큰 예산 가드: 출력이 임계값을 초과하면 잘라냄
if len(output) > 4000:
result["role_summary"] = [
...
세 가지 변경 사항이 적용되었습니다. 페이지네이션 (Pagination), 관련성 정렬 (relevance sorting), 그리고 안전 밸브 (safety valve)입니다. 이로 인해 SecurityScanner가 재시도를 멈췄습니다.
나의 개선 사항
수정 자체는 간단합니다. 흥미로운 부분은 제가 이를 어떻게 찾아냈는가 하는 점입니다.
Sentry의 트레이스 폭포수 (trace waterfall)가 없었다면, 제가 볼 수 있었던 것은 그저 "파이프라인이 62초 걸린다"는 사실뿐이었을 것입니다. 아마도 Python 코드를 프로파일링하거나, 각 에이전트 주변에 time.time() 호출을 추가했을지도 모릅니다. 솔직히 말해서 저의 첫 번째 본능은 Bedrock의 지연 시간 (latency)을 탓하는 것이었습니다. 무언가 느려질 때마다 LLM을 탓하게 되곤 하니까요, 그렇지 않나요? 하지만 트레이스는 다른 사실을 말해주고 있었습니다. 진짜 문제는 Python의 실행 시간이 아니었습니다. LLM이 첫 번째 시도에서 깔끔하게 처리할 수 없는 컨텍스트 페이로드 (context payload)를 전달받은 것이 문제였습니다.
접근 방식은 다음과 같습니다:
- 각 에이전트 실행을
gen_ai.invoke_agent스팬 (span)으로 감쌉니다. - 각 도구 호출 (tool call)을
gen_ai.execute_tool스팬으로 감쌉니다. - 파이프라인을 실행하고 트레이스 폭포수 (trace waterfall)를 살펴봅니다.
- SecurityScanner 스팬이 시각적으로 확연히 드러났습니다. 다른 모든 것보다 두 배나 넓었습니다.
- 그 내부의
iam_analyzer도구 스팬은 26,980자의result_length_chars를 보여주었습니다. - 이를 4,200자의
security_group_analyzer및 3,800자의s3_config_checker와 비교했습니다.
이 불균형이 결정적인 단서였습니다. 수정은 자연스럽게 이어졌습니다. 도구의 출력이 다른 형제 도구들보다 7배나 크다면, 이를 줄여야 합니다.
결과:
| 지표 (Metric) | 이전 (Before) | 이후 (After) | 개선 사항 (Improvement) |
|---|---|---|---|
| IAM 도구 출력 (IAM tool output) | 26,980 자 | 15,532 자 | 42% 감소 |
| ... | |||
| SecurityScanner의 21% 개선은 LLM이 재시도하는 대신 단 한 번의 패스 (single pass)로 분석을 완료한 덕분이었습니다. |
Sentry의 최적 활용법
저는 Sentry의 AI Agent Monitoring을 사용하여 CrewAI 멀티 에이전트 파이프라인을 처음부터 계측 (instrument)했습니다. 이것은 웹 앱이나 API가 아닙니다. LLM 호출을 수행하고 커스텀 도구 (custom tools)를 실행하는 5개의 자율 AI 에이전트입니다. 표준 APM (Application Performance Monitoring)으로는 여기서 도움을 받을 수 없습니다.
계측한 내용
모든 파이프라인 실행은 다음과 같은 스팬 (span) 계층 구조를 가진 Sentry 트랜잭션 (transaction)을 생성합니다:
Transaction: "Security Posture Scan" (57s)
├── gen_ai.invoke_agent: ResourceDiscovery
│ └── gen_ai.execute_tool: aws_resource_scanner
...
계측 코드
각 에이전트별 (main.py 내):
with start_span(
op="gen_ai.invoke_agent",
name=f"invoke_agent {agent_name}",
...
각 도구별 (monitoring.py 내 데코레이터):
def trace_tool(tool_name: str):
def decorator(func):
@functools.wraps(func)
...
사용된 Sentry 기능
| 기능 (Feature) | 활용 방법 |
|---|---|
| 분산 트레이싱 (Distributed Tracing) | 시작부터 최종 보고서까지의 전체 파이프라인 트레이스 |
| ... |
Sentry가 밝혀낸 것
트레이스 워터폴 (trace waterfall)을 통해 병목 현상이 시각적으로 명확하게 드러났습니다. SecurityScanner 스팬은 다른 에이전트들의 평균이 510초인 반면, 거의 두 배에 달하는 22.6초를 차지했습니다. 그 내부를 살펴보면, 4,200을 보여주었습니다. 이러한 세분화 (granularity)는 개별 boto3 호출 수준까지 내려가며, 모든 s3 get_public_access_block (호출당 206ms × 14개 버킷)과 같은 개별 AWS API 호출과 iam_analyzer 도구 스팬은 result_length_chars: 26980을 보여준 반면, s3_config_checker와 같은 다른 도구들은 3,800GetPublicAccessBlock, ListRoles, ListAttachedRolePolicies가 각각의 독립된 스팬으로 나타납니다.


수정 후에는 모든 에이전트 스팬(agent spans)이 실제 작업 복잡도에 비례하게 나타납니다. 어느 하나의 에이전트가 트레이스(trace)를 지배하지 않습니다. iam_analyzer의 출력은 26,980자에서 15,532자로 감소했으며, SecurityScanner는 첫 번째 패스에서 재시도 로직(retry logic)을 트리거하는 것을 중단했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기