GuardDutyとその結果をFirehose経由でDatadogに連携するCloudFormationテンプレートを作ってみた

GuardDutyと、Datadog Logs 連携した Firehose の設定をCloudFormationテンプレート化、StackSetで全リージョン一括展開してみました。
2020.08.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS チームのすずきです。

HTTPエンドポイントに対応した Kinesis Data Firehose を利用して、 Guradduty の 検出結果をを、Datadog Log に連携して利用する方法について紹介させて頂きました。

今回、Guradduty、EventBrige、Firehose を StackSetを利用して一括設定できる CloudFormation テンプレート を用意する機会がありましたので、紹介させていただきます。

CloudFormation

Firehose

  • HttpEndpointDestinationConfiguration」以下でHTTPエンドポイント設定を行います。

  • Datadog 指定のURLと APIキーを「EndpointConfiguration」以下に反映します。

  FirehoseStream:
    Type: AWS::KinesisFirehose::DeliveryStream
    Properties:
      HttpEndpointDestinationConfiguration:
        EndpointConfiguration:
          AccessKey: !Ref 'DatadogAccessKey'
          Url: https://aws-kinesis-http-intake.logs.datadoghq.com/v1/input
          Name: Datadog
        BufferingHints:
          SizeInMBs: 4
          IntervalInSeconds: 60
        CloudWatchLoggingOptions:
          Enabled: true
          LogGroupName: !Sub '/aws/kinesisfirehose/${AWS::StackName}'
          LogStreamName: HttpEndpointDelivery
        RequestConfiguration:
          ContentEncoding: GZIP
        RoleARN: !GetAtt 'FirehoseStreamRole.Arn'
        RetryOptions:
          DurationInSeconds: 60
        S3BackupMode: AllData 
        S3Configuration: 
          RoleARN: !GetAtt 'FirehoseStreamRole.Arn'
          BucketARN: !Sub 'arn:aws:s3:::${S3BucketFirehose}'
          Prefix: !Sub '${AWS::StackName}-backup/'
          ErrorOutputPrefix: !Sub '${AWS::StackName}-error/'
          BufferingHints:
            SizeInMBs: 10
            IntervalInSeconds: 600
          CompressionFormat: GZIP 
          CloudWatchLoggingOptions:
            Enabled: true
            LogGroupName: !Sub '/aws/kinesisfirehose/${AWS::StackName}'
            LogStreamName: S3Delivery

EventBridge

  • GuardDuty により検出されたイベントを Firehoseに転送します。
  EventsRuleGuardDutyFinding:
    Type: AWS::Events::Rule
    Properties:
      Description: EventRule
      EventPattern:
        source:
          - aws.guardduty
        detail-type:
          - GuardDuty Finding
      State: ENABLED
      Targets:
      - Arn: !GetAtt 'FirehoseStream.Arn'
        Id: EventsRuleGuardDutyFinding
        RoleArn: !GetAtt 'EventBridgeRole.Arn'
  • 重要度の高い GuardDuty検出結果(severity:[5,8])のみ、処理対象とするフィルタも可能です。
      EventPattern:
        source:
          - aws.guardduty
        detail-type:
          - GuardDuty Finding
        detail:
          severity:
            - 8
            - 5

IAM

EventBridge と Firehose 用のIAMロールを用意しました。

  EventBridgeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: firehose-putrecord
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - firehose:PutRecord
                  - firehose:PutRecords
                Resource: !GetAtt 'FirehoseStream.Arn'

  FirehoseStreamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: ''
            Effect: Allow
            Principal:
              Service: firehose.amazonaws.com
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: !Ref 'AWS::AccountId'

  FirehoseStreamPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: firehose_delivery_policy
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - logs:PutLogEvents
            Resource:
              - !Sub '${LogGroupFirehose.Arn}:log-stream:*'
          - Effect: Allow
            Action:
              - s3:AbortMultipartUpload
              - s3:GetBucketLocation
              - s3:GetObject
              - s3:ListBucket
              - s3:ListBucketMultipartUploads
              - s3:PutObject
            Resource:
              - !Sub 'arn:aws:s3:::${S3BucketFirehose}'
              - !Sub 'arn:aws:s3:::${S3BucketFirehose}/*'
      Roles:
        - !Ref 'FirehoseStreamRole'

CloudWatch logs

Firehose ログ書き込み用の設定を用意します。

CloudFormation でロググループを設置する事で、CloudWatchLogsに登録されたログが残り続ける事を回避します。

  LogGroupFirehose:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName:  !Sub '/aws/firehose/${AWS::StackName}'
      RetentionInDays: 7
  LogStreamS3Delivery:
    Type: AWS::Logs::LogStream
    Properties:
      LogGroupName: !Ref 'LogGroupFirehose'
      LogStreamName: S3Delivery
  LogStreamHttpEndpointDelivery:
    Type: AWS::Logs::LogStream
    Properties:
      LogGroupName: !Ref 'LogGroupFirehose'
      LogStreamName: HttpEndpointDelivery

S3

Firehose の出力先となるS3バケットを設置します。

S3のストレージ費用を抑制するため、S3のライフサイクル設定を実施、パブリックアクセスは禁止としています。

  S3BucketFirehose:
    Type: AWS::S3::Bucket
    Properties:
      LifecycleConfiguration:
        Rules:
          - Id: AutoDelete
            Status: Enabled
            ExpirationInDays: 14
          - Id: NoncurrentVersionExpiration
            Status: Enabled
            NoncurrentVersionExpirationInDays: 7
          - Id: AbortIncompleteMultipartUpload
            Status: Enabled
            AbortIncompleteMultipartUpload:
              DaysAfterInitiation: 7
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      VersioningConfiguration:
        Status: Enabled

テンプレートリンク

今回のテンプレート、全文は以下で公開中です。

StackSet

StackSetsによる全リージョン一括有効化 の手順で、任意のリージョンに一括展開する事が可能です。

Firehoseによるデータ圧縮や、S3のライフサイクル設定により、S3のコストは抑制した利用が期待できますが、 S3バケットの設置数は、1つのAWSアカウントあたり100個の制限が存在します。

今回のテンプレートでは、Firehose のバックアップ先となるS3バケットが各リージョンに設置されます。

多数のS3バケットを設置済みの環境では、事前にサービスクォータを利用した上限緩和を実施してご利用ください。

まとめ

今回紹介したCloudFormationテンプレート、以下ブログで紹介されている、SNS / Lambda を Kinesis Data Firehose で置き換えた内容となります。

Firehose は 簡単な設定で 安定したデータ転送を実現する事が可能です。 連携先が Firehose との連携をサポートする場合、Firehose をぜひお試しください。

参考

SNS(Eメール)連携

Lambda + 集約用SNS