パブリックアクセス可能なDMSレプリケーションインスタンスの非公開化設定手順

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

この記事では、DMSレプリケーションインスタンスのパブリックアクセス設定に関するセキュリティポリシーについて解説します。

ポリシーの説明

[DMS.1] Database Migration Service のレプリケーションインスタンスは非パブリックである必要があります

Security Hub コントロール AWS DMS – AWS Security Hub

このコントロールは、 AWS DMS レプリケーションインスタンスがパブリックかどうかをチェックします。これを行うために、PubliclyAccessible フィールドの値を調査します。

このポリシーは、DMSレプリケーションインスタンスがインターネットから直接アクセスできないようにすることを求めています。パブリックアクセスを許可すると、レプリケーションインスタンス自体への不正アクセスや、移行中のデータへの意図しないアクセス・漏洩のリスクが高まります。DMSレプリケーションインスタンスは機密データにアクセスしたり、処理したりすることがあるため、厳格なアクセス制御が必要です。

修復方法

AWSコンソールでの修正手順

注意: DMSレプリケーションインスタンスのパブリックアクセス設定の変更は、インスタンスの置換を伴います。変更の適用には時間がかかり、一時的にインスタンスが利用できなくなる可能性があります。

  1. AWSマネジメントコンソールにログインし、DMSコンソールを開きます。
  2. 左側のナビゲーションペインで「レプリケーションインスタンス」を選択します。
  3. 修正対象のインスタンスを選択し、「変更」をクリックします。
  4. 「接続とセキュリティ」セクションで、「パブリックアクセス可能」のチェックボックスをオフにします。

Terraformでの修復手順

以下は、パブリックアクセスを無効にし、その他のセキュリティ設定(暗号化、プライベートサブネット配置など)を施した新しいDMSレプリケーションインスタンスをTerraformで作成するコード例です。

# KMS key for DMS encryption
resource "aws_kms_key" "dms" {
  description             = "KMS key for DMS encryption"
  deletion_window_in_days = 7
  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 = "*"
      }
    ]
  })

  tags = var.tags
}

# DMS用のIAMロール
resource "aws_iam_role" "dms" {
  name = "dms-vpc-role-${var.environment}"

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

# DMSのサブネットグループ(プライベートサブネットで構成)
resource "aws_dms_replication_subnet_group" "private" {
  replication_subnet_group_id          = "private-subnet-group-${var.environment}"
  replication_subnet_group_description = "Private subnet group for DMS"

  # ★重要: プライベートサブネットのみを使用
  subnet_ids = var.private_subnet_ids

  tags = var.tags
}

# DMSのセキュリティグループ
resource "aws_security_group" "dms" {
  name        = "dms-sg-${var.environment}"
  description = "Security group for DMS replication instance"
  vpc_id      = var.vpc_id

  # ★重要: インバウンドルールは必要最小限に制限
  ingress {
    description     = "Access from source database"
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    security_groups = var.source_security_group_ids
  }

  egress {
    description     = "Access to target database"
    from_port       = var.target_db_port
    to_port         = var.target_db_port
    protocol        = "tcp"
    security_groups = var.target_security_group_ids
  }

  tags = merge(var.tags, {
    Name = "dms-sg-${var.environment}"
  })
}

# DMSレプリケーションインスタンス
resource "aws_dms_replication_instance" "main" {
  replication_instance_id     = "dms-${var.environment}"
  replication_instance_class  = var.instance_class
  allocated_storage          = var.allocated_storage

  # ★重要: パブリックアクセスを無効化
  publicly_accessible        = false

  # ★重要: プライベートサブネットグループを使用
  replication_subnet_group_id = aws_dms_replication_subnet_group.private.id

  # ★重要: セキュリティグループの適用
  vpc_security_group_ids     = [aws_security_group.dms.id]

  # 暗号化設定
  kms_key_arn               = aws_kms_key.dms.arn

  # 可用性とメンテナンス
  multi_az                  = var.enable_multi_az
  preferred_maintenance_window = "sun:03:00-sun:04:00"
  auto_minor_version_upgrade  = true

  tags = var.tags
}

# CloudWatch アラーム
resource "aws_cloudwatch_metric_alarm" "dms_cpu" {
  alarm_name          = "dms-cpu-utilization-${var.environment}"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name        = "CPUUtilization"
  namespace          = "AWS/DMS"
  period             = "300"
  statistic          = "Average"
  threshold          = "80"
  alarm_description  = "DMS instance CPU utilization"
  alarm_actions      = var.alarm_sns_topic_arns

  dimensions = {
    ReplicationInstanceIdentifier = aws_dms_replication_instance.main.id
  }

  tags = var.tags
}

# Variables
variable "environment" {
  description = "Environment name"
  type        = string
}

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

variable "private_subnet_ids" {
  description = "List of private subnet IDs for DMS"
  type        = list(string)
}

variable "source_security_group_ids" {
  description = "List of security group IDs for source databases"
  type        = list(string)
}

variable "target_security_group_ids" {
  description = "List of security group IDs for target databases"
  type        = list(string)
}

variable "target_db_port" {
  description = "Port number of target database"
  type        = number
}

variable "instance_class" {
  description = "DMS instance class"
  type        = string
  default     = "dms.t3.medium"
}

variable "allocated_storage" {
  description = "Storage allocated to DMS instance in GB"
  type        = number
  default     = 50
}

variable "enable_multi_az" {
  description = "Enable Multi-AZ deployment"
  type        = bool
  default     = true
}

variable "tags" {
  description = "Tags for resources"
  type        = map(string)
  default     = {}
}

variable "alarm_sns_topic_arns" {
  description = "List of SNS topic ARNs for CloudWatch alarms"
  type        = list(string)
  default     = []
}

# Data sources
data "aws_caller_identity" "current" {}

主要な修正ポイントは以下の通りです:

  1. パブリックアクセスの無効化(最重要):
resource "aws_dms_replication_instance" "main" {
  # この設定が最も重要
  publicly_accessible = false
}

  1. プライベートサブネットの使用:
resource "aws_dms_replication_subnet_group" "private" {
  # プライベートサブネットのみを使用
  subnet_ids = var.private_subnet_ids
}

  1. セキュリティグループの適切な設定:
resource "aws_security_group" "dms" {
  # インバウンド/アウトバウンドルールを必要最小限に制限
  ingress {
    security_groups = var.source_security_group_ids
  }
  egress {
    security_groups = var.target_security_group_ids
  }
}

使用方法:

  1. 変数の設定:
# terraform.tfvars
environment              = "production"
vpc_id                  = "vpc-xxxxxx"
private_subnet_ids      = ["subnet-xxxxx", "subnet-yyyyy"]
source_security_group_ids = ["sg-source"]
target_security_group_ids = ["sg-target"]
target_db_port          = 3306
enable_multi_az         = true

  1. 既存のDMSインスタンスを修正する場合の手順: a. 新しいプライベートインスタンスを作成: terraform apply b. 移行タスクの停止と再作成:
    • 既存のタスクを停止
    • 新しいインスタンスで同じタスクを作成
    • タスクの設定を確認して開始
    c. 古いインスタンスの削除: terraform destroy -target=aws_dms_replication_instance.old

重要な注意点:

  • パブリックアクセス設定の変更には、上記のように新しいインスタンスの作成とタスクの再構成が必要です。
  • プライベートサブネット内のDMSインスタンスから、ソースデータベースやターゲットデータベースへネットワーク的に接続可能か(ルートテーブル、ネットワークACL、セキュリティグループ)を確認してください。
  • DMSインスタンスがAWSの他のサービス(S3など)にアクセスする必要がある場合は、VPCエンドポイント(Interface型またはGateway型)やNAT Gatewayなどの設定が必要になる場合があります。
  • セキュリティグループのルールは常に最小権限の原則に従って設定してください。

最後に

今回は、DMSレプリケーションインスタンスのパブリックアクセス設定について解説しました。パブリックアクセスを許可すると、不正アクセスやデータ漏洩のリスクが高まります。必ずパブリックアクセスを無効にし、VPC内に隔離して運用してください。

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。

運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。

最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです

この記事をシェアする

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

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

料金プランを詳しく見る