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

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

ポリシーの説明
Amazon Simple Queue Service (SQS) は、分散型アプリケーション間でメッセージを安全に送受信するためのフルマネージドメッセージキューイングサービスです。SQSキューへのアクセスは、キューアクセスポリシー(リソースベースのポリシー)によって制御されます。
しかし、アクセスポリシーの設定を誤ると、意図せずにインターネット全体からキューへのアクセスを許可してしまう可能性があります。これは、Principal に “*” を指定し、適切な条件(Condition)を設定しない場合に発生します。
パブリックアクセスが許可される典型的なパターン:
- Principal に “*” を使用し、Condition で制限を設けていない
- Principal.AWS に “*” を使用している
- 誤って Effect を “Allow” に設定し、広範囲なアクセスを許可している
修復方法
修復前の確認事項
修復を開始する前に、以下の点を確認してください:
- 現在のキューアクセスパターンを把握し、正当なアクセス元を特定
- CloudTrail ログで実際のアクセス履歴を確認
- アプリケーションが使用している認証メカニズムを理解
コンソールでの修復手順
AWSのコンソールを使用して、SQSキューのアクセスポリシーを確認し、パブリックアクセスを禁止する手順を説明します。
- Amazon SQSコンソールにアクセス
- AWSマネジメントコンソールにログイン
- 「Amazon SQS」サービスを検索して開く
- キューの一覧を確認
- 左側のナビゲーションペインで「キュー」を選択
- 既存のキューの一覧が表示される
- キューのアクセスポリシーを確認
- 確認したいキュー名をクリック
- 「アクセスポリシー」タブを選択
- 現在のポリシーをレビュー
- パブリックアクセスを特定 以下のようなポリシーがある場合は修正が必要です。
{
"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"
}]
}
- アクセスポリシーを編集
- 「編集」ボタンをクリック
- ポリシーエディターが開く
- 制限的なポリシーに更新
- Principal を特定のAWSアカウントやIAMロールに変更または、Condition を追加して送信元を制限
{
"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"
}]
}
- 例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"
}]
}
- 例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"
}
}
}]
}
- 変更を保存
- 「変更の保存」ボタンをクリック
- 確認ダイアログで「保存」を選択
- ポリシーの検証
- 保存後、ポリシーが正しく適用されていることを確認
- 「パブリックアクセス」の警告が表示されていないことを確認
- 正当なアプリケーションからのアクセスが継続して機能することをテスト
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コードの主要なポイント:
- 明示的なPrincipal指定: ワイルドカード()の使用を避け、特定のAWSアカウント、IAMロール、またはサービスを明示的に指定します。
- 最小権限の原則: 必要最小限のアクション(SendMessage、ReceiveMessage等)のみを許可し、不要な権限は付与しません。
- 条件の活用: Conditionブロックを使用して、アクセス元のIPアドレス、VPCエンドポイント、セキュアな転送の要求などの追加制限を設定します。
- 暗号化の実装: KMSを使用してキューの内容を暗号化し、データの機密性を保護します。
- VPCエンドポイントの利用: プライベートネットワーク内からのみアクセス可能にすることで、インターネット経由のアクセスを完全に遮断します。
- タグによる管理: Purpose タグなどを使用して、キューの用途を明確にし、監査やコスト管理を容易にします。
最後に
この記事では、Amazon SQS キューアクセスポリシーでパブリックアクセスを禁止する設定手順について、リスクと対策を解説しました。
SQSキューへのパブリックアクセスを適切に制限することは、データセキュリティの基本です。定期的なアクセスポリシーの監査と、最小権限の原則に基づいた設定により、メッセージキューのセキュリティを維持することができます。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。