AWS re:Post을(를) 사용하면 다음에 동의하게 됩니다. AWS re:Post 이용 약관

Lambda 함수를 활용하여 외부 API나 서비스의 IP 변경에 대한 Security Group의 Outbound Rule 관리를 자동화 하는 방안

6분 분량
콘텐츠 수준: 기초
2

Lambda 함수를 활용하여 외부 API나 서비스의 IP 변경에 대한 Security Group의 Outbound Rule 관리를 자동화하여 보안 규정 준수 및 운영 효율성 향상을 하는 방안을 알아봅니다.

VPC 내부의 리소스가 외부 API나 서비스와 통신해야 하는 경우, 보안을 위해 Security Group의 아웃바운드 규칙을 특정 IP로 제한해야 할 수 있습니다. 문제는 Security Group에서 도메인 기반의 규칙을 설정할 수 없다는 점입니다. 따라서 외부 서비스의 도메인 주소는 그대로더라도 실제 IP 주소가 주기적으로 변경되는 경우, Security Group의 아웃바운드 규칙도 이에 맞춰 계속해서 업데이트해야 하는 번거로움이 있습니다.

만약 Security Group의 아웃바운드 규칙 업데이트를 매번 수동으로 진행하면 여러 가지 문제가 발생할 수 있습니다. 담당자가 지속적으로 IP 변경 여부를 모니터링해야 하고, 변경 사항 적용이 지연되어 서비스가 중단될 위험이 있으며, 수동 작업 중 설정 오류가 발생할 가능성도 있습니다. 이러한 운영상의 어려움을 해결하기 위해서는 자동화된 방식이 필요합니다.

Lambda 함수를 활용하면 이러한 IP 관리 프로세스를 자동화할 수 있습니다. Lambda 함수가 주기적으로 실행되면서 외부 서비스의 IP 변경 여부를 확인하고, 변경사항이 있을 경우 자동으로 Security Group을 업데이트하도록 구성할 수 있습니다. 이때 일반적으로는 Security Group을 직접 업데이트하는 방식을 사용하지만, 이 문서에서는 더 효율적인 방식인 고객 관리형 Prefix List를 사용하도록 하겠습니다.

Prefix List는 IP 주소 목록을 중앙에서 관리할 수 있게 해주는 서비스로, 하나의 Prefix List에 IP 주소 리스트를 등록하고, Security Group Rule에서 IP 주소를 직접 지정하는 대신, Prefix List를 참조하는 방식으로 동작합니다. 이 방식을 사용하면 중앙 집중식 IP 주소 관리로 인해 IP 주소 관리가 간소화 될 뿐 아니라, 하나의 Prefix List를 여러 Security Group에서 동시에 참조할 수 있어 재사용성이 높아집니다. 결과적으로 전체적인 관리 효율성이 향상됩니다.

아키텍쳐

여기에 이미지 설명 입력

세부 절차

이러한 자동화된 솔루션을 구현하는 방안을 단계별로 살펴보겠습니다.

Step1. 고객관리형 Prefix List 생성

  1. AWS Management Console에 로그인한 뒤, VPC > Managed Prefix Lists에 접속합니다. Create managed prefix list 버튼을 클릭합니다. 여기에 이미지 설명 입력

  2. 기본 정보를 입력합니다.

  • Prefix list name: 적절한 Prefix List 이름을 입력합니다. Prefix List 이름을 "com.amazonaws., com.amazon., com.aws."로는 시작할 수 없는 제약조건이 있음을 유의하십시오. 예를 들어, 쿼리하려 하는 Domain 이름이 "route53.amazonaws.com" 일 경우, "com.global.route53"과 같이 설정할 수 있습니다.
  • Max entries: 적절한 크기의 최대 항목수를 지정합니다. 예상 가능한 크기보다 더 여유롭게 설정합니다.
  • Prefix list entries: 여기서는 Entry를 설정하지 않습니다. 여기에 이미지 설명 입력 Create prefix list 버튼을 눌러 Prefix list를 생성합니다.
  1. 생성된 Prefix list ID를 기록해 놓습니다.

Step2. Lambda 함수 생성

  1. Lambda > Functions에 접속합니다. Create function 버튼을 클릭합니다. 여기에 이미지 설명 입력

  2. 기본 정보를 입력합니다.

  • Function name: 적절한 Function 이름을 입력합니다. (예> update-managed-prefix-list-entry)
  • Runtime: Latest Support Python Version (예> Python 3.13)
  • Permissions: 권한으로는 "Create a new role with basic Lambda permissions" 혹은 "Use an existing role"을 선택합니다. "Use an existing role"을 선택한 경우 사전에 Lambda 실행 역할을 생성해 놓아야 합니다. 여기에 이미지 설명 입력 Create function 버튼을 눌러 Function을 생성합니다.
  1. Code 탭 > Code source 에디터에서 lambda_function.py에 다음의 코드를 붙여넣은 뒤, Deploy 버튼을 클릭하여 배포합니다.

    import socket
    import boto3
    import os
    import logging
    from datetime import datetime
    
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    
    def get_prefix_list_version(prefix_list_id):
        ec2 = boto3.client("ec2")
    
        try:
            prefix_list = ec2.describe_managed_prefix_lists(PrefixListIds=[prefix_list_id])["PrefixLists"][0]
            prefix_list_version = prefix_list["Version"]
            logger.info(f"Retrieved prefix list version: {prefix_list_version}")
            return prefix_list_version
        except Exception as e:
            logger.error(f"Failed to retrieve prefix list: {e}")
            raise
    
    
    def get_current_cidrs(prefix_list_id):
        ec2 = boto3.client("ec2")
    
        try:
            current_entries = ec2.get_managed_prefix_list_entries(PrefixListId=prefix_list_id, MaxResults=100)["Entries"]
            current_cidrs = {entry["Cidr"] for entry in current_entries}
            logger.info(f"Current CIDR list: {current_cidrs}")
            return current_cidrs
        except Exception as e:
            logger.error(f"Failed to retrieve current CIDR list: {e}")
            raise
    
    
    def get_new_cidrs(domain):
        try:
            ip_addresses = [ip for ip in socket.gethostbyname_ex(domain)[2] if ":" not in ip]
            new_cidrs = {f"{ip}/32" for ip in ip_addresses}
            logger.info(f"New CIDR list: {new_cidrs}")
            return new_cidrs
        except Exception as e:
            logger.error(f"Failed to resolve domain IP addresses: {e}")
            raise
    
    
    def update_prefix_list(prefix_list_id, prefix_list_version, current_cidrs, new_cidrs):
        ec2 = boto3.client("ec2")
    
        try:
            if sorted(current_cidrs) == sorted(new_cidrs):
                logger.info("No changes detected")
                return
    
            iso_date = datetime.now().isoformat()
    
            addEntries = [{"Cidr": cidr, "Description": f"Automated update by Lambda: {iso_date}"} for cidr in (new_cidrs - current_cidrs)]
            logger.info(f"CIDR entries to add: {addEntries}")
            removeEntries = [{"Cidr": cidr} for cidr in (current_cidrs - new_cidrs)]
            logger.info(f"CIDR entries to remove: {removeEntries}")
    
            ec2.modify_managed_prefix_list(
                PrefixListId=prefix_list_id,
                CurrentVersion=prefix_list_version,
                AddEntries=addEntries,
                RemoveEntries=removeEntries,
            )
            logger.info(f"Successfully updated prefix list: {prefix_list_id}")
        except Exception as e:
            logger.error(f"Failed to update prefix list: {e}")
            raise
    
    
    def lambda_handler(event, context):
        try:
            prefix_list_id = os.environ["PREFIX_LIST_ID"]
            domain = os.environ["TARGET_DOMAIN"]
    
            prefix_list_version = get_prefix_list_version(prefix_list_id)
    
            current_cidrs = get_current_cidrs(prefix_list_id)
            new_cidrs = get_new_cidrs(domain)
    
            update_prefix_list(prefix_list_id, prefix_list_version, current_cidrs, new_cidrs)
            return {"statusCode": 200, "message": "Lambda execution succeeded"}
    
        except Exception as e:
            logger.error(f"Lambda execution failed: {e}")
            return {"statusCode": 500, "error": str(e)}

    여기에 이미지 설명 입력

  2. Configurations 탭 > General configuration에서 Edit 버튼을 클릭한 뒤, timeout을 20초로 조정합니다. 여기에 이미지 설명 입력 여기에 이미지 설명 입력

  3. Configurations 탭 > Environment variables에서 Edit 버튼을 클릭한 뒤, 다음 환경변수를 추가합니다.

  • PREFIX_LIST_ID: Step1에서 생성한 Prefix List의 ID입니다.
  • TARGET_DOMAIN: IP를 쿼리하려하는 Domain 이름입니다. 본 기사에서는 "route53.amazonaws.com"을 사용합니다. 여기에 이미지 설명 입력 여기에 이미지 설명 입력
  1. Lambda 실행 역할에 적절한 권한을 추가해야합니다. 역할 이름은 Configurations 탭 > Permissions 에서 확인할 수 있습니다. 여기에 이미지 설명 입력 해당 IAM Role이름을 클릭하면 IAM Role 상세 화면에 이동합니다. 연결된 Policy의 Edit 버튼을 클릭하여 다음의 Action을 Allow로 추가하여야 합니다.
  • ec2:GetManagedPrefixListEntries
  • ec2:ModifyManagedPrefixList
  • ec2:DescribeManagedPrefixLists 여기에 이미지 설명 입력 여기에 이미지 설명 입력
  1. Test 탭 > Test 버튼을 눌러 테스트를 실행합니다. 여기에 이미지 설명 입력 {"statusCode": 200,"message": "Lambda execution succeeded"} 메시지가 표시되면 정상적으로 실행이 완료된 것입니다. 상세 Log output을 확인하십시오. 여기에 이미지 설명 입력

  2. VPC > Managed Prefix Lists 화면에서 Prefix List를 선택한뒤 Entry가 업데이트 되었는지 확인합니다. 여기에 이미지 설명 입력

Step3. EventBridge Scheduler를 이용하여 Lambda 함수 호출 자동화

  1. EventBridge > Scheduler > Schedules에 접속합니다. Create schedule 버튼을 클릭합니다. 여기에 이미지 설명 입력

  2. 기본 정보를 입력합니다.

  • Schedule name: 적절한 Schedule Name을 입력합니다 (예> execute-update-managed-prefix-list-entry-function)
  • Occurrence: Recurring schedule
  • Schedule type: Rate-based schedule
  • Rate expression: 적절한 주기를 선택합니다 (예> 5 minutes)
  • Flexible time window: off 여기에 이미지 설명 입력 Next버튼을 눌러 다음 페이지로 이동합니다.
  1. Target을 설정합니다.
  • Target API: AWS Lambda Invoke
  • Lambda function: update-managed-prefix-list-entry 여기에 이미지 설명 입력 Next버튼을 눌러 다음 페이지로 이동합니다.
  1. 나머지는 기본값으로 두고 Schedule 생성을 마무리합니다.

  2. 설정한 주기 별로 Lambda 함수가 잘 실행되는지 확인합니다.

Step4. SecurityGroup의 Outbound Rule에 Prefix List를 설정합니다.

  1. VPC > Security groups에 접속합니다. Outbound rule을 적용할 Security group을 선택하고, Outbound rules 탭에서 Edit outbound rules 버튼을 클릭합니다. 여기에 이미지 설명 입력

  2. Step1에서 생성한 Managed Prefix List를 대상으로 하는 Rule을 생성합니다. 여기에 이미지 설명 입력

  3. 마지막으로, 본 SecurityGroup을 이용한 VPC 내부 리소스에서 Outbound 통신이 정상적으로 이루어지는지 확인합니다.

결론

지금까지 Lambda 함수를 활용하여 외부 API나 서비스의 IP 변경에 대한 Security Group의 Outbound Rule 관리를 자동화 하는 방안에 대해 알아보았습니다. 이러한 자동화 구현을 통해 보안 규정을 준수 하면서도 운영 효율성을 높일 수 있으며, 향후 다양한 외부 서비스들이 추가 되더라도 동일한 패턴을 적용하여 확장할 수 있어, 클라우드 환경에서의 네트워크 보안 관리를 보다 체계적으로 수행할 수 있을 것으로 기대합니다.

댓글 없음

관련 콘텐츠