Network Firewall のログ記録を有効化する設定手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、 「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。

この記事では、Network Firewall のログ記録を有効にする必要があることについて、リスクと対策を解説します。

ポリシーの説明

AWS Network Firewallは、VPCレベルでのネットワークトラフィックの検査と制御を提供するマネージドファイアウォールサービスです。ファイアウォールのログ記録を有効にすることで、許可・拒否されたトラフィック、アラート、フロー情報などを記録し、セキュリティの可視性を高め、インシデント対応やコンプライアンス要件を満たすことができます。

リスク Network Firewallのログ記録が無効な場合、以下のようなリスクが存在します:

  • ネットワーク攻撃や不正アクセス試行を検知できない
  • セキュリティインシデント発生時の原因調査や影響範囲の特定が困難
  • ファイアウォールルールの効果を検証できず、過剰または不足なルール設定に気づけない
  • コンプライアンス要件(PCI-DSS、HIPAA等)で求められる監査証跡を提供できない
  • トラフィックパターンの分析ができず、異常な通信を識別できない

修復方法

コンソールでの修復手順 AWSのコンソールを使用して、Network Firewallのログ記録を有効化します。

  1. AWS管理コンソールにログインし、VPCコンソールに移動します
  2. 左側のナビゲーションペインから「ネットワークファイアウォール」→「ファイアウォール」を選択します
  1. ログ記録を有効にしたいファイアウォールの名前をクリックします
  2. 「Firewallの詳細」で「ログ記録」セクションを確認します
  3. 「Edit」ボタンをクリックしてログ設定画面を開きます
  4. 「Logging」セクションで以下の設定を行います:
    • 「Enable logging」チェックボックスをオンにします
    • ログタイプを選択(複数選択可能):
      • Alert logs: ルールマッチによるアラート情報
      • Flow logs: すべての接続フロー情報
  5. ログの送信先を設定:
    • CloudWatch Logs: ロググループを選択または新規作成
    • S3 bucket: S3バケットを選択、プレフィックスを指定
    • Kinesis Data Firehose: 配信ストリームを選択
  6. 各ログタイプごとに送信先を設定できます
  1. 「Save」ボタンをクリックして設定を保存します
  2. ステータスが「Updating」から「Active」に戻るまで待ちます

Terraformでの修復手順

Network Firewallのログ記録を有効にするTerraformコードのサンプルです。

logging_configuration にて、Log Typeと送付先を指定すればよいです。

# ログ設定
resource "aws_networkfirewall_logging_configuration" "main" {
  firewall_arn = aws_networkfirewall_firewall.main.arn

  logging_configuration {
    # アラートログの設定
    log_destination_config {
      log_type             = "ALERT"
      log_destination_type = "CloudWatchLogs"

      log_destination = {
        logGroup = aws_cloudwatch_log_group.network_firewall_alert.name
      }
    }

    # フローログの設定(CloudWatch Logs)
    log_destination_config {
      log_type             = "FLOW"
      log_destination_type = "CloudWatchLogs"

      log_destination = {
        logGroup = aws_cloudwatch_log_group.network_firewall_flow.name
      }
    }

    # アラートログの設定(S3への長期保存)
    log_destination_config {
      log_type             = "ALERT"
      log_destination_type = "S3"

      log_destination = {
        bucketName = aws_s3_bucket.firewall_logs.id
        prefix     = "alert-logs/"
      }
    }
  }
}

# CloudWatch Logsロググループの作成
resource "aws_cloudwatch_log_group" "network_firewall_alert" {
  name              = "/aws/networkfirewall/${var.firewall_name}/alert"
  retention_in_days = 30

  kms_key_id = aws_kms_key.logs.arn

  tags = {
    Name = "${var.firewall_name}-alert-logs"
    Type = "NetworkFirewall"
  }
}

resource "aws_cloudwatch_log_group" "network_firewall_flow" {
  name              = "/aws/networkfirewall/${var.firewall_name}/flow"
  retention_in_days = 7  # フローログは量が多いため短期間保持

  kms_key_id = aws_kms_key.logs.arn

  tags = {
    Name = "${var.firewall_name}-flow-logs"
    Type = "NetworkFirewall"
  }
}

# S3バケット(ログ保存用)
resource "aws_s3_bucket" "firewall_logs" {
  bucket = "${var.firewall_name}-logs-${data.aws_caller_identity.current.account_id}"

  tags = {
    Name = "${var.firewall_name}-logs"
    Type = "NetworkFirewall"
  }
}

# S3バケットの暗号化設定
resource "aws_s3_bucket_server_side_encryption_configuration" "firewall_logs" {
  bucket = aws_s3_bucket.firewall_logs.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.s3.arn
    }
  }
}

# S3バケットのライフサイクル設定
resource "aws_s3_bucket_lifecycle_configuration" "firewall_logs" {
  bucket = aws_s3_bucket.firewall_logs.id

  rule {
    id     = "archive_old_logs"
    status = "Enabled"

    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 90
      storage_class = "GLACIER"
    }

    expiration {
      days = 365  # 1年後に削除
    }
  }
}

# S3バケットポリシー(Network Firewallのログ書き込み許可)
resource "aws_s3_bucket_policy" "firewall_logs" {
  bucket = aws_s3_bucket.firewall_logs.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AWSNetworkFirewallLogs"
        Effect = "Allow"
        Principal = {
          Service = "network-firewall.amazonaws.com"
        }
        Action = [
          "s3:PutObject"
        ]
        Resource = "${aws_s3_bucket.firewall_logs.arn}/*"
        Condition = {
          StringEquals = {
            "aws:SourceAccount" = data.aws_caller_identity.current.account_id
          }
        }
      }
    ]
  })
}

# KMSキー(ログ暗号化用)
resource "aws_kms_key" "logs" {
  description             = "KMS key for Network Firewall CloudWatch logs"
  deletion_window_in_days = 10
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "Enable IAM User Permissions"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
        }
        Action   = "kms:*"
        Resource = "*"
      },
      {
        Sid    = "Allow CloudWatch Logs"
        Effect = "Allow"
        Principal = {
          Service = "logs.${data.aws_region.current.name}.amazonaws.com"
        }
        Action = [
          "kms:Encrypt",
          "kms:Decrypt",
          "kms:ReEncrypt*",
          "kms:GenerateDataKey*",
          "kms:CreateGrant",
          "kms:DescribeKey"
        ]
        Resource = "*"
      }
    ]
  })
}

# Network Firewallポリシー
resource "aws_networkfirewall_firewall_policy" "main" {
  name = "${var.firewall_name}-policy"

  firewall_policy {
    stateless_default_actions          = ["aws:forward_to_sfe"]
    stateless_fragment_default_actions = ["aws:forward_to_sfe"]

    stateful_engine_options {
      rule_order = "STRICT_ORDER"
    }

    stateful_rule_group_reference {
      resource_arn = aws_networkfirewall_rule_group.main.arn
    }
  }

  tags = {
    Name = "${var.firewall_name}-policy"
  }
}

# Network Firewall
resource "aws_networkfirewall_firewall" "main" {
  name                = var.firewall_name
  firewall_policy_arn = aws_networkfirewall_firewall_policy.main.arn
  vpc_id              = var.vpc_id

  # サブネット設定
  dynamic "subnet_mapping" {
    for_each = var.firewall_subnet_ids
    content {
      subnet_id = subnet_mapping.value
    }
  }

  # 削除保護とサブネット変更保護
  delete_protection                = true
  subnet_change_protection         = true
  firewall_policy_change_protection = true

  tags = {
    Name = var.firewall_name
  }
}

# CloudWatchメトリクスアラーム(脅威検出)
resource "aws_cloudwatch_metric_alarm" "high_threat_count" {
  alarm_name          = "${var.firewall_name}-high-threat-count"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "DroppedPackets"
  namespace           = "AWS/NetworkFirewall"
  period              = "300"
  statistic           = "Sum"
  threshold           = "100"
  alarm_description   = "This metric monitors dropped packets"

  dimensions = {
    FirewallName = var.firewall_name
  }

  alarm_actions = [aws_sns_topic.alerts.arn]
}

# ログメトリクスフィルター(特定の脅威検出)
resource "aws_cloudwatch_log_metric_filter" "malware_detection" {
  name           = "${var.firewall_name}-malware-detection"
  log_group_name = aws_cloudwatch_log_group.network_firewall_alert.name
  pattern        = "[timestamp, request_id, firewall_name, availability_zone, event_type=ALERT, alert_type=MALWARE, ...]"

  metric_transformation {
    name      = "MalwareDetectionCount"
    namespace = "NetworkFirewall/Security"
    value     = "1"
  }
}

# SNSトピック(アラート通知用)
resource "aws_sns_topic" "alerts" {
  name = "${var.firewall_name}-alerts"

  kms_master_key_id = aws_kms_key.sns.id
}

# Lambda関数(ログ分析用)
resource "aws_lambda_function" "log_analyzer" {
  filename         = "log_analyzer.zip"
  function_name    = "${var.firewall_name}-log-analyzer"
  role            = aws_iam_role.lambda.arn
  handler         = "index.handler"
  source_code_hash = filebase64sha256("log_analyzer.zip")
  runtime         = "python3.9"
  timeout         = 60

  environment {
    variables = {
      SNS_TOPIC_ARN = aws_sns_topic.alerts.arn
    }
  }
}

# CloudWatch Logsサブスクリプションフィルター
resource "aws_cloudwatch_log_subscription_filter" "alert_logs" {
  name            = "${var.firewall_name}-alert-subscription"
  log_group_name  = aws_cloudwatch_log_group.network_firewall_alert.name
  filter_pattern  = ""
  destination_arn = aws_lambda_function.log_analyzer.arn
}

# 変数定義
variable "firewall_name" {
  description = "Name of the Network Firewall"
  type        = string
}

variable "vpc_id" {
  description = "VPC ID where the firewall will be deployed"
  type        = string
}

variable "firewall_subnet_ids" {
  description = "Subnet IDs for firewall endpoints"
  type        = list(string)
}

最後に

この記事では、Network Firewall のログ記録を有効化について、リスクと対策を解説しました。

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。

この記事をシェアする

クラウドセキュリティ対策実践集一覧へ戻る

貴社の利用状況に合わせた見積もりを作成します。

料金プランを詳しく見る