Cloud SQLインスタンスのrootユーザーアクセス制限設定手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、 「どうやって直すのか?」 という具体的な修復手順(コンソール、gcloud CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、Cloud SQLインスタンスのrootユーザーに対するホストベースのアクセス制限について、リスクと対策を解説します。

ポリシーの説明
Cloud SQLインスタンスのrootユーザーは、データベースシステムにおける最高権限を持つ特権アカウントです。このアカウントに対して適切なアクセス制限を設定せずに、どこからでもアクセス可能な状態(0.0.0.0/0)にしておくことは、重大なセキュリティリスクとなります。
※ 併せてパブリックIPの無効化も行うようにしましょう。
ホストベースのアクセス制限(IPホワイトリスト)を実装することで、特定のIPアドレスやネットワークからのみrootユーザーでの接続を許可し、不正アクセスのリスクを大幅に低減できます。Google Cloudでは、Cloud SQLインスタンスレベルとユーザーレベルの両方でアクセス制御を設定できます。
修復方法
前提条件の確認
修復を行う前に、以下を確認してください:
- 現在のrootユーザーからの接続元IPアドレス
- アプリケーションやバックアップツールがrootユーザーを使用している場合、その接続元IPアドレス
- 緊急時のアクセス経路(VPN、踏み台サーバーなど)
コンソールでの修復手順
- Google Cloud Consoleにアクセス
- Cloud Consoleにログイン
- ナビゲーションメニューから「SQL」を選択
- インスタンスレベルのアクセス制御設定(推奨)
- 対象のCloud SQLインスタンスを選択
- 「概要」タブから「編集」をクリック
- 「接続」セクションまでスクロール
- 「承認済みネットワーク」で「ネットワークを追加」をクリック
- 信頼できるIPアドレス/CIDR範囲を追加
- ユーザーレベルのアクセス制御設定
- 左側のメニューから「ユーザー」を選択
- rootユーザーの行を見つけ、右端の「⋮」(その他の操作)メニューをクリック
- 「編集」を選択
- ホスト制限を設定
- 「ホスト名」セクションで「制限する」を選択
- 許可するIPアドレスまたはCIDR範囲を入力
- 例: 内部ネットワーク:
10.0.0.0/8
- 例: 特定のサーバー:
192.168.1.100
- 例: 内部ネットワーク:
- 複数のIPアドレスを追加する場合は「+追加」をクリック
- 設定を保存
- 「保存」ボタンをクリックして変更を適用
- 変更が反映されるまで数秒待機
- 設定の確認
- ユーザー一覧でrootユーザーの「ホスト」列に制限が表示されていることを確認
- 「概要」タブで承認済みネットワークが正しく設定されていることを確認
Terraformでの修復手順
# Cloud SQLインスタンスの定義(セキュリティ強化版)
resource "google_sql_database_instance" "main" {
name = "secure-mysql-instance"
database_version = "MYSQL_8_0"
region = "asia-northeast1"
# 重要: 削除保護を有効化
deletion_protection = true
settings {
tier = "db-n1-standard-2"
# バックアップ設定
backup_configuration {
enabled = true
start_time = "03:00"
location = "asia-northeast1"
point_in_time_recovery_enabled = true
transaction_log_retention_days = 7
backup_retention_settings {
retained_backups = 30
retention_unit = "COUNT"
}
}
# IPベースのアクセス制御(インスタンスレベル)
ip_configuration {
ipv4_enabled = true
require_ssl = true # SSL接続を強制
# プライベートIPを使用する場合
private_network = var.enable_private_ip ? google_compute_network.vpc[0].id : null
# パブリックIPを使用する場合の承認済みネットワーク
dynamic "authorized_networks" {
for_each = var.authorized_networks
content {
name = authorized_networks.value.name
value = authorized_networks.value.cidr
}
}
}
# セキュリティ関連のデータベースフラグ
database_flags {
name = "skip_name_resolve"
value = "ON"
}
database_flags {
name = "local_infile"
value = "OFF" # LOCAL INFILEを無効化
}
# 監査ログの有効化
database_flags {
name = "cloudsql_mysql_audit"
value = "ON"
}
}
}
# rootユーザーの設定(ホスト制限付き)
# 注意: 本番環境ではrootユーザーの使用を最小限に抑える
resource "google_sql_user" "root_restricted" {
name = "root"
instance = google_sql_database_instance.main.name
# 特定のネットワークからのみ許可
host = var.root_allowed_host # 例: "10.0.0.0/8"
# パスワードはGoogle Secret Managerから取得
password = data.google_secret_manager_secret_version.root_password.secret_data
}
# 無制限のrootユーザー(%)が存在しないことを確認するnullリソース
resource "null_resource" "remove_unrestricted_root" {
provisioner "local-exec" {
command = <<-EOT
# 無制限のrootユーザーが存在する場合は削除
if gcloud sql users list --instance=${google_sql_database_instance.main.name} | grep -q "root.*%"; then
gcloud sql users delete root --host='%' --instance=${google_sql_database_instance.main.name} --quiet
fi
EOT
}
depends_on = [google_sql_database_instance.main]
}
# アプリケーション用の最小権限ユーザー(推奨)
resource "google_sql_user" "app_user" {
name = "application"
instance = google_sql_database_instance.main.name
host = var.app_allowed_host # 例: "10.1.0.0/16"
password = data.google_secret_manager_secret_version.app_password.secret_data
}
# 読み取り専用ユーザー
resource "google_sql_user" "readonly_user" {
name = "readonly"
instance = google_sql_database_instance.main.name
host = var.monitoring_allowed_host
password = data.google_secret_manager_secret_version.readonly_password.secret_data
}
# データベースの作成
resource "google_sql_database" "app_db" {
name = "application_db"
instance = google_sql_database_instance.main.name
charset = "utf8mb4"
collation = "utf8mb4_unicode_ci"
}
# Secret Managerでパスワードを管理
resource "google_secret_manager_secret" "root_password" {
secret_id = "cloudsql-root-password"
replication {
automatic = true
}
}
resource "google_secret_manager_secret_version" "root_password" {
secret = google_secret_manager_secret.root_password.id
secret_data = random_password.root.result
}
resource "random_password" "root" {
length = 32
special = true
override_special = "!#$%&*()-_=+[]{}<>:?"
}
# 変数定義
variable "authorized_networks" {
description = "List of authorized networks for Cloud SQL instance"
type = list(object({
name = string
cidr = string
}))
default = [
{
name = "office-network"
cidr = "203.0.113.0/24"
},
{
name = "vpn-gateway"
cidr = "198.51.100.50/32"
}
]
}
variable "root_allowed_host" {
description = "Allowed host pattern for root user"
type = string
default = "10.0.0.0/8" # 内部ネットワークのみ
}
variable "app_allowed_host" {
description = "Allowed host pattern for application user"
type = string
default = "10.1.0.0/16" # アプリケーションサブネット
}
variable "enable_private_ip" {
description = "Enable private IP for Cloud SQL instance"
type = bool
default = true
}
# 出力値
output "instance_connection_name" {
value = google_sql_database_instance.main.connection_name
description = "Instance connection name for Cloud SQL Proxy"
}
output "instance_ip_address" {
value = google_sql_database_instance.main.ip_address
description = "The IPv4 address assigned"
}
その他ベストプラクティスについて
- 最小権限の原則
- rootユーザーの使用を最小限に抑え、アプリケーション用の専用ユーザーを作成
- 各ユーザーには必要最小限の権限のみを付与
- 多層防御
- インスタンスレベルの承認済みネットワーク設定
- ユーザーレベルのホスト制限
- SSL/TLS接続の強制
- Cloud SQL Proxyの使用
- 定期的な監査
- 定期的にユーザーとそのホスト制限を確認
- 不要なユーザーやアクセス許可を削除
- 接続ログを監視して異常なアクセスを検出
- パスワード管理
- Google Secret Managerを使用してパスワードを安全に管理
- 定期的なパスワードローテーション
- 強力なパスワードポリシーの実施
まとめ
Cloud SQLインスタンスのrootユーザーに対するホストベースのアクセス制限は、データベースセキュリティの基本的かつ重要な対策です。この記事で紹介した手順により、rootユーザーへの不正アクセスリスクを大幅に低減できます。
さらに、Cloud SQL Proxy、プライベートIP、IAM認証などの追加のセキュリティ機能を組み合わせることで、より堅牢なデータベースセキュリティを実現できます。定期的な監査とモニタリングを実施し、継続的にセキュリティ態勢を改善していくことが重要です。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。
参考情報
- Cloud SQL のアクセス制御
- Cloud SQL での承認済みネットワークの使用
- Cloud SQL Proxy について
- Cloud SQL のセキュリティ ベスト プラクティス
- MySQL ユーザー アカウントの管理