Recopila registros de Druva Backup

Compatible con:

En este documento, se explica cómo recopilar registros de Druva Backup configurando una función de Google Cloud Run que recupera eventos de la API de REST de Druva y los escribe en un bucket de Google Cloud Storage, y, luego, configurando un feed de Google Security Operations con Google Cloud Storage V2.

Druva es una plataforma de administración y protección de datos nativa de la nube que proporciona servicios de copia de seguridad, recuperación ante desastres y archivo para endpoints, aplicaciones de SaaS y cargas de trabajo empresariales. La plataforma genera registros de auditoría integrales, eventos de copias de seguridad, actividades de restablecimiento y alertas de seguridad que se pueden integrar con soluciones de SIEM para la supervisión y el cumplimiento.

Antes de comenzar

Asegúrate de cumplir con los siguientes requisitos previos:

  • Una instancia de Google SecOps
  • Un proyecto de Google Cloud con la facturación habilitada.
  • Se habilitaron las siguientes APIs de Google Cloud:
    • API de funciones de Cloud Run
    • API de Cloud Scheduler
    • API de Cloud Storage
    • API de Pub/Sub
    • API de IAM
  • Acceso de administrador de Druva Cloud a la consola de Druva Cloud Platform
  • Acceso al Centro de integración de Druva para la creación de credenciales de API

Crear un bucket de Google Cloud Storage

  1. Ve a la consola de Google Cloud.
  2. Selecciona tu proyecto o crea uno nuevo.
  3. En el menú de navegación, ve a Cloud Storage > Buckets.
  4. Haz clic en Crear bucket.
  5. Proporciona los siguientes detalles de configuración:

    Configuración Valor
    Asigna un nombre a tu bucket Ingresa un nombre global único (por ejemplo, druva-backup-logs).
    Tipo de ubicación Elige según tus necesidades (región, birregional, multirregional)
    Ubicación Selecciona la ubicación más cercana a tu instancia de Google SecOps (por ejemplo, us-central1).
    Clase de almacenamiento Estándar (recomendado para los registros a los que se accede con frecuencia)
    Control de acceso Uniforme (recomendado)
    Herramientas de protección Opcional: Habilita el control de versiones de objetos o la política de retención
  6. Haz clic en Crear.

Recopila las credenciales de la API de Druva

Para permitir que la función de Cloud Run recupere eventos de Druva, debes crear credenciales de API con autenticación de OAuth 2.0.

Crea credenciales de API

  1. Accede a la consola de Druva Cloud Platform.
  2. En el menú de Navegación global, selecciona Centro de integración.
  3. En el panel izquierdo, haz clic en Credenciales de API.
  4. Haz clic en New Credentials.
  5. En la ventana New Credentials, proporciona los siguientes detalles: Name: Ingresa un nombre descriptivo (por ejemplo, Google SecOps Cloud Storage Integration).
  6. Para aplicar restricciones de autorización, haz lo siguiente:
    1. Selecciona Administrador de Druva Cloud para permitir el acceso completo a la recuperación y modificación de datos.
    2. También puedes seleccionar Administrador de productos y elegir una de las siguientes opciones: Rol de administrador de Cloud (solo lectura): Para restringir el acceso solo a la recuperación de datos sin derechos de modificación (se recomienda para la integración de SIEM)
  7. Haz clic en Guardar.

Registra las credenciales de la API

Después de crear las credenciales de la API, aparecerá la ventana Detalles de la credencial:

  1. Haz clic en el ícono de copiar junto a ID de cliente para copiar el valor en el portapapeles.
  2. Guarda el ID de cliente de forma segura (por ejemplo, McNkxxxx4Vicxxxx4Ldpxxxx/09Uxxxx).
  3. Haz clic en el ícono de copiar junto a Clave secreta para copiar el valor en el portapapeles.
  4. Guarda la clave secreta de forma segura (por ejemplo, Xmcxxxx8j5xxxx6NxxxxRbRxxxxNNyPt).

Crea una cuenta de servicio

Crea una cuenta de servicio dedicada para que la función de Cloud Run acceda a Google Cloud Storage.

  1. En la consola de Google Cloud, ve a IAM y administración > Cuentas de servicio.
  2. Haz clic en Crear cuenta de servicio.
  3. Proporciona los siguientes detalles de configuración:
    • Nombre de la cuenta de servicio: Ingresa druva-backup-function (o un nombre descriptivo).
    • Descripción de la cuenta de servicio: Ingresa Service account for Druva Backup Cloud Run function.
  4. Haz clic en Crear y continuar.
  5. En la sección Otorga a esta cuenta de servicio acceso al proyecto, agrega los siguientes roles:
    1. Haz clic en Seleccionar un rol y, luego, selecciona Administrador de objetos de Storage.
    2. Haz clic en Agregar otro rol y selecciona Invocador de Cloud Run.
  6. Haz clic en Continuar.
  7. Haz clic en Listo.
  8. Registra el correo electrónico de la cuenta de servicio (por ejemplo, druva-backup-function@PROJECT_ID.iam.gserviceaccount.com).

Crea un tema de Pub/Sub

Crea un tema de Pub/Sub que Cloud Scheduler usará para activar la función de Cloud Run.

  1. En la consola de Google Cloud, ve a Pub/Sub > Temas.
  2. Haz clic en Crear tema.
  3. Proporciona los siguientes detalles de configuración:
    • ID del tema: Ingresa druva-backup-trigger.
  4. Desmarca Agregar una suscripción predeterminada.
  5. Haz clic en Crear.

Crea la función de Cloud Run

Prepara el código de la función

Crea una función de Cloud Run que se autentique con la API de Druva usando credenciales de cliente de OAuth 2.0, recupere eventos a través del extremo de eventos con paginación y escriba los resultados como NDJSON en el bucket de GCS.

Implementa la Cloud Run function

  1. En la consola de Google Cloud, ve a Cloud Run functions.
  2. Haz clic en Crear función.
  3. Proporciona los siguientes detalles de configuración:

    • Entorno: Selecciona 2ª gen..
    • Nombre de la función: Ingresa druva-backup-to-gcs.
    • Región: Selecciona la región más cercana a tu bucket de GCS (por ejemplo, us-central1).
    • Tipo de activador: Selecciona Cloud Pub/Sub.
    • Tema de Cloud Pub/Sub: Selecciona druva-backup-trigger.
    • Cuenta de servicio: Selecciona druva-backup-function@PROJECT_ID.iam.gserviceaccount.com.
    • Memoria asignada: 512 MiB
    • Tiempo de espera: 540 segundos
    • Cantidad máxima de instancias: 1
  4. Haz clic en Siguiente.

  5. Selecciona Python 3.11 como el Entorno de ejecución.

  6. Establece el Punto de entrada en main.

  7. En el editor de código fuente, reemplaza el contenido de main.py por lo siguiente:

    import base64
    import json
    import os
    import time
    from datetime import datetime, timezone, timedelta
    
    import requests
    from google.cloud import storage
    
    GCS_BUCKET = os.environ["GCS_BUCKET"]
    GCS_PREFIX = os.environ.get("GCS_PREFIX", "druva_backup")
    STATE_KEY = os.environ.get("STATE_KEY", "druva_state.json")
    DRUVA_BASE_URL = os.environ.get("DRUVA_BASE_URL", "apis.druva.com")
    CLIENT_ID = os.environ["CLIENT_ID"]
    CLIENT_SECRET = os.environ["CLIENT_SECRET"]
    MAX_RECORDS = int(os.environ.get("MAX_RECORDS", "10000"))
    PAGE_SIZE = int(os.environ.get("PAGE_SIZE", "500"))
    LOOKBACK_HOURS = int(os.environ.get("LOOKBACK_HOURS", "24"))
    
    def get_oauth_token():
        """Obtain OAuth 2.0 access token using client credentials grant."""
        token_url = f"https://{DRUVA_BASE_URL}/token"
        payload = {
            "grant_type": "client_credentials",
            "scope": "read",
        }
        resp = requests.post(
            token_url,
            data=payload,
            auth=(CLIENT_ID, CLIENT_SECRET),
            timeout=30,
        )
        resp.raise_for_status()
        return resp.json()["access_token"]
    
    def load_state(storage_client):
        """Load the persisted state (last event time and tracker) from GCS."""
        bucket = storage_client.bucket(GCS_BUCKET)
        blob = bucket.blob(f"{GCS_PREFIX}/{STATE_KEY}")
        if blob.exists():
            return json.loads(blob.download_as_text())
        return {}
    
    def save_state(storage_client, state):
        """Persist state to GCS."""
        bucket = storage_client.bucket(GCS_BUCKET)
        blob = bucket.blob(f"{GCS_PREFIX}/{STATE_KEY}")
        blob.upload_from_string(
            json.dumps(state),
            content_type="application/json",
        )
    
    def fetch_events(token, state):
        """Fetch events from Druva API with pagination via nextPageToken."""
        events_url = f"https://{DRUVA_BASE_URL}/insync/eventmanagement/v2/events"
        headers = {
            "Authorization": f"Bearer {token}",
            "Accept": "application/json",
        }
    
        params = {"pageSize": PAGE_SIZE}
    
        tracker = state.get("tracker")
        last_event_time = state.get("last_event_time")
    
        if tracker:
            params["tracker"] = tracker
        elif last_event_time:
            params["fromTime"] = last_event_time
        else:
            lookback = datetime.now(timezone.utc) - timedelta(hours=LOOKBACK_HOURS)
            params["fromTime"] = lookback.strftime("%Y-%m-%dT%H:%M:%SZ")
    
        all_events = []
        total_fetched = 0
    
        while total_fetched < MAX_RECORDS:
            resp = requests.get(
                events_url,
                headers=headers,
                params=params,
                timeout=60,
            )
            resp.raise_for_status()
            data = resp.json()
    
            events = data.get("events", [])
            all_events.extend(events)
            total_fetched += len(events)
    
            new_tracker = data.get("tracker")
            next_page_token = data.get("nextPageToken")
    
            if new_tracker:
                state["tracker"] = new_tracker
    
            if next_page_token:
                params["nextPageToken"] = next_page_token
                params.pop("tracker", None)
                params.pop("fromTime", None)
            else:
                break
    
        if all_events:
            last_ts = all_events[-1].get("eventTime", "")
            if last_ts:
                state["last_event_time"] = last_ts
    
        return all_events, state
    
    def write_events_to_gcs(storage_client, events):
        """Write events as NDJSON to GCS."""
        if not events:
            return
    
        now = datetime.now(timezone.utc)
        filename = now.strftime("%Y%m%d_%H%M%S") + ".ndjson"
        blob_path = f"{GCS_PREFIX}/{now.strftime('%Y/%m/%d')}/{filename}"
    
        ndjson_lines = "\n".join(json.dumps(event) for event in events)
    
        bucket = storage_client.bucket(GCS_BUCKET)
        blob = bucket.blob(blob_path)
        blob.upload_from_string(
            ndjson_lines,
            content_type="application/x-ndjson",
        )
        print(f"Wrote {len(events)} events to gs://{GCS_BUCKET}/{blob_path}")
    
    def main(event, context):
        """Cloud Run function entry point triggered by Pub/Sub."""
        storage_client = storage.Client()
    
        token = get_oauth_token()
    
        state = load_state(storage_client)
    
        events, updated_state = fetch_events(token, state)
    
        write_events_to_gcs(storage_client, events)
    
        save_state(storage_client, updated_state)
    
        print(f"Completed: fetched {len(events)} events")
        return f"OK: {len(events)} events"
    
  8. Reemplaza el contenido de requirements.txt por lo siguiente:

    requests>=2.31.0
    google-cloud-storage>=2.14.0
    

Configure las variables de entorno

  1. En la configuración de la función de Cloud Run, ve a la sección Configuración del entorno de ejecución, la compilación, las conexiones y la seguridad.
  2. En Variables de entorno de ejecución, agrega las siguientes variables:

    • GCS_BUCKET: El nombre de tu bucket de GCS (por ejemplo, druva-backup-logs)
    • GCS_PREFIX: Es la ruta de acceso del prefijo para los archivos de registro (por ejemplo, druva_backup).
    • STATE_KEY: El nombre del archivo de estado (por ejemplo, druva_state.json)
    • DRUVA_BASE_URL: URL base de la API de Druva:
      • apis.druva.com para Druva Cloud (estándar)
      • govcloudapis.druva.com para Druva GovCloud
    • CLIENT_ID: Es el ID de cliente de las credenciales de la API de Druva.
    • CLIENT_SECRET: La clave secreta de las credenciales de la API de Druva
    • MAX_RECORDS: Cantidad máxima de registros que se recuperarán por invocación (por ejemplo, 10000)
    • PAGE_SIZE: Cantidad de eventos por página de la API (máximo 500)
    • LOOKBACK_HOURS: Cantidad de horas que se deben tener en cuenta en la primera ejecución (por ejemplo, 24)
  3. Haz clic en Implementar.

  4. Espera a que se complete la implementación correctamente.

Crea un trabajo de Cloud Scheduler

Crea un trabajo de Cloud Scheduler para activar la función de Cloud Run a intervalos regulares.

  1. En la consola de Google Cloud, ve a Cloud Scheduler.
  2. Haz clic en Crear trabajo.
  3. Proporciona los siguientes detalles de configuración:

    • Nombre: Ingresa druva-backup-scheduler.
    • Región: Selecciona la misma región que tu función de Cloud Run (por ejemplo, us-central1).
    • Descripción: Ingresa Triggers Druva Backup log collection every 30 minutes.
    • Frecuencia: Ingresa */30 * * * * (cada 30 minutos).
    • Zona horaria: Selecciona tu zona horaria preferida (por ejemplo, UTC).
  4. Haz clic en Continuar.

  5. Configura el destino:

    • Tipo de destino: Selecciona Pub/Sub.
    • Tema de Cloud Pub/Sub: Selecciona druva-backup-trigger.
    • Cuerpo del mensaje: Ingresa {"trigger": "scheduled"}.
  6. Haz clic en Crear.

Prueba el trabajo de Cloud Scheduler

  1. En la lista de Cloud Scheduler, busca druva-backup-scheduler.
  2. Haz clic en Forzar ejecución para activar la función de inmediato.
  3. Para verificar la ejecución, comprueba lo siguiente:
    • Los registros de la función de Cloud Run en Cloud Run Functions > druva-backup-to-gcs > Registros
    • El bucket de GCS para los archivos NDJSON nuevos en Cloud Storage > druva-backup-logs

Recupera la cuenta de servicio de Google SecOps y configura el feed

Obtén el correo electrónico de la cuenta de servicio

  1. Ve a Configuración de SIEM > Feeds.
  2. Haz clic en Agregar feed nuevo.
  3. Haz clic en Configura un feed único.
  4. En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, Druva Backup Events).
  5. Selecciona Google Cloud Storage V2 como el Tipo de fuente.
  6. Selecciona Copia de seguridad de Druva como el Tipo de registro.
  7. Haz clic en Obtener cuenta de servicio. Se mostrará un correo electrónico único de la cuenta de servicio, por ejemplo:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Copia esta dirección de correo electrónico para usarla en el siguiente paso.

Configura el feed

  1. Haz clic en Siguiente.
  2. Especifica valores para los siguientes parámetros de entrada:

    • URL del bucket de almacenamiento: Ingresa el URI del bucket de GCS con la ruta de acceso del prefijo:

      gs://druva-backup-logs/druva_backup/
      
    • Opción de borrado de la fuente: Selecciona la opción de borrado según tu preferencia:

      • Nunca: Nunca borra ningún archivo después de las transferencias (se recomienda para las pruebas)
      • Borrar archivos transferidos: Borra los archivos después de una transferencia exitosa.
      • Borrar los archivos transferidos y los directorios vacíos: Borra los archivos y los directorios vacíos después de la transferencia exitosa.
    • Antigüedad máxima del archivo: Incluye los archivos modificados en la cantidad de días más reciente (el valor predeterminado es 180 días).

    • Espacio de nombres del recurso: Es el espacio de nombres del recurso.

    • Etiquetas de transmisión: Es la etiqueta que se aplicará a los eventos de este feed.

  3. Haz clic en Siguiente.

  4. Revisa la nueva configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.

Otorga permisos de IAM a la cuenta de servicio de Google SecOps

La cuenta de servicio de Google SecOps necesita el rol de Visualizador de objetos de Storage en tu bucket de GCS para leer los archivos de registro que escribe la función de Cloud Run.

  1. Ve a Cloud Storage > Buckets.
  2. Haz clic en el nombre de tu bucket (por ejemplo, druva-backup-logs).
  3. Ve a la pestaña Permisos.
  4. Haz clic en Otorgar acceso.
  5. Proporciona los siguientes detalles de configuración:
    • Agregar principales: Pega el correo electrónico de la cuenta de servicio de Google SecOps (por ejemplo, chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com).
    • Asignar roles: Selecciona Visualizador de objetos de Storage.
  6. Haz clic en Guardar.

Tabla de asignación de UDM

Campo de registro Asignación de UDM Lógica
inSyncUserID, eventsGroupId, FilesMissed, FilesBackedup, TotalBackupSize, TotalBytesTransferred, facility, inSyncDataSourceID, initiator, event_type additional.fields Se combina con las etiquetas creadas a partir de cada campo si no está vacío.
iniciador extensions.auth.type Se establece en "AUTHTYPE_UNSPECIFIED" si el iniciador coincide con la regex de correo electrónico.
metadata.event_type Se establece en "USER_LOGIN" si has_target_user es verdadero y has_principal es verdadero; en "STATUS_UPDATE" si has_principal es verdadero y has_target es falso; de lo contrario, se establece en "GENERIC_EVENT".
eventID metadata.product_log_id Se convirtió en cadena
metadata.product_name Se establece en "DRUVA_BACKUP".
clientVersion metadata.product_version Valor copiado directamente
inSyncDataSourceName principal.asset.hostname Valor copiado directamente
ip principal.asset.ip Se combinó desde la IP
inSyncDataSourceName principal.hostname Valor copiado directamente
ip principal.ip Se combinó desde la IP
clientOS principal.platform Se establece en "LINUX" si coincide con (?i)Linux; en "WINDOWS" si coincide con (?i)windows; en "MAC" si coincide con (?i)mac.
profileName principal.resource.name Valor copiado directamente
profileID principal.resource.product_object_id Se convirtió en cadena
eventState security_result.action Se establece en "ALLOW" si coincide con (?i)Success; de lo contrario, se establece en "BLOCK".
eventState security_result.action_details Valor copiado directamente
gravedad, security_result.severity Se establece en "LOW" si está en [0,1,2,3,LOW]; "MEDIUM" si está en [4,5,6,MEDIUM,SUBSTANTIAL,INFO]; "HIGH" si está en [7,8,HIGH,SEVERE]; "CRITICAL" si está en [9,10,VERY-HIGH,CRITICAL]
inSyncUserEmail, iniciador target.user.email_addresses Se fusionó de inSyncUserEmail; también del iniciador si coincide con la regex de correo electrónico
inSyncUserName target.user.userid Valor copiado directamente
metadata.vendor_name Se establece en "DRUVA_BACKUP".

¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.