Xác thực và kết nối với cơ sở dữ liệu

Chỉ áp dụng cho phiên bản Cloud Firestore Enterprise.

Yêu cầu về kết nối

Sau đây là những yêu cầu đối với Cloud Firestore có các ứng dụng tương thích với MongoDB:

  • Trình điều khiển phải kết nối ở chế độ load balanced. Điều này ngăn các trình điều khiển cố gắng tìm hiểu chính xác cấu trúc liên kết máy chủ mà chúng đang kết nối.
  • Trình điều khiển phải kết nối bằng SSL.
  • Trình điều khiển phải tắt các thao tác ghi có thể thử lại. Cloud Firestore có khả năng tương thích với MongoDB không hỗ trợ các thao tác ghi có thể thử lại. Bạn không cần tắt các thao tác đọc có thể thử lại vì chúng được hỗ trợ.

Truy xuất chuỗi kết nối

Chuỗi kết nối cơ sở dữ liệu phụ thuộc vào UID của cơ sở dữ liệu, vị trí của cơ sở dữ liệu và cơ chế xác thực. Hướng dẫn sau đây mô tả cách tạo chuỗi kết nối.

Chuỗi kết nối chính xác phụ thuộc vào cơ chế xác thực, nhưng chuỗi kết nối cơ sở sử dụng định dạng sau:

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

Bạn có thể lấy chuỗi kết nối cơ sở theo một trong những cách sau:

Firebase bảng điều khiển
  1. Trong bảng điều khiển Firebase, hãy chuyển đến trang Cơ sở dữ liệu Firestore.

    Chuyển đến Cơ sở dữ liệu Firestore

  2. Nhấp vào cơ sở dữ liệu mà bạn muốn xác thực.
  3. Trong bảng điều khiển Explorer (Trình khám phá), hãy nhấp vào biểu tượng Xem thêm.
  4. Chọn Kết nối bằng các công cụ của MongoDB.
  5. Sao chép chuỗi kết nối.
gcloud

Sử dụng gcloud firestore database describe để truy xuất UID và thông tin vị trí:

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

Thay thế DATABASE_ID bằng mã cơ sở dữ liệu.

Kết quả đầu ra bao gồm vị trí và UID của cơ sở dữ liệu. Sử dụng thông tin này để tạo chuỗi kết nối cơ sở.

Sử dụng chuỗi kết nối cơ sở và một trong các phương thức sau để xác thực và kết nối với cơ sở dữ liệu của bạn:

Kết nối bằng tên người dùng và mật khẩu (SCRAM)

Hãy làm theo các bước sau để tạo thông tin đăng nhập của người dùng cho cơ sở dữ liệu và kết nối với cơ sở dữ liệu.

Trước khi bắt đầu

Để có được các quyền cần thiết để tạo người dùng, hãy yêu cầu quản trị viên cấp cho bạn vai trò IAM userCredsAdmin (roles/datastore.userCredsAdmin) trên cơ sở dữ liệu của bạn. Để biết thêm thông tin về cách cấp vai trò, hãy xem bài viết Quản lý quyền truy cập vào dự án, thư mục và tổ chức.

Bạn cũng có thể nhận được các quyền cần thiết thông qua vai trò tuỳ chỉnh hoặc các vai trò xác định trước khác.

Tạo người dùng và kết nối với cơ sở dữ liệu

Để tạo người dùng cho cơ sở dữ liệu Cloud Firestore có khả năng tương thích với MongoDB, hãy sử dụng một trong các phương thức sau:

Bảng điều khiển Google Cloud
  1. Trong bảng điều khiển Google Cloud, hãy chuyển đến trang Cơ sở dữ liệu.

    Chuyển đến phần Cơ sở dữ liệu

  2. Chọn một cơ sở dữ liệu trong danh sách cơ sở dữ liệu.
  3. Trong trình đơn điều hướng, hãy nhấp vào Auth (Uỷ quyền).
  4. Nhấp vào Thêm người dùng.
  5. Nhập Tên người dùng.
  6. Chọn vai trò cho người dùng mới.
  7. Nhấp vào Thêm.

    Mật khẩu của người dùng mới sẽ xuất hiện trong hộp thoại xác nhận.

gcloud CLI
  1. Để xác thực bằng SCRAM, trước tiên, bạn phải tạo thông tin đăng nhập của người dùng. Sử dụng lệnh gcloud firestore user-creds:
    gcloud firestore user-creds create USERNAME --database=DATABASE_ID
    Thay thế nội dung sau:
    • USERNAME: tên người dùng cần tạo.
    • DATABASE_ID: mã cơ sở dữ liệu.

    Kết quả của lệnh này bao gồm mật khẩu của người dùng.

    Kết quả sẽ có dạng như sau:

    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. Theo mặc định, thông tin đăng nhập của người dùng mới này không có quyền nào. Để có quyền đọc và ghi vào cơ sở dữ liệu, hãy thêm vai trò roles/datastore.user cho cơ sở dữ liệu cụ thể này:

    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"'
    Thay thế nội dung sau:
Java

Phần này cung cấp một ví dụ về mã để tạo thông tin đăng nhập của người dùng và định cấu hình chính sách IAM bằng cách sử dụng các thư viện ứng dụng quản trị Java. Mẫu này sử dụng thư viện Ứng dụng quản trị Firestore để tạo tên người dùng và mật khẩu, đồng thời sử dụng thư viện Google Cloud Resource Manager để định cấu hình IAM.

Đối với bản dựng Maven, bạn có thể sử dụng các toạ độ sau:

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

Cung cấp thông tin xác thực người dùng và chính sách 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

Phần này cung cấp một ví dụ về mã để tạo thông tin đăng nhập của người dùng và định cấu hình chính sách IAM bằng thư viện ứng dụng quản trị Python. Mẫu này dùng thư viện Thư viện ứng dụng Google Cloud Firestore API để tạo tên người dùng và mật khẩu, Thư viện ứng dụng Google Cloud Iam APIThư viện ứng dụng Google Cloud Resource Manager API để định cấu hình IAM.

Bạn có thể cài đặt các thư viện Python cần thiết bằng công cụ pip:

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

Cung cấp thông tin xác thực người dùng và chính sách 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}]')

Sử dụng chuỗi kết nối sau để kết nối với cơ sở dữ liệu bằng SCRAM:

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

Thay thế nội dung sau:

  • USERNAME: tên người dùng.
  • PASSWORD: mật khẩu bạn đã tạo cho người dùng này.
  • UID: UID của cơ sở dữ liệu.
  • LOCATION: vị trí của cơ sở dữ liệu.
  • DATABASE_ID: mã cơ sở dữ liệu.

Kết nối với Thư viện xác thực của Google

Mã mẫu sau đây đăng ký một trình xử lý gọi lại OIDC bằng cách sử dụng thư viện OAuth tiêu chuẩn Google Cloud.

Thư viện này cho phép bạn sử dụng một số loại xác thực (Thông tin xác thực mặc định của ứng dụng, Liên kết danh tính của tải).

Bạn cần phải thêm thư viện xác thực làm phần phụ thuộc:

// 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'

Mẫu mã sau đây minh hoạ cách kết nối:

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);
}

Thay thế nội dung sau:

  • DATABASE_UID: tên dự án của bạn.
  • LOCATION: vị trí của cơ sở dữ liệu.
  • DATABASE_ID mã nhận dạng cơ sở dữ liệu.

Kết nối từ môi trường điện toán Google Cloud

Phần này mô tả cách kết nối với Cloud Firestore có khả năng tương thích với MongoDB từ một môi trường điện toán Google Cloud, chẳng hạn như Compute Engine hoặc một dịch vụ hay công việc Cloud Run.

Kết nối từ máy ảo Compute Engine

Bạn có thể xác thực và kết nối với cơ sở dữ liệu của mình bằng tài khoản dịch vụ Compute Engine. Để thực hiện việc này, hãy tạo một chính sách IAM cho dự án Google Cloud chứa cơ sở dữ liệu của bạn.

Trước khi bắt đầu

Định cấu hình tài khoản dịch vụ do người dùng quản lý cho VM:

Hãy xem hướng dẫn trong phần Định cấu hình thông tin đăng nhập để hoàn tất việc định cấu hình chính sách IAM cho tài khoản dịch vụ Compute Engine.

Kết nối từ Cloud Run

Bạn có thể xác thực và kết nối với cơ sở dữ liệu của mình bằng tài khoản dịch vụ Cloud Run. Để thực hiện việc này, hãy tạo một chính sách IAM cho dự án Google Cloud chứa cơ sở dữ liệu của bạn.

Trước khi bắt đầu

Hãy xem hướng dẫn trong phần Định cấu hình thông tin đăng nhập để hoàn tất việc định cấu hình chính sách IAM cho tài khoản dịch vụ Cloud Run.

Định cấu hình thông tin đăng nhập

Để cấp cho tài khoản dịch vụ vai trò roles/datastore.user để đọc và ghi vào Cloud Firestore, hãy chạy lệnh sau:

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

Thay thế nội dung sau:

  • PROJECT_NAME: tên dự án của bạn.
  • SERVICE_ACCOUNT_EMAIL: địa chỉ email của tài khoản dịch vụ mà bạn đã tạo.

Tạo chuỗi kết nối

Hãy sử dụng định dạng sau để tạo chuỗi kết nối:

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

Thay thế nội dung sau:

  • DATABASE_UID: tên dự án của bạn.
  • LOCATION: vị trí của cơ sở dữ liệu.
  • DATABASE_ID mã nhận dạng cơ sở dữ liệu.

Để biết thêm thông tin về cách truy xuất UID và vị trí, hãy xem phần Truy xuất chuỗi kết nối.

Kết nối bằng mã truy cập tạm thời

Bạn có thể dùng mã truy cập Google Cloud tạm thời để chạy các công cụ chẩn đoán như mongosh. Bạn có thể dùng gcloud auth print-access-token để xác thực bằng mã truy cập ngắn hạn. Mã thông báo này có hiệu lực trong một giờ.

Ví dụ: hãy dùng lệnh sau để kết nối với cơ sở dữ liệu bằng 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'

Thay thế nội dung sau:

  • DATABASE_UID: UID của cơ sở dữ liệu
  • LOCATION: vị trí của cơ sở dữ liệu
  • DATABASE_ID: mã nhận dạng cơ sở dữ liệu