Configura y administra proyectos y productos de Firebase mediante Terraform

1. Introducción

Objetivos

Puedes usar Terraform para configurar y administrar un proyecto de Firebase, incluida la configuración programática de la infraestructura y los productos de Firebase.

En este codelab, primero se describe cómo compilar un archivo de configuración de Terraform para crear un nuevo proyecto de Firebase. Luego, se explica cómo configurar las apps y los productos de Firebase que quieras usar en ese proyecto. También veremos los conceptos básicos de la línea de comandos de Terraform, como la vista previa de los cambios que se realizarán y, luego, su implementación.

Si quieres aprender a configurar y administrar proyectos y productos de Firebase con Terraform, este codelab es para ti.

Aprendizajes esperados

  • Cómo crear un archivo de configuración de Terraform (*.tf)
  • Cómo usar los comandos de la CLI de Terraform para administrar tu infraestructura
  • Cómo modificar la configuración para actualizar los recursos y servicios
  • Cómo aplicar tu configuración en una aplicación web real (llamada Friendly Chat)
  • Cómo definir configuraciones paralelas (y sincronizadas) en diferentes entornos (producción, etapa de pruebas, etcétera)

Requisitos

Para completar este codelab correctamente, debes tener conocimientos básicos sobre Terraform y su terminología, incluidos los siguientes requisitos previos:

En este codelab, se proporciona una app de ejemplo real para que puedas probar lo que aprovisionas a través de Terraform y también interactuar con él. Para ello, necesitarás lo siguiente:

  • El código de muestra para una app web: Descárgalo en el siguiente paso del codelab
  • Instala estas herramientas en el administrador de paquetes npm (que suele incluir Node.js).
  • Firebase CLI: Instala esta CLI y accede

2. Obtén el código de partida

En este codelab, puedes probar lo que aprovisionas mediante Terraform con una app web real. Te recomendamos que lo hagas de modo que comprendas todos los pasos necesarios para usar los recursos aprovisionados por Terraform.

Clona el repositorio de GitHub del codelab desde la línea de comandos:

git clone https://github.com/firebase/codelab-friendlychat-web

Como alternativa, si no tienes instalado Git, puedes descargar el repositorio como un archivo ZIP.

3. Cómo crear una configuración de Terraform

Configuración de Terraform

  1. En la base de código de la app de ejemplo descargada, navega hasta la raíz del directorio web.
  2. En la raíz de ese directorio, crea un archivo de configuración de Terraform llamado main.tf con la siguiente configuración inicial:

    main.tf
    # Terraform configuration to set up providers by version.
    terraform {
      required_providers {
        google-beta = {
          source  = "hashicorp/google-beta"
          version = "~> 4.0"
        }
      }
    }
    
    # Configure the provider not to use the specified project for quota check.
    # This provider should only be used during project creation and initializing services.
    provider "google-beta" {
      alias                 = "no_user_project_override"
      user_project_override = false
    }
    
    # Configure the provider that uses the new project's quota.
    provider "google-beta" {
      user_project_override = true
    }
    

Cada uno de los proveedores de google-beta tiene un atributo llamado user_project_override que determina cómo se verificarán las cuotas de las operaciones de Terraform. Para aprovisionar la mayoría de los recursos, debes usar user_project_override = true, lo que significa que debes verificar la cuota en tu propio proyecto de Firebase. Sin embargo, si quieres configurar tu proyecto nuevo para que pueda aceptar verificaciones de cuotas, primero debes usar user_project_override=false. La sintaxis alias de Terraform te permite distinguir entre las dos configuraciones del proveedor en los siguientes pasos de este codelab.

Inicializa Terraform en el directorio

Para crear una configuración nueva por primera vez, debes descargar el proveedor especificado en la configuración.

Para realizar esta inicialización, ejecuta el siguiente comando desde la raíz del mismo directorio que el archivo de configuración main.tf:

terraform init

4. Crea un proyecto de Firebase mediante Terraform

Para “crear un proyecto de Firebase”, es importante recordar que cada proyecto de Firebase es en realidad un proyecto de Google Cloud, solo que tiene habilitados los servicios de Firebase.

Agrega bloques para el proyecto de Google Cloud subyacente y las APIs.

  1. Primero, aprovisiona el proyecto subyacente de Google Cloud.

    Agrega el siguiente bloque de recursos al archivo de configuración main.tf.

    Debes especificar el nombre del proyecto (como "Terraform FriendlyChat Codelab") y el ID del proyecto (como "terraform-codelab-your-initials"). Ten en cuenta que el valor name solo se usa dentro de las interfaces de Firebase y no es visible para los usuarios finales. Sin embargo, el valor project_id identifica tu proyecto de forma única para Google, así que asegúrate de especificar un valor único. main.tf
    ...
    
    # Create a new Google Cloud project.
    resource "google_project" "default" {
      provider = google-beta.no_user_project_override
    
      name            = "<PROJECT_NAME_OF_YOUR_PROJECT>"
      project_id      = "<PROJECT_ID_OF_YOUR_PROJECT>"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
  2. A continuación, debes habilitar las APIs subyacentes requeridas: la API de Service Usage y la API de Firebase Management.

    Por lo general, la habilitación de la API se realiza en segundo plano cuando se usa Firebase console para crear un proyecto de Firebase. Sin embargo, se le debe indicar explícitamente a Terraform que lo haga.

    En tu archivo de configuración main.tf (justo debajo del bloque que crea el nuevo proyecto de Cloud), agrega el siguiente bloque de recursos:

    Las verificaciones de uso de la nueva API de Service.
    ...
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "serviceusage" {
      provider = google-beta.no_user_project_override
    
      project = google_project.default.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "firebase" {
      provider = google-beta.no_user_project_override
    
      project = google_project.default.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    Por lo tanto, para todo el aprovisionamiento de recursos y la habilitación de servicios posteriores, debes usar el proveedor con user_project_override (sin alias).

Agrega un bloque para habilitar los servicios de Firebase

Lo último que debes hacer para “crear un proyecto de Firebase” es habilitar los servicios de Firebase en el proyecto.

En el archivo de configuración main.tf, agrega el siguiente bloque de recursos.

Como se mencionó anteriormente, ten en cuenta que este bloque de recursos usa el proveedor con user_project_override (no se necesita alias).

main.tf

...

# Enable Firebase services for the new project created above.
resource "google_firebase_project" "default" {
  provider = google-beta

  project = google_project.default.project_id

  # Wait until the required APIs are enabled.
  depends_on = [
    google_project_service.firebase,
    google_project_service.serviceusage,
  ]
}

En el bloque de recursos anterior, es posible que veas la cláusula depends_on, que le indica a Terraform que espere a que se habiliten las APIs subyacentes. Sin esta cláusula, Terraform no conoce la dependencia y puede experimentar errores cuando se aprovisionan recursos en paralelo.

Aplica la configuración

  1. Para aprovisionar los recursos nuevos y habilitar las APIs especificadas en tu archivo de configuración, ejecuta el siguiente comando desde la raíz del mismo directorio que tu archivo main.tf (que debería ser web):
    terraform apply
    
  2. En la terminal, Terraform imprime un plan de acciones que realizará.

    Si todo se ve como se esperaba, ingresa yes para aprobar las acciones.

    main.tf
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      + create
    
    Terraform will perform the following actions:
    
      # google_firebase_project.default will be created
      + resource "google_firebase_project" "default" {
          + display_name   = (known after apply)
          + id             = (known after apply)
          + project        = "terraform-friendlychat-codelab"
          + project_number = (known after apply)
        }
    
      # google_project.default will be created
      + resource "google_project" "default" {
          + auto_create_network = true
          + id                  = (known after apply)
          + labels              = {
              + "firebase" = "enabled"
            }
          + name                = "Terraform FriendlyChat Codelab"
          + number              = (known after apply)
          + project_id          = "terraform-friendlychat-codelab"
          + skip_delete         = (known after apply)
        }
    
      # google_project_service.firebase will be created
      + resource "google_project_service" "firebase" {
          + disable_on_destroy = false
          + id                 = (known after apply)
          + project            = "terraform-friendlychat-codelab"
          + service            = "firebase.googleapis.com"
        }
    
      # google_project_service.serviceusage will be created
      + resource "google_project_service" "serviceusage" {
          + disable_on_destroy = false
          + id                 = (known after apply)
          + project            = "terraform-friendlychat-codelab"
          + service            = "serviceusage.googleapis.com"
        }
    
    Plan: 4 to add, 0 to change, 0 to destroy.
    
    Do you want to perform these actions?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
    
      Enter a value: yes # <----
    

Ten en cuenta que, si solo necesitas obtener una vista previa de los cambios sin aplicarlos, puedes usar el comando terraform plan en su lugar.

Valida los cambios

Cuando Terraform termine de ejecutarse, puedes inspeccionar el estado de todos los recursos y servicios aprovisionados por Terraform que estén habilitados ejecutando el siguiente comando:

terraform show

Este es un ejemplo de lo que deberías ver impreso. El estado contendrá valores específicos para tu proyecto.

# google_firebase_project.default:
resource "google_firebase_project" "default" {
    display_name   = "Terraform FriendlyChat Codelab"
    id             = "projects/terraform-friendlychat-codelab"
    project        = "terraform-friendlychat-codelab"
    project_number = "000000000"
}

# google_project.default:
resource "google_project" "default" {
    auto_create_network = true
    id                  = "projects/terraform-friendlychat-codelab"
    labels              = {
        "firebase" = "enabled"
    }
    name                = "Terraform FriendlyChat Codelab"
    number              = "000000000"
    project_id          = "terraform-friendlychat-codelab"
}

# google_project_service.firebase:
resource "google_project_service" "firebase" {
    disable_on_destroy = false
    id                 = "terraform-friendlychat-codelab/firebase.googleapis.com"
    project            = "terraform-friendlychat-codelab"
    service            = "firebase.googleapis.com"
}

# google_project_service.serviceusage:
resource "google_project_service" "serviceusage" {
    disable_on_destroy = false
    id                 = "terraform-friendlychat-codelab/serviceusage.googleapis.com"
    project            = "terraform-friendlychat-codelab"
    service            = "serviceusage.googleapis.com"
}

También puedes verificar que el proyecto se creó en Firebase console.

El proyecto del codelab de Terraform FriendlyChat seleccionado en Firebase console

5. Registra tu app de Firebase mediante Terraform

Para usar Firebase, debes registrar cada variante de plataforma de tu app en el proyecto de Firebase. En este codelab, usarás una app real para probar lo que aprovisiones a través de Terraform y poder interactuar con él. Esta app es una app web, por lo que debes indicarle a Terraform que registre una app web de Firebase en el proyecto de Firebase que acabas de crear.

Agrega un bloqueo para registrar la app web

Para registrar la app web en tu proyecto de Firebase, agrega el archivo main.tf con el siguiente bloque de recursos.

Debes especificar tu propio display_name para tu aplicación web. Ten en cuenta que este nombre solo se usa dentro de las interfaces de Firebase y no es visible para los usuarios finales.

main.tf

...

# Create a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "default" {
  provider = google-beta

  project      = google_firebase_project.default.project
  display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
  deletion_policy = "DELETE"
}

Aplica la configuración

  1. Para aprovisionar el recurso nuevo, ejecuta el siguiente comando desde la raíz del mismo directorio en el que se encuentra el archivo main.tf (que debería ser web).
    terraform apply
    
    Ten en cuenta que este comando no volverá a crear un proyecto de Google Cloud nuevo. Terraform detectará que ya existe un proyecto con el ID del proyecto especificado, comparará el estado actual del proyecto con el contenido del archivo .tf y realizará los cambios que encuentre.
  2. Revisa el plan de acciones impreso. Si todo se ve como se espera, escribe yes y presiona Intro para aprobar las acciones.

Valida los cambios

Puedes inspeccionar el estado del recurso recién aprovisionado; para ello, ejecuta el siguiente comando:

terraform show

También puedes verificar que la app se haya registrado correctamente en tu proyecto. Para ello, ve a Firebase console. Ve a Configuración del proyecto y, luego, desplázate hacia abajo hasta la sección Tus apps.

6. Configura Firebase Authentication

La autenticación es una parte importante de cualquier app. Para permitir que los usuarios finales accedan a tu app web con sus Cuentas de Google, puedes habilitar Firebase Authentication y configurar el método de acceso con Google.

Ten en cuenta que, en este codelab, proporcionamos dos opciones diferentes para configurar Firebase Authentication:

  • Opción 1 (recomendada): Configura Firebase Authentication en la consola, que no requiere GCIP.
    • Usar esta opción significa que no tienes que asociar tu proyecto nuevo con una cuenta de Facturación de Cloud.
  • Opción 2: Configura Firebase Authentication mediante Terraform con las APIs de Google Cloud Identity Platform (GCIP).
    • Si usas esta opción, deberás asociar el proyecto nuevo con una cuenta de Facturación de Cloud, ya que GCIP requiere que el proyecto tenga el plan de precios Blaze.

Opción 1: Configura Authentication con Firebase console

Para configurar Firebase Authentication con Firebase console, no es necesario que tu proyecto tenga el plan de precios Blaze.

Aquí te mostramos cómo configurar Firebase Authentication y acceder con Google:

  1. En Firebase console, busca la sección Compilación en el panel izquierdo.
  2. Haz clic en Authentication, en Get started y, por último, en la pestaña Sign-in method (o haz clic aquí para ir directamente allí).
  3. Haz clic en Agregar proveedor nuevo y, en la sección Proveedores adicionales, selecciona Google.
  4. Activa el botón de activación Habilitar.
  5. Configura el nombre público de tu app con un valor como FriendlyChat (no es necesario que sea único a nivel global).
  6. Elige un Correo electrónico de asistencia del proyecto en el menú desplegable y, luego, haz clic en Guardar.Configura Firebase Auth en Firebase console
  7. Deberías ver a Google como un proveedor de acceso habilitado.Página de autenticación de Firebase console: Acceso con Google habilitado

Opción 2: Configura la autenticación mediante Terraform con las APIs de Google Cloud Identity Platform (GCIP)

Para configurar Firebase Authentication mediante Terraform, debes usar las APIs de GCIP, lo que significa que el proyecto debe tener el plan de precios Blaze. Asocia una cuenta de Facturación de Cloud al proyecto para actualizar tu proyecto de Firebase y poder usar el plan Blaze.

Habilita la facturación mediante Terraform

  1. Si todavía no tienes una cuenta de Facturación de Cloud, el primer paso es crear una cuenta nueva en la consola de Google Cloud. Cuando lo hagas, toma nota del ID de la cuenta de facturación. Puedes encontrar el ID de la cuenta de facturación en la página Facturación, en el ID de la cuenta de facturación asociado a tu proyecto.Habilita una cuenta de facturación con la consola de Google Cloud
  2. Para habilitar la facturación en tu proyecto mediante Terraform, agrega un atributo billing_account al recurso google_project existente en tu archivo main.tf:

    main.tf
    ...
    
    # Create a new Google Cloud project.
    resource "google_project" "default" {
      provider = google-beta.no_user_project_override
    
      name            = "<PROJECT_NAME_OF_YOUR_PROJECT>"
      project_id      = "<PROJECT_ID_OF_YOUR_PROJECT>"
      billing_account = "<YOUR_BILLING_ACCOUNT_ID>" # Add this line with your Cloud Billing account ID
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    ...
    

Habilita Firebase Authentication y accede con Google mediante Terraform

  1. Para aprovisionar Firebase Authentication con GCIP, agrega tu archivo main.tf con los siguientes bloques de recursos:

    main.tf
    ...
    
    # Enable the Identity Toolkit API.
    resource "google_project_service" "auth" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      service =  "identitytoolkit.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Create an Identity Platform config.
    # Also, enable Firebase Authentication using Identity Platform (if Authentication isn't yet enabled).
    resource "google_identity_platform_config" "auth" {
      provider = google-beta
      project  = google_firebase_project.default.project
    
      # For example, you can configure to auto-delete anonymous users.
      autodelete_anonymous_users = true
    
      # Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication.
      depends_on = [
        google_project_service.auth,
      ]
    }
    
  2. Para habilitar el acceso con Google, es necesario tener un cliente de OAuth. Ve a la sección APIs y servicios de la consola de Google Cloud para realizar esta configuración.
  3. Dado que es la primera vez que creas un ID de cliente para este proyecto, debes configurar tu pantalla de consentimiento de OAuth.
    1. Abre la página Pantalla de consentimiento de OAuth y, luego, selecciona el proyecto que acabas de crear.
    2. Configura el Tipo de usuario como Externo y, luego, haz clic en Crear.
    3. En la siguiente pantalla, completa lo siguiente y, luego, haz clic en Save and continue.
      • Configura el Nombre de la app para el público con un nombre como FriendlyChat (no es necesario que sea único a nivel global).
      • Elige un Correo electrónico de asistencia al usuario en el menú desplegable.
      • Ingresa un correo electrónico para la información de contacto del desarrollador.
    4. En las próximas pantallas, completa lo siguiente:
      • Acepta la configuración predeterminada en la página Permisos y, luego, haz clic en Guardar y continuar.
      • Acepta los valores predeterminados en la página Usuarios de prueba y, luego, haz clic en Guardar y continuar.
      • Revisa el resumen y, luego, haz clic en Volver al panel.
      Configura un cliente de OAuth2 con la consola de Google Cloud
  4. Para configurar un cliente de OAuth en la página Credenciales, haz lo siguiente:
    1. Haz clic en Crear credenciales y, luego, selecciona ID de cliente OAuth.
    2. En el menú desplegable Tipo de aplicación, selecciona Aplicación web.
    3. En el campo Nombre, ingresa el nombre de tu app, por ejemplo, FriendlyChat (no es necesario que sea único a nivel global).
    4. Para permitir que la URL de tu app use este cliente de OAuth, configura lo siguiente:
      • En Orígenes autorizados de JavaScript, haz clic en Agregar URI y, luego, ingresa
        https://<PROJECT_ID>.firebaseapp.com, donde <PROJECT_ID> es el ID del proyecto que configuraste en main.tf.
      • En URI de redireccionamiento autorizados, haz clic en Agregar URI y, luego, ingresa
        https://<PROJECT_ID>.firebaseapp.com/__/auth/handler, en el que <PROJECT_ID> es el ID del proyecto que configuraste en main.tf.
    5. Haz clic en Guardar.
    Cómo obtener el secreto y el ID de cliente de OAuth2 de la página de credenciales de la consola de Google Cloud
  5. Para habilitar el acceso con Google a través del secreto de cliente y el ID de cliente de OAuth, agrega el archivo main.tf con el siguiente bloque:

    main.tf
    ...
    
    variable "oauth_client_secret" {
      type = string
    
      description = "OAuth client secret. For this codelab, you can pass in this secret through the environment variable TF_VAR_oauth_client_secret. In a real app, you should use a secret manager service."
    
      sensitive = true
    }
    
    resource "google_identity_platform_default_supported_idp_config" "google_sign_in" {
      provider = google-beta
      project  = google_firebase_project.default.project
    
      enabled       = true
      idp_id        = "google.com"
      client_id     = "<YOUR_OAUTH_CLIENT_ID>"
      client_secret = var.oauth_client_secret
    
      depends_on = [
         google_identity_platform_config.auth
      ]
    }
    

Aplica la configuración

  1. Para configurar Authentication según tu configuración, ejecuta los siguientes comandos desde la raíz del mismo directorio en el que está tu archivo main.tf (que debería ser web):
    export TF_VAR_oauth_client_secret="<YOUR_OAUTH_CLIENT_SECRET>"
    
    terraform apply
    
    Ten en cuenta que ejecutar terraform apply no volverá a crear un proyecto de Google Cloud nuevo. Terraform detectará que ya existe un proyecto con el ID del proyecto especificado y comparará el estado actual del proyecto con el contenido del archivo .tf. Luego, realizará los cambios que encuentre.
  2. Revisa el plan de acciones impreso. Si todo se ve como se espera, escribe yes y presiona Intro para aprobar las acciones.

Valida los cambios

  1. En Firebase console, busca la sección Compilación en el panel izquierdo.
  2. Haz clic en Authentication y, luego, en la pestaña Sign-in method (o haz clic aquí para ir directamente allí).
  3. Deberías ver a Google como un proveedor de acceso habilitado.Página de autenticación de Firebase console: Acceso con Google habilitado

7. Configura una base de datos de Firestore y sus reglas de seguridad

En la app web de este codelab, almacenarás mensajes entre los usuarios finales en una base de datos de Firestore.

  1. Para habilitar las APIs necesarias y aprovisionar la instancia de base de datos, agrega tu archivo main.tf con los siguientes bloques de recursos:

    main.tf
    ...
    
    # Enable required APIs for Cloud Firestore.
    resource "google_project_service" "firestore" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      for_each = toset([
        "firestore.googleapis.com",
        "firebaserules.googleapis.com",
      ])
      service = each.key
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Provision the Firestore database instance.
    resource "google_firestore_database" "default" {
      provider                    = google-beta
    
      project                     = google_firebase_project.default.project
      name                        = "(default)"
      # See available locations:
      # https://firebase.google.com/docs/firestore/locations
      location_id                 = "<NAME_OF_DESIRED_REGION>"
      # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs,
      # authentication, and Firebase Security Rules.
      type                        = "FIRESTORE_NATIVE"
      concurrency_mode            = "OPTIMISTIC"
    
      depends_on = [
        google_project_service.firestore
      ]
    }
    
  2. Cambia <NAME_OF_DESIRED_REGION> a la región en la que quieres que resida la base de datos.

    Cuando desarrolles una app de producción, lo ideal es que esté en una región cercana a la mayoría de los usuarios y que sea común con otros servicios de Firebase, como Cloud Functions. En este codelab, puedes usar us-east1 (Carolina del Sur) o la región más cercana a ti (consulta Ubicaciones de Cloud Firestore).
  3. Cada instancia de base de datos de Firestore a la que Firebase puede acceder debe estar protegida por las reglas de seguridad de Firebase.

    El código de muestra de este codelab proporciona un conjunto de reglas seguras de Firestore en el archivo firestore.rules, que puedes encontrar en la raíz del directorio web.
  4. Agrega tu archivo main.tf con los siguientes bloques de recursos para hacer lo siguiente:
    • Crea un conjunto de reglas de las reglas de seguridad de Firebase desde el archivo local firestore.rules.
    • Libera el conjunto de reglas para la instancia de Firestore.
    Ten en cuenta que estos bloques de recursos logran el equivalente a hacer clic en el botón Publicar en Firebase console o ejecutar firebase deploy --only firestore:rules.

    main.tf
    ...
    
    # Create a ruleset of Firestore Security Rules from a local file.
    resource "google_firebaserules_ruleset" "firestore" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      source {
        files {
          name = "firestore.rules"
          # Write security rules in a local file named "firestore.rules".
          # Learn more: https://firebase.google.com/docs/firestore/security/get-started
          content = file("firestore.rules")
        }
      }
    
      # Wait for Firestore to be provisioned before creating this ruleset.
      depends_on = [
        google_firestore_database.default,
      ]
    }
    
    # Release the ruleset for the Firestore instance.
    resource "google_firebaserules_release" "firestore" {
      provider     = google-beta
    
      name         = "cloud.firestore"  # must be cloud.firestore
      ruleset_name = google_firebaserules_ruleset.firestore.name
      project      = google_firebase_project.default.project
    
      # Wait for Firestore to be provisioned before releasing the ruleset.
      depends_on = [
        google_firestore_database.default,
      ]
    
      lifecycle {
        replace_triggered_by = [
          google_firebaserules_ruleset.firestore
        ]
      }
    }
    
  5. Ejecuta terraform apply para aprovisionar la base de datos de Firestore y, luego, implementar sus reglas de seguridad.
  6. Verifica que la base de datos esté aprovisionada y que las reglas de seguridad estén implementadas:
    1. En Firebase console, busca la sección Compilación en el panel izquierdo.
    2. Ve a la sección Base de datos de Firestore y, luego, haz clic en la pestaña Reglas.
    Verifica las reglas de Cloud Firestore con Firebase console

8. Configura un bucket de Cloud Storage y sus reglas de seguridad

En la app web de este codelab, almacenarás imágenes compartidas entre usuarios finales en un bucket de Cloud Storage.

  1. Para habilitar las APIs necesarias y aprovisionar tu bucket predeterminado de Cloud Storage, agrega los siguientes bloques de recursos a tu archivo main.tf.

    Ten en cuenta que el bucket predeterminado de Cloud Storage de tu proyecto se aprovisiona a través de Google App Engine y debe tener la misma ubicación que tu base de datos de Firestore. Consulta Ubicaciones de App Engine para obtener más información.

    Si quieres tener varios buckets en tu proyecto, aprovisiona los buckets con el recurso google_storage_bucket (que no se muestra en este codelab).

    main.tf
    ...
    
    # Enable required APIs for Cloud Storage for Firebase.
    resource "google_project_service" "storage" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      for_each = toset([
        "firebasestorage.googleapis.com",
        "storage.googleapis.com",
      ])
      service = each.key
    
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Provision the default Cloud Storage bucket for the project via Google App Engine.
    resource "google_app_engine_application" "default" {
      provider    = google-beta
    
      project     = google_firebase_project.default.project
      # See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
      # This will set the location for the default Storage bucket and the App Engine App.
      location_id = "<NAME_OF_DESIRED_REGION_FOR_DEFAULT_BUCKET>"  # Must be in the same location as Firestore (above)
    
      # Wait until Firestore is provisioned first.
      depends_on = [
        google_firestore_database.default
      ]
    }
    
    # Make the default Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
    resource "google_firebase_storage_bucket" "default-bucket" {
      provider  = google-beta
    
      project   = google_firebase_project.default.project
      bucket_id = google_app_engine_application.default.default_bucket
    }
    
  2. Cada bucket de Cloud Storage al que puede acceder Firebase debe estar protegido por las reglas de seguridad de Firebase.

    El código de muestra de este codelab proporciona un conjunto de reglas seguras de Firestore en el archivo storage.rules, que puedes encontrar en la raíz del directorio web.
  3. Agrega tu archivo main.tf con los siguientes bloques de recursos para hacer lo siguiente:
    • Crea un conjunto de reglas de las reglas de seguridad de Firebase desde el archivo local.
    • Libera el conjunto de reglas del bucket de Storage.
    Ten en cuenta que estos bloques de recursos logran el equivalente a hacer clic en el botón Publicar en Firebase console o ejecutar firebase deploy --only storage.

    main.tf
    ...
    
    # Create a ruleset of Cloud Storage Security Rules from a local file.
    resource "google_firebaserules_ruleset" "storage" {
      provider = google-beta
    
      project  = google_firebase_project.default.project
      source {
        files {
          # Write security rules in a local file named "storage.rules".
          # Learn more: https://firebase.google.com/docs/storage/security/get-started
          name    = "storage.rules"
          content = file("storage.rules")
        }
      }
    
      # Wait for the default Storage bucket to be provisioned before creating this ruleset.
      depends_on = [
        google_firebase_storage_bucket.default-bucket,
      ]
    }
    
    # Release the ruleset to the default Storage bucket.
    resource "google_firebaserules_release" "default-bucket" {
      provider     = google-beta
    
      name         = "firebase.storage/${google_app_engine_application.default.default_bucket}"
      ruleset_name = "projects/${google_firebase_project.default.project}/rulesets/${google_firebaserules_ruleset.storage.name}"
      project      = google_firebase_project.default.project
    
      lifecycle {
        replace_triggered_by = [
          google_firebaserules_ruleset.storage
        ]
      }
    }
    
  4. Ejecuta terraform apply para aprovisionar el bucket predeterminado de Cloud Storage y, luego, implementar sus reglas de seguridad.
  5. Verifica que el bucket esté aprovisionado y que las reglas de seguridad estén implementadas:
    1. En Firebase console, busca la sección Compilación en el panel izquierdo.
    2. Ve a la sección Almacenamiento y, luego, haz clic en la pestaña Reglas.
    Verifica las reglas de seguridad con Firebase console

9. Ejecuta tu app de manera local

Ya está todo listo para que ejecutes tu app web por primera vez. Usarás el emulador de Firebase Hosting para entregar la app de forma local.

  1. Abre una nueva ventana de terminal y, desde el directorio web, ejecuta el siguiente comando de Firebase CLI para iniciar el emulador:
    firebase emulators:start --project=<PROJECT_ID>
    
  2. En el navegador, abre la aplicación web en la URL local que muestra la CLI (por lo general, http://localhost:5000).

Deberías ver la IU de tu app de FriendlyChat, que aún no está funcionando. La app aún no está conectada a Firebase, pero cuando completes los próximos pasos de este codelab, podrás hacerlo.

Ten en cuenta que, cada vez que realices cambios en tu app web (como lo harás en los siguientes pasos de este codelab), actualiza el navegador para actualizar la URL local con esos cambios.

10. Instala, configura e inicializa Firebase

Para que una app funcione con Firebase, tu app necesita el SDK de Firebase y la configuración de Firebase de tu proyecto de Firebase.

El código de muestra de este codelab ya es una app funcional con todas las dependencias y las funciones necesarias para usar varios productos de Firebase en la app. Puedes buscar en web/package.json y web/src/index.js si deseas ver lo que ya se hizo.

A pesar de que el código de muestra está casi completo, debes realizar algunas acciones para ejecutar tu app, como instalar el SDK de Firebase, comenzar tu compilación, agregar la configuración de Firebase a tu app e inicializar Firebase.

Instala el SDK de Firebase y comienza la compilación de tu webpack

Debes ejecutar algunos comandos para iniciar la compilación de tu app.

  1. Abre una nueva ventana de terminal.
  2. Asegúrate de estar en la raíz del directorio web.
  3. Ejecuta npm install para descargar el SDK de Firebase.
  4. Ejecuta npm update para actualizar las dependencias.
  5. Ejecuta npm run start para iniciar Webpack.

Para el resto del codelab, webpack volverá a compilar tu código fuente de forma continua.

Agrega la configuración de Firebase a la app

También debes agregar la configuración de Firebase a la app para que los SDK de Firebase sepan qué proyecto de Firebase quieres que usen.

En este codelab, tienes dos opciones diferentes para obtener tu configuración de Firebase:

  • Opción 1: Obtén la configuración de Firebase en Firebase console.
  • Opción 2: Obtén la configuración de Firebase a través de Terraform.

Opción 1: Obtén la configuración de Firebase console y agrégala a tu base de código

  1. En Firebase console, ve a Configuración del proyecto.
  2. Desplázate hacia abajo hasta la tarjeta Tus apps y, luego, selecciona tu aplicación web.
  3. Selecciona Config en el panel de fragmentos del SDK de Firebase y, luego, copia el fragmento de configuración.
  4. Pega la configuración en el archivo web/src/firebase-config.js de tu app de la siguiente manera:

    firebase-config.js
    ...
    
    const config = {
      apiKey: "<API_KEY>",
      authDomain: "<PROJECT_ID>.firebaseapp.com",
      projectId: "<PROJECT_ID>",
      storageBucket: "<PROJECT_ID>.appspot.com",
      messagingSenderId: "<SENDER_ID>",
      appId: "<APP_ID>",
      measurementId: "<G-MEASUREMENT_ID>",
    };
    
    ...
    

Opción 2: Obtén la configuración a través de Terraform y agrégala a tu base de código

De forma alternativa, puedes obtener la configuración de Firebase a través de Terraform como un valor de salida en la CLI.

  1. En el archivo main.tf, busca tu bloque de recursos google_firebase_web_app (el bloque que registró una app web con tu proyecto).
  2. Inmediatamente después de ese bloque, agrega los siguientes bloques:

    main.tf
    ...
    
    data "google_firebase_web_app_config" "default" {
      provider     = google-beta
      project      = google_firebase_project.default.project
      web_app_id   = google_firebase_web_app.default.app_id
    }
    
    output "friendlychat_web_app_config" {
      value = {
        projectId         = google_firebase_project.default.project
        appId             = google_firebase_web_app.default.app_id
        apiKey            = data.google_firebase_web_app_config.default.api_key
        authDomain        = data.google_firebase_web_app_config.default.auth_domain
        storageBucket     = lookup(data.google_firebase_web_app_config.default, "storage_bucket", "")
        messagingSenderId = lookup(data.google_firebase_web_app_config.default, "messaging_sender_id", "")
        measurementId     = lookup(data.google_firebase_web_app_config.default, "measurement_id", "")
      }
    }
    
    ...
    
  3. Dado que los bloques data y output no están diseñados para modificar la infraestructura de ninguna manera, solo debes ejecutar los siguientes comandos.
    1. Para cargar la configuración de Firebase de tu aplicación web en el estado de Terraform de tu directorio, ejecuta este comando:
      terraform refresh
      
    2. Para imprimir los valores de configuración de Firebase, ejecuta este comando:
      terraform output –json
      
      El siguiente es un resultado de ejemplo de una configuración. El resultado impreso contendrá los valores de tu proyecto y app.
      {
        "friendlychat_web_app_config": {
          "sensitive": false,
          "type": [
            "object",
            {
              "apiKey": "string",
              "appId": "string",
              "authDomain": "string",
              "measurementId": "string",
              "messagingSenderId": "string",
              "projectId": "string",
              "storageBucket": "string"
            }
          ],
          "value": {
            "apiKey": "<API_KEY>",
            "appId": "<APP_ID>",
            "authDomain": "<PROJECT_ID>.firebaseapp.com",
            "measurementId": "<G-MEASUREMENT_ID>",
            "messagingSenderId": "<SENDER_ID>",
            "projectId": "<PROJECT_ID>",
            "storageBucket": "<PROJECT_ID>.appspot.com"
          }
        }
      }
      
  4. Copia los valores del mapa value.
  5. Pega estos valores (tu configuración) en el archivo web/src/firebase-config.js de tu app, de esta manera:

    firebase-config.js
    ...
    
    const config = {
      apiKey: "<API_KEY>",
      appId: "<APP_ID>",
      authDomain: "<PROJECT_ID>.firebaseapp.com",
      measurementId: "<G-MEASUREMENT_ID>",
      messagingSenderId: "<SENDER_ID>",
      projectId: "<PROJECT_ID>",
      storageBucket: "<PROJECT_ID>.appspot.com",
    };
    
    ...
    

Inicializa Firebase en la app

Por último, para inicializar Firebase, agrega el archivo web/src/index.js de tu app con lo siguiente:

index.js.

...

const firebaseAppConfig = getFirebaseConfig();
initializeApp(firebaseAppConfig);

Prueba tu app

Ahora que todo está configurado para Firebase, puedes probar tu app web funcional.

  1. Actualiza el navegador que entrega tu app.
  2. Ahora deberías poder acceder con Google y comenzar a publicar mensajes en el chat. Si tienes archivos de imagen, incluso puedes subirlos.

11. Replica tu configuración en todos los entornos

Terraform se destaca por administrar varias infraestructuras configuradas de forma similar (por ejemplo, configurar un proyecto de Firebase de etapa de pruebas similar a un proyecto de producción).

En este codelab, crearás un segundo proyecto de Firebase para que sea un entorno de etapa de pruebas.

Si quieres replicar una configuración existente para crear este proyecto de etapa de pruebas, tienes dos opciones:

  • Opción 1: Haz una copia de la configuración de Terraform.
    Esta opción ofrece la mayor flexibilidad en cuanto a la diferencia entre el proyecto replicado y el proyecto de origen.
  • Opción 2: Vuelve a usar la configuración con for_each.
    Esta opción ofrece más reutilización del código en caso de que cada proyecto no deba diferir de manera significativa y deseas propagar los cambios a todos los proyectos a la vez.

Opción 1: Crea una copia de la configuración de Terraform

Esta opción ofrece la mayor flexibilidad en cuanto a la diferencia que puede diferir el proyecto replicado del proyecto de origen; por ejemplo, tener apps con diferentes nombres visibles y lanzamientos en etapas.

  1. En la raíz de tu directorio web, crea un nuevo archivo de configuración de Terraform llamado main_staging.tf.
  2. Copia todos los bloques de recursos de tu archivo main.tf (excepto los bloques terraform y provider) y, luego, pégalos en el archivo main_staging.tf.
  3. Luego, debes modificar cada uno de los bloques de recursos replicados en main_staging.tf para que funcionen con el proyecto de etapa de pruebas:
    • Etiquetas de recursos: Usa un nombre nuevo para evitar conflictos. Por ejemplo, cambia el nombre de resource "google_project" "default" a resource "google_project" "staging".
    • Referencias de recursos: Actualiza cada una. Por ejemplo, actualiza google_firebase_project.default.project a google_firebase_project.staging.project.
    Puedes encontrar la configuración completa de un archivo main_staging.tf en el repositorio de GitHub de este codelab:

    web/terraform-checkpoints/replicate-config/main_staging-copypaste.tf

    Si deseas usar esta configuración, asegúrate de hacer lo siguiente:
    1. Copia la configuración de main_staging-copypaste.tf y, luego, pégala en el archivo main_staging.tf.
    2. En tu archivo main_staging.tf, haz lo siguiente:
      • En el bloque de recursos google_project, actualiza el atributo name, el atributo project-id y (si configuras la autenticación a través de Terraform) el atributo billing_account con tus propios valores.
      • En el bloque de recursos google_firebase_web_app, actualiza el atributo display_name con tu propio valor.
      • En los bloques de recursos google_firestore_database y google_app_engine_application, actualiza los atributos location_id con tu propio valor.
    main_staging.tf
    # Create a new Google Cloud project.
    resource "google_project" "staging" {
      provider = google-beta.no_user_project_override
    
      name            = "<PROJECT_NAME_OF_STAGING_PROJECT>"
      project_id      = "<PROJECT_ID_OF_STAGING_PROJECT"
      # Required if you want to set up Authentication via Terraform
      billing_account = "<YOUR_BILLING_ACCOUNT_ID>"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "staging_serviceusage" {
      provider = google-beta.no_user_project_override
    
      project = google_project.staging.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "staging_firebase" {
      provider = google-beta.no_user_project_override
    
      project = google_project.staging.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable Firebase services for the new project created above.
    resource "google_firebase_project" "staging" {
      provider = google-beta
    
      project = google_project.staging.project_id
    
      # Wait until the required APIs are enabled.
      depends_on = [
        google_project_service.staging_serviceusage,
        google_project_service.staging_firebase,
      ]
    }
    
    # Create a Firebase Web App in the new project created above.
    resource "google_firebase_web_app" "staging" {
      provider = google-beta
    
      project      = google_firebase_project.staging.project
      display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
      deletion_policy = "DELETE"
    }
    
  4. Ejecuta terraform apply para aprovisionar tu nuevo proyecto de “etapa de pruebas” de Firebase y todos sus recursos, y habilitar sus servicios.
  5. Verifica que todo se haya aprovisionado y habilitado como se esperaba. Para ello, revísalo en Firebase console como antes.

Opción 2: Vuelve a usar la configuración con for_each

Esta opción ofrece más reutilización del código si cada proyecto no debe diferir de manera significativa y deseas propagar los cambios a todos los proyectos a la vez. Usa el metaargumento for_each en el lenguaje de Terraform.

  1. Abre el archivo main.tf.
  2. En cada bloque de recursos que desees replicar, agrega un metaargumento for_each de la siguiente manera:

    main.tf
    # Create new Google Cloud projects.
    resource "google_project" "default" {
      provider        = google-beta.no_user_project_override
      name            = each.value
      # Create a unique project ID for each project, with each ID starting with <PROJECT_ID>.
      project_id      = "<PROJECT_ID>-${each.key}"
      # Required if you want to set up Authentication via Terraform
      billing_account = "<YOUR_BILLING_ACCOUNT_ID>"
    
      # Required for the projects to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    
      for_each = {
        prod    = "<PROJECT_NAME_OF_PROD_PROJECT>"
        staging = "<PROJECT_NAME_OF_STAGING_PROJECT>"
      }
    }
    
    # Enable the required underlying Service Usage API.
    resource "google_project_service" "serviceusage" {
      provider = google-beta.no_user_project_override
      for_each = google_project.default
    
      project = each.value.project_id
      service = "serviceusage.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable the required underlying Firebase Management API.
    resource "google_project_service" "firebase" {
      provider = google-beta.no_user_project_override
      for_each = google_project.default
    
      project = each.value.project_id
      service = "firebase.googleapis.com"
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enable Firebase services for each of the new projects created above.
    resource "google_firebase_project" "default" {
      provider = google-beta
      for_each = google_project.default
    
      project = each.value.project_id
    
      depends_on = [
        google_project_service.serviceusage,
        google_project_service.firebase,
      ]
    }
    
    # Create a Firebase Web App in each of the new projects created above.
    resource "google_firebase_web_app" "default" {
      provider = google-beta
      for_each = google_firebase_project.default
    
      project      = each.value.project
      # The Firebase Web App created in each project will have the same display name.
      display_name = "<DISPLAY_NAME_OF_YOUR_WEB_APP>"
      deletion_policy = "DELETE"
    }
    
    
    # NOTE: For this codelab, we recommend setting up Firebase Authentication
    # using the Firebase console. However, if you set up Firebase Authentication
    # using Terraform, copy-paste from your main.tf the applicable blocks.
    # Make sure to add the `for_each` meta-argument into each block.
    
    
    # Copy-paste from your main.tf file the applicable resource blocks
    # for setting up Cloud Firestore (including rules) and
    # for setting up Cloud Storage for Firebase (including rules).
    # Make sure to add the `for_each` meta-argument into each block.
    
    Puedes encontrar la configuración completa de un archivo main.tf que usa el metaargumento for_each en el repositorio de GitHub de este codelab:

    web/terraform-checkpoints/replicate-config/main-foreach.tf

    Si deseas usar esta configuración, asegúrate de hacer lo siguiente:
    1. Copia la configuración de main-foreach.tf y, luego, pégala en el archivo main.tf.
    2. En tu archivo main.tf, haz lo siguiente:
      • En el bloque de recursos google_project, actualiza el atributo name, el atributo project-id y (si configuras la autenticación a través de Terraform) el atributo billing_account con tus propios valores.
      • En el bloque de recursos google_firebase_web_app, actualiza el atributo display_name con tu propio valor.
      • En los bloques de recursos google_firestore_database y google_app_engine_application, actualiza los atributos location_id con tu propio valor.
  3. En lugar de aplicar esta configuración de inmediato, es importante comprender y corregir algunos aspectos sobre la forma en que Terraform interpreta esta configuración en comparación con la infraestructura existente.
    1. En este momento, si aplicaste esta configuración que usa for_each, las direcciones de recursos se verían de la siguiente manera:
      google_project.default["prod"]
      google_project.default["staging"]
      google_firebase_project.default["prod"]
      google_firebase_project.default["staging"]
      google_firebase_web_app.default["prod"]
      google_firebase_web_app.default["staging"]
      
      Sin embargo, Terraform conoce el proyecto existente que creaste en la primera parte de este codelab de la siguiente manera:
      google_project.default
      google_firebase_project.default
      google_firebase_android_app.default
      
    2. Ejecuta terraform plan para ver qué acciones realizaría Terraform según el estado actual.

      El resultado debería mostrar que Terraform borraría el proyecto que creaste en la primera parte de este codelab y crearía dos proyectos nuevos. Esto se debe a que Terraform no sabe que el proyecto en la dirección google_project.default se movió a la nueva dirección google_project.default["prod"].
    3. Para solucionar este problema, ejecuta el comando terraform state mv:
      terraform state mv "google_project.default" "google_project.default[\"prod\"]"
      
    4. De manera similar, para corregir todos los demás bloques de recursos, ejecuta terraform state mv para google_firebase_project, google_firebase_web_app y todos los demás bloques de recursos de tu archivo main.tf.
    5. Ahora, si vuelves a ejecutar terraform plan, no debería mostrar que Terraform borraría el proyecto que creaste en la primera parte de este codelab.
  4. Ejecuta terraform apply para aprovisionar tu nuevo proyecto de “etapa de pruebas” de Firebase y todos sus recursos, y habilitar sus servicios.
  5. Verifica que todo se haya aprovisionado y habilitado como se esperaba. Para ello, revísalo en Firebase console como antes.

12. Paso adicional: Implementa tus apps de etapa de pruebas y producción

  1. En la base de código de tu app, cambia el firebase-config.js para usar la configuración de Firebase de tu proyecto de etapa de pruebas.

    Para recordar cómo obtener la configuración de Firebase y agregarla a tu app, consulta el paso anterior de este codelab: Agrega la configuración de Firebase a tu app.
  2. En la raíz del directorio web, ejecuta el siguiente comando para implementar tu app en el proyecto de etapa de pruebas de Firebase.
    firebase deploy --only hosting --project=<STAGING_PROJECT_ID>
    
  3. Abre la app de etapa de pruebas en el navegador a través de la URL que se imprime en el resultado de firebase deploy. Intenta acceder, enviar mensajes y subir imágenes.

    Cuando implementas una app en un proyecto de Firebase, esta usa recursos reales de Firebase, no recursos emulados. Cuando interactúes con la app de etapa de pruebas, deberías ver que los datos y las imágenes aparecen en el proyecto de etapa de pruebas en Firebase console.
  4. Después de probar tu app en la etapa de pruebas, vuelve a cambiar el firebase-config.js a la configuración de Firebase del proyecto de producción (el primer proyecto que creaste en este codelab).
  5. En la raíz del directorio web, ejecuta el siguiente comando para implementar la app en tu proyecto de producción de Firebase.
    firebase deploy --only hosting --project=<PRODUCTION_PROJECT_ID>
    
  6. Abre la app de producción en el navegador a través de la URL que está impresa en el resultado de firebase deploy. Intenta acceder, enviar mensajes y subir imágenes.

    Deberías ver que los datos y las imágenes aparecen en tu proyecto de producción en Firebase console.
  7. Cuando termines de interactuar con las dos apps de este codelab, puedes evitar que Firebase las entregue. Ejecuta el siguiente comando para cada uno de tus proyectos:
    firebase hosting:disable --project=<STAGING_PROJECT_ID>
    
    firebase hosting:disable --project=<PRODUCTION_PROJECT_ID>
    

13. ¡Felicitaciones!

Utilizaste Terraform para configurar una aplicación web de chat en tiempo real. Además, seguiste las prácticas recomendadas para los entornos de desarrollo con la creación de proyectos de Firebase independientes para etapa de pruebas y producción.

Temas abordados

  • Usa la CLI de Terraform para administrar los recursos de la nube
  • Usar Terraform para configurar los productos de Firebase (Authentication, Firestore, Cloud Storage y reglas de seguridad)
  • Ejecuta y prueba una aplicación web de forma local con Firebase Local Emulator Suite
  • Importa Firebase a una app web
  • Usar Terraform para replicar una configuración en varios entornos

Para obtener más información sobre Firebase y Terraform, visita nuestra documentación. Puedes encontrar una lista de todos los productos de Firebase compatibles con Terraform, muestras de configuraciones de Terraform para casos de uso comunes y preguntas frecuentes y soluciones de problemas útiles.