アクセスログを有効化したNLBとS3バケットをCloudFormationで作成してみた

TLS リスナーを有効とした Network Load Balancer (NLB)と、 NLB のアクセスログ保存を許可するバケットポリシーと、ライフサイクル設定を行ったS3バケットをCloudFormationを利用して作成する方法を紹介します。
2019.06.11

AWSチームのすずきです。

CloudFormationを利用して TLS リスナーを有効とした Network Load Balancer (NLB)と、 NLB のアクセスログ保存を許可するバケットポリシーと、ライフサイクル設定を行ったS3バケットを作成する機会がありましたので、 紹介させていただきます。

構成図

設定

ACM

TLSリスナーで利用するサーバ証明書、同一リージョンのACMに登録済みの証明書のARNを指定し利用します。

Parameters:
  AcmArnRegional:
    Description: SSL certificate for ELB
    Type: String
    Default: 'arn:aws:acm:ap-northeast-1:000000000000:certificate/000-000-000-000'

NLB

LoadBalancerAttributes

EIP、TLSリスナー設定を行ったNLB、S3へのアクセスログ出力を有効化しています。

Parameters:
  VpcId:
    Description: VPC ID
    Type: AWS::EC2::VPC::Id
    Default: ''
  ElbSubnetId1:
    Description: Subnet IDs
    Type: AWS::EC2::Subnet::Id
    Default: ''
  ElbSubnetId2:
    Description: Subnet IDs
    Type: AWS::EC2::Subnet::Id
    Default: ''
Resources:
  NlbEIP1:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  NlbEIP2:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  NlbLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    DependsOn: NlbEIP2
    Properties:
      LoadBalancerAttributes:
        - Key: access_logs.s3.enabled
          Value: true
        - Key: access_logs.s3.bucket
          Value: !Ref 'S3BucketLogs'
        - Key: access_logs.s3.prefix
          Value: !Sub 'nlb/${AWS::StackName}'
      SubnetMappings:
        - AllocationId: !GetAtt 'NlbEIP1.AllocationId'
          SubnetId: !Ref 'ElbSubnetId1'
        - AllocationId: !GetAtt 'NlbEIP2.AllocationId'
          SubnetId: !Ref 'ElbSubnetId2'
      Tags:
        - Key: StackId
          Value: !Sub '${AWS::StackId}'
      Type: network
  NlbTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Port: 80
      Protocol: TCP
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: '20'
      VpcId: !Ref 'VpcId'
  NlbListenerHTTPS:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref 'NlbTargetGroup'
      LoadBalancerArn: !Ref 'NlbLoadBalancer'
      Port: '443'
      Protocol: TLS
      Certificates:
        - CertificateArn: !Ref 'AcmArnRegional'

S3

ライフサイクル設定

ログ保存に伴うS3費用を抑制するため、S3に保存したログは14日で自動削除、 誤操作に備えて有効化したバージョニング情報は、7日間保持する設定としました。

パブリックアクセス設定制限

Webコンソールで新規作成したS3バケットを踏襲し、パブリックアクセスを制限する設定を行いました。

Resources:
  S3BucketLogs:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    Properties:
      BucketName: !Sub 'nlb-accesslogs-${AWS::Region}-${AWS::AccountId}'
      LifecycleConfiguration:
        Rules:
          - Id: AutoDelete
            Status: Enabled
            ExpirationInDays: 14
          - Id: NoncurrentVersionExpiration
            Status: Enabled
            NoncurrentVersionExpirationInDays: 7
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      VersioningConfiguration:
        Status: Enabled

S3バケットポリシー

Webコンソール (EC2ダッシュボード) の「ロードバランサー設定」で アクセスログの設定時に「この場所の作成」をチェックして作成したS3バケットは、 ALB/CLB 用と、 NLB 用のバケットポリシーが併記されます。(2019年6月現在)

Webコンソール設定例

  • 属性の編集

  • S3バケット作成指定

  • S3バケットポリシー

Webコンソール設定を踏襲し、 従来のELB(ALB/CLB) 用の許可に加え、NLBのS3アクセスログを担う「delivery.logs.amazonaws.com」に対し、「s3:PutObject」、「s3:GetBucketAcl」の許可を付与、 ALB/CLB 、NLB のアクセスログ保存先として利用できるS3バケットポリシーを作成しました。

Mappings:
  S3Config:
    us-east-1:
      BucketPrincipal: '127311923021'
    us-east-2:
      BucketPrincipal: '033677994240'
    us-west-1:
      BucketPrincipal: '027434742980'
    us-west-2:
      BucketPrincipal: '797873946194'
    ca-central-1:
      BucketPrincipal: '985666609251'
    eu-central-1:
      BucketPrincipal: '054676820928'
    eu-west-1:
      BucketPrincipal: '156460612806'
    eu-west-2:
      BucketPrincipal: '652711504416'
    eu-west-3:
      BucketPrincipal: '009996457667'
    eu-north-1:
      BucketPrincipal: '897822967062'
    ap-east-1:
      BucketPrincipal: '754344448648'
    ap-northeast-1:
      BucketPrincipal: '582318560864'
    ap-northeast-2:
      BucketPrincipal: '600734575887'
    ap-northeast-3:
      BucketPrincipal: '383597477331'
    ap-southeast-1:
      BucketPrincipal: '114774131450'
    ap-southeast-2:
      BucketPrincipal: '783225319266'
    ap-south-1:
      BucketPrincipal: '718504428378'
    sa-east-1:
      BucketPrincipal: '507241528517'
    us-gov-west-1:
      BucketPrincipal: '048591011584'
    us-gov-east-1:
      BucketPrincipal: '190560391635'
    cn-north-1:
      BucketPrincipal: '638102146993'
    cn-northwest-1:
      BucketPrincipal: '037604701340'
Resources:
  S3BucketLogsPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref 'S3BucketLogs'
      PolicyDocument:
        Id: ElblogsBucketPolicy
        Statement:
          - Sid: AWSLogDeliveryWrite
            Effect: Allow
            Action:
              - s3:PutObject
            Resource:
              - !Sub 'arn:aws:s3:::${S3BucketLogs}/*'
            Principal:
              Service: delivery.logs.amazonaws.com
            Condition:
              StringEquals:
                s3:x-amz-acl: bucket-owner-full-control
          - Sid: AWSLogDeliveryAclCheck
            Effect: Allow
            Action:
              - s3:GetBucketAcl
            Resource:
              - !Sub 'arn:aws:s3:::${S3BucketLogs}'
            Principal:
              Service: delivery.logs.amazonaws.com
          - Sid: AddPerm
            Effect: Allow
            Action:
              - s3:PutObject
            Resource:
              - !Sub 'arn:aws:s3:::${S3BucketLogs}/*'
            Principal:
              AWS: !FindInMap
                - S3Config
                - !Ref 'AWS::Region'
                - BucketPrincipal

既存の ELB アクセスログ 用に設定されたS3 バケットを NLBのアクセスログ保存先とする場合、パケットポリシーの追記が必要です。

  • ELB(ALB/CLB)、NLB兼用のバケットポリシー(東京リージョン例)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AWSConsoleStmt",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::582318560864:root"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::bucket_name/AWSLogs/123456789012/*"
    },
    {
      "Sid": "AWSLogDeliveryWrite",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "delivery.logs.amazonaws.com"
        ]
      },
      "Action": [
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::bucket_name/AWSLogs/123456789012",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    },
    {
      "Sid": "AWSLogDeliveryAclCheck",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "delivery.logs.amazonaws.com"
        ]
      },
      "Action": [
        "s3:GetBucketAcl"
      ],
      "Resource": "arn:aws:s3:::bucket_name/AWSLogs/123456789012/*"
    }
  ]
}

Network Load Balancer のアクセスログ: バケットの要件

まとめ

NLBのアクセスログ 、HTTPS 接続に問題が発生した際のトラブルシューティングに有用な情報が記録されています。 NLBのTLSリスナーを不特定多数のクライアントがHTTPS接続するシステムでは、NLBのアクセスログを設定する事をおすすめします。

NLB と ALB のアクセスログは違うんやで、という話

テンプレート

今回利用したCloudFormationテンプレートです。