😸

【CloudFormation】VPC Flow Logsをデプロイしてみる(CloudWatch Logs,S3)

2022/07/18に公開

1. はじめに

 こんにちわ、Mitsuoです。
色んな方の技術ブログを見ていたのですが、端的に書いているのが一番分かりやすいなと思いました。
シンプルに書いていけるように頑張っていきます。

2. 今回のお題

 今回はCloudFormationを用いてVPC Flow Logsをデプロイしてみました。
VPCフローログの仕様に関する解説は無いので、公式ドキュメントや他の技術ブログを参照ください。

Logging IP traffic using VPC Flow Logs

3. 作成したリソース

 テンプレートで作成するリソースは以下の通りです。

  • ログ保管先がCloudWatch Logs

    • IAMロール
    • ロググループ
    • フローログ
  • ログ保管先がS3バケット

    • S3バケット
    • フローログ

image

ログの保管先がCloudWatch Logs、S3かによって、作成するリソースを分ける様にしています。
このテンプレートを利用する前に、フローログを作成するVPCを準備してください。
Parameterセクションで選択したVPC IDに対して設定します。

テンプレートにはEC2は含まれていないです。
ログを出力する検証のために後から手動で作成しています。

4 テンプレート情報

 作成したテンプレートになります。


AWSTemplateFormatVersion: "2010-09-09"
Description: Create VPC Flow Logs and related resources.
# ------------------------------------------------------------#
#  Caution:
#  This template is for deploying the Flow logs in existing VPC. In addition to Flow logs, it deploys related resources such as bucket. 
#  log group and IAM Role depending on LogType. 
#  For more information, see https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-flowlog.html
#  
# ------------------------------------------------------------#
#  Metadata:
#  This can privide details about the template.
#  For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html.
#  As Metadata Keys, AWS::CloudFormation::Interface can Defines the grouping and ordering of input parameters
#  when they are displayed in the AWS CloudFormation console.
#  For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html.
# ------------------------------------------------------------# 

Metadata: 
  "AWS::CloudFormation::Interface": 
    ParameterGroups:
      -  
        Parameters:
          - SystemName
          - EnvType 
          - Tagprefix
          - Owner
          - VPCID
          - FilterType
          - LogType
          - RetentionDays          
    ParameterLabels: 
      SystemName:
        default: "Type the Systemname"
      EnvType:
        default: "Select the environment in which you deploy resources"
      Tagprefix:
        default: "Type the Tagprefix which is logical unit name about this stack(e.g. Webserver,Monitoring,Logging)"
      Owner:
        default: "Type who owns these resources (e.g. project name or worker, whether this purpose is just verification or not)"    
      VPCID: 
        default: "Select the VPC ID"
      FilterType:
        default: "Select the type of traffic to capture (Accept, Reject, or All traffic)"
      LogType:
        default: "Select the type of Log sent to(CloudWatch Logs or S3 Bucket)"  
      RetentionDays:
        default: "Select the duration of retention for CloudWatch Logs" 

# ------------------------------------------------------------#
# Parameters
# This Can enable templates to input custom values each time you create or update a stack.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html.
# ------------------------------------------------------------# 

Parameters:
  SystemName:
    Type: String
  EnvType:
    Type: String
    Default: "dev"
    AllowedValues:
      - dev
      - stg
      - prod 
  Tagprefix:
    Type: String      
  Owner:
    Type: String 
  VPCID:
    Type: AWS::EC2::VPC::Id
    ConstraintDescription: "Select the VPC ID"  
  FilterType:
    Type: String
    Default: ALL
    AllowedValues: [ ALL, ACCEPT, REJECT ] 
  LogType:
    Type: String
    Default: cloud-watch-logs
    AllowedValues: [ cloud-watch-logs, s3 ]
  RetentionDays:
    Type: Number
    Default: 30
    AllowedValues: [ 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, 3653 ]   

Conditions:
  EqualtoLogs: !Equals [!Ref LogType, cloud-watch-logs]
  Equaltos3: !Equals [!Ref LogType, s3]

# ------------------------------------------------------------#
# Resources
# This can declare the AWS resources that you want to include in the stack.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html.
# ------------------------------------------------------------# 

Resources:

# ------------------------------------------------------------#
# Create Logs(CloudWatch) and VPC Flow Logs.
# In case of destination for logging is cloud-watch-logs, you can create these resources below. 
# ------------------------------------------------------------#

  IAMRoleforFlowlogs:
    Type: "AWS::IAM::Role"
    Condition: "EqualtoLogs" 
    Properties:
      RoleName: !Sub ${SystemName}-${EnvType}-${Tagprefix}-flowlogs-iamrole
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "vpc-flow-logs.amazonaws.com"
            Action:
              - "sts:AssumeRole"      
      Policies:
        - PolicyName: !Sub ${SystemName}-${EnvType}-${Tagprefix}-flowlogs-iampolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "logs:CreateLogGroup"
                  - "logs:CreateLogStream"
                  - "logs:PutLogEvents"
                  - "logs:DescribeLogGroups"
                  - "logs:DescribeLogStreams"
                Resource: "*"
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-flowlogs-iamrole
        - Key: Owner
          Value: !Sub ${Owner}    

  LogsforFlowlogs:
    Type: "AWS::Logs::LogGroup"
    Condition: "EqualtoLogs" 
    Properties:
      LogGroupName: !Sub ${SystemName}-${EnvType}-${Tagprefix}-logging
      RetentionInDays: !Ref RetentionDays
      Tags:
        - Key: Name
          Value: !Sub!Sub ${SystemName}-${EnvType}-${Tagprefix}-logging
        - Key: Owner
          Value: !Sub ${Owner}          

  VPCFlowLogs1:
    Type: AWS::EC2::FlowLog
    Condition: "EqualtoLogs" 
    Properties: 
      DeliverLogsPermissionArn: !GetAtt IAMRoleforFlowlogs.Arn
      LogDestinationType: !Ref LogType
      LogGroupName: !Ref LogsforFlowlogs
      MaxAggregationInterval: 600
      ResourceId: !Ref VPCID
      ResourceType: VPC
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-flowlogs
        - Key: Owner
          Value: !Sub ${Owner}    
      TrafficType: !Ref FilterType
    DependsOn: [ IAMRoleforFlowlogs, LogsforFlowlogs ]

# ------------------------------------------------------------#
# Create S3 Bucket and VPC Flow Logs.
# In case of destination for logging is s3, you can create these resources below. 
# ------------------------------------------------------------#

  S3BucketforFlowlogs:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Retain
    Condition: "Equaltos3" 
    Properties:
      BucketName: !Sub ${SystemName}-${EnvType}-${Tagprefix}-s3bucket-logging-${AWS::AccountId}
      PublicAccessBlockConfiguration: 
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      VersioningConfiguration:
        Status: Suspended          
      BucketEncryption:
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault: 
              SSEAlgorithm: AES256                  
      LifecycleConfiguration:
        Rules:
          - Id: !Sub ${SystemName}-${EnvType}-${Tagprefix}-lifecycle-s3bucket-logging
            Status: Enabled
            ExpirationInDays: 30
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      NotificationConfiguration:
        EventBridgeConfiguration:
          EventBridgeEnabled: true           
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-s3bucket-logging-${AWS::AccountId}
        - Key: Owner
          Value: !Sub ${Owner}     
   
  VPCFlowLogs2:
    Type: AWS::EC2::FlowLog
    Condition: "Equaltos3" 
    Properties: 
      DestinationOptions:
        FileFormat: plain-text
        HiveCompatiblePartitions: false
        PerHourPartition: false 
      LogDestination: !Sub "arn:aws:s3:::${S3BucketforFlowlogs}"
      LogDestinationType: !Ref LogType
      MaxAggregationInterval: 600
      ResourceId: !Ref VPCID
      ResourceType: VPC
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-flowlogs
        - Key: Owner
          Value: !Sub ${Owner}    
      TrafficType: !Ref FilterType
    DependsOn: S3BucketforFlowlogs

# ------------------------------------------------------------#
# Outputs
# This can output each value specified as output section.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html.
# ------------------------------------------------------------# 

Outputs:

# ------------------------------------------------------------#
# For CloudWatch logs
# ------------------------------------------------------------#

  IAMRoleforFlowlogs:
    Description: IAMRoleforFlowlogs
    Value: !Ref IAMRoleforFlowlogs
    Condition: "EqualtoLogs" 

  LogsforFlowlogs:
    Description: LogsforFlowlogs
    Value: !Ref LogsforFlowlogs  
    Condition: "EqualtoLogs" 

  VPCFlowLogs1:
    Description: VPCFlowLogs1
    Value: !Ref VPCFlowLogs1  
    Condition: "EqualtoLogs"   

# ------------------------------------------------------------#
# For S3 Bucket
# ------------------------------------------------------------#

  VPCFlowLogsS3Bucket:
    Description: S3BucketforFlowlogs
    Value: !Ref S3BucketforFlowlogs
    Condition: "Equaltos3" 

  VPCFlowLogs2:
    Description: VPCFlowLogs2
    Value: !Ref VPCFlowLogs2
    Condition: "Equaltos3"

5. テンプレートの補足

テンプレートに関して、以下の通り補足します。

5.1 Metadata/Parameters

 メタデータおよびパラメターセクションで、以下の値を定義します。

項目 備考
SystemName プロジェクト名や利用目的等を入力する
EnvType デプロイする環境を選択する
検証、ステージング、本番の3点
Tagprefix 任意で入力するPrefix値
Owner 作業者、所有者、コスト管理用に入力する
VPCID フローログを作成するVPC情報を入力する
FilterType 取得するトラフィックの種類を選択する
ACCEPT 許可されたトラフィックのみ
REJECT 拒否されたトラフィックのみ
ALL 全てのトラフィック
LogType フローログの格納先を選択する
cloud-watch-logs CloudWatch Logs
s3 S3バケット
RetentionDays フローログを格納先をCloudWatch Logsにした場合、保管する期間を指定する
  • テンプレートで生成する各リソース名とNameタグの値に、SystemNameEnvTypeTagprefixの3点を含みます。

    • OwnerはOwnerタグの値に利用します。
  • Parameterに入力する関係でRetentionDaysは格納先がS3の場合でも入力する必要があります。

    • S3の場合はライフサイクル設定で30日固定にしています。変更されたい場合はプロパティ側の値を直接変更するか、Parameterに追加する等の工夫が必要です。

5.2 想定ユースケース

 今回のテンプレートは、次の様なユースケースを想定して作成しました。

  • フローログは顧客の要望に応じて、CloudWatch Logs、S3の好きな方に格納する
    • ConditionsセクションでLogTypeに応じて作成するリソースを分けている
  • デフォルトフォーマットで使用する
    • カスタムフォーマットに変更したい場合は、プロパティでLogFormatを用いる必要がある
  • フローログを作成するリソースは「VPC」
    • VPC、サブネット、ネットワークインタフェースのいずれかから選択できるが、このテンプレートでは「VPC」固定にしている
  • フローログの集約期間は10分
  • ファイルフォーマットはデフォルト
    • parquetを利用したい場合はDestinationOptionsFileFormatplain-textから変更する
    • HiveCompatiblePartitionsfalse
    • PerHourPartitionfalseのログのパーティーションを変更したい場合はTrueに変更する

5.3 動作確認

 実際に動作を確認してみます。
上記のテンプレートを用いてLogs用とS3用のフローログを作成します。

スタック名:FlowLogs-ClouWatchLogs
格納先がCloudWatch Logs

項目 備考
SystemName mitsuo1
EnvType dev
Tagprefix logging
Owner mitsuo
VPCID 別途作成済みのVPCID
FilterType ALL
LogType cloud-watch-logs
RetentionDays 30

スタック名:FlowLogs-S3
格納先がS3バケット

項目 備考
SystemName mitsuo2
EnvType dev
Tagprefix logging
Owner mitsuo
VPCID 別途作成済みのVPCID
FilterType ALL
LogType s3
RetentionDays 30

ではスタックを作成します。

image

VPCにフローログが作成されたことを確認します。

image
image
image

VPC内にEC2を2台作成し、一方のインスタンスからもう一方のインスタンスに対してpingコマンドを実行します。

image

続いてフローログが出力されている事を確認します。

CloudWatch Logs

image

S3バケット

image

また、S3バケットの場合は、バケットポリシーが自動的に追加された事が確認できています。
XXXXXXXXXXXXにはアカウントIDが入ります。

{
    "Version": "2012-10-17",
    "Id": "AWSLogDeliveryWrite20150319",
    "Statement": [
        {
            "Sid": "AWSLogDeliveryWrite",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::mitsuo2-dev-logging-s3bucket-logging-XXXXXXXXXXXX/AWSLogs/XXXXXXXXXXXX/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "XXXXXXXXXXXX",
                    "s3:x-amz-acl": "bucket-owner-full-control"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:*"
                }
            }
        },
        {
            "Sid": "AWSLogDeliveryAclCheck",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws:s3:::mitsuo2-dev-logging-s3bucket-logging-XXXXXXXXXXXX",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "XXXXXXXXXXXX"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:*"
                }
            }
        }
    ]
}

5.4 まとめ

 顧客の要望によって可変になる部分はどうしてもありますが、なるべく標準化をする事が出来たのではないでしょうか。
S3ログへ直接格納できる機能は後からリリースされたので、テンプレートが分かれて紹介されるケースはよくありますが、まとめた物があまりなかったので作ってみました。

設定する単位がVPC、サブネットなどのリソース毎になるので、別にテンプレートが分かれてても良いのでは?と思った事は秘密です

このブログが誰かの役に立てばと思います。Mituoでした!!

5.5 参考資料

AWS::EC2::FlowLog

Discussion