CloudFormation으로 SSM Automation문서 생성하기

2022.01.19

소개

안녕하세요! 클래스메소드 금상원 입니다. 이번 블로그에서는 CloudFormation으로 SSM Automation문서를 생성하는 방법에 대한 설명을 하려고 합니다.

목표

WAF의 로깅활성화를 자동으로 설정해주는 SSM Automation문서를 CloudFormation으로 작성해보자!

SSM Automation문서 템플릿파일 작성(YAML)

AWSTemplateFormatVersion: "2010-09-09"

Resources:
  AutomationDoc:
      Type: "AWS::SSM::Document"
      Properties:
        DocumentType: "Automation"
        Name: 'EnableWAFV2Logging'
        DocumentFormat: "YAML"
        Content:
          schemaVersion: '0.3'
          assumeRole: "{{ AutomationAssumeRole }}"
          outputs:
            - EnableWAFV2LoggingAndVerify.Output
          parameters:
            AutomationAssumeRole:
              type: String
              description: (Required) The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that allows Systems Manager Automation to perform the actions on your behalf.
              allowedPattern: ^arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role/[\w+=,.@/-]+$
            LogDestinationConfigs:
              type: String
              description: (Required) The S3 Name that you want to associate with the web ACL.
              allowedPattern: ^aws-waf-logs-.*
            WebAclArn:
              type: String
              description: (Required) ARN of the web ACL for which logging will be enabled.
              allowedPattern: ^arn:(aws[a-zA-Z-]*)?:wafv2:.*
          mainSteps:
            - name: EnableWAFV2LoggingAndVerify
              action: "aws:executeScript"
              isEnd: true
              timeoutSeconds: 600
              description: >-
                ## EnableWAFV2LoggingAndVerify
                Enables logging for the AWS WAFV2 web ACL and verifies that the logging has the specified configuration.
                ## Outputs
                * Output: Success message with HTTP Response from PutLoggingConfiguration, GetLoggingConfiguration API calls or failure exception.
              inputs:
                Runtime: python3.7
                Handler: enable_wafv2_logging_and_verify
                InputPayload:
                  LogDestinationConfigs: "{{ LogDestinationConfigs }}"
                  ResourceArn: "{{ WebAclArn }}"
                Script: |-
                  import boto3

                  def enable_wafv2_logging_and_verify(event, context):

                      wafv2_client = boto3.client('wafv2')
                      web_acl_arn = event["ResourceArn"]

                      s3 = boto3.resource('s3')
                      bucket_name = event["LogDestinationConfigs"]
                      bucket_arn ='arn:aws:s3:::'+bucket_name

                      if s3.Bucket(bucket_name).creation_date is None:
                          raise Exception("UPDATE FAILED, AMAZON KINESIS DATA FIREHOSE ARN PROVIDED DOESN'T EXISTS.")

                      update_response = wafv2_client.put_logging_configuration(
                          LoggingConfiguration={
                              "ResourceArn": web_acl_arn,
                              "LogDestinationConfigs": [
                                  bucket_arn,
                              ]
                          }
                      )
                      get_response = wafv2_client.get_logging_configuration(ResourceArn=web_acl_arn)
                      if get_response["LoggingConfiguration"]["LogDestinationConfigs"] == [bucket_arn]:
                          return {
                              "output": {
                                  "Message": "Enable Logging configuration for AWS WAFV2 web ACL is SUCCESSFUL",
                                  "HTTPResponsePutAPI": update_response,
                                  "HTTPResponseGetAPI": get_response
                                  }
                              }
                      raise Exception("VERIFICATION FAILED, LOGGING CONFIGURATION FOR AWS WAFV2 IS NOT ENABLED.")
              outputs:
                - Name: Output
                  Selector: $.Payload.output
                  Type: StringMap
  • AutomationDoc 이라는 새로운 리소스를 작성합니다.
  • Type 에는 AWS::SSM::Document 를 입력합니다.
  • Properties
    • DocumentType 에는 Automation을 입력합니다.
    • Name을 작성하여 문서의 이름을 설정합니다.
    • DocumentFormat 에 YAML을 입력하여 문서의 타입을 설정해줍니다.
    • Content
      • schemaVersion0.3으로 설정합니다. SSM Automation문서사용되는 버전은 0.3입니다.
      • outputs에는 EnableWAFV2LoggingAndVerify.Output를 입력해줍니다
      • parameters 에는 필요한 각각의 파라미터를 입력해줍니다.
      • MainSteps
        • name 을 입력하여 Runbook의 모든 단계 이름에서 고유해야 하는 식별자을 입력합니다.
        • action 작업의 예를 입력합니다.
        • isEnd 을 설정하여 특정 단계가 끝나면 자동화를 중지합니다.
        • timeoutSeconds 단계의 시간 초과 값을 입력해줍니다.
        • inputs 작업과 관련된 속성을 입력해 줍니다.

문제 해결

위의 코드로 SSM Automation 문서를 작성 했을 경우 위의 사진과 같이 | 가 인식이 안되어 pyhon 코드가 문장이 되버리는 문제가 있습니다. 이러한 문제는 아래의 방법을 참고해 주세요.

오른쪽 상단에서 작업 탭에서 새로운 버전 생성을 클릭합니다.

그 후 변경사항 없이 맨 아래에서 새 버전을 기본값으로 설정을 체크 해주고 새로운 버전 생성버튼을 클릭하면 정상적인 형태의 문서로 변하게 됩니다.

마무리

이번 블로그에서는 CloudFormation으로 SSM Automation을 구축하고, WAF의 로깅을 활성화 시키는 문서를 작성 해보았습니다. 생성한 후 바로 원하는 형태의 문서로 작성이 되지않았던 문제가 있지만 다행이 해결가능한 문제이므로 잘 확인하고 사용하시면 좋을 것 같습니다.
평소에 SSM Automation을 CloudFormation으로 작성하고 싶으신분들에게 도움이 되었으면 합니다.

참고자료

Systems Manager 자동화 작업 참조