AWS 보안 그룹에 동적으로 IP를 등록하는 스크립트 예제

Jiyeon's TechNote·2025년 5월 21일
2

AWS 보안 그룹(Security Group)에 설정된 기존 IP 범위(OLD_PREFIX)를 기반으로 새로운 IP 범위(NEW_PREFIX)를 자동으로 추가하는 스크립트입니다.

핵심 목적
기존 IP가 111.222.333.N/32이면, 자동으로 110.220.330.N/32를 같은 규칙에 추가합니다.
단, 동일한 IP가 이미 등록되어 있으면 생략합니다.


#!/usr/bin/env python3

import argparse
import sys
import boto3
from botocore.exceptions import ClientError

def normalize(cidr):
    return cidr.split('/')[0]

def replicate_permission(sg_id, perm, old_prefix, new_prefix, ec2):
    proto = perm['IpProtocol']
    from_port = perm.get('FromPort')
    to_port   = perm.get('ToPort')
    existing = [normalize(r.get('CidrIp','')) for r in perm.get('IpRanges', [])]

    if any(ip.startswith(new_prefix + '.') for ip in existing):
        print(f"  [SKIP] SG {sg_id} {proto} {from_port}-{to_port}, new-prefix already present")
        return

    old_ips = [ip for ip in existing if ip.startswith(old_prefix + '.')]
    if not old_ips:
        return

    print(f"  [INFO] SG {sg_id} {proto} {from_port}-{to_port}: found old-prefix entries {old_ips}")
    for old_ip in old_ips:
        last = old_ip.split('.')[-1]
        new_ip = f"{new_prefix}.{last}"
        if new_ip in existing:
            print(f"    - skip {new_ip}/32, already exists")
            continue
        ip_perm = {
            'IpProtocol': proto,
            **({'FromPort': from_port, 'ToPort': to_port} if from_port is not None else {}),
            'IpRanges': [{'CidrIp': f"{new_ip}/32"}]
        }
        print(f"    + adding {new_ip}/32 ... ", end='')
        try:
            ec2.authorize_security_group_ingress(
                GroupId=sg_id,
                IpPermissions=[ip_perm]
            )
            print("OK")
        except ClientError as e:
            code = e.response['Error']['Code']
            if code == 'InvalidPermission.Duplicate':
                print("AlreadyExists")
            else:
                print(f"ERROR ({code})")

def main():
    parser = argparse.ArgumentParser(
        description="Replicate OLD_PREFIX→NEW_PREFIX CIDRs for all SGs in a region"
    )
    parser.add_argument('--old-prefix', required=True,
                        help="Old prefix, e.g. 111.222.333")
    parser.add_argument('--new-prefix', required=True,
                        help="New prefix, e.g. 110.220.330")
    parser.add_argument('--region', required=True,
                        help="AWS region, e.g. ap-northeast-2")
    parser.add_argument('--profile',
                        help="AWS CLI profile name")
    args = parser.parse_args()

    sess_kwargs = {'region_name': args.region}
    if args.profile:
        sess_kwargs['profile_name'] = args.profile
    session = boto3.Session(**sess_kwargs)
    ec2 = session.client('ec2')

    paginator = ec2.get_paginator('describe_security_groups')
    sg_ids = []
    for page in paginator.paginate():
        sg_ids += [sg['GroupId'] for sg in page['SecurityGroups']]
    print(f"[INFO] Found {len(sg_ids)} SGs in {args.region}")

    for sg_id in sg_ids:
        try:
            sg = ec2.describe_security_groups(GroupIds=[sg_id])['SecurityGroups'][0]
        except ClientError as e:
            print(f"[ERROR] describe SG {sg_id}: {e}", file=sys.stderr)
            continue
        perms = sg.get('IpPermissions', [])
        print(f"\n[PROCESS] SG {sg_id} ({len(perms)} permissions)")
        for perm in perms:
            replicate_permission(sg_id, perm, args.old_prefix, args.new_prefix, ec2)

if __name__ == '__main__':
    main()

사용 예시

python sg_replicate_by_prefix.py \
  --old-prefix 111.222.333 \
  --new-prefix 110.220.330 \
  --region ap-northeast-2 \
  --profile my-aws-profile

특정 리전에 존재하는 모든 보안 그룹에 IP를 자동으로 등록함으로써, 매번 수동으로 IP를 추가해야 하는 번거로움을 효과적으로 해소했습니다.

profile
바쁘다 바빠 현대사회 엔지니어🙋‍♀️

0개의 댓글