Cloud SQL MySQLインスタンスの管理者ユーザーにおけるパスワード設定について

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

ポリシーの説明
Cloud SQL MySQLインスタンスの管理者ユーザー(root)にパスワードを設定し、不正アクセスを防止します。
Cloud SQL MySQLインスタンスを作成する際、デフォルトではrootユーザーにパスワードが設定されない場合があります。これにより、誰でも管理者権限でデータベースに接続できる状態となり、深刻なセキュリティリスクを招きます。管理者ユーザーには必ず強力なパスワードを設定し、適切なアクセス制御を実施することが重要です。
修復方法
コンソールでの修復手順
Google Cloud コンソールを使用して、Cloud SQL MySQLインスタンスのrootユーザーにパスワードを設定します。
- Google Cloud Consoleにログインし、SQLページに移動します。

- 対象のCloud SQL MySQLインスタンスを選択します。
- 左側のメニューからユーザーを選択します。
- rootユーザーを見つけて、その行の右端にあるその他の操作(3点メニュー)をクリックします。
- パスワードを変更を選択します。
- 新しいパスワードを入力します:
- 最低16文字以上の長さ
- 大文字・小文字・数字・特殊文字を含む
- 推測しにくい複雑なパスワード
- 保存をクリックして変更を適用します。
Terraformでの修復手順
Cloud SQL MySQLインスタンスで管理者パスワードを設定するTerraformコードと、主要な修正ポイントを説明します。
# -------------------- ① ランダムパスワードの生成 --------------------
resource "random_password" "mysql_root_password" {
length = 20
special = true
override_special = "!#$%&*()-_=+[]{}<>:?"
min_lower = 2
min_upper = 2
min_numeric = 2
min_special = 2
}
# -------------------- ② Secret Managerでの保存 --------------------
resource "google_secret_manager_secret" "mysql_root_password" {
secret_id = "mysql-root-password-${var.environment}"
replication {
automatic = true
}
}
resource "google_secret_manager_secret_version" "mysql_root_password" {
secret = google_secret_manager_secret.mysql_root_password.id
secret_data = random_password.mysql_root_password.result
}
# -------------------- ③ Cloud SQLインスタンス --------------------
resource "google_sql_database_instance" "mysql" {
name = "mysql-instance-${var.environment}"
database_version = "MYSQL_8_0"
region = var.region
# rootパスワードの設定
root_password = random_password.mysql_root_password.result
settings {
tier = "db-n1-standard-2"
# --- IPアクセス制御 ---
ip_configuration {
ipv4_enabled = true
# 必要最小限のIPアドレスのみ許可
authorized_networks {
name = "office-network"
value = var.office_ip_cidr
}
# SSL接続を強制
require_ssl = true
}
# --- セキュリティ強化設定 ---
database_flags {
name = "require_secure_transport"
value = "on"
}
database_flags {
name = "skip-grant-tables"
value = "off" # 認証をバイパスしない
}
database_flags {
name = "local_infile"
value = "off"
}
# --- バックアップ設定 ---
backup_configuration {
enabled = true
start_time = "02:00"
point_in_time_recovery_enabled = true
transaction_log_retention_days = 7
backup_retention_settings {
retained_backups = 30
retention_unit = "COUNT"
}
}
# --- 監査ログ設定 ---
insights_config {
query_insights_enabled = true
query_string_length = 1024
record_application_tags = true
}
}
deletion_protection = true
}
# -------------------- ④ アプリケーション用ユーザーの作成 --------------------
resource "random_password" "app_user_password" {
length = 16
special = true
override_special = "!#$%&*()-_=+[]{}<>:?"
}
resource "google_sql_user" "app_user" {
name = "app_user"
instance = google_sql_database_instance.mysql.name
password = random_password.app_user_password.result
# rootユーザーと異なり、限定的な権限を付与
}
# -------------------- ⑤ データベースの作成 --------------------
resource "google_sql_database" "app_database" {
name = "application_db"
instance = google_sql_database_instance.mysql.name
charset = "utf8mb4"
}
# -------------------- ⑥ IAMロールの設定 --------------------
resource "google_project_iam_member" "sql_client" {
project = var.project_id
role = "roles/cloudsql.client"
member = "serviceAccount:${var.app_service_account_email}"
}
# -------------------- ⑦ 変数定義 --------------------
variable "environment" {
description = "Environment name (dev/staging/prod)"
type = string
}
variable "region" {
description = "The GCP region for resources"
type = string
default = "asia-northeast1"
}
variable "project_id" {
description = "GCP Project ID"
type = string
}
variable "office_ip_cidr" {
description = "Office network IP CIDR for authorized access"
type = string
}
variable "app_service_account_email" {
description = "Application service account email"
type = string
}
# -------------------- ⑧ 出力 --------------------
output "instance_connection_name" {
value = google_sql_database_instance.mysql.connection_name
description = "The connection name of the Cloud SQL instance"
}
output "root_password_secret_id" {
value = google_secret_manager_secret.mysql_root_password.id
description = "The Secret Manager secret ID for root password"
}
output "app_user_password" {
value = random_password.app_user_password.result
sensitive = true
description = "The password for app_user (store this securely)"
}
主要な修正ポイント
- root_password: インスタンス作成時に必ずrootパスワードを設定
- random_password: 強力なランダムパスワードを自動生成
- google_secret_manager_secret: パスワードをSecret Managerで安全に管理
- require_secure_transport: SSL/TLS接続を強制
- skip-grant-tables = off: 認証バイパスを無効化
重要な注意事項
- 既存インスタンスの場合: すでに作成されたインスタンスには
root_password
パラメータは使用できません。gcloud CLIまたはコンソールでパスワードを設定してください - パスワードポリシーの適用: MySQL 8.0の場合、デフォルトでvalidate_passwordプラグインが有効になっています
最後に
この記事では、Cloud SQL MySQLインスタンスの管理者ユーザーパスワード設定について、リスクと対策を解説しました。
パスワードなしの管理者アカウントは、データベースセキュリティにおける最も重大な脆弱性の一つです。本記事で紹介した手順により、強力なパスワードを設定し、適切なアクセス制御を実装することで、データベースへの不正アクセスを防止できます。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。
参考情報
Google Cloud公式ドキュメント
- Cloud SQL for MySQLの概要(2025年1月更新)
- Cloud SQLインスタンスのユーザー管理
- Cloud SQLのセキュリティベストプラクティス
- Cloud SQLの認証と承認
- Cloud SQLのデータベースフラグ