全リージョンの GuardDuty ログを一つの S3 バケットにエクスポートする

2020年8月16日

概要

やりたいこと

全リージョンの GuardDuty ログを東京リージョンのバケットにエクスポートしたい。

全リージョンの GuardDuty 有効化や、東京リージョンの GuardDuty のログエクスポートは以下でやったので参考組み合わせる。

GuardDuty のログエクスポート

作成しないといけないものは2つ。

  • KMSキー
  • S3バケット

GuardDuty ログをエクスポートするにはKMS キーによる暗号化が必須。

さらに、KMS キーはバケットと同一リージョンである必要がある。

ただし、GuardDuty のリージョンと KMS キー・バケットのリージョンは異なっていても大丈夫なため、全リージョンの GuardDuty ログを東京リージョンのバケットに集約することができる。

CloudFormation

StackSets で GuardDuty を有効化

GuardDutyを有効化する。

AWSTemplateFormatVersion: 2010-09-09
Description: GuardDuty
Resources:
  GuardDuty:
    Type: AWS::GuardDuty::Detector
    Properties:
      Enable: true

StackSets 作成。

aws cloudformation create-stack-set --stack-set-name guardduty-stackset --template-body file://guardduty.yaml --administration-role-arn arn:aws:iam::111122223333:role/AWSCloudFormationStackSetAdministrationRole --execution-role-name AWSCloudFormationStackSetExecutionRole

有効化するリージョンを登録。

aws cloudformation create-stack-instances --stack-set-name guardduty-stackset --accounts '["111122223333"]' --regions '["ap-northeast-1","ap-northeast-2", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "sa-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2"]' --operation-preferences FailureToleranceCount=0,MaxConcurrentCount=1

全リージョンが有効化されていれば OK。

KMS キー

東京リージョンに一つだけ作成する。

AWSTemplateFormatVersion: 2010-09-09
Description: GuardDuty KMS
Resources:
  KmsKey:
    Type: AWS::KMS::Key
    Properties:
      Description: "Key for GuardDuty"
      EnableKeyRotation: true
      KeyPolicy:
        Version: "2012-10-17"
        Id: "kms-guardduty"
        Statement:
         -
            Sid: "Enable IAM User Permissions"
            Effect: "Allow"
            Principal:
               AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action: "kms:*"
            Resource: "*"
         -
            Sid: "Allow GuardDuty to use the key"
            Effect: "Allow"
            Principal:
              Service: "guardduty.amazonaws.com"
            Action:
              - "kms:GenerateDataKey"
            Resource: "*"
      PendingWindowInDays: 7
  KmsKeyAlias:
    Type: AWS::KMS::Alias
    Properties:
      AliasName: "alias/KMS-GuardDuty"
      TargetKeyId:
        Ref: KmsKey

Outputs:
    KmsKey:
    Value: !GetAtt KmsKey.Arn
    Export:
      Name: KmsKeyArn

普通の CloudFormation Stack でデプロイ。

aws cloudformation deploy --stack-name guardduty-kms --template-file guardduty_kms.yaml

S3

東京リージョンに一つだけ作成する。

AWSTemplateFormatVersion: 2010-09-09
Description: S3 for Config

Resources:
  GuardDutyBucket:
    DeletionPolicy: Retain
    Type: AWS::S3::Bucket
    Properties:
      BucketName: guardduty-all-region-log-kms-test
      VersioningConfiguration:
        Status: Enabled
      LifecycleConfiguration:
        Rules:
          - Id: 365days-All-LifeCycleRule
            Status: Enabled
            ExpirationInDays: 365
            NoncurrentVersionExpirationInDays: 10
      AccessControl: Private
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True

  GuardDutyBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref GuardDutyBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: "Deny non-HTTPS access"
            Action: ['s3:*']
            Effect: "Deny"
            Resource:
            - !Join ['', ['arn:aws:s3:::', !Ref GuardDutyBucket,'/*']]
            Principal:
              Service: [guardduty.amazonaws.com]
            Condition:
              Bool:
                aws:SecureTransport: "false"
          - Sid: "Deny incorrect encryption header"
            Action: ['s3:PutObject']
            Effect: "Deny"
            Resource:
            - !Join ['', ['arn:aws:s3:::', !Ref GuardDutyBucket,'/*']]
            Principal:
              Service: [guardduty.amazonaws.com]
            Condition:
              StringNotEquals:
                s3:x-amz-server-side-encryption-aws-kms-key-id: !ImportValue KmsKeyArn
          - Sid: "Deny unencrypted object uploads"
            Action: ['s3:PutObject']
            Effect: "Deny"
            Resource:
            - !Join ['', ['arn:aws:s3:::', !Ref GuardDutyBucket,'/*']]
            Principal:
              Service: [guardduty.amazonaws.com]
            Condition:
              StringNotEquals:
                s3:x-amz-server-side-encryption: "aws:kms"
          - Sid: "Allow PutObject"
            Action: ['s3:PutObject']
            Effect: "Allow"
            Resource:
            - !Join ['', ['arn:aws:s3:::', !Ref GuardDutyBucket,'/*']]
            Principal:
              Service: [guardduty.amazonaws.com]
          - Sid: "Allow GetBucketLocation"
            Action: ['s3:GetBucketLocation']
            Effect: "Allow"
            Resource:
            - !Join ['', ['arn:aws:s3:::', !Ref GuardDutyBucket]]
            Principal:
              Service: [guardduty.amazonaws.com]

デプロイ。

aws cloudformation deploy --stack-name s3-guardduty --template-file guardduty_s3.yaml

S3 へのエクスポート設定(手動)

手動!AWS さん、 CloudFormation 対応していただけませんかね。

以下のようにバケットと KMS キーを選択する。

ログはリージョンごとに prefix が切られ保存される。

エラー

ResourceLogicalId:GuardDuty, ResourceType:AWS::GuardDuty::Detector, ResourceStatusReason:The request is rejected because the input detectorId is not owned by the current account.

入力 detectorId が現在のアカウントによって所有されていないため、リクエストは拒否されました。

過去に StackSet で作ったスタックが残っていたので、そのスタックを消したらエラーは解消した。

参考

結果のエクスポート

GuardDutyの検出結果をエクスポートするためのKMSキーとS3バケットをCloudFormationで作った