RDSデータベースインスタンスでIAMデータベース認証が有効化する手順

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

この記事では、「[RDS.10] IAM 認証は RDS インスタンス用に設定する必要があります」について、リスクと対策を解説します。

ポリシーの説明

Amazon RDS の Security Hub コントロール – AWS Security Hub

このコントロールは、RDS DB インスタンスで IAM データベース認証が有効になっているかどうかをチェックします。RDS DB インスタンスに IAM 認証が設定されていない場合、コントロールは失敗します。このコントロールは、mysqlpostgresauroraaurora-mysqlaurora-postgresql および mariadb のエンジンタイプの RDS インスタンスのみを評価します。また、RDS インスタンスが結果を生成するには、availablebacking-upstorage-optimizationstorage-full のいずれかの状態になっている必要があります。

リスク

Amazon Relational Database Service (RDS) は、リレーショナルデータベースのセットアップ、運用、スケーリングを容易にするマネージドサービスです。RDSデータベースインスタンスへの認証に、従来のユーザー名とパスワードの組み合わせではなくIAMデータベース認証を使用していない場合、以下のようなセキュリティと運用上のリスクが発生します。

  • 認証情報の管理の複雑化と漏洩リスク:
    • 従来のパスワード認証では、パスワードのローテーション、安全な保管、配布が開発者や運用者にとって大きな負担となります。
    • ハードコードされたパスワードや、不適切に管理されたパスワードは、漏洩の主要な原因となり、不正アクセスにつながる可能性があります。
    • パスワードが漏洩した場合、それを更新し、すべてのアプリケーションやサービスに適用する作業は大規模なものになりがちです。
  • 権限管理の粒度の粗さ:
    • パスワード認証では、データベースユーザーごとにアクセス権限を設定する必要がありますが、AWS IAMの強力なポリシー管理機能と統合されていないため、AWSリソース全体の権限管理と一貫性が失われがちです。
    • 特定のIAMユーザーやロールからのデータベースアクセスを簡単に制限したり、許可したりすることが困難です。
  • 監査証跡の不十分さ:
    • 従来のデータベース認証では、誰がいつデータベースにアクセスしたか、そのアクセスがどのAWSのエンティティに関連付けられているかを特定するのが難しい場合があります。
    • IAMデータベース認証を有効にすると、CloudTrailログを通じてIAMユーザーやロールがデータベースにアクセスした履歴を詳細に追跡できるようになり、セキュリティ監査の精度が向上します。
  • コンプライアンス違反:
    • 多くのセキュリティフレームワークや規制(例: PCI DSS, HIPAA, GDPR)では、最小特権の原則の適用、認証情報の安全な管理、アクセスログの監視などが求められます。IAMデータベース認証を使用しない場合、これらのコンプライアンス要件を満たせない可能性があります。
  • 通信の暗号化の欠如:
    • IAMデータベース認証は、TLS(Transport Layer Security)/SSLを使用してデータベース接続を自動的に暗号化します。これにより、クライアントとデータベース間のデータ転送中にデータが傍受されるリスクが軽減されます。従来のパスワード認証では、別途TLS/SSL設定を行う必要があります。

対策

RDSデータベースインスタンスでIAMデータベース認証を有効にすることは、これらのリスクを軽減し、セキュリティと運用効率を大幅に向上させるためのベストプラクティスです。

  • IAMデータベース認証の有効化:
    • RDSインスタンス(またはクラスター)を作成または変更する際に、IAMデータベース認証を有効にします。
  • IAMポリシーの作成と適用:
    • データベースへのアクセスを許可するIAMユーザーまたはIAMロールに対して、適切なデータベースアクセス権限を付与するIAMポリシーを作成します。このポリシーには、rds-db:connectアクションを含める必要があります。
    • ポリシーでは、どのデータベースユーザー名として接続できるか、どのデータベースインスタンスに接続できるかを指定します。
  • DBユーザーの作成とマッピング:
    • データベース内には、対応するIAMユーザーまたはロールが接続時に使用するデータベースユーザーを作成します。例えば、MySQLではCREATE USER 'iam_user'@'%' IDENTIFIED WITH AWSAuthenticationPlugin; のように作成します。
  • アプリケーションからの接続方法の更新:
    • アプリケーションやクライアントがデータベースに接続する際、従来のパスワードではなく、AWS SDKやIAM認証に対応したデータベースドライバーを使用して一時的な認証トークンを取得し、それを使用して接続するようにコードを更新します。
  • CloudTrailとの統合:
    • IAMデータベース認証による接続試行はCloudTrailに記録されます。CloudTrailログをCloudWatch Logsに連携し、異常なアクセスパターンを検知するためのアラートを設定します。
  • 最小特権の原則の適用:
    • IAMポリシーを厳密に定義し、データベースへのアクセス権限を必要最小限に抑えます。

修復方法

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

AWSコンソールを使用して、RDSデータベースインスタンスでIAMデータベース認証を有効にします。

  1. RDSサービスへ移動:
    • AWSコンソールにログインし、RDSサービスを開きます。
  2. データベースインスタンスの選択:
    • 左側のナビゲーションペインで「データベース」を選択します。
    • IAMデータベース認証を有効にしたいRDSデータベースインスタンス(またはクラスター)を選択します。
  3. インスタンスの変更:
    • インスタンスの詳細ページの上部にある「変更」をクリックします。
  4. IAM DB認証の有効化:
    • 「認証」セクションまでスクロールします。
    • 「パスワードとIAMデータベース認証」にチェックを入れます。
  5. 変更の適用:
    • 変更画面の最下部にある「変更の適用」セクションで、変更をいつ適用するかを選択します。
      • すぐに適用: インスタンスのメンテナンスウィンドウを待たずに変更が適用されます。場合によっては、インスタンスの短時間のダウンタイムが発生する可能性があります
      • 次のメンテナンスウィンドウで適用: 次に予定されているメンテナンスウィンドウ中に変更が適用されます。
    • 選択後、「DB インスタンスを変更」をクリックして設定を完了します。
  6. (重要)データベース内のユーザー設定:
    • データベースに接続し、IAMユーザーやロールが接続時に使用するユーザー名(例: CREATE USER 'my_iam_user'@'%' IDENTIFIED WITH AWSAuthenticationPlugin; for MySQL)を作成します。
  7. (重要)IAMポリシーの設定:
    • IAMコンソールに移動し、データベースにアクセスするIAMユーザーやロールに、rds-db:connect アクションを許可するポリシーをアタッチします。

Terraformでの修復手順

TerraformでRDSデータベースインスタンスのIAMデータベース認証を有効にするには、aws_db_instance または aws_rds_cluster リソースの manage_master_user_password パラメータを true に設定し、iam_database_authentication_enabled パラメータを true に設定します。

注: manage_master_user_password は、RDS DBインスタンスのIAMデータベース認証を有効にするための前提条件ではありません。これは、RDSがマスターユーザーのパスワードを自動生成し、Secrets Managerに保存するかどうかを制御する別の設定です。IAMデータベース認証を有効にする場合は、単にiam_database_authentication_enabled = trueを設定すれば十分です。

以下は、aws_db_instance (単一インスタンス) の例ですが、aws_rds_cluster (クラスター) でも同様にiam_database_authentication_enabledを設定します。

# RDS DBインスタンスの定義
resource "aws_db_instance" "my_db_instance" {
  allocated_storage    = 20
  storage_type         = "gp2"
  engine               = "mysql" # または postgres, auroraなど
  engine_version       = "8.0.32" # 使用するバージョンに合わせる
  instance_class       = "db.t3.micro"
  db_name              = "mydb"
  username             = "admin" # 従来のマスターユーザー (IAM認証とは別)
  password             = "your_strong_password" # Secrets Manager等で管理を推奨

  # IAMデータベース認証を有効化
  iam_database_authentication_enabled = true

  multi_az             = false
  skip_final_snapshot  = true # 本番環境では false に設定
  publicly_accessible  = false # 公開アクセスは無効にすることを推奨
  vpc_security_group_ids = [aws_security_group.db_sg.id] # DBインスタンスのSG
  db_subnet_group_name = aws_db_subnet_group.main_db_subnet_group.name

  tags = {
    Name = "MyRDSInstanceWithIAMAuth"
  }
}

# DBインスタンスにアクセスするためのセキュリティグループ
resource "aws_security_group" "db_sg" {
  name        = "db-security-group"
  description = "Allow inbound traffic to RDS instance"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 3306 # MySQLのポート (PostgreSQLは5432など)
    to_port     = 3306
    protocol    = "tcp"
    # ここにアプリケーションサーバーのセキュリティグループIDなどを設定
    security_groups = [aws_security_group.app_sg.id] # 例: アプリケーションサーバーのSG
    # または、より限定されたCIDRブロックを設定
    # cidr_blocks = ["10.0.0.0/16"] 
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# DBサブネットグループの定義
resource "aws_db_subnet_group" "main_db_subnet_group" {
  name       = "main-db-subnet-group"
  subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_c.id] # あなたのプライベートサブネットIDに置き換え
  tags = {
    Name = "MainDBSubnetGroup"
  }
}

# アプリケーションサーバーのセキュリティグループ (例: DBにアクセスする側)
resource "aws_security_group" "app_sg" {
  name        = "app-security-group"
  description = "Security group for application servers"
  vpc_id      = aws_vpc.main.id

  # アプリケーションサーバーからのアウトバウンドDBアクセスを許可
  egress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    security_groups = [aws_security_group.db_sg.id]
  }
  # その他のルール
}

# (オプション) データベースにアクセスするIAMロールの定義例
resource "aws_iam_role" "db_access_role" {
  name = "application-db-access-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com" # EC2インスタンスからアクセスする場合
        }
      },
    ]
  })
}

# (オプション) IAMロールにDB接続権限を付与するポリシー
resource "aws_iam_policy" "db_connect_policy" {
  name        = "application-db-connect-policy"
  description = "Policy for application to connect to RDS via IAM"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = "rds-db:connect"
        Resource = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${aws_db_instance.my_db_instance.db_instance_identifier}/${aws_db_instance.my_db_instance.username}" # ここでDBインスタンスとDBユーザーを指定
      },
    ]
  })
}

# (オプション) IAMロールにポリシーをアタッチ
resource "aws_iam_role_policy_attachment" "db_access_attach" {
  role       = aws_iam_role.db_access_role.name
  policy_arn = aws_iam_policy.db_connect_policy.arn
}

# (オプション) EC2インスタンスにロールをアタッチするためのインスタンスプロファイル
resource "aws_iam_instance_profile" "db_access_profile" {
  name = "application-db-access-profile"
  role = aws_iam_role.db_access_role.name
}

# VPCおよびサブネットの定義例 (必要に応じて)
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "private_a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.10.0/24"
  availability_zone = "ap-northeast-1a" # あなたのリージョンに合わせて変更
  tags = {
    Name = "private-subnet-a"
  }
}

resource "aws_subnet" "private_c" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.11.0/24"
  availability_zone = "ap-northeast-1c" # あなたのリージョンに合わせて変更
  tags = {
    Name = "private-subnet-c"
  }
}

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

上記のTerraformコードでは、aws_db_instance リソースの iam_database_authentication_enabled = true を設定することで、IAMデータベース認証を有効にしています。

また、aws_iam_policyaws_iam_role_policy_attachment を使用して、指定したIAMロールが特定のRDSインスタンスとユーザー名でDBに接続できる権限を付与する方法も示しています。your_strong_passwordmy_db_instance などのプレースホルダーは、実際の環境に合わせて修正してください。パスワードはAWS Secrets Managerなどの安全な方法で管理することを強く推奨します。

最後に

この記事では、RDSデータベースインスタンスでIAMデータベース認証が有効になっていない状態について、リスクと対策を解説しました。IAMデータベース認証を導入することは、RDSへのアクセスをより安全に、より効率的に管理するための重要なステップです。パスワード管理の負担軽減、きめ細やかな権限制御、監査証跡の強化、そして自動的な通信暗号化といったメリットを享受できます。

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

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

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

この記事をシェアする

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

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

料金プランを詳しく見る