【CloudFormation】CloudWatch Logs のログを Subscription Filterと Firehose で S3 に移行する

本記事では、CloudFormationによる、CloudWatch Logs のログを Subscription Filterと Firehose で S3 に移行する方法をコード付きで解説します。

S3 Bucket Policy

前提


各リソースの名前は下記。

・CloudWatch Log Group:aws-waf-logs

・Subscription Filter:test-subscriptionfilter-aws-waf-logs

・Kinesis Firehose:test-firehose-aws–waf-logs

・S3:test-cluster:test-s3-logs-destination

説明


・今回は、WAFのログ(aws-waf-logs)をS3へ移行する。

・併せて、Log Groupの保持期間を任意の値にすることで、Log Groupからは指定の日数後に削除され、その後はS3で保管することが出来る。

・S3では90日でデータをGlacierへ移行、365日で削除するよう設定している。

・データの移動は下記のように行われる。

Log Group(WAFログ)→ Subscription Filter → Kinesis Firehose → S3

実際のコード


AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  System:
    Type: String
    Default: test 

Resources:     
# ------------------------------------------#
#  IAM Policy, Role for Subscription Filter
# ------------------------------------------#
  SubscriptionFilterRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${System}-subscription-filter-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: !Sub 'logs.${AWS::Region}.amazonaws.com'
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: !Sub ${System}-subscription-filter-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - firehose:PutRecord
                  - firehose:PutRecords
                Resource: !Sub 'arn:aws:firehose:${AWS::Region}:${AWS::AccountId}:deliverystream/*' #エクスポート先firehoseへの許可

# ------------------------------#
#  Subscription Filter
# ------------------------------#
  SubscriptionFilter1: 
    Type: AWS::Logs::SubscriptionFilter
    Properties: 
      DestinationArn: !GetAtt Log1Firehose.Arn
      FilterName: !Sub ${System}-subscriptionfilter-aws-waf-logs
      FilterPattern: ""
      LogGroupName: aws-waf-logs #エクスポートしたいロググループ名
      RoleArn: !GetAtt SubscriptionFilterRole.Arn   

# ------------------------------#
#  IAM Policy, Role for firehose
# ------------------------------#
  LogFirehosePolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: "Allow Put Logs to Amazon S3"
      ManagedPolicyName: !Sub ${System}-policy-logfirehose
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - "s3:AbortMultipartUpload"
              - "s3:GetBucketLocation"
              - "s3:GetObject"
              - "s3:ListBucket"
              - "s3:ListBucketMultipartUploads"
              - "s3:PutObject"
              - "logs:PutLogEvents"
            Resource:
              - !Sub arn:aws:s3:::${System}-s3-logs-destination               #エクスポート先S3への許可
              - !Sub arn:aws:s3:::${System}-s3-logs-destination/*             #エクスポート先S3への許可            
              - !Sub "arn:aws:logs:*:${AWS::AccountId}:log-group:*:log-stream:*"   #読み取り元ロググループ・ログストリームからの許可

  LogFirehoseRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${System}-role-logfirehose
      ManagedPolicyArns:
        - !GetAtt LogFirehosePolicy.PolicyArn #上記ポリシーを参照
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service: firehose.amazonaws.com

# ------------------------------#
#  Kinesis Firehose
# ------------------------------#
  Log1Firehose:
    Type: AWS::KinesisFirehose::DeliveryStream
    Properties:
      DeliveryStreamEncryptionConfigurationInput:
        KeyType: AWS_OWNED_CMK #KMSキー暗号化
      DeliveryStreamName: !Sub ${System}-firehose-aws--waf-logs
      DeliveryStreamType: DirectPut
      S3DestinationConfiguration:
        BucketARN: !Sub arn:aws:s3:::${System}-s3-logs-destination
        BufferingHints:
          IntervalInSeconds: 900
          SizeInMBs: 128
        Prefix: firehose/aws-waf-logs/ #ログエクスポート先S3のプレフィックス
        ErrorOutputPrefix: firehose/error/aws-waf-logs/ #失敗時のログエクスポート先S3のプレフィックス
        CompressionFormat: UNCOMPRESSED
        CloudWatchLoggingOptions:
          Enabled: false
        RoleARN: !GetAtt LogFirehoseRole.Arn          

# ------------------------------#
#  S3
# ------------------------------#
  S3BucketForAWSResourceLogs:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${System}-s3-logs-destination
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256      
      AccessControl: Private
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration: 
        Rules: 
          - Id: !Sub ${System}-s3-logs-destination-life-cycle
            Status: "Enabled"
            ExpirationInDays: 365 #365日後に削除
            Transitions:
              - StorageClass: GLACIER
                TransitionInDays: 90 #90日後にGlacierへ移動