본문 바로가기

Devops 솔루션/Terraform

Terraform+CSV로 SecurityGroup 관리

반응형

요약

  • CSV파일 + Terraform 으로 SG 관리하는 법 정리
  • 하면서 알게된 팁 및 내용들 정리

목적 및 고려 사항

  • AWS-GUI를 통해 SG를 관리하게 되면, 변경할 때 불편사항이 많다. (클릭이 귀찮음..)
  • Terraform을 통해 IaC로 인프라를 관리하게 될 경우, SG-Rule을 하나 추가할 때 마다 번잡한 코드가 많아짐 (대략 1개 SG-rule 추가 할 때 마다 최소 5줄은 필요)
  • CSV형식으로 SG-Rule을 관리하기 편하게 해보자

내용

  • AWS에서 SG가져오는 코드
"""
1. 정보를 가져와서 CSV만들기 (EC2) 
- aws-cli가 되는 프로필 설정은 먼저 해놓기 
"""

import json
import boto3
import csv
from botocore.config import Config

input = dict()

# aws-cli가 되는 프로파일 설정은 먼저 해놓기
input['servicetag'] = 'test'
input['region_name'] = 'ap-northeast-2'
input['enviorment'] = 'production'

# 호출부 (전체 리스트)
def get_sg_list():
    my_config = Config(
        region_name = input['region_name']
    )

    client = boto3.client('ec2', config=my_config)

    res = client.describe_security_groups(
        Filters=[
            {
                'Name': 'tag:servicetag',
                'Values' : [
                    input['servicetag']
                ],
                'Name': 'tag:Environment',
                'Values' : [
                    input['enviorment']
                ]
            }
        ]
    )
    print (len(res['SecurityGroups']))
    return res

# 보안 그룹 개수 체크하는 것
def write_sg_list_json():
    file_path_json="/custom_path/sg.json"
    res = get_sg_list()
    with open(file_path_json, 'w') as outfile:
        json.dump(res['SecurityGroups'], outfile)

def make_csv():
    file_path_csv="/custom_path/"+input['enviorment']+".csv"
    with open(file_path_csv,'w',newline="") as outfile:
        wr = csv.writer(outfile)
        wr.writerow(['key','sg_name','rule_type','protocol','from_port','to_port','src','description'])
    return

# json 데이터 -> csv 변환 
# 데이터 : key(Auto Increase),sg_name,rule_type,protocol, from_port, to_port, src, description
# key 값이 뽑을 때 마다 달라질 수 있음 (3. 업데이트 치는 기능 만들기 )
def update_make_csv(key,sg_name,rule_type,protocol,from_port,to_port,src,description):
    file_path_csv="/custom_path/"+input['enviorment']+".csv"
    with open(file_path_csv,'a',newline="") as outfile:
        wr = csv.writer(outfile)
        wr.writerow([key,sg_name,rule_type,protocol,from_port,to_port,src,description])
    return

def make_json_to_csv():

    res = get_sg_list()
    make_csv()

    for sg in res['SecurityGroups']:
        key=0
        sg_name=sg['GroupName']

        for sg_rule_ingress in sg['IpPermissions']:
            protocol = sg_rule_ingress['IpProtocol']
            from_port = sg_rule_ingress['FromPort']
            to_port = sg_rule_ingress['ToPort']

            for IpRange in sg_rule_ingress['IpRanges']:
                src = IpRange['CidrIp']
                desc = IpRange['Description']+"(CSV)"
                key += 1
                update_make_csv(key,sg_name,'ingress',protocol,from_port,to_port,src,desc) 

        for sg_rule_egress in sg['IpPermissionsEgress']:
            protocol = sg_rule_egress['IpProtocol']
            from_port = sg_rule_egress['FromPort']
            to_port = sg_rule_egress['ToPort']

            for IpRange in sg_rule_egress['IpRanges']:
                src = IpRange['CidrIp']
                desc = IpRange['Description']+"(CSV)"
                key += 1
                update_make_csv(key,sg_name,'egress',protocol,from_port,to_port,src,desc)      
    return

# 실행
make_json_to_csv()
  • 출력 CSV 예시
key,rule_type,protocol,from_port,to_port,src,description
1,ingress,tcp,0,65000,0.0.0.0/0,All Allow Ingress
2,egress,tcp,80,443,0.0.0.0/0,All Allow Egress
  • Terraform 적용 코드
resource "aws_security_group" "allow_bastion_sg_csv" {
    name   = format("%s_bastion_csv_sg", var.name_prefix)
    vpc_id = var.vpc_id
}

resource "aws_security_group_rule" "allow_bastion_firewall_csv" {
    for_each = true ? { for csv in local.sg_rules : csv.key => csv } : {}
    type              = each.value.rule_type
    from_port         = each.value.from_port
    to_port           = each.value.to_port
    protocol          = each.value.protocol
    cidr_blocks       = [each.value.src]
    security_group_id = aws_security_group.allow_bastion_sg_csv.id
    description       = each.value.description

    lifecycle {
        create_before_destroy = true
    }
}

추가 팁 정리

  • CSV 안에 Key값을 두게 되면, tfstate 내에 일종의 SG-rule의 키 값으로 테라폼에서 관리
    • Key값이 없을 경우 SG-rule을 Array형태로 관리하기 때문에 하나만 변동 되어도, 전체 Replace수행 예상 (테스트는 필요)
  • 같은 키 값의 사항에 변경 사항이 생기면 -/+로 Replace가 생기고, 다른 키 값으로 만들면 + 즉 add가 됨
  • 중복되는 값이 있을 경우, terraform apply 시에 중복 된 것에 대해 에러코드를 출력함
  • 별도의 관리 정책을 통해, 바로 이전 정상 상태로 원복이 가능하고, 코드 레벨로 SG-Rule 변경 사항을 계속 트랙킹 할 수 있다
  • lifecycle에 create_before_destory를 적용해놓으면 +/-의 형태로 변경된다.
  • AMQP... SG Change가 안된다 (이건 좀..)

해볼 것

  • Terraform Resource가 현재 SecurityGroup와 SecrutityGroupRule로 나누어져 있는 데, 이것을 SecurityGroup으로 모두 합칠 지 테스트 필요
    • 변동할 경우 -/+되는 상황이 발생하는 지
    • Replace 상황에서 순단이 발생하는 지 확인 필요

참고자료

728x90
반응형

'Devops 솔루션 > Terraform' 카테고리의 다른 글

[Terraform] terraform_remote_state 이란  (0) 2023.03.23
[Terraform] for_each, for loop 란  (0) 2023.03.05