Amazon RDS DBクラスターにおけるIAM認証の設定手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、IAMデータベース認証がRDSクラスター用に設定されていない状態について、リスクと対策を解説します。

ポリシーの説明
Amazon RDS の Security Hub コントロール – AWS Security Hub
このコントロールは、Amazon RDS DB クラスターで IAM データベース認証が有効になっているかどうかをチェックします。
リスク
Amazon Relational Database Service (RDS) は、リレーショナルデータベースのセットアップ、運用、スケーリングを容易にするマネージドサービスです。RDS DBクラスターへの認証に、従来のユーザー名とパスワードの組み合わせではなくIAMデータベース認証を使用していない場合、以下のようなセキュリティと運用上のリスクが発生します。
- 認証情報の管理負担と漏洩リスク: 従来のパスワード認証では、パスワードのローテーション、安全な保管、配布が大きな負担となり、不適切な管理による認証情報の漏洩リスクが高まります。ハードコードされたパスワードは特に危険で、不正アクセスに直結します。パスワードが漏洩した場合、それを更新し、すべてのアプリケーションやサービスに適用する作業は、大規模なものになりがちです。
- 権限管理の粒度の粗さ: パスワード認証では、データベースユーザーごとにアクセス権限を設定する必要がありますが、AWS IAMの強力なポリシー管理機能と統合されていないため、AWSリソース全体の権限管理と一貫性が失われがちです。特定のIAMユーザーやロールからのデータベースアクセスをきめ細かく制限したり、許可したりすることが困難になります。
- 監査証跡の不十分さ: 従来の認証方法では、データベースへのアクセス元がAWSのどのIAMエンティティであるかを直接特定するのが難しい場合があります。IAMデータベース認証を有効にすると、すべての接続試行がAWS CloudTrail に記録され、誰が、いつ、どこからデータベースにアクセスしたかという詳細な監査証跡が得られます。これにより、セキュリティ監査の精度が向上し、不正アクセスを迅速に特定できます。
- コンプライアンス違反: 多くのセキュリティフレームワークや規制(例: PCI DSS、HIPAA、GDPR)では、最小特権の原則の適用、認証情報の安全な管理、アクセスログの監視などが求められます。IAMデータベース認証を使用しない場合、これらのコンプライアンス要件を満たせず、法的リスクや罰金に直面する可能性があります。
- 通信の暗号化の欠如: IAMデータベース認証は、SSL/TLS を使用してクライアントとデータベース間のネットワークトラフィックを自動的に暗号化します。これにより、データ転送中に情報が傍受されるリスクを低減できます。従来のパスワード認証では、別途SSL/TLS設定を行う必要があります。
対策
RDS DBクラスターでIAMデータベース認証を有効にすることは、これらのリスクを軽減し、セキュリティと運用効率を大幅に向上させるためのベストプラクティスです。
- IAMデータベース認証の有効化: RDSクラスターを作成または変更する際に、IAMデータベース認証を有効にします。
- IAMポリシーの作成と適用: データベースへのアクセスを許可する IAMユーザー または IAMロール に対して、適切なデータベースアクセス権限を付与するIAMポリシーを作成します。このポリシーには、
rds-db:connect
アクションを含める必要があります。ポリシーでは、どのデータベースユーザー名として接続できるか、どのDBクラスター/インスタンスに接続できるかを指定します。 - DBユーザーの作成とマッピング: データベース内には、対応するIAMユーザーまたはロールが接続時に使用するデータベースユーザーを作成します。例えば、MySQLでは
CREATE USER 'iam_user'@'%' IDENTIFIED WITH AWSAuthenticationPlugin;
のように作成します。 - アプリケーションからの接続方法の更新: アプリケーションやクライアントがデータベースに接続する際、従来のパスワードではなく、AWS SDKやIAM認証に対応したデータベースドライバーを使用して一時的な認証トークンを取得し、それを使用して接続するようにコードを更新します。
- CloudTrailとの統合: IAMデータベース認証による接続試行はCloudTrailに記録されます。CloudTrailログをCloudWatch Logsに連携し、異常なアクセスパターンを検知するためのアラートを設定します。
- 最小特権の原則の適用: IAMポリシーを厳密に定義し、データベースへのアクセス権限を必要最小限に抑えます。
修復方法
AWSコンソールでの修復手順
AWSコンソールを使用して、RDSデータベースクラスターでIAMデータベース認証を有効にします。
- RDSサービスへ移動: AWSコンソールにログインし、RDSサービスを開きます。
- データベースクラスターの選択: 左側のナビゲーションペインで「データベース」を選択します。 IAMデータベース認証を有効にしたいRDS DBクラスターを選択します。
- クラスターの変更: クラスターの詳細ページの上部にある「変更」をクリックします。
- IAM DB認証の有効化: 「認証」セクションまでスクロールします。 「IAM DB 認証」のチェックボックスにチェックを入れます。
- 変更の適用: 変更画面の最下部にある「変更の適用」セクションで、変更をいつ適用するかを選択します。
- すぐに適用: クラスターのメンテナンスウィンドウを待たずに変更が適用されます。場合によっては、クラスターの短時間のダウンタイムが発生する可能性があります。
- 次のメンテナンスウィンドウで適用: 次に予定されているメンテナンスウィンドウ中に変更が適用されます。 選択後、「クラスターを変更」をクリックして設定を完了します。
- (重要)データベース内のユーザー設定: データベースに接続し、IAMユーザーやロールが接続時に使用するデータベースユーザー名(例:
CREATE USER 'my_iam_user'@'%' IDENTIFIED WITH AWSAuthenticationPlugin;
for MySQL)を作成します。 - (重要)IAMポリシーの設定: IAMコンソールに移動し、データベースにアクセスするIAMユーザーやロールに、
rds-db:connect
アクションを許可するポリシーをアタッチします。

Terraformでの修復手順
TerraformでRDS DBクラスターのIAMデータベース認証を有効にするには、aws_rds_cluster
リソースの iam_database_authentication_enabled
パラメータを true
に設定します。
# RDS DBクラスターの定義
resource "aws_rds_cluster" "my_rds_cluster" {
cluster_identifier = "my-rds-cluster"
engine = "aurora-mysql" # または aurora-postgresql
engine_version = "8.0.mysql_aurora.3.04.0" # 使用するバージョンに合わせる
db_subnet_group_name = aws_db_subnet_group.main_db_subnet_group.name
vpc_security_group_ids = [aws_security_group.rds_sg.id]
master_username = "admin" # 従来のマスターユーザー (IAM認証とは別)
master_password = "your_strong_password" # Secrets Manager等で管理を推奨
skip_final_snapshot = true # 本番環境では false に設定し、最終スナップショットを取得することを推奨
# IAMデータベース認証を有効化
iam_database_authentication_enabled = true
tags = {
Name = "MyRDSClusterWithIAMAuth"
}
}
# RDS DBクラスターインスタンスの定義 (クラスターに紐づくインスタンス)
resource "aws_rds_cluster_instance" "cluster_instances" {
count = 1 # 必要なインスタンス数に調整 (最小1、通常は複数AZに配置)
identifier = "my-rds-cluster-instance-${count.index}"
cluster_identifier = aws_rds_cluster.my_rds_cluster.id
instance_class = "db.r5.large" # インスタンスクラスを適切なものに調整
engine = aws_rds_cluster.my_rds_cluster.engine
engine_version = aws_rds_cluster.my_rds_cluster.engine_version
publicly_accessible = false # 公開アクセスは無効にすることを推奨
}
# 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"
}
}
# セキュリティグループの定義 (RDSへのアクセスを許可)
resource "aws_security_group" "rds_sg" {
name = "rds-security-group"
description = "Allow inbound traffic to RDS cluster"
vpc_id = aws_vpc.main.id
ingress {
from_port = 3306 # MySQLのデフォルトポート (PostgreSQLは5432など)
to_port = 3306
protocol = "tcp"
# ここにRDSにアクセスするEC2インスタンスやLambdaのセキュリティグループIDなどを設定
# 例: security_groups = [aws_security_group.app_sg.id]
# または、より限定されたCIDRブロックを設定
cidr_blocks = ["10.0.0.0/16"] # 適切なIP範囲に制限してください
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "RDSSecurityGroup"
}
}
# 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"
}
}
# (オプション) データベースにアクセスするIAMロールの定義例
resource "aws_iam_role" "rds_access_role" {
name = "application-rds-access-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com" # EC2インスタンスからアクセスする場合
}
},
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com" # Lambda関数からアクセスする場合
}
},
]
})
}
# (オプション) IAMロールにDB接続権限を付与するポリシー
resource "aws_iam_policy" "rds_connect_policy" {
name = "application-rds-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"
# リソースARNは、db-user-nameとdb-instance-identifier/cluster-identifierを含む
# 例: arn:aws:rds-db:region:account-id:dbuser:db-instance-identifier/db-user-name
# クラスターの場合: arn:aws:rds-db:region:account-id:dbuser:cluster-identifier/db-user-name
Resource = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${aws_rds_cluster.my_rds_cluster.cluster_identifier}/*"
},
]
})
}
# (オプション) IAMロールにポリシーをアタッチ
resource "aws_iam_role_policy_attachment" "rds_access_attach" {
role = aws_iam_role.rds_access_role.name
policy_arn = aws_iam_policy.rds_connect_policy.arn
}
# (オプション) EC2インスタンスにロールをアタッチするためのインスタンスプロファイル
resource "aws_iam_instance_profile" "rds_access_profile" {
name = "application-rds-access-profile"
role = aws_iam_role.rds_access_role.name
}
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
上記のTerraformコードでは、aws_rds_cluster
リソースの iam_database_authentication_enabled = true
を設定することで、IAMデータベース認証を有効にしています。
また、aws_iam_policy
と aws_iam_role_policy_attachment
を使用して、指定したIAMロールが特定のRDSクラスターに接続できる権限を付与する方法も示しています。your_strong_password
や my-rds-cluster
、サブネットIDなどのプレースホルダーは、実際の環境に合わせて修正してください。パスワードはAWS Secrets Managerなどの安全な方法で管理することを強く推奨します。
最後に
この記事では、RDS DBクラスターでIAMデータベース認証が有効になっていない状態について、リスクと対策を解説しました。IAMデータベース認証を導入することは、RDSへのアクセスをより安全に、より効率的に管理するための重要なステップです。パスワード管理の負担軽減、きめ細やかな権限制御、監査証跡の強化、そして自動的な通信暗号化といったメリットを享受できます。
貴社のRDSクラスターでは、IAMデータベース認証が適切に設定されていますか?この機会にぜひご確認ください。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。
運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。