Amazon SQS キューアクセスポリシーでパブリックアクセスを禁止する設定手順

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

この記事では、Amazon SQS キューアクセスポリシーでパブリックアクセスを禁止する設定手順について、リスクと対策を解説します。

ポリシーの説明

Amazon Simple Queue Service (SQS) は、分散型アプリケーション間でメッセージを安全に送受信するためのフルマネージドメッセージキューイングサービスです。SQSキューへのアクセスは、キューアクセスポリシー(リソースベースのポリシー)によって制御されます。

しかし、アクセスポリシーの設定を誤ると、意図せずにインターネット全体からキューへのアクセスを許可してしまう可能性があります。これは、Principal に “*” を指定し、適切な条件(Condition)を設定しない場合に発生します。

パブリックアクセスが許可される典型的なパターン:

  • Principal に “*” を使用し、Condition で制限を設けていない
  • Principal.AWS に “*” を使用している
  • 誤って Effect を “Allow” に設定し、広範囲なアクセスを許可している

修復方法

修復前の確認事項

修復を開始する前に、以下の点を確認してください:

  • 現在のキューアクセスパターンを把握し、正当なアクセス元を特定
  • CloudTrail ログで実際のアクセス履歴を確認
  • アプリケーションが使用している認証メカニズムを理解

コンソールでの修復手順

AWSのコンソールを使用して、SQSキューのアクセスポリシーを確認し、パブリックアクセスを禁止する手順を説明します。

  1. Amazon SQSコンソールにアクセス
    • AWSマネジメントコンソールにログイン
    • 「Amazon SQS」サービスを検索して開く
  2. キューの一覧を確認
    • 左側のナビゲーションペインで「キュー」を選択
    • 既存のキューの一覧が表示される
  3. キューのアクセスポリシーを確認
    • 確認したいキュー名をクリック
    • 「アクセスポリシー」タブを選択
    • 現在のポリシーをレビュー
  4. パブリックアクセスを特定 以下のようなポリシーがある場合は修正が必要です。
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": [
      "sqs:SendMessage",
      "sqs:ReceiveMessage",
      "sqs:DeleteMessage",
      "sqs:GetQueueAttributes"
    ],
    "Resource": "arn:aws:sqs:region:account-id:queue-name"
  }]
}
  1. アクセスポリシーを編集
    • 「編集」ボタンをクリック
    • ポリシーエディターが開く
  2. 制限的なポリシーに更新
    • Principal を特定のAWSアカウントやIAMロールに変更または、Condition を追加して送信元を制限
    例1: 特定のAWSアカウントのみに制限
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::123456789012:root"
    },
    "Action": ["sqs:SendMessage", "sqs:ReceiveMessage", "sqs:DeleteMessage"],
    "Resource": "arn:aws:sqs:region:account-id:queue-name"
  }]
}
  1. 例2: 特定のIAMロールのみに制限
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": [
        "arn:aws:iam::123456789012:role/ApplicationRole",
        "arn:aws:iam::123456789012:role/ProcessingRole"
      ]
    },
    "Action": ["sqs:SendMessage", "sqs:ReceiveMessage", "sqs:DeleteMessage"],
    "Resource": "arn:aws:sqs:region:account-id:queue-name"
  }]
}
  1. 例3: VPCエンドポイント経由のアクセスのみ許可
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::123456789012:root"
    },
    "Action": [
      "sqs:SendMessage",
      "sqs:ReceiveMessage",
      "sqs:DeleteMessage",
      "sqs:GetQueueAttributes"
    ],
    "Resource": "arn:aws:sqs:region:account-id:queue-name",
    "Condition": {
      "StringEquals": {
        "aws:SourceVpce": "vpce-1234567890abcdef0"
      }
    }
  }]
}
  1. 変更を保存
    • 「変更の保存」ボタンをクリック
    • 確認ダイアログで「保存」を選択
  2. ポリシーの検証
    • 保存後、ポリシーが正しく適用されていることを確認
    • 「パブリックアクセス」の警告が表示されていないことを確認
    • 正当なアプリケーションからのアクセスが継続して機能することをテスト

Terraformでの修復手順

SQSキューのアクセスポリシーでパブリックアクセスを禁止するTerraformコードと、主要な修正ポイントを説明します。

# SQSキューの定義
resource "aws_sqs_queue" "application_queue" {
  name                      = "application-messages-queue"
  delay_seconds            = 0
  max_message_size         = 262144
  message_retention_seconds = 345600
  receive_wait_time_seconds = 10

  # 暗号化の設定(セキュリティのベストプラクティス)
  kms_master_key_id                 = aws_kms_key.sqs_key.id
  kms_data_key_reuse_period_seconds = 300

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

  tags = {
    Name        = "ApplicationQueue"
    Environment = "Production"
    Purpose     = "Internal-Only"
  }
}

# KMSキーの定義(暗号化用)
resource "aws_kms_key" "sqs_key" {
  description             = "KMS key for SQS queue encryption"
  deletion_window_in_days = 10
  enable_key_rotation     = true
}

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

# デッドレターキュー
resource "aws_sqs_queue" "dlq" {
  name                      = "application-messages-dlq"
  kms_master_key_id         = aws_kms_key.sqs_key.id
  message_retention_seconds = 1209600  # 14 days
}

# 制限的なアクセスポリシー
resource "aws_sqs_queue_policy" "application_queue_policy" {
  queue_url = aws_sqs_queue.application_queue.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowSpecificAccountsOnly"
        Effect = "Allow"
        Principal = {
          AWS = [
            "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
          ]
        }
        Action = [
          "sqs:SendMessage",
          "sqs:ReceiveMessage",
          "sqs:DeleteMessage",
          "sqs:GetQueueAttributes"
        ]
        Resource = aws_sqs_queue.application_queue.arn
      },
      {
        Sid    = "AllowSpecificRolesOnly"
        Effect = "Allow"
        Principal = {
          AWS = [
            aws_iam_role.application_role.arn,
            aws_iam_role.processing_role.arn
          ]
        }
        Action = [
          "sqs:SendMessage",
          "sqs:ReceiveMessage",
          "sqs:DeleteMessage"
        ]
        Resource = aws_sqs_queue.application_queue.arn
      },
      {
        Sid    = "DenyInsecureTransport"
        Effect = "Deny"
        Principal = "*"
        Action = "sqs:*"
        Resource = aws_sqs_queue.application_queue.arn
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      }
    ]
  })
}

# 現在のアカウント情報
data "aws_caller_identity" "current" {}

# アプリケーションロール
resource "aws_iam_role" "application_role" {
  name = "sqs-application-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
  })
}

# 処理用ロール
resource "aws_iam_role" "processing_role" {
  name = "sqs-processing-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "lambda.amazonaws.com"
      }
    }]
  })
}

# VPCエンドポイント経由のアクセスに限定する例
resource "aws_sqs_queue_policy" "vpc_endpoint_only_policy" {
  queue_url = aws_sqs_queue.application_queue.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowVPCEndpointOnly"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
        }
        Action   = "sqs:*"
        Resource = aws_sqs_queue.application_queue.arn
        Condition = {
          StringEquals = {
            "aws:SourceVpce" = aws_vpc_endpoint.sqs_endpoint.id
          }
        }
      }
    ]
  })
}

# VPCエンドポイントの定義(プライベートアクセス用)
resource "aws_vpc_endpoint" "sqs_endpoint" {
  vpc_id              = var.vpc_id
  service_name        = "com.amazonaws.${var.region}.sqs"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = var.private_subnet_ids
  security_group_ids  = [aws_security_group.vpc_endpoint_sg.id]
  private_dns_enabled = true
}

# VPCエンドポイント用セキュリティグループ
resource "aws_security_group" "vpc_endpoint_sg" {
  name        = "sqs-vpc-endpoint-sg"
  description = "Security group for SQS VPC endpoint"
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [var.vpc_cidr]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# 出力:キューのセキュリティ状態を確認
output "queue_security_status" {
  value = {
    queue_url        = aws_sqs_queue.application_queue.url
    encryption_enabled = aws_sqs_queue.application_queue.kms_master_key_id != null
    vpc_endpoint_id   = aws_vpc_endpoint.sqs_endpoint.id
  }
  description = "SQSキューのセキュリティ設定状態"
}

Terraformコードの主要なポイント:

  1. 明示的なPrincipal指定: ワイルドカード()の使用を避け、特定のAWSアカウント、IAMロール、またはサービスを明示的に指定します。
  2. 最小権限の原則: 必要最小限のアクション(SendMessage、ReceiveMessage等)のみを許可し、不要な権限は付与しません。
  3. 条件の活用: Conditionブロックを使用して、アクセス元のIPアドレス、VPCエンドポイント、セキュアな転送の要求などの追加制限を設定します。
  4. 暗号化の実装: KMSを使用してキューの内容を暗号化し、データの機密性を保護します。
  5. VPCエンドポイントの利用: プライベートネットワーク内からのみアクセス可能にすることで、インターネット経由のアクセスを完全に遮断します。
  6. タグによる管理: Purpose タグなどを使用して、キューの用途を明確にし、監査やコスト管理を容易にします。

最後に

この記事では、Amazon SQS キューアクセスポリシーでパブリックアクセスを禁止する設定手順について、リスクと対策を解説しました。

SQSキューへのパブリックアクセスを適切に制限することは、データセキュリティの基本です。定期的なアクセスポリシーの監査と、最小権限の原則に基づいた設定により、メッセージキューのセキュリティを維持することができます。

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

参考情報

この記事をシェアする

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

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

料金プランを詳しく見る