테라폼 운영 강좌 #4 보안·비용 스캔: trivy, checkov, Infracost로 PR 가드레일

4 분 소요

#3까지의 검사는 코드가 올바른가를 봤습니다. 이번 편의 두 검사는 다른 질문을 던집니다. 안전한가, 그리고 얼마인가. 보안 그룹을 인터넷에 활짝 여는 코드도, 월 수백 달러짜리 인스턴스를 올리는 코드도 문법적으로는 완벽하기 때문에 지금까지의 검사를 전부 통과합니다. 이 두 종류의 사고를 PR 단계에서 잡는 것이 이번 편의 목표입니다.

보안 정적 분석: trivy와 checkov #

IaC 보안 스캐너는 리소스 설정을 알려진 위험 패턴과 대조합니다. 대표 도구는 둘입니다.

  • trivy: 컨테이너 스캐너로 유명한 Aqua의 통합 도구입니다. 테라폼 전용이던 tfsec이 trivy로 통합되어, 검색에서 tfsec 자료를 만나면 “지금은 trivy"로 읽으면 됩니다.
  • checkov: Prisma Cloud(Palo Alto) 계열의 스캐너로, 룰 수가 많고 컴플라이언스 프레임워크 매핑이 강합니다.

어느 쪽이든 하나면 충분하고, 실습에서는 설치가 가벼운 trivy로 갑니다. 실전 시리즈의 코드에 돌려 봅니다.

스캔 실행
$ trivy config envs/dev
HIGH: S3 bucket does not have logging enabled
MEDIUM: Instance metadata service v1 is enabled
...

멀쩡히 동작하던 코드에서도 지적이 나옵니다. 스캐너 지적은 세 부류로 나눠 처리합니다. 실제 위험(고치면 됩니다), 알고 받아들인 위험(예외 처리), 우리 상황에 안 맞는 룰(룰 비활성화)입니다. 중요한 것은 두 번째의 처리 방식입니다.

main.tf
#trivy:ignore:AVD-AWS-0089 -- 실습 환경이라 액세스 로그 버킷 미구성. prod 전환 시 활성화
resource "aws_s3_bucket" "assets" {
  # ...
}

예외는 범위를 그 리소스로 좁히고, 이유를 주석으로 남깁니다. 이유 없는 ignore가 쌓인 코드는 스캐너를 끈 것과 같아지고, 이유가 있으면 예외 자체가 리뷰 대상이 됩니다. checkov도 #checkov:skip 주석으로 같은 방식을 지원합니다.

CI에 얹기 #

PR 워크플로(#1)에 스텝 하나를 추가합니다.

.github/workflows/terraform-plan.yml
      - name: trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: config
          scan-ref: envs/dev
          exit-code: "1"
          severity: CRITICAL,HIGH

severity 조절이 운영 요령입니다. 처음부터 MEDIUM까지 실패 처리하면 기존 코드의 지적이 쏟아져 팀이 스캐너를 원망하게 됩니다. CRITICAL·HIGH만 차단으로 시작하고, 기존 지적을 정리해 가며 기준을 올리는 점진 도입이 안착률이 높습니다.

Infracost: PR에 가격표 붙이기 #

비용 사고의 구조적 원인은 비용이 보이는 시점입니다. 코드를 리뷰할 때는 안 보이고 월말 청구서에서 보입니다. 실전 #2의 NAT 개수, 실전 #5의 인스턴스 클래스 같은 결정이 전부 비용 결정이었는데, 리뷰어가 그 금액을 암산할 수는 없습니다. Infracost는 plan 결과에 단가표를 곱해 PR에 코멘트로 붙여 주는 도구입니다.

코멘트 예시
Infracost 코멘트 예시:
  aws_db_instance.main
    ~ instance_class: db.t4g.micro → db.r6g.large
  Monthly cost change: +$210 (총 $XX → $XX)

인스턴스 클래스 한 줄 변경이 “+$210/월"로 보이는 순간, 비용 리뷰가 청구서 단계에서 PR 단계로 당겨집니다. CI 연동은 공식 액션(infracost/actions)으로 붙이며, 무료 티어로 시작할 수 있습니다(요금 정책은 도입 시점에 확인하는 것을 권합니다). 절대 금액이 완벽하지는 않아도(트래픽 종량 요금 등은 추정 한계), 변경의 방향과 규모를 보는 데는 충분합니다.

태그: 사후 추적의 기반 #

PR 가드레일이 사전 방어라면 사후 추적의 기반은 태그입니다. 실전 #1에서 default_tags로 모든 리소스에 Project와 Env를 걸어 둔 덕분에, 비용 탐색기에서 태그 기준으로 “myapp의 dev가 얼마"를 바로 답할 수 있습니다. 스캐너 룰 중에 태그 필수화 룰을 켜 두면 태그 누락도 PR에서 걸립니다. 이미 낭비가 의심되는 계정이라면 AWS 비용 낭비 체크리스트의 점검 항목과 병행하면 됩니다.

정리 #

이번 글에서 다룬 내용입니다.

  • 보안 스캐너는 trivy(tfsec 통합) 또는 checkov 하나면 충분합니다. 문법이 완벽한 위험 설정을 알려진 패턴 대조로 잡습니다
  • 예외 처리는 리소스 단위로 좁히고 이유를 주석으로 남깁니다. 이유 없는 ignore의 축적은 스캐너를 끈 것과 같습니다
  • CI 차단 기준은 CRITICAL·HIGH부터 시작해 점진적으로 올립니다
  • Infracost는 PR에 월 비용 변화를 코멘트로 붙여, 비용 리뷰를 청구서에서 PR로 당깁니다
  • default_tags 기반 태그가 사후 비용 추적의 축이며, 태그 필수화 룰로 누락도 막습니다

다음 글(#5 대규모 구조화)에서는 코드와 팀이 커질 때의 구조를 다룹니다. state를 스택으로 나누는 기준, 스택 간 참조, 그리고 Terragrunt가 필요해지는 시점입니다.

X