본문 바로가기

AWS/Config

Config Auto Remediation(자동 문제 해결) 작업하기

안녕하세요!!

 

정말 오랜만에 포스팅으로 인사드립니다..(__)

이직준비 및 이직 후 이것저것으로 바빴..ㅇ... 게을렀습니다..(__)

 

오늘은 AWS Config를 사용하여 규정 미준수 리소스에 대한 자동화 작업을 포스팅 하고자 합니다.


 

우선 들어가기전에.. 많이들 햇갈려 하시는 CloudTrail, Config에 대해 간략히 정리하면..

 

CloudTrail : 누가 뭐 했어? (Who)
Config : 어떻게 바뀌었어? (How)

 

라고 생각하시면 편하실 듯 합니다.

 

Config는 리소스 변경 추적 서비스로써, 변경된 리소스에 대한 추적 및 감사가 가능하고,

규칙을 배포하여, 해당 리소스가 규정을 준수하고 있는지 여부를 파악합니다.

 

Config는 배포된 규칙에 대해 Remediation 이라는 옵션(?)을 부여할 수 있으며,

Managed Runbook이나 Custom Runbook을 통해 Auto Remediation 작업을 연결할 수 있습니다.

 

Auto Remediation 작업의 필요성은 역시 제가 강조하는.. 최첨단 수동 프로세스 탈피 입니다.

지속적으로 변경되고, 생성되는 리소스들의 규정준수를 위해 관리자가 콘솔을 일일이 찍어가며 작업하기란 불가능에 가깝습니다.

또한, 관리 가시성과 비용을 위하여 미사용 리소스는 주기적으로 정리하는 것이 권고됩니다.

 

위와 같은 이유로 Config Auto Remediation 을 적극 활용해야 한다고 생각합니다.

물론, 리소스에 대한 변경,삭제 등 작업에는 관리자의 승인/거부 프로세스가 필수적으로 들어가야하겠죠.

아래 포스팅에서 함께 다루도록 하겠습니다.


오늘 포스팅에서 소개하며 사용할 서비스는 아래와 같습니다.

 

1. Config

2. SNS

3. Systems Manager Autoamtion

4. Systems Manager *Runbook

5. IAM Role

 

*. Runbook은 Automation 작업에 사용되는 문서를 칭합니다.


오늘 포스팅에서 소개할 서비스의 로직은 아래와 같습니다.

(Config 규칙은 Securit Group이 ENI에 부착되어 있지 않을 때, Non Compliance로 식별하는 규칙을 배포합니다.)

 

 

1. Config 규칙의 미준수 리소스 명을 Automation 작업에서 사용할 Parameter로 넘깁니다.

2. Automation 작업은 미준수 리소스 명을 필터로 Describe API를 호출하여 존재하는지 확인합니다.

3. Automation 작업은 미준수 리소스가 Default 리소스인지 확인합니다.

4. Automation 작업은 Delete 단계를 진행하기 전에 관리자에게 승인/거부 프로세스를 대기하며, SNS Publish API를 호출합니다.
5. SNS Topic에는 관리자의 Email이 Subscription 되어 있으며, Automation이 보낸 Publish API로 인해 관리자에게 Inform 됩니다.

6. Automation은 관리자의 액션에 따라 후속 단계를 실행/중지 합니다.


1. SNS Topic 및 Email Subsciption 생성

Automation 작업 중 승인/거부 단계 발생 시 관리자에게 Infrom 하기 위한 Topic과 Subscription을 생성합니다.

 

1. SNS Topic 생성.

 

1-1. SNS -> Topics -> Create Topic

 

 

1-2. Standard type -> Name/Display name은 임의로 지정 -> 그 외 옵션 Default -> Create topic

 

 

2. Subscription 생성.

 

2-1. SNS -> Subscriptions -> Create subscription

 

 

2-2. 위에서 생성한 Topic 선택 -> Email -> 승인/거부 Inform 할 Admin Email 주소 기입 -> Confirm Subscription 필요.

 


2. Automation Runbook 생성

 

Automation Runbook은 아래의 단계로 구성되어 있습니다.

 

1. DescribeSecurityGroups -> Security Group이 존재하는지 확인.

2. CheckNonDefaultSecurityGroup -> Security Group이 Default가 아닌지 확인.

3. Approve -> 후속 단계(DeleteSecurityGroup)를 진행하기전에 승인/거부 단계를 대기.

4. DeleteSecurityGroup -> Security Group 삭제.

5. VerifySecurityGroupDeleted -> Security Group이 삭제된지 확인.

 

 

Automation Runbook은 아래의 단계로 작업을 수행합니다.

 

1. 미사용 Security Group 식별. (Default Security Group 제외)

2. 삭제 전 승인/거부 프로세스 대기.

3. 삭제.

4. 확인.

 

 

1. Systems Manager -> Documents -> Create Document -> Automation

 

 

 

2. Name : Runbook 이름 입력.

3. Editor -> Edit

 

 

4. 코드 박스 내용 붙여넣기. (61, 62, 63 번째 줄 수정 필요)

 

61, 62 : 승인/거부 작업에 대한 권한을 줄 IAM User 및 IAM Role의 ARN

63 : 승인/거부 작업에 대해 Infrom 할 SNS Topic의 ARN (1단계에서 생성한 Topic ARN)

=> 포스팅에서는 승인/거부 작업에 대해 권한을 갖은 관리자의 Email이 SNS Topic에 Subscription될 예정.

 

[Option] 64 : 다음 Automation 단계를 진행하기 위해 필요한 최소 승인 수.

 

description: |
  ### Document name - JunHyeong.Jang

  ## What does this document do?
  This document deletes a non-default security group that is not utilized by an elastic network interface. A non-default security group is defined as any security group whose name is not `default`. If the security group ID passed to this automation document belongs to a default security group, this document does not perform any changes to the AWS account.

  ## Input Parameters
  * GroupId: (Required) The unique ID of the security group to be deleted.
  * AutomationAssumeRole: (Required) The ARN of the role that allows Automation to perform the actions on your behalf.

  ## Output Parameters
  * DeleteSecurityGroup.SecurityGroupApiResponse - The standard HTTP response from the DeleteSecurityGroup API.
schemaVersion: '0.3'
assumeRole: '{{ AutomationAssumeRole }}'
outputs:
  - DeleteSecurityGroup.SecurityGroupApiResponse
parameters:
  GroupId:
    type: String
    description: (Required) The unique ID of the security group to be deleted.
    allowedPattern: 'sg-[a-z0-9]+$'
  AutomationAssumeRole:
    type: String
    description: (Required) The ARN of the role that allows Automation to perform the actions on your behalf.
    allowedPattern: '^arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role/[\w+=,.@-]+$'
mainSteps:
  - name: DescribeSecurityGroups
    action: 'aws:executeAwsApi'
    description: |
      ## DescribeSecurityGroups
      Describes Security Groups using security group ID.
      ## Outputs
      * GroupName: The name of the security group.
    inputs:
      Service: ec2
      Api: DescribeSecurityGroups
      Filters:
        - Name: group-id
          Values:
            - '{{ GroupId }}'
    outputs:
      - Name: GroupName
        Selector: '$.SecurityGroups[0].GroupName'
        Type: String
  - name: CheckNonDefaultSecurityGroup
    action: 'aws:branch'
    description: |
      ## CheckNonDefaultSecurityGroup
      Verifies that the security group name does not match `default`. If the group name does not match `default`, go to the next step: DeleteSecurityGroup.
    inputs:
      Choices:
        - NextStep: Approve
          Not:
            Variable: '{{ DescribeSecurityGroups.GroupName }}'
            StringEquals: default
    isEnd: true
  - name: Approve
    action: 'aws:approve'
    inputs:
      Approvers:
        - '### arn:aws:iam::12자리-계정번호:user/IAMUser이름 ###'
        - '### arn:aws:iam::12자리-계정번호:role/IAMRole이름 ###'
      NotificationArn: '### SNS Topic ARN ###'
      MinRequiredApprovals: 1
      Message: '''Please approve/reject deletion of {{DescribeSecurityGroups.GroupName}}.'''
    description: Wait for the manager's Approval/Rejection
    nextStep: DeleteSecurityGroup
  - name: DeleteSecurityGroup
    action: 'aws:executeAwsApi'
    description: |
      ## DeleteSecurityGroup
      Deletes the security group based on the input security group ID.
      ## Outputs
      * SecurityGroupApiResponse: The standard HTTP response from the DeleteSecurityGroup API.
    outputs:
      - Name: SecurityGroupApiResponse
        Selector: $
        Type: StringMap
    inputs:
      Service: ec2
      Api: DeleteSecurityGroup
      GroupId: '{{ GroupId }}'
  - name: VerifySecurityGroupDeleted
    action: 'aws:executeScript'
    description: |
      ## VerifySecurityGroupDeleted
      Verifies that the security group has been deleted.
      ## Outputs
      * Output: Success message or failure exception.
    isEnd: true
    timeoutSeconds: 600
    inputs:
      Runtime: python3.6
      Handler: handler
      InputPayload:
        GroupId: '{{GroupId}}'
      Script: |-
        import boto3
        from botocore.exceptions import ClientError

        def handler(event, context):
            ec2_client = boto3.client("ec2")
            group_id = event["GroupId"]

            try:
              desc_group = ec2_client.describe_security_groups(GroupIds=[group_id])
              info = "ERROR IN VERIFICATION, SECURITY GROUP {} NOT DELETED ".format(group_id)
              raise Exception(info)
            except ClientError as ex:
              if ex.response['Error']['Code'] == 'InvalidGroup.NotFound':
                 return {
                   "output": "Security group deleted successfully."
                 }
              raise Exception(ex)
    outputs:
      - Name: Output
        Selector: $.Payload.output
        Type: String

 

5. 적절한 이름으로 Create


3. IAM Policy 생성

 

Systems Manager Automation 작업이 단계에 정의된 API들을 호출할 수 있는 Policy가 연결된 Role을 생성합니다.

 

1. IAM - Policies -> Create Policy

 

 

2. 아래 코드박스 내용 붙여넣기.

 

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "*"
        }
    ]
}

 


4. IAM Role 생성

Systems Manager Automation 작업이 Asssume 할 Role을 생성합니다.

 

1. IAM Role -> Roles -> Create Role

 

 

2. AWS service -> Systems Manager -> Select your use case -> Systems Manager -> Next.

 

 

3. 위 단계(3단계 : IAM Policy 생성)에서 생성한 Policy + EC2FullAccess Policy Attach.

 


5. Config Rule 생성

규정 준수 여부를 판단 할 Config 규칙을 생성합니다.

 

1. Config -> Rules -> Add rule

 

 

2. Add AWS managed rule -> ec2-security-group-attached-to-eni -> Next

 

 

2-1. Scope of changes = Resource -> Next -> Add rule

 


6. Config Auto Remediation 연결

규정 미준수 리소스 발생 시 자동으로 처리할 Automation Runbook을 연결합니다.

 

1. Config -> Rules -> Action -> Manage remediation

 

 

2. Automatic remediation 선택

2-1. 위 2단계에서 생성한 Automation Runbook 선택.

2-2. Regource ID parameter를 GroupId로 선택

2-3. AutomationAssumeRole을 위 4단계에서 생성한 IAM Role ARN 입력

 


 

여기까지!!

 

테스트를 위한 리소스는 모두 생성했습니다.

 

위의 Config 규칙 생성시 정의한 리소스가 생성,변경,삭제 시 마다 Config 규칙이 리소스들을 다시 검사하도록 했고,

미준수 리소스에 대해서는 아래와 같이 Noncompliant resource로 식별될겁니다.

 

미사용 Security Group 식별

 

우리가 생성한 규칙은 미사용 Security Group을 식별하는 규칙으로 ENI에 Security Group이 부착되어 있지 않으면

위와 같이 식별됩니다.

 

Noncompliant resource로 식별되면, Automation 작업이 호출되며, Automation 작업은 위에서 만든 Runbook의

단계로 작업을 처리합니다.

 

Automation 실행 화면

 

또한, 우리는 Noncompliant resource에 대한 실질적인 Action을 취하기 전 관리자의 승인/거부를 대기하도록 설정했습니다.

해서, 3번째 단계에서 SNS Publish API를 통해 Subscription된 관리자의 Email로 Infrom 합니다.

 

관리자 Email Infrom

 

여기서, 위에 Runbook에서 지정한 보안 주체의 권한으로만 승인/거부 할 수 있으며, 최소 승인 횟수는 1회로 설정했습니다.

만약, 관리자가 여러명이거나 해당 VPC(Ex.Dev/Prd/Stg)를 관리하는 개발자 등의 추가 승인이 필요하다면,

승인 횟수를 늘리고, 승인할 수 있는 보안 주체를 추가하면 됩니다.

 

      Approvers:
        - '### arn:aws:iam::12자리-계정번호:user/IAMUser이름 ###'
        - '### arn:aws:iam::12자리-계정번호:role/IAMRole이름 ###'
      MinRequiredApprovals: 1

* 생성한 Runbook 중 일부.


AWS가 Config Remediation에서 Managed로 제공하는 Runbook은 꽤나 있습니다.

다만, 해당 Runbook들은 모두 승인/거부 프로세스가 존재하지 않으며, 의도치 않은 Action이 발생할 수 있습니다.

따라서, 필히 승인/거부 프로세스를 포함한 Custom Runbook을 생성하시길 권고드립니다.

 

정말 오랜만에 포스팅으로 인사드렸는데요.

게으른 제 몸뚱이와 나태한 정신머리를 수시로 점검하여 자주 인사드릴 수 있도록 하겠습니다.. (__)

 

감사합니다 !!