Uwierzytelnianie i łączenie się z bazą danych

Wymagania dotyczące połączenia

Wymagania dotyczące klientów Cloud Firestore:

  • Sterowniki muszą łączyć się w trybie load balanced (zrównoważonym obciążeniu). Zapobiega to próbom sterowników zrozumienia dokładnej topologii serwera, z którym się łączą.
  • Sterowniki muszą łączyć się z włączonym protokołem SSL.
  • Sterowniki muszą wyłączyć zapisy, które można ponowić. Cloud Firestore nie obsługuje zapisów, które można ponowić. Nie musisz wyłączać odczytów, które można ponowić, ponieważ są one obsługiwane.

Pobieranie ciągu znaków połączenia

Ciąg znaków połączenia z bazą danych zależy od identyfikatora UID bazy danych, jej lokalizacji i mechanizmu uwierzytelniania. Poniższe instrukcje opisują, jak tworzony jest ciąg znaków połączenia.

Dokładny ciąg znaków połączenia zależy od mechanizmu uwierzytelniania, ale podstawowy ciąg znaków połączenia ma ten format:

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

Podstawowy ciąg znaków połączenia możesz uzyskać na jeden z tych sposobów:

Konsola Firebase
  1. W konsoli Firebase otwórz stronę Baza danych Firestore.

    Otwórz bazę danych Firestore

  2. Kliknij bazę danych, którą chcesz uwierzytelnić.
  3. W panelu Eksplorator kliknij Wyświetl więcej.
  4. Kliknij Połącz za pomocą narzędzi MongoDB.
  5. Skopiuj ciąg znaków połączenia.
gcloud

Aby pobrać identyfikator UID i informacje o lokalizacji, użyj polecenia gcloud firestore database describe:

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

Zastąp DATABASE_ID identyfikatorem bazy danych.

Dane wyjściowe zawierają lokalizację i identyfikator UID bazy danych. Użyj tych informacji, aby utworzyć podstawowy ciąg znaków połączenia.

Aby uwierzytelnić się i połączyć z bazą danych, użyj podstawowego ciągu znaków połączenia i jednej z tych metod:

Łączenie się za pomocą nazwy użytkownika i hasła (SCRAM)

Aby utworzyć dane logowania użytkownika do bazy danych i połączyć się z nią, wykonaj te czynności.

Zanim zaczniesz

Aby uzyskać uprawnienia potrzebne do utworzenia użytkownika, poproś administratora o przypisanie Ci w bazie danych roli userCredsAdmin (roles/datastore.userCredsAdmin). Więcej informacji o przyznawaniu ról znajdziesz w artykule na temat zarządzania dostępem do projektów, folderów i organizacji.

Wymagane uprawnienia możesz też uzyskać, używając ról niestandardowych lub innych gotowych ról.

Tworzenie użytkownika i łączenie się z bazą danych

Aby utworzyć użytkownika bazy danych Cloud Firestore, użyj jednej z tych metod:

Konsola Firebase
  1. W konsoli Firebase otwórz stronę Baza danych Firestore.

    Otwórz bazę danych Firestore

  2. Wybierz bazę danych z listy.
  3. W menu nawigacyjnym kliknij Zabezpieczenia.
  4. Kliknij Add User (Dodaj konto użytkownika).
  5. Wpisz Username (Nazwa użytkownika).
  6. Wybierz rolę nowego użytkownika.
  7. Kliknij Dodaj użytkownika.
  8. Hasło nowego użytkownika zostanie wyświetlone w oknie potwierdzenia.

gcloud CLI
  1. Aby uwierzytelnić się za pomocą SCRAM, musisz najpierw utworzyć dane logowania użytkownika. Użyj polecenia gcloud firestore user-creds:
    gcloud firestore user-creds create USERNAME --database=DATABASE_ID
    Zastąp te elementy:
    • USERNAME: nazwa użytkownika, którą chcesz utworzyć.
    • DATABASE_ID: identyfikator bazy danych.

    Dane wyjściowe tego polecenia zawierają hasło użytkownika.

    Dane wyjściowe wyglądają tak:

    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. Domyślnie te nowe dane logowania użytkownika nie mają żadnych uprawnień. Aby uzyskać dostęp do odczytu i zapisu w bazie danych, dodaj rolę roles/datastore.user dla tej konkretnej bazy danych:

    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"'
    Zastąp te elementy:
    • PROJECT_NAME: nazwa projektu.
    • PROJECT_NUMBER: numer projektu .
    • DATABASE_ID: identyfikator bazy danych.
    • USERNAME: nazwa użytkownika utworzona wcześniej.
    • CONDITION_TITLE: tytuł tego warunku. Ten warunek ogranicza dostęp tylko do tej bazy danych.
Java

W tej sekcji znajdziesz przykład kodu tworzenia danych logowania użytkownika i konfigurowania zasad uprawnień za pomocą bibliotek klienta administracyjnego w języku Java. Przykład używa biblioteki klienta administracyjnego Firestore do tworzenia nazwy użytkownika i hasła oraz biblioteki Google Cloud Resource Manager do konfigurowania uprawnień.

W przypadku kompilacji Maven możesz użyć tych współrzędnych:

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

Zainicjuj dane logowania użytkownika i zasady uprawnień:

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

W tej sekcji znajdziesz przykład kodu tworzenia danych logowania użytkownika i konfigurowania zasad uprawnień za pomocą bibliotek klienta administracyjnego w Pythonie. Przykład używa biblioteki klienta Google Cloud Firestore API do tworzenia nazwy użytkownika i hasła oraz biblioteki klienta Google Cloud Iam API i biblioteki klienta Google Cloud Resource Manager API do konfigurowania uprawnień.

Wymagane biblioteki Pythona można zainstalować za pomocą narzędzia pip:

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

Zainicjuj dane logowania użytkownika i zasady uprawnień:

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}]')

Aby połączyć się z bazą danych za pomocą SCRAM, użyj tego ciągu znaków połączenia:

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

Zastąp te elementy:

  • USERNAME: nazwa użytkownika.
  • PASSWORD: hasło wygenerowane dla tego użytkownika.
  • UID: identyfikator UID bazy danych. Na przykład: f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: lokalizacja bazy danych.
  • DATABASE_ID: identyfikator bazy danych.

Łączenie się za pomocą biblioteki Google Auth

Ten przykładowy kod rejestruje moduł obsługi wywołania zwrotnego OIDC i używa Google Cloud standardowej biblioteki OAuth.

Ta biblioteka umożliwia korzystanie z różnych typów uwierzytelniania (domyślne uwierzytelnianie aplikacji, federacja tożsamości zadań).

Wymaga to dodania biblioteki uwierzytelniania jako zależności:

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

Ten przykładowy kod pokazuje, jak się połączyć:

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

Zastąp te elementy:

  • DATABASE_UID: identyfikator UID bazy danych. Na przykład: f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: lokalizacja bazy danych.
  • DATABASE_ID identyfikator bazy danych.

Łączenie się ze środowiska obliczeniowego Google Cloud

W tej sekcji opisujemy, jak połączyć się z Cloud Firestore ze środowiska Google Cloud obliczeniowego, takiego jak Compute Engine lub usługa Cloud Run lub zadanie.

Łączenie się z maszyny wirtualnej Compute Engine

Możesz uwierzytelnić się i połączyć z bazą danych za pomocą Compute Engine konta usługi. Aby to zrobić, utwórz zasady uprawnień dla projektu Google Cloud, który zawiera Twoją bazę danych.

Zanim zaczniesz

Skonfiguruj konto usługi zarządzane przez użytkownika na maszynie wirtualnej:

Aby skonfigurować zasady uprawnień dla konta usługi Compute Engine, postępuj zgodnie z instrukcjami w sekcjach Konfigurowanie danych logowania.

Łączenie się z Cloud Run

Możesz uwierzytelnić się i połączyć z bazą danych za pomocą Cloud Run konta usługi. Aby to zrobić, utwórz zasady uprawnień dla projektu Google Cloud, który zawiera Twoją bazę danych.

Zanim zaczniesz

Aby skonfigurować zasady uprawnień dla konta usługi Cloud Run, postępuj zgodnie z instrukcjami w sekcjach Konfigurowanie danych logowania.

Konfigurowanie danych logowania

Aby przyznać kontu usługi rolę roles/datastore.user do odczytu i zapisu w Cloud Firestore, uruchom to polecenie:

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

Zastąp te elementy:

  • PROJECT_NAME: nazwa projektu.
  • SERVICE_ACCOUNT_EMAIL: adres e-mail konta usługi utworzonego przez Ciebie.

Tworzenie ciągu znaków połączenia

Aby utworzyć ciąg znaków połączenia, użyj tego formatu:

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

Zastąp te elementy:

  • DATABASE_UID: identyfikator UID bazy danych. Na przykład: f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: lokalizacja bazy danych.
  • DATABASE_ID identyfikator bazy danych.

Więcej informacji o pobieraniu identyfikatora UID i lokalizacji znajdziesz w artykule Pobieranie ciągu znaków połączenia.

Łączenie się za pomocą tymczasowego tokena dostępu

Aby uruchamiać narzędzia diagnostyczne, takie jak mongosh, możesz użyć tymczasowego Google Cloud tokena dostępu. Aby uwierzytelnić się za pomocą krótkoterminowego tokena dostępu, możesz użyć polecenia gcloud auth print-access-token. Ten token jest ważny przez godzinę.

Aby na przykład połączyć się z bazą danych za pomocą mongosh, użyj tego polecenia:

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'

Zastąp te elementy:

  • DATABASE_UID: identyfikator UID bazy danych. Na przykład: f116f93a-519c-208a-9a72-3ef6c9a1f081
  • LOCATION: lokalizacja bazy danych.
  • DATABASE_ID: identyfikator bazy danych.