Cloud SQLでSSL/TLS接続の必須化の手順

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

この記事では、Cloud SQLインスタンスのSSL/TLS接続有効化手順について、リスクと対策を解説します。

ポリシーの説明

Cloud SQLインスタンスとクライアント間の通信をSSL/TLSで暗号化することで、データベース通信の機密性と完全性を確保します。SSL/TLS接続が無効の場合、データベースとアプリケーション間で送受信されるデータ(SQLクエリ、認証情報、クエリ結果など)が平文で送信され、ネットワーク上で盗聴や改ざんのリスクにさらされます。

Cloud SQLはTLS 1.2以上をサポートし、古いプロトコル(SSL 3.0、TLS 1.0/1.1)は無効化されているため、安全な暗号化通信が保証されます。

リスク

SSL/TLS接続が無効化されている場合、攻撃者がネットワーク通信を傍受した際にSQLクエリや結果データを盗聴できたり、データベースのユーザー名とパスワードが平文で送信され、不正アクセスのリスクが高まります。

修復方法

コンソールでの修復手順

Google Cloud コンソールを使用して、Cloud SQLインスタンスのSSL/TLS接続を有効化します。

  1. Cloud SQLページへ移動
    • ナビゲーションメニューから「SQL」を選択し、接続へ遷移する
  1. SSL設定の変更
    • 対象のインスタンスを選定し、[セキュリティ]- [信頼できるクライアント証明書を必須にする]を選択する
  2. 承認済みネットワークの設定(推奨)
    • 「承認済みネットワーク」セクションで、接続を許可するIPアドレスを追加
    • 0.0.0.0/0(すべてのIP)は避け、特定のIPアドレスまたはCIDRブロックを指定
  3. SSL証明書の作成
    • 「証明書」タブに移動
    • 「新しいクライアント証明書を作成」をクリック
    • 証明書に名前を付けて「作成」をクリック
    • 生成された証明書(server-ca.pem、client-cert.pem、client-key.pem)をダウンロード
    • 重要: ダウンロードした証明書は安全な場所に保管し、アクセス権限を適切に設定
    • 注意: 証明書は作成時にのみダウンロード可能で、後から再取得はできません
    • 推奨: Secret Managerやハードウェアセキュリティモジュール(HSM)での管理を検討
  4. 設定の保存
    • 「保存」ボタンをクリックして変更を適用
    • 数分で設定が反映されます(インスタンスの再起動は不要)

Terraformでの修復手順

Cloud SQLインスタンスのSSL/TLS接続を有効にするTerraformコードと、主要な修正ポイントを説明します。

# Cloud SQLインスタンスの設定
resource "google_sql_database_instance" "main" {
  name             = "secure-mysql-instance"
  database_version = "MYSQL_8_0"
  region           = "asia-northeast1"

  settings {
    tier = "db-n1-standard-2"

    # IPコンフィグレーション
    ip_configuration {
      ipv4_enabled = true

      # SSL/TLS接続を必須にする(重要:falseにしないこと)
      require_ssl = true

      # SSLモードの暗号スイートを最新に保つ
      # Cloud SQLは自動的に安全な暗号スイートを選択
      # TLS 1.2以上が使用され、古いプロトコルは無効化されています

      # 承認済みネットワーク(特定のIPからのみ接続を許可)
      authorized_networks {
        name  = "office-network"
        value = "203.0.113.0/24"  # 実際のオフィスIPに置き換え
      }

      authorized_networks {
        name  = "app-server"
        value = "198.51.100.10/32"  # アプリケーションサーバーのIP
      }

      # プライベートIPの設定(推奨)
      private_network = google_compute_network.private_network.id
    }

    # バックアップ設定
    backup_configuration {
      enabled                        = true
      start_time                     = "02:00"
      binary_log_enabled             = true
      transaction_log_retention_days = 7
    }

    # データベースフラグ(MySQL用のセキュリティ強化設定)
    database_flags {
      name  = "skip_show_database"
      value = "on"
    }

    database_flags {
      name  = "local_infile"
      value = "off"
    }

    # PostgreSQL の場合は以下のフラグを使用
    # database_flags {
    #   name  = "cloudsql.enable_pgaudit"
    #   value = "on"
    # }
    # database_flags {
    #   name  = "log_connections"
    #   value = "on"
    # }
  }

  deletion_protection = true
}

# SSL証明書の作成
resource "google_sql_ssl_cert" "client_cert" {
  common_name = "application-client"
  instance    = google_sql_database_instance.main.name

  # ライフサイクル管理
  lifecycle {
    create_before_destroy = true
  }
}

# 証明書の有効期限監視用メタデータ
resource "google_project_metadata_item" "ssl_cert_expiry" {
  key   = "cloudsql-ssl-cert-${google_sql_ssl_cert.client_cert.sha1_fingerprint}"
  value = timestamp()
}

# プライベートVPC設定(推奨)
resource "google_compute_network" "private_network" {
  name                    = "sql-private-network"
  auto_create_subnetworks = false
}

resource "google_compute_global_address" "private_ip_address" {
  name          = "sql-private-ip"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = google_compute_network.private_network.id
}

resource "google_service_networking_connection" "private_vpc_connection" {
  network                 = google_compute_network.private_network.id
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}

# アプリケーション用の接続情報を出力
output "connection_name" {
  value       = google_sql_database_instance.main.connection_name
  description = "Instance connection name for application configuration"
}

output "private_ip_address" {
  value       = google_sql_database_instance.main.private_ip_address
  description = "Private IP address for VPC internal access"
}

output "public_ip_address" {
  value       = google_sql_database_instance.main.public_ip_address
  description = "Public IP address (use with SSL only)"
  sensitive   = true
}

output "server_ca_cert" {
  value       = google_sql_database_instance.main.server_ca_cert[0].cert
  description = "Server CA certificate for SSL connection"
  sensitive   = true
}

output "client_cert" {
  value       = google_sql_ssl_cert.client_cert.cert
  description = "Client certificate for SSL connection"
  sensitive   = true
}

output "client_key" {
  value       = google_sql_ssl_cert.client_cert.private_key
  description = "Client private key for SSL connection"
  sensitive   = true
}

# 接続監視アラート
resource "google_monitoring_alert_policy" "ssl_connection_failures" {
  display_name = "Cloud SQL SSL Connection Failures"
  combiner     = "OR"

  conditions {
    display_name = "SSL connection failures detected"

    condition_threshold {
      filter     = <<-EOT
        resource.type="cloudsql_database"
        AND metric.type="cloudsql.googleapis.com/database/network/connections"
        AND metric.label.is_ssl="false"
      EOT

      duration   = "60s"
      comparison = "COMPARISON_GT"

      threshold_value = 0

      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "ALIGN_RATE"
      }
    }
  }

  notification_channels = [google_monitoring_notification_channel.email.id]

  documentation {
    content = "Non-SSL connections detected to Cloud SQL instance. Investigate immediately."
  }
}

# アプリケーション設定例(MySQL接続文字列)
locals {
  mysql_connection_config = {
    host     = google_sql_database_instance.main.private_ip_address
    port     = 3306
    database = "application_db"
    ssl_mode = "VERIFY_IDENTITY"  # 最も安全な設定
    # ssl_mode の選択肢:
    # - REQUIRED: SSL接続を必須とする(最低限)
    # - VERIFY_CA: サーバー証明書の検証を行う(推奨)
    # - VERIFY_IDENTITY: サーバー証明書とホスト名の検証を行う(最も安全)
    ssl_ca   = "/path/to/server-ca.pem"
    ssl_cert = "/path/to/client-cert.pem"
    ssl_key  = "/path/to/client-key.pem"
  }
}

 

ベストプラクティス

  1. 多層防御の実装
    • SSL/TLS接続の必須化と併せて、プライベートIPアドレスの使用を検討
    • Cloud SQL ProxyやIAM認証の併用を推奨
    • VPCサービスコントロールによる境界セキュリティの実装
  2. 証明書管理
    • クライアント証明書の定期的なローテーション(90日ごとを推奨)
    • Secret ManagerやHashiCorp Vaultなどの証明書管理ツールの活用
    • 証明書の有効期限監視とアラート設定
  3. 監査とコンプライアンス
    • Cloud Auditログでの接続監視
    • 非SSL接続試行の検出とアラート
    • 定期的なセキュリティ評価の実施

最後に

この記事では、Cloud SQLインスタンスのSSL/TLS接続有効化手順について、リスクと対策を解説しました。

SSL/TLS接続の必須化は、データベース通信のセキュリティ確保の基本です。特にパブリックIPアドレスを使用する場合は必ず有効化し、可能な限りプライベートIPアドレスでの接続と組み合わせることを推奨します。

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。

参考情報

この記事をシェアする

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

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

料金プランを詳しく見る