データベースの認証と接続

Cloud Firestore Enterprise エディションにのみ関連します。

接続に関する要件

MongoDB 互換の Cloud Firestore クライアントの場合、次の要件を満たす必要があります。

  • ドライバは load balanced モードで接続する必要があります。 これにより、ドライバが接続先のサーバー トポロジを正確に把握しようとするのを防ぐことができます。
  • ドライバは SSL を有効にして接続する必要があります。
  • ドライバは再試行可能な書き込みを無効にする必要があります。 MongoDB 互換の Cloud Firestore は、再試行可能な書き込みをサポートしていません。再試行可能な読み取りはサポートされているため、無効にする必要はありません。

接続文字列を取得する

データベース接続文字列は、データベースの UID、データベースのロケーション、認証メカニズムによって異なります。次の手順では、接続文字列の形式について説明します。

正確な接続文字列は認証メカニズムによって異なりますが、ベース接続文字列は次の形式を使用します。

mongodb://UID.LOCATION.firestore.goog:443/DATABASE_ID?loadBalanced=true&tls=true&retryWrites=false

ベース接続文字列は、次のいずれかの方法で取得できます。

Firebase コンソール
  1. Firebase コンソールで、[Firestore データベース] ページに移動します。

    [Firestore データベース] に移動

  2. 認証するデータベースをクリックします。
  3. [エクスプローラ] パネルで、 [さらに表示] をクリックします。
  4. [MongoDB ツールを使用して接続] を選択します。
  5. 接続文字列をコピーします。
gcloud

gcloud firestore database describe を使用して UID とロケーション情報を取得します。

gcloud firestore databases describe \
--database=DATABASE_ID \
--format='yaml(locationId, uid)'

DATABASE_ID をデータベース ID に置き換えます。

出力には、データベースのロケーションと UID が含まれます。この情報を使用して、ベース接続文字列を作成します。

ベース接続文字列と次のいずれかの方法を使用してデータベースを認証し、データベースに接続します。

ユーザー名とパスワード(SCRAM)で接続する

データベースのユーザー認証情報を作成してデータベースに接続する手順は次のとおりです。

始める前に

ユーザーの作成に必要な権限を取得するには、データベースに対する userCredsAdminroles/datastore.userCredsAdmin)IAM ロールを付与するよう管理者に依頼してください。ロールの付与については、プロジェクト、フォルダ、組織に対するアクセス権の管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

ユーザーを作成してデータベースに接続する

MongoDB 互換の Cloud Firestore データベースのユーザーを作成するには、次のいずれかの方法を使用します。

Google Cloud コンソール
  1. Google Cloud コンソールで [データベース] ページに移動します。

    [データベース] に移動

  2. データベースのリストからデータベースを選択します。
  3. ナビゲーション メニューで [認証] をクリックします。
  4. [ユーザーを追加] をクリックします。
  5. [Username] にユーザー名を入力します。
  6. 新しいユーザーのロールを選択します。
  7. [追加] をクリックします。

    新しいユーザーのパスワードが確認ダイアログに表示されます。

gcloud CLI
  1. SCRAM で認証するには、まずユーザー認証情報を作成する必要があります。gcloud firestore user-creds コマンドを実行します。
    gcloud firestore user-creds create USERNAME --database=DATABASE_ID
    次のように置き換えます。
    • USERNAME: 作成するユーザー名。
    • DATABASE_ID: データベース ID。

    このコマンドの出力には、ユーザーのパスワードが含まれます。

    出力は次のようになります。

    name: projects/PROJECT_NAME/databases/DATABASE_ID/userCreds/USERNAME
    resourceIdentity:
      principal: principal://firestore.googleapis.com/projects/PROJECT_NUMBER/name/databases/DATABASE_ID/userCreds/USERNAME
    securePassword: PASSWORD
  2. デフォルトでは、この新しいユーザー認証情報に権限は設定されていません。データベースに対する読み取り / 書き込みアクセス権を付与するには、この特定のデータベースに対する roles/datastore.user ロールを追加します。

    gcloud projects add-iam-policy-binding PROJECT_NAME \
    --member='principal://firestore.googleapis.com/projects/PROJECT_NUMBER/name/databases/DATABASE_ID/userCreds/USERNAME' \
    --role=roles/datastore.user \
    --condition='expression=resource.name == "projects/PROJECT_NAME/databases/DATABASE_ID",title="CONDITION_TITLE"'
    次のように置き換えます。
Java

このセクションでは、Java 管理クライアント ライブラリを使用してユーザー認証情報を作成し、IAM ポリシーを構成するコード例を示します。このサンプルでは、ユーザー名とパスワードの作成に Firestore Admin Client ライブラリを使用し、IAM の構成に Google Cloud Resource Manager ライブラリを使用します。

Maven ビルドの場合は、次の座標を使用できます。

com.google.cloud:google-cloud-firestore-admin:3.33.1
com.google.cloud:google-cloud-resourcemanager:1.76.0

ユーザー認証情報と IAM ポリシーをプロビジョニングします。

import com.google.cloud.firestore.v1.FirestoreAdminClient;
import com.google.cloud.resourcemanager.v3.ProjectName;
import com.google.cloud.resourcemanager.v3.ProjectsClient;
import com.google.firestore.admin.v1.CreateUserCredsRequest;
import com.google.firestore.admin.v1.GetUserCredsRequest;
import com.google.firestore.admin.v1.UserCreds;
import com.google.iam.v1.Binding;
import com.google.iam.v1.GetIamPolicyRequest;
import com.google.iam.v1.GetPolicyOptions;
import com.google.iam.v1.Policy;
import com.google.iam.v1.SetIamPolicyRequest;
import com.google.protobuf.FieldMask;
import com.google.type.Expr;

public class FirestoreUserCredsExample {
  /**
   * Provision user credentials and configure an IAM policy to allow SCRAM authentication into the
   * specified Firestore with Mongo Compatibility database.
   */
  private static void provisionFirestoreUserCredsAndIAM(
      String projectId, String databaseId, String userName) throws Exception {
    UserCreds userCreds = createUserCreds(projectId, databaseId, userName);

    // Note the password returned in the UserCreds proto - it cannot be retrieved again
    // after the initial call to the createUserCreds API.
    System.out.printf(
        "Created credentials for username: %s:\nIAM principal: %s\nPassword: [%s]\n",
        userName, userCreds.getResourceIdentity().getPrincipal(), userCreds.getSecurePassword());

    // Provision an IAM binding for the principal associated with these user credentials.
    updateIamPolicyForUserCreds(projectId, databaseId, userName, userCreds);

    // Emit the password again.
    System.out.printf(
        "Successfully configured IAM policy for database: %s, username: %s\n",
        databaseId, userName);
    System.out.printf("Please make a note of the password: [%s]\n", userCreds.getSecurePassword());
  }

  /** Provision new user credentials using the FirestoreAdminClient. */
  private static UserCreds createUserCreds(String projectId, String databaseId, String userName)
      throws Exception {
    FirestoreAdminClient firestoreAdminClient = FirestoreAdminClient.create();
    return firestoreAdminClient.createUserCreds(
        CreateUserCredsRequest.newBuilder()
            .setParent(String.format("projects/%s/databases/%s", projectId, databaseId))
            .setUserCredsId(userName)
            .build());
  }

  /** Update the IAM policy using the Resource Manager ProjectsClient. */
  private static void updateIamPolicyForUserCreds(
      String projectId, String databaseId, String userName, UserCreds userCreds) throws Exception {
    try (ProjectsClient projectsClient = ProjectsClient.create()) {
      ProjectName projectName = ProjectName.of(projectId);

      // Get the current IAM policy.
      Policy currentPolicy =
          projectsClient.getIamPolicy(
              GetIamPolicyRequest.newBuilder()
                  .setResource(projectName.toString())
                  .setOptions(GetPolicyOptions.newBuilder().setRequestedPolicyVersion(3).build())
                  .build());

      String role = "roles/datastore.user";
      String title = String.format("Conditional IAM binding for %s", userName);
      String expression =
          String.format("resource.name == \"projects/%s/databases/%s\"", projectId, databaseId);

      // Construct an updated IAM policy with an additional binding for the user credentials.
      Policy.Builder policyBuilder = currentPolicy.toBuilder();
      Binding newBinding =
          Binding.newBuilder()
              .setRole(role)
              .setCondition(Expr.newBuilder().setTitle(title).setExpression(expression).build())
              .addMembers(userCreds.getResourceIdentity().getPrincipal())
              .build();
      policyBuilder.addBindings(newBinding);

      // Update the policy
      SetIamPolicyRequest request =
          SetIamPolicyRequest.newBuilder()
              .setResource(projectName.toString())
              .setPolicy(policyBuilder.build())
              .setUpdateMask(FieldMask.newBuilder().addPaths("bindings").addPaths("etag").build())
              .build();
      System.out.println(request);

      Policy updatedPolicy = projectsClient.setIamPolicy(request);
      System.out.println("Policy updated successfully: " + updatedPolicy);
    }
  }
}
Python

このセクションでは、Python 管理クライアント ライブラリを使用してユーザー認証情報を作成し、IAM ポリシーを構成するコード例を示します。このサンプルでは、ユーザー名とパスワードの作成に Google Cloud Firestore API クライアント ライブラリを使用し、IAM の構成に Google Cloud Iam API クライアント ライブラリGoogle Cloud Resource Manager API クライアント ライブラリを使用します。

必要な Python ライブラリは、pip ツールを使用してインストールできます。

pip install google-cloud-iam
pip install google-cloud-firestore
pip install google-cloud-resource-manager

ユーザー認証情報と IAM ポリシーをプロビジョニングします。

from google.cloud import resourcemanager_v3
from google.cloud.firestore_admin_v1 import FirestoreAdminClient
from google.cloud.firestore_admin_v1 import types
from google.iam.v1 import iam_policy_pb2
from google.iam.v1 import policy_pb2
from google.type import expr_pb2


def create_user_creds(project_id: str, database_id: str, user_name: str):
  """Provision new user credentials using the FirestoreAdminClient."""
  client = FirestoreAdminClient()
  request = types.CreateUserCredsRequest(
      parent=f'projects/{project_id}/databases/{database_id}',
      user_creds_id=user_name,
  )
  response = client.create_user_creds(request)
  return response


def update_iam_policy_for_user_creds(
    project_id: str, database_id: str, user_name: str, user_creds
):
  """Update the IAM policy using the Resource Manager ProjectsClient."""
  client = resourcemanager_v3.ProjectsClient()
  request = iam_policy_pb2.GetIamPolicyRequest()
  request.resource = f'projects/{project_id}'
  request.options.requested_policy_version = 3

  # Get the current IAM policy
  current_policy = client.get_iam_policy(request)

  # Construct an updated IAM policy with an additional binding
  # for the user credentials.
  updated_policy = policy_pb2.Policy()
  binding = policy_pb2.Binding()
  iam_condition = expr_pb2.Expr()

  iam_condition.title = f'Conditional IAM binding for {user_name}'
  iam_condition.expression = (
      f'resource.name == "projects/{project_id}/databases/{database_id}"'
  )

  binding.role = 'roles/datastore.user'
  binding.condition.CopyFrom(iam_condition)
  binding.members.append(user_creds.resource_identity.principal)
  updated_policy.bindings.append(binding)

  # Update the policy
  updated_policy.MergeFrom(current_policy)
  set_policy_request = iam_policy_pb2.SetIamPolicyRequest()
  set_policy_request.resource = f'projects/{project_id}'
  set_policy_request.policy.CopyFrom(updated_policy)

  final_policy = client.set_iam_policy(set_policy_request)
  print(f'Policy updated successfully {final_policy}')


def provision_firestore_user_creds_and_iam(
    project_id: str, database_id: str, user_name: str
):
  """Provision user credentials and configure an IAM policy."""
  user_creds = create_user_creds(project_id, database_id, user_name)

  # Note the password returned in the UserCreds proto - it cannot be
  # retrieved again after the initial call to the create_user_creds API.
  print(f'Created credentials for username: {user_name}')
  print(f'IAM principal: {user_creds.resource_identity.principal}')
  print(f'Password: [{user_creds.secure_password}]')

  # Provision an IAM binding for the principal associated with
  # these user credentials.
  update_iam_policy_for_user_creds(
      project_id, database_id, user_name, user_creds
  )

  # Emit the password again
  print(
      f'Successfully configured IAM policy for database: {database_id},'
      f' username: {user_name}'
  )
  print(f'Please make a note of the password: [{user_creds.secure_password}]')

次の接続文字列を使用して、SCRAM でデータベースに接続します。

mongodb://USERNAME:PASSWORD@UID.LOCATION.firestore.goog:443/DATABASE_ID?loadBalanced=true&authMechanism=SCRAM-SHA-256&tls=true&retryWrites=false

以下を置き換えます。

  • USERNAME: ユーザー名。
  • PASSWORD: このユーザー用に生成したパスワード。
  • UID: データベースの UID。
  • LOCATION: データベースのロケーション。
  • DATABASE_ID: データベース ID。

Google Auth ライブラリに接続する

次のコードサンプルは、Google Cloud 標準の OAuth ライブラリを使用して OIDC コールバック ハンドラを登録します。

このライブラリを使用すると、さまざまなタイプの認証(アプリケーションのデフォルト認証情報、Workload Identity 連携)を使用できます。

そのためには、認証ライブラリを依存関係として追加する必要があります。

// Maven
<dependency>
  <groupId>com.google.auth</groupId>
  <artifactId>google-auth-library-oauth2-http</artifactId>
  <version>1.19.0</version>
</dependency>

// Gradle
implementation 'com.google.auth:google-auth-library-oauth2-http:1.19.0'

次のコードサンプルは、接続方法を示しています。

val db = MongoClients.create(
    clientSettings(
      "DATABASE_UID",
      "LOCATION"
    ).build()
  ).getDatabase("DATABASE_ID")


/**
 * Creates a connection to a Firestore with MongoDB Compatibility database.
 * @param databaseUid The uid of the database to connect to as a string. For example: f116f93a-519c-208a-9a72-3ef6c9a1f081
 * @param locationId The location of the database to connect to, for example: nam5, us-central1, us-east4 etc...
 * @param environment Determines whether to try and fetch an authentication credential from the
 * Compute Engine VM metadata service or whether to call gcloud.
 */
private static MongoClientSettings.Builder clientSettings(
  String databaseUid: String
  String locationId:String
): MongoClientSettings.Builder {
  MongoCredential credential =
    MongoCredential.createOidcCredential(null)
      .withMechanismProperty(
        MongoCredential.OIDC_CALLBACK_KEY,
        new MongoCredential.OidcCallback() {
          @Override
          MongoCredential.OidcCallbackResult onRequest(
MongoCredential.OidcCallbackContext context) {
     // Customize this credential builder for additional credential types.
     GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
            return new MongoCredential.OidcCallbackResult(
         credentials.getAccessToken().getTokenValue(),
         Duration.between(Instant.now(),
credentials.getAccessToken().getExpirationTime().toInstant()));
          }
        },
      );
  return MongoClientSettings.builder()
    .hosts(listOf(ServerAddress(
        "$databaseUid.$locationId.firestore.goog", 443)))
    .credential(credential)
    .applyToClusterSettings(builder ->
         builder.mode(ClusterConnectionMode.LOAD_BALANCED))
    ).applyToSslSettings(ssl -> ssl.enabled(true)).retryWrites(false);
}

以下を置き換えます。

  • DATABASE_UID: プロジェクトの名前。
  • LOCATION: データベースのロケーション。
  • DATABASE_ID データベース ID。

Google Cloud コンピューティング環境から接続する

このセクションでは、Compute Engine などの Google Cloud コンピューティング環境、または Cloud Run サービスやジョブから MongoDB 互換の Cloud Firestore に接続する方法について説明します。

Compute Engine VM から接続する

Compute Engine サービス アカウントを使用して、データベースを認証して接続できます。これを行うには、データベースを含む Google Cloud プロジェクトの IAM ポリシーを作成します。

始める前に

VM のユーザー管理サービス アカウントを構成します。

認証情報を構成するセクションの手順に沿って、Compute Engine サービス アカウントの IAM ポリシーの構成を完了します。

Cloud Run から接続する

Cloud Run サービス アカウントを使用して、データベースを認証して接続できます。これを行うには、データベースを含む Google Cloud プロジェクトの IAM ポリシーを作成します。

始める前に

認証情報を構成するセクションの手順に沿って、Cloud Run サービス アカウントの IAM ポリシーの構成を完了します。

認証情報の構成

Cloud Firestore の読み取りと書き込みを行う roles/datastore.user ロールをサービス アカウントに付与するには、次のコマンドを実行します。

gcloud projects add-iam-policy-binding PROJECT_NAME --member="SERVICE_ACCOUNT_EMAIL" --role=roles/datastore.user

以下を置き換えます。

  • PROJECT_NAME: プロジェクトの名前。
  • SERVICE_ACCOUNT_EMAIL: 作成したサービス アカウントのメールアドレス。

接続文字列を作成する

次の形式で接続文字列を作成します。

mongodb://DATABASE_UID.LOCATION.firestore.goog:443/DATABASE_ID?loadBalanced=true&tls=true&retryWrites=false&authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:FIRESTORE

以下を置き換えます。

  • DATABASE_UID: プロジェクトの名前。
  • LOCATION: データベースのロケーション。
  • DATABASE_ID データベース ID。

UID とロケーションを取得する方法の詳細については、接続文字列を取得するをご覧ください。

一時アクセス トークンを使用して接続する

一時Google Cloudアクセス トークンを使用して、mongosh などの診断ツールを実行できます。gcloud auth print-access-token を使用して、短期的なアクセス トークンで認証できます。トークンは 1 時間有効です。

たとえば、次のコマンドを使用して、mongosh でデータベースに接続します。

mongosh --tls \
      --username access_token --password $(gcloud auth print-access-token) \
      'mongodb://UID.LOCATION.firestore.goog:443/DATABASE_ID?loadBalanced=true&authMechanism=PLAIN&authSource=$external&retryWrites=false'

以下を置き換えます。

  • DATABASE_UID: データベースの UID
  • LOCATION: データベースのロケーション
  • DATABASE_ID: データベース ID。