ตรวจสอบสิทธิ์และเชื่อมต่อกับฐานข้อมูล

ข้อกำหนดในการเชื่อมต่อ

ไคลเอ็นต์ Cloud Firestore ต้องมีสิ่งต่อไปนี้

  • ไดรเวอร์ต้องเชื่อมต่อในโหมด load balanced ซึ่งจะป้องกันไม่ให้ไดรเวอร์พยายามทำความเข้าใจโทโพโลยีของเซิร์ฟเวอร์ที่เชื่อมต่อ
  • ไดรเวอร์ต้องเชื่อมต่อโดยเปิดใช้ SSL
  • ไดรเวอร์ต้องปิดใช้การเขียนที่ลองใหม่ได้ Cloud Firestore ไม่รองรับ การเขียนที่ลองใหม่ได้ คุณไม่จำเป็นต้องปิดใช้การอ่านที่ลองใหม่ได้เนื่องจากระบบรองรับการอ่านดังกล่าว

ดึงข้อมูลสตริงการเชื่อมต่อ

สตริงการเชื่อมต่อฐานข้อมูลจะขึ้นอยู่กับ UID ของฐานข้อมูล ตำแหน่งของฐานข้อมูล และกลไกการตรวจสอบสิทธิ์ วิธีการต่อไปนี้อธิบายวิธีสร้างสตริงการเชื่อมต่อ

สตริงการเชื่อมต่อที่แน่นอนจะขึ้นอยู่กับกลไกการตรวจสอบสิทธิ์ แต่สตริงการเชื่อมต่อพื้นฐานจะใช้รูปแบบต่อไปนี้

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

คุณสามารถรับสตริงการเชื่อมต่อพื้นฐานได้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้

คอนโซล Firebase
  1. ในคอนโซล Firebase ให้ไปที่หน้าฐานข้อมูล Firestore

    ไปที่ฐานข้อมูล Firestore

  2. คลิกฐานข้อมูลที่ต้องการตรวจสอบสิทธิ์
  3. ในแผงExplorer ให้คลิก ดูเพิ่มเติม
  4. เลือกเชื่อมต่อโดยใช้เครื่องมือ MongoDB
  5. คัดลอกสตริงการเชื่อมต่อ
gcloud

ใช้ gcloud firestore database describe เพื่อดึงข้อมูล UID และตำแหน่ง

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

แทนที่ DATABASE_ID ด้วยรหัสฐานข้อมูล

เอาต์พุตจะมีตำแหน่งและ UID ของฐานข้อมูล ใช้ข้อมูลนี้เพื่อสร้างสตริงการเชื่อมต่อพื้นฐาน

ใช้สตริงการเชื่อมต่อพื้นฐานและวิธีใดวิธีหนึ่งต่อไปนี้เพื่อตรวจสอบสิทธิ์และเชื่อมต่อกับฐานข้อมูล

เชื่อมต่อด้วยชื่อผู้ใช้และรหัสผ่าน (SCRAM)

ทำตามขั้นตอนต่อไปนี้เพื่อสร้างข้อมูลเข้าสู่ระบบของผู้ใช้สำหรับฐานข้อมูลและเชื่อมต่อกับฐานข้อมูล

ก่อนเริ่มต้น

หากต้องการรับสิทธิ์ที่จำเป็นในการสร้างผู้ใช้ ให้ขอให้ผู้ดูแลระบบ มอบบทบาท userCredsAdmin (roles/datastore.userCredsAdmin) ของ IAM ในฐานข้อมูลให้คุณ ดูข้อมูลเพิ่มเติมเกี่ยวกับการมอบบทบาทได้ที่หัวข้อจัดการการเข้าถึงโปรเจ็กต์ โฟลเดอร์ และ องค์กร

นอกจากนี้ คุณอาจได้รับสิทธิ์ที่จำเป็นผ่านบทบาท ที่กำหนดเองหรือ บทบาทที่กำหนดไว้ล่วงหน้าอื่นๆ

สร้างผู้ใช้และเชื่อมต่อกับฐานข้อมูล

หากต้องการสร้างผู้ใช้สำหรับฐานข้อมูล Cloud Firestore ให้ใช้วิธีใดวิธีหนึ่งต่อไปนี้

คอนโซล Firebase
  1. ในคอนโซล Firebase ให้ไปที่หน้าฐานข้อมูล Firestore

    ไปที่ฐานข้อมูล Firestore

  2. เลือกฐานข้อมูลจากรายการฐานข้อมูล
  3. ในเมนูการนำทาง ให้คลิกความปลอดภัย
  4. คลิกเพิ่มผู้ใช้
  5. ป้อนชื่อผู้ใช้
  6. เลือกบทบาทสำหรับผู้ใช้ใหม่
  7. คลิกเพิ่มผู้ใช้
  8. รหัสผ่านของผู้ใช้ใหม่จะแสดงในกล่องโต้ตอบยืนยัน

gcloud CLI
  1. หากต้องการตรวจสอบสิทธิ์ด้วย SCRAM คุณต้องสร้างข้อมูลเข้าสู่ระบบของผู้ใช้ก่อน ใช้คำสั่ง gcloud firestore user-creds ดังนี้
    gcloud firestore user-creds create USERNAME --database=DATABASE_ID
    แทนที่ข้อมูลต่อไปนี้
    • USERNAME: ชื่อผู้ใช้ที่จะสร้าง
    • DATABASE_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

ส่วนนี้มีตัวอย่างโค้ดสำหรับการสร้างข้อมูลเข้าสู่ระบบของผู้ใช้และการกำหนดค่านโยบาย IAM โดยใช้ไลบรารีของไคลเอ็นต์การดูแลระบบ Java ตัวอย่างนี้ใช้ไลบรารีของ ไคลเอ็นต์การดูแลระบบ Firestore สำหรับการสร้างชื่อผู้ใช้ และรหัสผ่าน และใช้ไลบรารี Google Cloud Resource Manager สำหรับการกำหนดค่า IAM

สำหรับการสร้าง 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

ส่วนนี้มีตัวอย่างโค้ดสำหรับการสร้างข้อมูลเข้าสู่ระบบของผู้ใช้และการกำหนดค่านโยบาย IAM โดยใช้ไลบรารีของไคลเอ็นต์การดูแลระบบ Python ตัวอย่างนี้ใช้ไลบรารีของไคลเอ็นต์ Google Cloud Firestore API สำหรับสร้างชื่อผู้ใช้และรหัสผ่าน และใช้ ไลบรารีของไคลเอ็นต์ Google Cloud Iam API และไลบรารีของไคลเอ็นต์ Google Cloud Resource Manager API สำหรับกำหนดค่า IAM

คุณสามารถติดตั้งไลบรารี 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 ของฐานข้อมูล เช่น f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: ตำแหน่งของฐานข้อมูล
  • DATABASE_ID: รหัสฐานข้อมูล

เชื่อมต่อด้วยไลบรารีการตรวจสอบสิทธิ์ของ Google

ตัวอย่างโค้ดต่อไปนี้จะลงทะเบียนแฮนเดิลเลอร์การเรียกกลับ OIDC โดยใช้ไลบรารี OAuth มาตรฐาน Google Cloud ของ Google Cloud

ไลบรารีนี้ช่วยให้คุณใช้การตรวจสอบสิทธิ์ได้หลายประเภท (ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน, Workload Identity Federation)

คุณต้องเพิ่มไลบรารีการตรวจสอบสิทธิ์เป็นทรัพยากร Dependency ดังนี้: adding the auth library as a dependency

// 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: UID ของฐานข้อมูล เช่น f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: ตำแหน่งของฐานข้อมูล
  • DATABASE_ID รหัสฐานข้อมูล

เชื่อมต่อจากสภาพแวดล้อมการประมวลผลของ Google Cloud

ส่วนนี้อธิบายการเชื่อมต่อกับ Cloud Firestore จากสภาพแวดล้อมการประมวลผลGoogle Cloud เช่น Compute Engine หรือบริการหรือCloud Runงาน

เชื่อมต่อจาก VM Compute Engine

คุณสามารถตรวจสอบสิทธิ์และเชื่อมต่อกับฐานข้อมูลโดยใช้Compute Engine บัญชีบริการ โดยสร้างนโยบาย IAM สำหรับ Google Cloudโปรเจ็กต์ที่มีฐานข้อมูล

ก่อนเริ่มต้น

กำหนดค่าบัญชีบริการที่ผู้ใช้จัดการสำหรับ VM โดยทำดังนี้

ดูวิธีการในส่วนกำหนดค่าข้อมูลเข้าสู่ระบบเพื่อกำหนดค่านโยบาย IAM สำหรับบัญชีบริการCompute Engineให้เสร็จสมบูรณ์

เชื่อมต่อจาก Cloud Run

คุณสามารถตรวจสอบสิทธิ์และเชื่อมต่อกับฐานข้อมูลโดยใช้Cloud Run บัญชีบริการ โดยสร้างนโยบาย IAM สำหรับ Google Cloudโปรเจ็กต์ที่มีฐานข้อมูล

ก่อนเริ่มต้น

ดูวิธีการในส่วนกำหนดค่าข้อมูลเข้าสู่ระบบเพื่อกำหนดค่านโยบาย IAM สำหรับบัญชีบริการCloud Runให้เสร็จสมบูรณ์

กำหนดค่าข้อมูลเข้าสู่ระบบ

หากต้องการให้สิทธิ์บทบาท roles/datastore.user แก่บัญชีบริการสำหรับการอ่านและเขียน ไปยัง Cloud Firestore ให้เรียกใช้คำสั่งต่อไปนี้

gcloud projects add-iam-policy-binding PROJECT_NAME --member="serviceAccount: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: UID ของฐานข้อมูล เช่น f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: ตำแหน่งของฐานข้อมูล
  • DATABASE_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 ของฐานข้อมูล เช่น f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: ตำแหน่งของฐานข้อมูล
  • DATABASE_ID: รหัสฐานข้อมูล