Cloud SQL に IAM 認証を使ってパスワードレスの接続をする

Cloud SQL に IAM 認証を使ってパスワードレスの接続をする

2025.10.29

はじめに

こんにちは。すらぼです。好きな言葉は「パスワードレス」です。

Cloud SQL への接続にはパスワード認証を使うことが一般的でしたが、Google Cloud では IAM 認証を使った「パスワードを使わない認証方法」が提供されています。
この記事では、Cloud SQL(PostgreSQL)に対して IAM 認証でアクセスする方法を、実際の手順とともに紹介します。

やりたいこと

Cloud SQL に対して、パスワードではなく IAM 認証を使ってアクセスします。

具体的には以下のような構成を実現します。

  • サービスアカウントを使った自動認証
  • Cloud SQL 言語コネクタ(Node.js)を使った接続
  • パスワード管理が不要な認証方式の実装

※今回は前提として、Cloud Run functions から Cloud SQL に対してサーバーレスVPCコネクタを使用してプライベート接続を確立しています。

なぜ IAM 認証を使うのか

本題に入る前に、IAM 認証について少し説明したいと思います。
IAM 認証には、従来のパスワード認証と比較すると以下のようなメリットがあります。

  • パスワード管理が不要: Secret Manager などでパスワードを管理する必要がなくなる。
  • 権限管理の一元化: Google Cloud の IAM で権限を一元管理でき、権限管理が楽。
  • IPアドレス管理が不要: インスタンスのプライベートIPアドレスではなく、インスタンス名で接続が可能。
  • その他、設定の簡素化: SSL証明書、ファイアウォールルール、承認済みネットワークなどの設定が不要。

この中でも、パスワード管理が不要な点が一番のポイントかと思います。これにより、パスワードを保管・ローテーション・アクセスコントロールする手間そのものが無くなります。
また、ファイアウォールルールや承認済みネットワークなど、データベースに疎通経路を開ける必要も無くなるため、よりセキュアな状態を維持することができます。

どうですか?気になってきましたよね?

では、実際の作業に進んでいきます。

前提条件

この記事では以下の環境を前提としています。

  • Cloud SQL for PostgreSQL インスタンスが作成済み。
  • Cloud Shell でのコマンド実行が可能。
  • 適切な権限(Cloud SQL 管理者、IAM 管理者など)を持っている。

また、コマンドは全て Cloud Shell 上での実行を想定しており、$GOOGLE_CLOUD_PROJECT という変数にはデフォルトでターゲットとなるプロジェクト名が入っていることを想定しています。

手順1: サービスアカウントの作成

まず、Cloud SQL にアクセスするためのサービスアカウントを作成します。

# サービスアカウントを作成
gcloud iam service-accounts create cloud-sql-iam-user \
    --display-name="Cloud SQL IAM User" \
    --project=$GOOGLE_CLOUD_PROJECT

作成したサービスアカウントに、Cloud SQL クライアントの権限を付与します。

# Cloud SQL クライアント権限を付与
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member="serviceAccount:cloud-sql-iam-user@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
    --role="roles/cloudsql.client"

# Cloud SQL インスタンスユーザー権限を付与(IAM 認証に必要)
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member="serviceAccount:cloud-sql-iam-user@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
    --role="roles/cloudsql.instanceUser"

これで、2つの権限が付与されたサービスアカウントが作成されました。

CleanShot 2025-10-29 at 16.25.06@2x.png

手順2: Cloud SQL で IAM 認証を有効化

IAM 認証フラグの有効化

Cloud SQL インスタンスで IAM 認証を有効にします。
※<your-instance-name> は自身のSQLインスタンスに置き換えて実行してください。

# Cloud SQL インスタンス名を設定
export INSTANCE_NAME=<your-instance-name>

# IAM 認証を有効化
gcloud sql instances patch $INSTANCE_NAME \
    --database-flags=cloudsql.iam_authentication=on

IAM 認証設定はデフォルトでONになっている場合があります。
また、この変更にはインスタンスの再起動が必要な場合があります。

IAM データベースユーザーの追加

作成したサービスアカウントを Cloud SQL のユーザーとして追加します。

# IAM ユーザーを追加(PostgreSQL の場合)
gcloud sql users create cloud-sql-iam-user@$GOOGLE_CLOUD_PROJECT.iam \
    --instance=$INSTANCE_NAME \
    --type=CLOUD_IAM_SERVICE_ACCOUNT \
    --project=$GOOGLE_CLOUD_PROJECT

CleanShot 2025-10-29 at 16.27.47@2x.png

このように、 Cloud SQL インスタンスのユーザー画面から確認できます。

手順3: データベース権限の設定

作成した IAM ユーザーは、データベースに対する操作権限が何もない状態で作成されます。
なので、必要なデータベース内の操作権限を付与します。今回は Cloud SQL Studio を使用します。

まず、Google Cloud Console で Cloud SQL インスタンスのページを開き、「Cloud SQL Studio」タブをクリックします

CleanShot 2025-10-29 at 16.31.08@2x.png

ログイン画面で、管理者ユーザーのユーザー名とパスワードを使用してログインします。
(※パスワードがわからない場合は、ユーザーページよりパスワードを再設定してください。)

CleanShot 2025-10-29 at 16.32.15@2x.png

以下の SQL を実行します

-- ※ YOUR_PROJECT_ID を実際のプロジェクトIDに置き換えてください

-- IAM ユーザーに全権限を付与(開発環境など)
GRANT ALL PRIVILEGES ON DATABASE postgres TO "cloud-sql-iam-user@YOUR_PROJECT_ID.iam";

-- 必要最小限の権限のみ付与する場合(本番環境ではこちらを推奨)
GRANT CONNECT ON DATABASE postgres TO "cloud-sql-iam-user@YOUR_PROJECT_ID.iam";
GRANT USAGE ON SCHEMA public TO "cloud-sql-iam-user@YOUR_PROJECT_ID.iam";
GRANT CREATE ON SCHEMA public TO "cloud-sql-iam-user@YOUR_PROJECT_ID.iam";
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "cloud-sql-iam-user@YOUR_PROJECT_ID.iam";
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "cloud-sql-iam-user@YOUR_PROJECT_ID.iam";

クエリが正常に完了すれば、Cloud SQL 側の準備は完了です。

CleanShot 2025-10-29 at 16.39.23@2x.png

注意ポイント

PostgreSQL では、IAM ユーザー名は サービスアカウント名@プロジェクトID.iam のフォーマットで登録されます。
権限付与のクエリも、このユーザーに対して実行する必要があります。

ユーザー名がわからないなどの場合は、以下のクエリを実行してユーザー名を確認してください。

select * from pg_user where usename like '%@%';

手順4: Cloud Run functions での実装

IAM 認証を使って Cloud SQL に接続する Cloud Run functions を作成します。
今回は、検証のために test-cloud-sql-iam という関数を作っていきます。

今回は Node.js での実装を行うため、以下のファイルを作成します。

  • package.json
  • index.js

それぞれ、以下のように作成していきます。(全文は少し長いので畳んでいます。)

package.json
{
  "name": "test-cloud-sql-iam",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^3.3.0",
    "@google-cloud/cloud-sql-connector": "^1.0.0",
    "pg": "^8.11.0"
  }
}
index.js
const functions = require('@google-cloud/functions-framework');
const { Connector } = require('@google-cloud/cloud-sql-connector');
const { Pool } = require('pg');

// Connector インスタンスを作成(関数の外で初期化)
const connector = new Connector();

// 接続プールを作成
let pool;

async function getPool() {
  if (!pool) {
    try {
      const clientOpts = await connector.getOptions({
        instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
        ipType: 'PRIVATE',
        authType: 'IAM'
      });

      pool = new Pool({
        ...clientOpts,
        user: process.env.DB_USER,  // IAM ユーザー名(cloud-sql-iam-user@PROJECT_ID.iam)
        database: process.env.DB_NAME,
        max: 5
      });
    } catch (error) {
      console.error('Error getting connector options:', error);
      throw error;
    }
  }
  return pool;
}

functions.http('testConnection', async (req, res) => {
  try {
    const pool = await getPool();

    // 接続テスト:現在時刻を取得
    const result = await pool.query('SELECT NOW() as current_time');

    console.log('Connection successful:', result.rows[0]);

    res.status(200).json({
      success: true,
      message: 'Successfully connected to Cloud SQL using IAM authentication',
      timestamp: result.rows[0].current_time
    });
  } catch (error) {
    console.error('Connection failed:', error);
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

実装において、重要なポイントに絞って説明します。

まず、以下の部分でSQLコネクタの初期化を行なっています。
instanceConnectionName の値は後ほど改めて出てきますが、データベースのインスタンス名などの固定情報です。
また、ipTypeauthType はそれぞれ PRIVATE IAM を指定しています。

const clientOpts = await connector.getOptions({
    instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME, // PROJECT_ID:REGION:INSTANCE_NAME
    ipType: 'PRIVATE',
    authType: 'IAM'
});

そして、上記の clientOpts を使用して、DBとの接続を行います。

pool = new Pool({
    ...clientOpts,
    user: process.env.DB_USER,  // IAM ユーザー名(cloud-sql-iam-user@PROJECT_ID.iam)
    database: process.env.DB_NAME,
    max: 5
});

重要なのは パスワードを指定していないこと です。
また、同時にホストも指定する必要がなく DBインスタンス名だけでアクセス できます。

この プライベートIPやパスワードのような管理が煩雑なパラメータを気にせずアクセスできる のが SQL言語コネクタ を使ったIAM認証の大きなポイントです。

関数のデプロイ

作成した関数をデプロイしていきます。
2つのファイルがあるディレクトリで、以下のコマンドを実行します。
export コマンドでシェル用の変数設定を行なっているので、忘れずに設定してください。

# CONNECTOR_NAME と INSTANCE_NAME は、実際の VPC コネクタ名・インスタンス名に置き換えてください
export CONNECTOR_NAME=<your-vpc-connector>
export INSTANCE_NAME=<your-sql-instance>

# 環境変数を設定(このまま実行してください)
export REGION=asia-northeast1
export INSTANCE_CONNECTION_NAME=$GOOGLE_CLOUD_PROJECT:$REGION:$INSTANCE_NAME
export DB_USER=cloud-sql-iam-user@$GOOGLE_CLOUD_PROJECT.iam


# Cloud Run functions をデプロイ
gcloud functions deploy test-cloud-sql-iam \
    --gen2 \
    --runtime=nodejs20 \
    --region=$REGION \
    --source=. \
    --entry-point=testConnection \
    --trigger-http \
    --no-allow-unauthenticated \
    --vpc-connector=$CONNECTOR_NAME \
    --service-account="cloud-sql-iam-user@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
    --set-env-vars="INSTANCE_CONNECTION_NAME=$INSTANCE_CONNECTION_NAME,DB_USER=$DB_USER,DB_NAME=postgres,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT" \
    --memory=512Mi \
    --timeout=60s

手順5: 動作確認

デプロイした関数を実行して、IAM 認証が正しく動作することを確認します。

gcloud functions call test-cloud-sql-iam --region=asia-northeast1

成功すると、以下のようなレスポンスが返ってきます。

{
    "success":true,
    "message":"Successfully connected to Cloud SQL using IAM authentication",
    "timestamp":"2025-10-29T08:51:34.200Z"
}

CleanShot 2025-10-29 at 18.25.21@2x.png

これで無事、IAM認証でのDB接続が成功しました。

トラブルシュート

エラー: IAM authentication failed が表示される場合

認証エラーが発生する場合、以下の点を確認してください。

  1. Cloud SQL インスタンスで IAM 認証が有効になっているか
  2. サービスアカウントに roles/cloudsql.clientroles/cloudsql.instanceUser の両方の権限があるか
  3. 接続時のユーザー名が PostgreSQL 内のユーザー名(サービスアカウント名@PROJECT_ID.iam)と完全に一致しているか

特にデータベースのユーザー名はサービスアカウント名から一部が切り捨てられたものになるため、注意が必要です。

注: データベース ユーザー名には上限があるため、サービス アカウントの場合、Cloud SQL for PostgreSQL によって、メールアドレスの .gserviceaccount.com サフィックスが切り捨てられます。たとえば、サービス アカウント sa-name@project-id.iam.gserviceaccount.com のユーザー名は sa-name@project-id.iam になります。
https://cloud.google.com/sql/docs/postgres/add-manage-iam-users?hl=ja#creating-a-database-user

タイムアウトなど、通信に失敗する場合

以下の2点を確認してください。

  1. VPC コネクタが正しく設定されているか
  2. ポート 443 と 3307 に対する全てのIPへの外向き通信が、ファイアウォールルールでブロックされていないか

今回の実装では、3種類のリクエストが発生します。

  • Cloud Run functions 自体への呼び出しリクエスト
  • Cloud Run functions → Cloud SQL の方向 のリクエスト
  • Cloud SQL コネクタの sqladmin.googleapis.com へのアクセス

このうち Cloud Run functions の2つのリクエストは サーバーレスVPCコネクタを設定すれば問題なく通信できるはずです。
sqladmin.googleapis.com へのアクセスに関しては、 443 と 3307 ポートの全てIPに対して、外向き通信を許可する必要があります。

注: ポート 443 と 3307 への発信(または外向き)TCP 接続を許可する必要があります。
Cloud SQL コネクタを使用して、sqladmin.googleapis.com ドメイン名を介して API を呼び出します。このドメイン名には固定の IP アドレスがありません。したがって、ポート 443 ですべての下り(外向き)TCP 接続を許可する必要があります(ポート 443 は標準の HTTPS ポートです。ウェブサイトにアクセスする、または API リクエストを実行するたびに、ウェブサイトまたはエンドポイントが解決する IP アドレスのポート 443 を経由して、安全な接続が行われます)。
Cloud SQL コネクタではどのポートでもリッスンできますが、ポート 3307 にのみ Cloud SQL インスタンスへの送信(または外向き)接続が作成されます。クライアント マシンにアウトバウンド ファイアウォール ポリシーがある場合は、Cloud SQL インスタンスの IP アドレスでポート 3307 への送信接続が許可されていることを確認してください。詳細については、Cloud SQL コネクタの認証オプションをご覧ください。
https://cloud.google.com/sql/docs/postgres/iam-logins?hl=ja#log-in-with-automatic

まとめ

Cloud SQL の、SQL 言語コネクタ(Node.js) を使ったIAM認証の方法を紹介しました。

このアクセス方法を使うことで、パスワード管理の煩雑さから解放され、よりセキュアなデータベース接続を実現できます。今回は Node.js を使用しましたが、他にも Python や Go など複数の言語でライブラリが提供されています。

IAM 認証を活用して、よりセキュアで管理しやすいクラウドネイティブなアプリケーションを構築していきましょう。

参考資料

この記事をシェアする

FacebookHatena blogX

関連記事