SQSキューの暗号化を有効化してメッセージを保護する手順

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

この記事では、SQSキューの暗号化を有効化してメッセージを保護する手順について、リスクと対策を解説します。

ポリシーの説明

Amazon Simple Queue Service (SQS) は、分散システム間のメッセージングを可能にするフルマネージドメッセージキューイングサービスです。SQSキューでサーバーサイド暗号化(SSE)を有効にすることで、キューに保存されるすべてのメッセージが保管時に自動的に暗号化されます。AWS Key Management Service (KMS) またはSQSマネージド暗号化を使用して、メッセージの機密性を保護し、コンプライアンス要件を満たすことができます。暗号化されたメッセージは、受信時に透過的に復号化されるため、アプリケーションの変更は不要です。

修復方法

コンソールでの修復手順

AWSのコンソールを使用して、SQSキューの暗号化を有効化します。

ステップ1: 対象キューの選択

  1. SQSコンソールでキュー一覧を表示
  2. 暗号化を有効にしたいキューを選択
  3. 「編集」ボタンをクリック

ステップ2: 暗号化の有効化

  1. 「暗号化」セクションにスクロール
  2. 「サーバー側の暗号化」を有効化
  3. 暗号化キーを選択(AWS管理またはカスタマー管理)
  4. データキー再利用期間を設定

ステップ3: 変更の保存

  1. 「変更の保存」をクリック
  2. 既存のメッセージも自動的に暗号化される
  3. 暗号化状態の確認(キューの詳細ページ)

Terraformでの修復手順

TerraformでSQSキューの暗号化を有効にするコードと、主要な修正ポイントを説明します。

# KMSキーの作成(カスタマー管理キーを使用する場合)
resource "aws_kms_key" "sqs_key" {
  description             = "KMS key for SQS queue encryption"
  deletion_window_in_days = 10
  enable_key_rotation     = true  # 年次の自動キーローテーション

  tags = {
    Name        = "sqs-encryption-key"
    Environment = "Production"
    Purpose     = "SQS Message Encryption"
  }
}

# KMSキーエイリアスの作成
resource "aws_kms_alias" "sqs_key_alias" {
  name          = "alias/sqs-encryption"
  target_key_id = aws_kms_key.sqs_key.key_id
}

# KMSキーポリシー(SQSサービスアクセス許可)
resource "aws_kms_key_policy" "sqs_key_policy" {
  key_id = aws_kms_key.sqs_key.id

  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 SQS to use the key"
        Effect = "Allow"
        Principal = {
          Service = "sqs.amazonaws.com"
        }
        Action = [
          "kms:Decrypt",
          "kms:GenerateDataKey"
        ]
        Resource = "*"
      }
    ]
  })
}

# 標準キューの作成(暗号化有効)
resource "aws_sqs_queue" "encrypted_standard_queue" {
  name                       = "encrypted-standard-queue"
  visibility_timeout_seconds = 30
  message_retention_seconds  = 345600  # 4日間
  max_message_size          = 262144   # 256 KB
  delay_seconds             = 0
  receive_wait_time_seconds = 10  # ロングポーリング

  # 暗号化設定 - 最重要設定
  # 注意: sqs_managed_sse_enabled と kms_master_key_id は排他的
  sqs_managed_sse_enabled = false  # KMS暗号化を使用する場合はfalse
  kms_master_key_id       = aws_kms_key.sqs_key.id  # カスタマー管理キー
  kms_data_key_reuse_period_seconds = 300  # 5分間(パフォーマンスとセキュリティのバランス)

  # デッドレターキュー設定
  redrive_policy = jsonencode({
    deadLetterTargetArn = aws_sqs_queue.dlq.arn
    maxReceiveCount     = 3
  })

  # タグ
  tags = {
    Name        = "Encrypted Standard Queue"
    Environment = "Production"
    Encryption  = "KMS-Enabled"
    Compliance  = "PCI-DSS-HIPAA"
  }
}

# FIFOキューの作成(暗号化有効)
resource "aws_sqs_queue" "encrypted_fifo_queue" {
  name                        = "encrypted-fifo-queue.fifo"
  fifo_queue                  = true
  content_based_deduplication = true
  deduplication_scope        = "queue"
  fifo_throughput_limit      = "perQueue"

  # 暗号化設定 - SQSマネージド暗号化(SSE-SQS)を使用
  sqs_managed_sse_enabled = true  # SSE-SQSを有効化(コスト無料)

  # FIFOキュー特有の設定
  visibility_timeout_seconds = 30
  message_retention_seconds  = 345600

  tags = {
    Name        = "Encrypted FIFO Queue"
    Environment = "Production"
    Encryption  = "AWS-Managed"
    Type        = "FIFO"
  }
}

# デッドレターキュー(暗号化有効)
resource "aws_sqs_queue" "dlq" {
  name                       = "dead-letter-queue"
  message_retention_seconds  = 1209600  # 14日間(最大)

  # DLQも暗号化
  kms_master_key_id         = aws_kms_key.sqs_key.id
  kms_data_key_reuse_period_seconds = 300

  tags = {
    Name    = "Dead Letter Queue"
    Purpose = "Failed Message Storage"
  }
}

# キューポリシー(アクセス制御)
resource "aws_sqs_queue_policy" "queue_policy" {
  queue_url = aws_sqs_queue.encrypted_standard_queue.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowSendMessage"
        Effect = "Allow"
        Principal = {
          AWS = var.producer_role_arns  # メッセージ送信者のロールARN
        }
        Action = [
          "sqs:SendMessage",
          "sqs:GetQueueAttributes"
        ]
        Resource = aws_sqs_queue.encrypted_standard_queue.arn
      },
      {
        Sid    = "AllowReceiveMessage"
        Effect = "Allow"
        Principal = {
          AWS = var.consumer_role_arns  # メッセージ受信者のロールARN
        }
        Action = [
          "sqs:ReceiveMessage",
          "sqs:DeleteMessage",
          "sqs:GetQueueAttributes"
        ]
        Resource = aws_sqs_queue.encrypted_standard_queue.arn
      }
    ]
  })
}

# CloudWatchアラーム(監視)
resource "aws_cloudwatch_metric_alarm" "queue_depth" {
  alarm_name          = "sqs-queue-depth-high"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "ApproximateNumberOfMessagesVisible"
  namespace           = "AWS/SQS"
  period              = "300"
  statistic           = "Average"
  threshold           = "1000"
  alarm_description   = "Alert when queue depth exceeds 1000 messages"
  alarm_actions       = [aws_sns_topic.alerts.arn]

  dimensions = {
    QueueName = aws_sqs_queue.encrypted_standard_queue.name
  }
}

# データソース
data "aws_caller_identity" "current" {}

# 変数定義
variable "producer_role_arns" {
  description = "List of IAM role ARNs allowed to send messages"
  type        = list(string)
}

variable "consumer_role_arns" {
  description = "List of IAM role ARNs allowed to receive messages"
  type        = list(string)
}

# 出力値
output "queue_url" {
  value       = aws_sqs_queue.encrypted_standard_queue.url
  description = "URL of the encrypted SQS queue"
}

output "queue_arn" {
  value       = aws_sqs_queue.encrypted_standard_queue.arn
  description = "ARN of the encrypted SQS queue"
}

output "kms_key_id" {
  value       = aws_kms_key.sqs_key.id
  description = "KMS key ID used for encryption"
  sensitive   = true
}

 

主要な修正ポイント

  1. sqs_managed_sse_enabled: trueでSQSマネージド暗号化(SSE-SQS)を使用(コスト無料)
  2. kms_master_key_id: KMSキーを使用する場合のキーのIDまたはARNを指定
  3. kms_data_key_reuse_period_seconds: データキー再利用期間(60-86400秒)
  4. enable_key_rotation: KMSキーの年次自動ローテーションを有効化
  5. redrive_policy: デッドレターキューも同様に暗号化を設定

最後に

この記事では、SQSキューの暗号化を有効化してメッセージを保護する手順について、包括的なリスク分析と具体的な修復方法を解説しました。

SQSキューの暗号化は、メッセージの機密性を保護し、PCI DSS、HIPAA、GDPRなどのコンプライアンス要件を満たすために不可欠です。SQSマネージド暗号化(SSE-SQS)またはKMS暗号化(SSE-KMS)を使用して、すべてのキューで暗号化を有効にすることを強く推奨します。既存のキューも簡単に暗号化を有効化できるため、速やかに対応してセキュリティリスクを軽減してください。

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

参考資料

この記事をシェアする

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

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

料金プランを詳しく見る