Recopila registros del proxy de OAuth2
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
kubectlal 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.createen el bucket de GCS de destino
Crea un bucket de Google Cloud Storage
- Ve a la consola de Google Cloud.
- Selecciona tu proyecto o crea uno nuevo.
- En el menú de navegación, ve a Cloud Storage > Buckets.
- Haz clic en Crear bucket.
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 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=20El 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.
- En Google Cloud Console, ve a IAM y administración > Cuentas de servicio.
- Haz clic en Crear cuenta de servicio.
- 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.
- Nombre de la cuenta de servicio: Ingresa
- Haz clic en Crear y continuar.
- En la sección Otorga acceso al proyecto a esta cuenta de servicio, haz lo siguiente:
- Haz clic en Seleccionar un rol.
- Busca y selecciona Administrador de objetos de Storage.
- Haz clic en Continuar.
- Haz clic en Listo.
Crea y descarga la clave de la cuenta de servicio
- En la lista Cuentas de servicio, haz clic en la cuenta de servicio
fluentd-gcs-writer. - Ve a la pestaña Claves.
- Haz clic en Agregar clave > Crear clave nueva.
- Seleccione JSON como tipo de clave.
- Haz clic en Crear.
- 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.yamlcon 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.yamlcon 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
Verifica que los Pods de Fluentd se estén ejecutando en cada nodo:
kubectl get pods -n logging -l k8s-app=fluentd-gcsVerifica los registros de Fluentd para confirmar que se hayan escrito correctamente en GCS:
kubectl logs -l k8s-app=fluentd-gcs -n logging --tail=20Verifica que los archivos de registro aparezcan en el bucket de GCS:
- Ve a Cloud Storage > Buckets en la GCP Console.
- Haz clic en el bucket (por ejemplo,
oauth2-proxy-logs-bucket). - Navega a la carpeta
oauth2-proxy-logs/: - Verifica que los archivos
.jsonesté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
- Ve a Configuración de SIEM > Feeds.
- Haz clic en Add New Feed.
- Haz clic en Configura un feed único.
- En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo,
OAuth2 Proxy Logs). - Selecciona Google Cloud Storage V2 como el Tipo de fuente.
- Selecciona Proxy de autenticación de Kubernetes como el Tipo de registro.
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.comCopia esta dirección de correo electrónico para usarla en el siguiente paso.
Haz clic en Siguiente.
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-bucketpor 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.
Haz clic en Siguiente.
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.
- Ve a Cloud Storage > Buckets.
- Haz clic en el nombre de tu bucket (por ejemplo,
oauth2-proxy-logs-bucket). - Ve a la pestaña Permisos.
- Haz clic en Otorgar acceso.
- 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.
- Agregar entidades: Pega el correo electrónico de la cuenta de servicio de Google SecOps (por ejemplo,
- 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.