Browsing Tag

ACG

NCLOUD

[NCLOUD] ACG Backup – Access Control Group 정책 CSV로 내보내기

안녕하세요 MANVSCLOUD 김수현입니다.

네이버 클라우드 플랫폼에서 Access Control Group(ACG) 정책을 CSV 파일로 내보내는 것이 가능할까요?
가능은 합니다만 현재 네이버 클라우드 플랫폼 서비스에서는 따로 지원하고 있지 않은 기능입니다.

이러한 기능이 있다면 각 ACG의 INBOUND, OUTBOUND 정책을 모아서 볼 수 있고 특정 VPC 환경을 다른 계정으로 마이그레이션할 때도 활용할 수 있습니다.
AWS의 보안 그룹에서는 이러한 [CSV로 내보내기] 기능을 따로 지원하고 있는데요.

이 글을 통해 네이버 클라우드 플랫폼에서 Access Control Group(ACG)을 CSV 파일로 내보내는 방법뿐만 아니라 Object Storage에 정기적으로 백업하는 방법까지 알 수 있습니다.


ACG Backup (feat. 없으면 만들어야지)

네이버 클라우드 플랫폼에서 CSV 파일로 ACG 정책을 내보내는 기능은 기본적으로 제공되지 않지만 API를 활용하여 직접 구현할 수 있습니다.

① Cloud Functions을 이용하여 ACG 리스트를 조회하고 ② 조회된 ACG의 Inbound 및 Outbound 정책을 파악하여 ③ CSV 파일로 생성합니다. ④ 이후 생성된 CSV 파일은 Object Storage로 업로드하고 ⑤ Object Storage의 정책에 따라 삭제되거나 Archive Storage로 이동되도록 설정합니다.

Cloud Functions에서 CSV 파일 생성 시에는 io.StringIO 또는 io.BytesIO를 사용하여 메모리에 파일 객체를 생성할 것입니다. 이를 통해 로컬에 CSV 파일을 생성하지 않고 메모리에서 바로 오브젝트 스토리지로 업로드 될 수 있도록 구현해보겠습니다.


A to Z

# VPC, Server 생성에 대한 가이드는 생략합니다.
# Python은 3.7 버전이 사용되었습니다.

Cloud Functions에서는 Boto3 라이브러리를 제공하지 않기때문에 boto3 라이브러리를 포함시켜 압축한 후 .zip 파일로 업로드할 것입니다.

아래 예시는 Linux 환경을 기준으로 작성되었습니다.

  • 코드 작성 및 .zip 파일 생성
mkdir acg_backup
cd acg_backup
python -m venv venv
source venv/bin/activate
pip install boto3
cp -r venv/lib/python3.x/site-packages/* .
vi main__.py

venv를 이용하여 가상 환경을 만들어준 뒤 boto3를 install하고 main__.py를 작성하였습니다.

import hashlib
import hmac
import base64
import requests
import time
import json
import csv
import io
import boto3
from datetime import datetime

def generate_header(method, uri, access_key, secret_key):
    timestamp = str(int(time.time() * 1000))
    secret_key = bytes(secret_key, 'UTF-8')

    message = bytes(method + " " + uri + "\n" + timestamp + "\n" + access_key, 'UTF-8')
    signingKey = base64.b64encode(hmac.new(secret_key, message, digestmod=hashlib.sha256).digest())

    http_header = {
        'x-ncp-apigw-signature-v2': signingKey,
        'x-ncp-apigw-timestamp': timestamp,
        'x-ncp-iam-access-key': access_key,
    }

    return http_header

def write_csv_to_memory(csv_data):
    output = io.StringIO()
    writer = csv.writer(output, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    writer.writerows(csv_data)
    output.seek(0)
    return output

def get_ACG_list(access_key, secret_key, region, vpcid):

    method = "GET"
    api_server = "https://ncloud.apigw.ntruss.com"
    uri = "/vserver/v2/getAccessControlGroupList?regionCode=" + region + "&vpcNo=" + vpcid
    uri = uri + "&responseFormatType=json"

    http_header = generate_header(method, uri, access_key, secret_key)

    response = requests.get(api_server + uri, headers=http_header)

    json_data = json.loads(response.text)
    data = json_data['getAccessControlGroupListResponse']['accessControlGroupList']
    result = []

    for group in data:
        if 'default' not in group['accessControlGroupName']:
            result.append({
                'accessControlGroupNo': group['accessControlGroupNo'],
                'accessControlGroupName': group['accessControlGroupName']
            })

    return result


def create_ACG_rule_csv(access_key, secret_key, region, vpcid):

    acg_data = get_ACG_list(access_key, secret_key, region, vpcid)
    acg_dict = {item['accessControlGroupNo']: item['accessControlGroupName'] for item in acg_data}
    acgids = list(acg_dict.keys())

    csv_data = [['accessControlGroupNo', 'accessControlGroupName', 'codeName', 'codeName', 'portRange', 'ipBlock']]

    for acg_no in acgids:

        method = "GET"
        api_server = "https://ncloud.apigw.ntruss.com"
        uri = "/vserver/v2/getAccessControlGroupRuleList?regionCode=" + region + "&accessControlGroupNo=" + acg_no
        uri = uri + "&responseFormatType=json"

        http_header = generate_header(method, uri, access_key, secret_key)

        response = requests.get(api_server + uri, headers=http_header)

        data = json.loads(response.text)['getAccessControlGroupRuleListResponse']['accessControlGroupRuleList']

        for rule in data:
            row = [rule['accessControlGroupNo'],
                acg_dict[rule['accessControlGroupNo']],
                rule['accessControlGroupRuleType']['codeName'],
                rule['protocolType']['codeName'],
                rule['portRange'],
                rule['ipBlock'],
            ]

            csv_data.append(row)

    return csv_data

def upload_to_object_storage(file_object, bucket, object_name, s3_client):
    try:
        file_object = io.BytesIO(file_object.getvalue().encode('utf-8'))
        s3_client.upload_fileobj(file_object, bucket, object_name)
        print("Upload successful!")
    except Exception as e:
        print("Error:", e)
        return False
    return True


def main(args):

    access_key = args['NCLOUD_ACCESS_KEY']
    secret_key = args['NCLOUD_SECRET_KEY']

    obj_access_key = args['OBJ_ACCESS_KEY']
    obj_secret_key = args['OBJ_SECRET_KEY']
    obj_name = args['OBJ_NAME']
    obj_dir = args['OBJ_DIR']

    vpcid = args['VPC_ID']

    region = "KR"

    api_server = "https://ncloud.apigw.ntruss.com"

    s3_client = boto3.client('s3',
                             endpoint_url='https://kr.object.ncloudstorage.com',
                             aws_access_key_id=obj_access_key,
                             aws_secret_access_key=obj_secret_key)

    csv_data = create_ACG_rule_csv(access_key, secret_key, region, vpcid)
    output = write_csv_to_memory(csv_data)

    today = datetime.now().strftime("%Y%m%d")
    object_name = f"acg-{today}.csv"

    upload_to_object_storage(output, obj_name, f'{obj_dir}/{object_name}', s3_client)
    return {"result": "success"}

위 코드는 Cloud Functions에서 동작할 Python 코드입니다.
아래 결과를 확인 후 필요한 부분은 코드를 수정하여 추가 및 변경할 수 있습니다.

drwxr-xr-x 10 root root   210 Apr 21 10:01 boto3
drwxr-xr-x  2 root root   133 Apr 21 10:01 boto3-1.26.117.dist-info
drwxr-xr-x  8 root root  4096 Apr 21 10:01 botocore
drwxr-xr-x  2 root root   120 Apr 21 10:01 botocore-1.29.117.dist-info
drwxr-xr-x  6 root root   210 Apr 21 10:01 dateutil
-rw-r--r--  1 root root   126 Apr 21 10:01 easy_install.py
drwxr-xr-x  3 root root   167 Apr 21 10:01 jmespath
drwxr-xr-x  2 root root   106 Apr 21 10:01 jmespath-1.0.1.dist-info
-rw-r--r--  1 root root  4241 Apr 21 10:09 main__.py
drwxr-xr-x  5 root root   111 Apr 21 10:01 pip
drwxr-xr-x  2 root root   147 Apr 21 10:01 pip-22.0.4.dist-info
drwxr-xr-x  5 root root   113 Apr 21 10:01 pkg_resources
drwxr-xr-x  2 root root    67 Apr 21 10:01 __pycache__
drwxr-xr-x  2 root root   118 Apr 21 10:01 python_dateutil-2.8.2.dist-info
drwxr-xr-x  3 root root   318 Apr 21 10:01 s3transfer
drwxr-xr-x  2 root root   124 Apr 21 10:01 s3transfer-0.6.0.dist-info
drwxr-xr-x  6 root root  4096 Apr 21 10:01 setuptools
drwxr-xr-x  2 root root   187 Apr 21 10:01 setuptools-47.1.0.dist-info
drwxr-xr-x  2 root root   102 Apr 21 10:01 six-1.16.0.dist-info
-rw-r--r--  1 root root 34549 Apr 21 10:01 six.py
drwxr-xr-x  6 root root   291 Apr 21 10:01 urllib3
drwxr-xr-x  2 root root   106 Apr 21 10:01 urllib3-1.26.15.dist-info

main__.py가 잘 작성되었다면 위 파일 및 디렉토리가 리스트로 보여질 것입니다.

zip -r acg_backup.zip *

Cloud Functions으로 업로드할 수 있도록 .zip 파일로 압축합니다.

  • Cloud Functions
    Package 또는 Action에서 디폴트 파라미터는 아래와 같이 설정해줄 수 있습니다.

    VPC ID는 Access Control Group(ACG)가 존재하는 VPC에서 확인할 수 있으며 OBJ_ACCESS_KEY와 OBJ_SECRET_KEY는 Object Storage의 권한이 있는 최소한의 권한이 부여된 API용 Sub Account의 Access Key와 Secret key 등을 입력해줍니다.
{"VPC_ID":"0000","OBJ_ACCESS_KEY":"AAAAAAAAAA","OBJ_SECRET_KEY":"BBBBBBBBBBBBBBBBBBBB","NCLOUD_ACCESS_KEY":"CCCCCCCCCC","NCLOUD_SECRET_KEY":"DDDDDDDDDDDDDDDDDDDDDD","OBJ_DIR":"OBJECTSTRORAGE_DIR","OBJ_NAME":"OBJECTSTRORAGE_NAME"}
  • VPC_ID : VPC의 ID
  • OBJ_ACCESS_KEY : Object Storage에 대한 권한이 있는 ACCESS KEY
  • OBJ_SECRET_KEY : Object Storage에 대한 권한이 있는 SECRET KEY
  • NCLOUD_ACCESS_KEY : Access Control Group(ACG) 조회가 가능한 권한이 있는 ACCESS KEY
  • NCLOUD_SECRET_KEY : Access Control Group(ACG) 조회가 가능한 권한이 있는 SECRET KEY
  • OBJ_DIR : CSV 파일을 저장할 디렉토리 경로 ex) 2023
  • OBJ_NAME : CSV 파일을 저장할 Object Storage의 버킷 이름

파일 업로드가 완료되었다면 저장 후 Object Storage 설정도 해줍시다.
위 설정 시 Cloud Functions이 실행되면 CSV 파일이 Object Storage에 생성됩니다.

지속적으로 CSV 파일이 쌓이게되면 비용이 될테니 Object Storage의 수명주기 정책을 설정하여 특정 일수가 지나면 삭제되거나 Archive Storage로 이동되도록 설정해줍니다.

  • Object Storage 정책 설정

Result

Cloud Functions 실행 시 아래와 같이 result가 success로 출력되는지 확인합니다.

이후 Object Storage에서 아래와 같이 CSV 파일이 저장되는지 확인합니다.

저장된 CSV 파일을 다운로드하여 확인해보면 각 ACG별로 설정된 Inbound/Outbound 설정값을 확인할 수 있습니다.

위와 같이 CSV 파일로 주기적으로 백업을 해두면 추후 ACG에 어떤 수정이 일어났는지 비교하여 확인도 할 수 있고 해당 CSV 파일을 이용하여 동일한 ACG 생성을 만들 때 복원용으로 사용할 수도 있을 것입니다.


Personal Comments

지금까지 네이버 클라우드 플랫폼에서 ACG(Access Control Group) 정책을 CSV 형식으로 Object Storage에 주기적으로 백업하는 방법에 대해 알아보았습니다.

이 포스팅을 통해 이러한 방법으로도 ACG(Access Control Group)를 백업하고 관리할 수 있다는 것을 공유드리고 싶었습니다.

긴 글 읽어주셔서 감사합니다.