본문으로 건너뛰기
프로젝트 목록

PF-09 · AWS · Python

AWS 방화벽 요청 자동화

방화벽 요청이 이미 열려 있는지 먼저 확인하고, 막힌 것만 미리보기 뒤 적용하며, 실제 트래픽으로 검증하는 CLI입니다.

역할
설계 · 구현
기간
개인 프로젝트 · 2026.11 공개
CSP
AWS
규모
3단계 CLI · 입력 형식 4종 · 리소스 4종
핵심 기술
Python · boto3 · AWS · CloudWatch Logs · Athena · Excel
GitHub
3
단계: confirm, modify, flowlog
4
입력 형식
4
식별하는 리소스 종류

한눈에 보기

방화벽 요청출발지 · 목적지 · 포트netops confirmnetops modifynetops flowlog이미 열려 있는가막힌 흐름만 미리보기실제 트래픽으로 검증열림작업 불필요막힘다음 단계로미리보기영향받는 리소스와 규칙 출력--apply + apply 입력규칙 추가만트래픽 확인CloudWatch Logs · Athena변경은 기본으로 일어나지 않습니다
flowlog로 CloudWatch Logs나 Athena에서 실제 트래픽을 찾아 확인합니다.

문제

방화벽 요청은 이미 열린 통신을 다시 여는 경우가 많아 중복 규칙이 쌓였고, 어떤 리소스와 규칙이 걸리는지 계정마다 콘솔에서 찾아야 했습니다.

접근

netops confirm이 주소를 AWS 리소스로 식별하고 보안그룹 규칙과 라우트를 평가합니다. 막힌 통신만 modify로 넘겨 계획을 먼저 출력합니다. flowlog는 CloudWatch Logs나 Athena에서 실제 트래픽을 찾습니다.

결과

기본 실행은 아무것도 바꾸지 않습니다. 규칙 추가에는 --apply와 apply 입력이 필요하고, 규칙은 추가만 가능하며, 슬롯이 없는 보안그룹은 고르지 않습니다.

자세히 보기

주소IP · CIDR · IP 범위 ·RDS 주소리소스 식별EC2 · LB · RDS · ENI출발지 아웃바운드규칙 확인목적지 인바운드규칙 확인라우팅 확인목적지가 AWS 밖일 때판정: 불가 (Route needed)규칙 추가로 풀리지 않는 경우를 구분합니다규칙과 라우트를 함께 보아 불필요한 허용 규칙을 줄입니다
판정은 원인을 함께 남깁니다. Security group rule needed 또는 Route needed처럼 표시합니다.

규칙과 라우트로 판정

이 코드가 하는 일: 앞에서 평가한 보안그룹 규칙 중 하나라도 통과하지 못하면 판정을 실패로 바꾸고 “Security group rule needed”를 이유로 남깁니다. 출발지는 AWS 리소스인데 목적지가 AWS 밖이면, 출발지 서브넷의 라우트 테이블을 찾아 목적지로 가는 경로가 있는지 확인하고, 있으면 다음 홉을, 없으면 어느 테이블에 경로가 없는지를 기록합니다. 경로가 없을 때는 “Route needed”를 따로 남겨, 보안그룹을 열어도 해결되지 않는 경우를 구분합니다.

        if any(not c.ok for c in verdict.checks):
            verdict.ok = False
            verdict.issues.append("Security group rule needed")

        if source.resources and not target.resources:
            for resource in source.resources:
                ec2 = self.sessions.client("ec2", resource.account)
                result = route_analysis.evaluate(
                    route_analysis.find_table(ec2, resource.subnet_id, resource.vpc_id), dst
                )
                detail = (
                    f"via {route_analysis.next_hop(result.routes[0])}"
                    if result.ok
                    else f"no route in {result.table_id or 'any table'}"
                )
                verdict.checks.append(Check("route", resource.label, result.ok, detail))
                if not result.ok:
                    verdict.ok = False
                    verdict.issues.append("Route needed")
        return verdict

규칙 추가만 하는 적용

이 코드가 하는 일: 계획된 변경의 방향에 따라 인바운드 또는 아웃바운드 규칙 추가 API만 호출합니다. 규칙을 삭제하거나 고치는 호출은 없어서 이 도구가 기존 통신을 끊을 수 없습니다. 같은 규칙이 이미 있어 AWS가 InvalidPermission.Duplicate 오류를 돌려주면 “already present”로 처리하고 넘어가며, 그 밖의 오류는 숨기지 않고 그대로 올립니다.

    def apply(self, change: Change) -> str:
        ec2 = self.sessions.client("ec2", change.account)
        call = (
            ec2.authorize_security_group_ingress
            if change.direction == "ingress"
            else ec2.authorize_security_group_egress
        )
        try:
            call(GroupId=change.sg_id, IpPermissions=change.permissions)
        except ClientError as error:
            if error.response["Error"]["Code"] == "InvalidPermission.Duplicate":
                return "already present"
            raise
        return "applied"

배운 점

변경 도구에서는 안전한 동작이 플래그 없이 되는 기본값이어야 한다는 점을 배웠습니다. --dry-run 방식은 누군가 한 번 깜빡하면 바로 실제 변경이 일어나지만, 기본 실행이 아무것도 바꾸지 않고 --apply와 apply 입력이 둘 다 있어야 적용되면 실수가 변경으로 이어지지 않습니다. 변경 범위를 규칙 추가로만 좁힌 것도 같은 이유입니다. 할 수 있는 일을 줄이면 잘못됐을 때의 피해도 줄어듭니다. 또 요청을 받자마자 규칙을 여는 대신 이미 열려 있는지부터 확인하고, 막혔다면 규칙 때문인지 경로 때문인지 이유를 나눠 남기니, 중복 규칙이 쌓이지 않고 실제로 필요한 조치만 남았습니다.

관련 현장 노트

Open to work · 클라우드 인프라/보안

테마 고르기

사원증을 누르면 그 테마로, 보던 내용과 같은 곳으로 이동합니다. 끌면 흔들리기만 합니다.

처음 화면으로 →