Recopila registros del proxy de OAuth2

Se admite en los siguientes sistemas operativos:

En este documento, se explica cómo transferir registros de OAuth2 Proxy a Google Security Operations con Google Cloud Storage V2.

OAuth2 Proxy es un proxy inverso de CNCF Sandbox que proporciona autenticación con proveedores de OAuth2/OIDC (Google, GitHub, Keycloak, Azure AD y otros) para validar cuentas por correo electrónico, dominio o grupo. Genera registros de autenticación (acceso correcto o fallido), registros de solicitudes (solicitudes HTTP proxy con identidad del usuario) y registros de aplicaciones estándar. Debido a que OAuth2 Proxy se ejecuta como un contenedor en Kubernetes y escribe todos los registros en stdout, se usa un recopilador de registros nativo de Kubernetes (Fluentd) para reenviar los registros a un bucket de GCS para la incorporación de Google SecOps.

Antes de comenzar

Asegúrate de cumplir con los siguientes requisitos previos:

  • Una instancia de Google SecOps
  • Un proyecto de GCP con la API de Cloud Storage habilitada
  • Permisos para crear y administrar buckets de GCS
  • Permisos para administrar políticas de IAM en buckets de GCS
  • Un clúster de Kubernetes en ejecución con OAuth2 Proxy implementado (a través de un gráfico de Helm o una implementación manual)
  • Acceso kubectl al clúster de Kubernetes con permisos para crear DaemonSets, ConfigMaps, Secrets y Namespaces
  • Una clave JSON de cuenta de servicio de GCP con permiso de storage.objects.create en el bucket de GCS de destino

Crea 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:

    Parámetro de configuración Valor
    Asigna un nombre a tu bucket Ingresa un nombre global único (por ejemplo, oauth2-proxy-logs-bucket).
    Tipo de ubicación Elige según tus necesidades (regional, birregional o multirregional)
    Ubicación Selecciona la ubicación (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.

Cómo configurar el registro de OAuth2 Proxy

OAuth2 Proxy escribe tres tipos de registros en stdout: registros estándar, registros de autenticación y registros de solicitudes. Las tres opciones están habilitadas de forma predeterminada. Para garantizar que los registros contengan el máximo detalle pertinente para la seguridad, configura OAuth2 Proxy con las siguientes marcas de registro.

Opción 1: Configura los valores del gráfico de Helm

  • Si OAuth2 Proxy se implementa con el gráfico de Helm oficial, agrega lo siguiente a tu archivo values.yaml:

    config:
      configFile: |-
        standard_logging = true
        auth_logging = true
        request_logging = true
        silence_ping_logging = true
            standard_logging_format = "[{{.Timestamp}}] [{{.File}}] {{.Message}}"
        auth_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}"
        request_logging_format = "{{.Client}} - {{.RequestID}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"
    
  • Aplica los valores de Helm actualizados:

    helm upgrade oauth2-proxy oauth2-proxy/oauth2-proxy -f values.yaml -n <your-namespace>
    

Opción 2: Configura a través de marcas de línea de comandos

  • Si OAuth2 Proxy se implementa con un manifiesto de implementación de Kubernetes, agrega los siguientes argumentos a la especificación del contenedor:

    args:
      - --standard-logging=true
      - --auth-logging=true
      - --request-logging=true
      - --silence-ping-logging=true
    

Opción 3: Configura a través de variables de entorno

  • Establece las siguientes variables de entorno en el contenedor de OAuth2 Proxy:

    env:
      - name: OAUTH2_PROXY_STANDARD_LOGGING
        value: "true"
      - name: OAUTH2_PROXY_AUTH_LOGGING
        value: "true"
      - name: OAUTH2_PROXY_REQUEST_LOGGING
        value: "true"
      - name: OAUTH2_PROXY_SILENCE_PING_LOGGING
        value: "true"
    

Verifica el registro del proxy de OAuth2

  • Después de aplicar la configuración, verifica que OAuth2 Proxy esté generando registros:

    kubectl logs -l app=oauth2-proxy -n <your-namespace> --tail=20
    
  • El resultado incluye líneas similares a las siguientes:

    10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:00] [AuthSuccess] Authenticated via OAuth2
    10.0.0.1 - abc123 - user@example.com [2024/01/15 10:30:01] example.com GET 10.0.0.5:8080 "/dashboard" HTTP/1.1 "Mozilla/5.0" 200 1234 0.005
    

Crea una cuenta de servicio de GCP para Fluentd

Fluentd requiere una cuenta de servicio de GCP con acceso de escritura al bucket de GCS.

  1. En Google Cloud Console, 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 fluentd-gcs-writer.
    • Descripción de la cuenta de servicio: Ingresa Service account for Fluentd to write OAuth2 Proxy logs to GCS.
  4. Haz clic en Crear y continuar.
  5. En la sección Otorga acceso al proyecto a esta cuenta de servicio, haz lo siguiente:
    1. Haz clic en Seleccionar un rol.
    2. Busca y selecciona Administrador de objetos de Storage.
  6. Haz clic en Continuar.
  7. Haz clic en Listo.

Crea y descarga la clave de la cuenta de servicio

  1. En la lista Cuentas de servicio, haz clic en la cuenta de servicio fluentd-gcs-writer.
  2. Ve a la pestaña Claves.
  3. Haz clic en Agregar clave > Crear clave nueva.
  4. Seleccione JSON como tipo de clave.
  5. Haz clic en Crear.
  6. Guarda de forma segura el archivo de claves JSON que descargaste. Este archivo se usa en el siguiente paso.

Crea un secreto de Kubernetes para la clave de la cuenta de servicio

  • Crea un secreto de Kubernetes que contenga la clave de la cuenta de servicio de GCP en el espacio de nombres en el que se implementará Fluentd:

    kubectl create namespace logging
    kubectl create secret generic fluentd-gcs-key \
      --from-file=service-account-key.json=<path-to-downloaded-key>.json \
      -n logging
    

Implementa el DaemonSet de Fluentd para recopilar registros del proxy de OAuth2

Implementa Fluentd como un DaemonSet en el clúster de Kubernetes para recopilar registros de contenedores de Pods de OAuth2 Proxy y reenviarlos al bucket de GCS.

Crea un ConfigMap de Fluentd

  • Crea un archivo llamado fluentd-configmap.yaml con el siguiente contenido:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: fluentd-gcs-config
      namespace: logging
    data:
      fluent.conf: |
        <source>
          @type tail
          read_from_head true
          tag kubernetes.*
          path /var/log/containers/*oauth2-proxy*.log
          pos_file /var/log/fluentd-oauth2-proxy.log.pos
          <parse>
            @type regexp
            expression /^(?<time>[^ ]+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
            time_format %Y-%m-%dT%H:%M:%S.%N%z
          </parse>
        </source>
    
        <filter kubernetes.**>
          @type kubernetes_metadata
          @id filter_kube_metadata
        </filter>
    
        <match kubernetes.**>
          @type gcs
          project YOUR_GCP_PROJECT_ID
          keyfile /etc/secrets/service-account-key.json
          bucket oauth2-proxy-logs-bucket
          path oauth2-proxy-logs/%Y/%m/%d/
          object_key_format %{path}%{time_slice}_%{hostname}_%{index}.%{file_extension}
          <buffer tag,time>
            @type file
            path /var/log/fluentd/gcs
            timekey 300
            timekey_wait 60
            timekey_use_utc true
            chunk_limit_size 10MB
          </buffer>
          <format>
            @type json
          </format>
        </match>
    

Reemplaza los siguientes valores:

  • YOUR_GCP_PROJECT_ID: El ID de tu proyecto de GCP (por ejemplo, my-project-123456)
  • oauth2-proxy-logs-bucket: Es el nombre del bucket de GCS que se creó antes.

  • Aplica el ConfigMap:

    kubectl apply -f fluentd-configmap.yaml
    

Crea un DaemonSet de Fluentd

  • Crea un archivo llamado fluentd-daemonset.yaml con el siguiente contenido:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: fluentd-gcs
      namespace: logging
      labels:
        k8s-app: fluentd-gcs
    spec:
      selector:
        matchLabels:
          k8s-app: fluentd-gcs
      template:
        metadata:
          labels:
            k8s-app: fluentd-gcs
        spec:
          tolerations:
            - key: node-role.kubernetes.io/control-plane
              effect: NoSchedule
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
          containers:
            - name: fluentd-gcs
              image: fluent/fluentd-kubernetes-daemonset:v1-debian-gcs
              resources:
                limits:
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 200Mi
              volumeMounts:
                - name: fluentd-gcs-config-volume
                  mountPath: /fluentd/etc/fluent.conf
                  subPath: fluent.conf
                  readOnly: true
                - name: fluentd-gcs-secrets-volume
                  mountPath: /etc/secrets/service-account-key.json
                  subPath: service-account-key.json
                  readOnly: true
                - name: varlog
                  mountPath: /var/log
                - name: dockercontainerlogdirectory
                  mountPath: /var/log/pods
                  readOnly: true
                - name: fluentd-buffer
                  mountPath: /var/log/fluentd
          terminationGracePeriodSeconds: 30
          volumes:
            - name: fluentd-gcs-config-volume
              configMap:
                name: fluentd-gcs-config
            - name: fluentd-gcs-secrets-volume
              secret:
                secretName: fluentd-gcs-key
            - name: varlog
              hostPath:
                path: /var/log
            - name: dockercontainerlogdirectory
              hostPath:
                path: /var/log/pods
            - name: fluentd-buffer
              emptyDir: {}
    
  • Aplica el DaemonSet:

    kubectl apply -f fluentd-daemonset.yaml
    

Verifica la implementación de Fluentd

  1. Verifica que los Pods de Fluentd se estén ejecutando en cada nodo:

    kubectl get pods -n logging -l k8s-app=fluentd-gcs
    
  2. Verifica los registros de Fluentd para confirmar que se hayan escrito correctamente en GCS:

    kubectl logs -l k8s-app=fluentd-gcs -n logging --tail=20
    
  3. Verifica que los archivos de registro aparezcan en el bucket de GCS:

    1. Ve a Cloud Storage > Buckets en la GCP Console.
    2. Haz clic en el bucket (por ejemplo, oauth2-proxy-logs-bucket).
    3. Navega a la carpeta oauth2-proxy-logs/:
    4. Verifica que los archivos .json estén presentes con marcas de tiempo recientes.

Recupera la cuenta de servicio de Google SecOps

Google SecOps usa una cuenta de servicio única para leer datos de tu bucket de GCS. Debes otorgar acceso a tu bucket a esta cuenta de servicio.

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

  1. Ve a Configuración de SIEM > Feeds.
  2. Haz clic en Add New Feed.
  3. Haz clic en Configura un feed único.
  4. En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, OAuth2 Proxy Logs).
  5. Selecciona Google Cloud Storage V2 como el Tipo de fuente.
  6. Selecciona Proxy de autenticación de Kubernetes 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.

  9. Haz clic en Siguiente.

  10. 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://oauth2-proxy-logs-bucket/oauth2-proxy-logs/
      
    • Reemplaza oauth2-proxy-logs-bucket por el nombre de tu bucket de GCS.

    • Opción de eliminación del código fuente: Selecciona la opción de eliminación 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 que se transfirieron correctamente.
      • Borrar los archivos transferidos y los directorios vacíos: Borra los archivos y los directorios vacíos después de que se transfirieron correctamente.

    • Antigüedad máxima del archivo: Incluye los archivos modificados en la cantidad de días especificada (el valor predeterminado es 180 días).

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

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

  11. Haz clic en Siguiente.

  12. 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.

  1. Ve a Cloud Storage > Buckets.
  2. Haz clic en el nombre de tu bucket (por ejemplo, oauth2-proxy-logs-bucket).
  3. Ve a la pestaña Permisos.
  4. Haz clic en Otorgar acceso.
  5. Proporciona los siguientes detalles de configuración:
    • Agregar entidades: 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.

Referencia de registros del proxy de OAuth2

En la siguiente tabla, se describen los campos de registro que genera OAuth2 Proxy y su relevancia para la seguridad:

Campos de registro de autenticación

Campo Ejemplo Descripción
Cliente 10.0.0.1 Dirección IP remota o del cliente (usa el encabezado X-Real-IP si es --reverse-proxy=true)
RequestID 00010203-0405-4607-8809-0a0b0c0d0e0f ID de solicitud del encabezado X-Request-Id (UUID aleatorio si está vacío)
Nombre de usuario user@example.com Correo electrónico o nombre de usuario de la solicitud de autenticación
Marca de tiempo 2024/01/15 10:30:00 Fecha y hora del evento de autenticación
Estado AuthSuccess Resultado de la autenticación: AuthSuccess, AuthFailure o AuthError
Mensaje Authenticated via OAuth2 Detalles del intento de autenticación

Campos de registro de solicitud

Campo Ejemplo Descripción
Cliente 10.0.0.1 Dirección IP del cliente o remota
RequestID 00010203-0405-4607-8809-0a0b0c0d0e0f ID de solicitud
Nombre de usuario user@example.com Correo electrónico del usuario autenticado
Marca de tiempo 2024/01/15 10:30:01 Fecha y hora de la solicitud
Host app.example.com Valor del encabezado Host
RequestMethod GET Método de solicitud HTTP
Upstream 10.0.0.5:8080 Servidor upstream que controló la solicitud
RequestURI /dashboard Ruta de URI de la solicitud
Protocolo HTTP/1.1 Protocolo de solicitud
UserAgent Mozilla/5.0 Cadena de usuario-agente completa
StatusCode 200 Código de estado de respuesta HTTP
ResponseSize 1234 Tamaño de la respuesta en bytes
RequestDuration 0.005 Tiempo de procesamiento de la solicitud en segundos

Tabla de asignación de UDM

Campo de registro Asignación de UDM Lógica
acerca de acerca de Información sobre el evento
http_req_id_field additional.fields Campos adicionales no incluidos en el esquema de UDM estándar
http_req_path_field additional.fields
k8s_pod_app_field additional.fields
k8s_pod_template_hash_field additional.fields
k8s_pod_tls_mode_field additional.fields
k8s_pod_canonical_revision_field additional.fields
k8s_pod_canonical_name_field additional.fields
pod_name additional.fields
cntnr_name additional.fields
destination_canonical_revision additional.fields
requested_server additional.fields
nodename_label additional.fields
componentName_label additional.fields
componentVersion_label additional.fields
azureResourceID_label additional.fields
producer_label additional.fields
first_label additional.fields
last_label additional.fields
meta_name additional.fields
resource_version_label additional.fields
request_apiVersion additional.fields
request_kind_label additional.fields
request_type_label additional.fields
response_apiVersion additional.fields
response_kind_label additional.fields
response_type_label additional.fields
jsonPayload.message metadata.description Descripción del evento
event_type metadata.event_type Tipo de evento
labels.request_id metadata.product_log_id Identificador de registro específico del producto
insertId metadata.product_log_id
jsonPayload.chartVersion metadata.product_version Versión del producto
httpRequest.protocol network.application_protocol Protocolo de aplicación que se usa en la conexión de red
network.direction network.direction Dirección del tráfico de red
httpRequest.requestMethod network.http.method Método HTTP
http_method network.http.method
httpRequest.status network.http.response_code Código de respuesta HTTP
httpRequest.userAgent network.http.user_agent Usuario-agente HTTP
requestMetadata.callerSuppliedUserAgent network.http.user_agent
labels.protocol network.ip_protocol Protocolo IP
httpRequest.responseSize network.received_bytes Cantidad de bytes recibidos
labels.total_received_bytes network.received_bytes
httpRequest.requestSize network.sent_bytes Cantidad de bytes enviados
labels.total_sent_bytes network.sent_bytes
jsonPayload.session network.session_id Identificador de la sesión
labels.service_authentication_policy network.tls.cipher Conjunto de algoritmos de cifrado TLS
entidad entidad Entidad principal involucrada en el evento
principal_hostname principal.hostname Nombre de host de la entidad principal
prin_userid principal.user.userid ID de usuario de la principal
security_result security_result Resultado de la evaluación de seguridad
objetivo objetivo Entidad objetivo involucrada en el evento
target_hostname target.hostname Nombre de host del destino
resource_sub_type target.resource.resource_subtype Subtipo del recurso de destino
target_userid target.user.userid ID de usuario del objetivo
metadata.product_name metadata.product_name Nombre del producto
metadata.vendor_name metadata.vendor_name Nombre del proveedor

Registro de cambios

Consulta el registro de cambios de este analizador

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