Recopila registros de auditoría de Azure DevOps

Compatible con:

Descripción general

Este analizador controla los registros de auditoría de Azure DevOps en formato JSON. Extrae campos de estructuras JSON anidadas y de nivel superior, y los asigna al UDM. La lógica condicional basada en valores de campos específicos categoriza los eventos y enriquece el resultado con información de seguridad pertinente. El analizador también controla los mensajes con formato no JSON intentando extraer una carga útil JSON con patrones de Grok.

Antes de comenzar

Asegúrate de cumplir con los siguientes requisitos previos:

  • Instancia de Google SecOps
  • Una organización activa de Azure DevOps
  • Acceso con privilegios a la organización de Azure DevOps y a Azure

Configura feeds

Existen dos puntos de entrada diferentes para configurar feeds en la plataforma de Google SecOps:

  • Configuración de SIEM > Feeds
  • Centro de contenido > Paquetes de contenido

Configura feeds desde Configuración del SIEM > Feeds

Para configurar varios feeds para diferentes tipos de registros dentro de esta familia de productos, consulta Cómo configurar feeds por producto.

Para configurar un solo feed, sigue estos pasos:

  1. Ve a SIEM Settings > Feeds.
  2. Haz clic en Agregar feed nuevo.
  3. En la siguiente página, haz clic en Configurar un solo feed.
  4. En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, Registros de Azure DevOps).
  5. Selecciona Webhook como el Tipo de origen.
  6. Selecciona Auditoría de Azure DevOps como el Tipo de registro.
  7. Haz clic en Siguiente.
  8. Opcional: Especifica valores para los siguientes parámetros de entrada:
    • Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como \n.
    • Espacio de nombres del recurso: Es el espacio de nombres del recurso.
    • Etiquetas de transferencia: Es la etiqueta que se aplica a los eventos de este feed.
  9. Haz clic en Siguiente.
  10. Revisa la configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.
  11. Haz clic en Generar clave secreta para generar una clave secreta que autentique este feed.
  12. Copia y almacena la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes regenerar una clave secreta nueva, pero esta acción hace que la clave secreta anterior quede obsoleta.
  13. En la pestaña Detalles, copia la URL del extremo del feed del campo Información del extremo. Debes especificar esta URL de extremo en tu aplicación cliente.
  14. Haz clic en Listo.

Configura feeds desde el Centro de contenido

Especifica valores para los siguientes campos:

  • Delimitador de división: Es el delimitador que se usa para separar las líneas de registro, como \n.

Opciones avanzadas

  • Nombre del feed: Es un valor completado previamente que identifica el feed.
  • Tipo de fuente: Es el método que se usa para recopilar registros en Google SecOps.
  • Espacio de nombres del recurso: Es el espacio de nombres del recurso.
  • Etiquetas de transferencia: Es la etiqueta que se aplica a los eventos de este feed.
  • Haz clic en Siguiente.
  • Revisa la configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.
  • Haz clic en Generar clave secreta para generar una clave secreta que autentique este feed.

Crea una clave de API para el feed del webhook

  1. Ve a Google Cloud consola > Credenciales.

    Ir a Credenciales

  2. Haz clic en Crear credenciales y selecciona Clave de API.

  3. Restringe el acceso a la clave de API a la API de Google Security Operations.

Especifica la URL del extremo

  1. En tu aplicación cliente, especifica la URL del extremo HTTPS que se proporciona en el feed de webhook.
  2. Para habilitar la autenticación, especifica la clave de API y la clave secreta como parte del encabezado personalizado con el siguiente formato:

    X-goog-api-key = API_KEY
    X-Webhook-Access-Key = SECRET
    

    Recomendación: Especifica la clave de API como un encabezado en lugar de hacerlo en la URL. Si tu cliente de webhook no admite encabezados personalizados, puedes especificar la clave de API y la clave secreta con parámetros de búsqueda en el siguiente formato:

    ENDPOINT_URL?key=API_KEY&secret=SECRET
    

Reemplaza lo siguiente:

  • ENDPOINT_URL: Es la URL del extremo del feed.
  • API_KEY: Es la clave de API para autenticarse en Google Security Operations.
  • SECRET: Es la clave secreta que generaste para autenticar el feed.

Configura la función de auditoría en Azure DevOps

  1. Accede a tu organización (https://dev.azure.com/{yourorganization}).
  2. Selecciona el ícono de ajustes para Configuración de la organización.
  3. En Seguridad, selecciona Políticas.
  4. Activa el botón Registrar eventos de auditoría.

Configura un tema de Event Grid en Azure

  1. Accede al portal de Azure.
  2. Busca Event Grid y accede a él.
  3. Ubica Topics en Custom events.
  4. Haz clic en + Crear.
  5. Selecciona tu suscripción y tu grupo de recursos. Proporciona un nombre (por ejemplo, DevopsAuditLog) y selecciona la región. Haz clic en Revisar y crear.
  6. Accede al nuevo tema y copia la URL del extremo del tema.
  7. Ve a Configuración > Claves de acceso y copia la Clave 1.

Configura el flujo de registros de Azure DevOps en Event Grid

  1. Accede a tu organización (https://dev.azure.com/{yourorganization}).
  2. Selecciona el ícono de ajustes para Configuración de la organización.
  3. Selecciona Auditing.
  4. Ve a la pestaña Flujos y selecciona Flujo nuevo > Event Grid.
  5. Ingresa el extremo del tema y la clave de acceso que creaste en Configura un tema de Event Grid en Azure.

Configura un webhook en Azure DevOps para Google SecOps

  1. En el portal de Azure, busca Event Grid y accede a él.
  2. Selecciona el tema creado anteriormente.
  3. Ve a Entities > Event Subscription.
  4. Haz clic en + Suscripción a eventos.
  5. Proporciona un nombre descriptivo (por ejemplo, *Google SecOps Integration).
  6. Selecciona Web Hook y haz clic en Configurar un extremo.
  7. Configura el extremo:
    1. Extremo del suscriptor: Ingresa la URL del extremo de API de Google SecOps.
    2. En la sección Encabezados HTTP, agrega los siguientes encabezados:
    3. Configura el encabezado Content-Type como application/json.
  8. Haz clic en Crear.

Tabla de asignación de UDM

Campo de registro Asignación de UDM Lógica
ActivityId metadata.product_log_id Se asigna directamente desde el campo Id en el registro sin procesar cuando el campo records no está presente, o desde el campo ActivityId dentro del objeto data cuando records está presente.
ActionId metadata.product_event_type Se asigna directamente desde el campo ActionId dentro del objeto data.
ActorCUID additional.fields Se incluye como un campo adicional con la clave "CUID del actor".
ActorDisplayName principal.user.user_display_name Se asigna directamente desde el campo ActorDisplayName si no es "Azure DevOps Service". Si es "Azure DevOps Service", se agrega como etiqueta a principal.resource.attribute.labels.
ActorUPN principal.user.email_addresses Se asigna directamente desde el campo ActorUPN si coincide con un patrón de dirección de correo electrónico.
ActorUserId principal.user.userid Se asigna directamente desde el campo ActorUserId.
Area target.application Se usa para construir el campo target.application anteponiendo "DevOps " al valor de Area.
AuthenticationMechanism extensions.auth.auth_details, security_result.rule_id Se analiza para extraer los detalles de autenticación y el ID de la regla. Los detalles de autenticación se asignan a extensions.auth.auth_details. El ID de regla extraído se asigna a security_result.rule_id.
CategoryDisplayName security_result.action_details Se asigna directamente a security_result.action_details.
City principal.location.city Se asigna directamente desde el campo City.
Conditions additional.fields Se agregó como un campo adicional con la clave "Conditions".
Country principal.location.country_or_region Se asigna directamente desde el campo Country.
Data.* Varios Los campos dentro del objeto Data se asignan a diferentes campos del UDM según sus nombres y contexto. Consulta los ejemplos específicos a continuación.
Data.AccessLevel target.resource.attribute.labels Se agregó como una etiqueta con la clave "AccessLevel".
Data.AgentId target.resource.product_object_id Se asigna a target.resource.product_object_id si PipelineId y AuthorizationId no están presentes.
Data.AgentName target.resource.name Se asigna a target.resource.name si no están presentes PipelineName, NamespaceName y DisplayName.
Data.AuthorizationId target.resource.product_object_id Se asigna a target.resource.product_object_id si PipelineId no está presente.
Data.CallerProcedure additional.fields Se agregó como un campo adicional con la clave "CallerProcedure".
Data.CheckSuiteId additional.fields Se agregó como un campo adicional con la clave "CheckSuiteId".
Data.CheckSuiteStatus additional.fields Se agregó como un campo adicional con la clave "CheckSuiteStatus".
Data.ConnectionId additional.fields Se agregó como un campo adicional con la clave "ConnectionId".
Data.ConnectionName additional.fields Se agregó como un campo adicional con la clave "ConnectionName".
Data.ConnectionType additional.fields Se agregó como un campo adicional con la clave "ConnectionType".
Data.DefinitionId additional.fields Se agregó como un campo adicional con la clave "DefinitionId".
Data.DeploymentResult additional.fields Se agregó como un campo adicional con la clave "DeploymentResult".
Data.DisplayName target.resource.name Se asigna a target.resource.name si PipelineName y NamespaceName no están presentes.
Data.EndpointIdList additional.fields Se agregó como un campo adicional con la clave "EndpointIdList".
Data.EnvironmentName additional.fields Se agregó como un campo adicional con la clave "EnvironmentName".
Data.Filter.continuationToken target.resource.attribute.labels Se agregó como una etiqueta con la clave "continuation_token".
Data.Filter.endTime target.resource.attribute.labels Se agregó como una etiqueta con la clave "filter_end_time".
Data.Filter.startTime target.resource.attribute.labels Se agregó como una etiqueta con la clave "filter_start_time".
Data.FinishTime additional.fields Se agregó como un campo adicional con la clave "FinishTime".
Data.GroupId target.group.product_object_id Se asigna directamente a target.group.product_object_id cuando Data.Updates.0.GroupId no está presente.
Data.GroupName target.group.group_display_name Se asigna directamente a target.group.group_display_name.
Data.JobName additional.fields Se agregó como un campo adicional con la clave "JobName".
Data.MemberId target.user.userid Se asigna directamente a target.user.userid cuando Data.Updates.0.MemberId no está presente.
Data.MemberDisplayName target.user.user_display_name Se asigna directamente a target.user.user_display_name.
Data.NamespaceId target.resource.product_object_id Se asigna a target.resource.product_object_id si no están presentes PipelineId, AuthorizationId y AgentId.
Data.NamespaceName target.resource.name Se asigna a target.resource.name si PipelineName no está presente.
Data.ownerDetails additional.fields Se agregó como un campo adicional con la clave "OwnerDetails".
Data.OwnerId additional.fields Se agregó como un campo adicional con la clave "OwnerId".
Data.PipelineId target.resource.product_object_id Se asigna directamente a target.resource.product_object_id.
Data.PipelineName target.resource.name Se asigna directamente a target.resource.name.
Data.PipelineRevision target.resource.attribute.labels Se agregó como una etiqueta con la clave "PipelineRevision".
Data.PipelineScope target.resource.attribute.labels Se agregó como una etiqueta con la clave "PipelineScope".
Data.PlanType additional.fields Se agregó como un campo adicional con la clave "PlanType".
Data.PreviousAccessLevel target.resource.attribute.labels Se agregó como una etiqueta con la clave "PreviousAccessLevel".
Data.PublisherName target.resource.attribute.labels Se agregó como una etiqueta con la clave "PublisherName".
Data.Reason additional.fields Se agregó como un campo adicional con la clave "Reason".
Data.ReleaseId additional.fields Se agregó como un campo adicional con la clave "ReleaseId".
Data.ReleaseName additional.fields Se agregó como un campo adicional con la clave "ReleaseName".
Data.RequesterId additional.fields Se agregó como un campo adicional con la clave "RequesterId".
Data.RetentionLeaseId additional.fields Se agregó como un campo adicional con la clave "RetentionLeaseId".
Data.RetentionOwnerId additional.fields Se agregó como un campo adicional con la clave "RetentionOwnerId".
Data.RunName additional.fields Se agregó como un campo adicional con la clave "RunName".
Data.Scopes target.resource.attribute.labels Se agregan como etiquetas con la clave "Scope".
Data.StageName additional.fields Se agregó como un campo adicional con la clave "StageName".
Data.StartTime additional.fields Se agregó como un campo adicional con la clave "StartTime".
Data.TargetUser target.user.userid Se asigna directamente a target.user.userid.
Data.Timestamp metadata.event_timestamp Se analizó y se asignó a metadata.event_timestamp.
Data.TokenType target.resource.attribute.labels Se agregó como una etiqueta con la clave "TokenType".
Data.Updates.0.GroupId target.group.product_object_id Se asigna directamente a target.group.product_object_id.
Data.Updates.0.MemberId target.user.userid Se asigna directamente a target.user.userid.
Data.ValidFrom target.resource.attribute.labels Se agregó como una etiqueta con la clave "ValidFrom".
Data.ValidTo target.resource.attribute.labels Se agregó como una etiqueta con la clave "ValidTo".
DewPoint additional.fields Se agregó como un campo adicional con la clave "DewPoint".
Details metadata.description Se asigna directamente a metadata.description.
Humidity additional.fields Se agregó como un campo adicional con la clave "Humedad".
Icon additional.fields Se agregó como un campo adicional con la clave "Icon".
Id metadata.product_log_id Se asigna directamente a metadata.product_log_id.
IpAddress principal.ip Se asigna directamente a principal.ip.
MoonPhase additional.fields Se agregó como un campo adicional con la clave "MoonPhase".
Moonrise additional.fields Se agregó como un campo adicional con la clave "Moonrise".
Moonset additional.fields Se agregó como un campo adicional con la clave "Moonset".
OperationName metadata.product_event_type Se asigna directamente a metadata.product_event_type.
Precipitation additional.fields Se agregó como un campo adicional con la clave "Precipitation".
Pressure additional.fields Se agregó como un campo adicional con la clave "Pressure".
ProjectId target.resource_ancestors.product_object_id Se usa para completar el campo product_object_id dentro de target.resource_ancestors cuando el elemento superior es de tipo CLOUD_PROJECT.
ProjectName target.resource_ancestors.name, target.resource.attribute.labels Se usa para completar el campo name dentro de target.resource_ancestors cuando el elemento superior es de tipo CLOUD_PROJECT. También se agregó como etiqueta a target.resource.attribute.labels con la clave "ProjectName".
RoleLocation target.location.name Se asigna directamente a target.location.name.
ScopeDisplayName target.resource_ancestors.name Se usa para completar el campo name dentro de target.resource_ancestors cuando el elemento superior es de tipo CLOUD_ORGANIZATION.
ScopeId target.resource_ancestors.product_object_id Se usa para completar el campo product_object_id dentro de target.resource_ancestors cuando el elemento superior es de tipo CLOUD_ORGANIZATION.
ScopeType additional.fields Se agregó como un campo adicional con la clave "ScopeType".
Sunrise additional.fields Se agregó como un campo adicional con la clave "Sunrise".
Sunset additional.fields Se agregó como un campo adicional con la clave "Sunset".
Temperature additional.fields Se agregó como un campo adicional con la clave "Temperature".
TenantId metadata.product_deployment_id, additional.fields Se asigna directamente a metadata.product_deployment_id. También se agregó como un campo adicional con la clave "TenantId".
TimeGenerated metadata.event_timestamp Se analizó y se asignó a metadata.event_timestamp.
UserAgent network.http.user_agent, network.http.parsed_user_agent Se asigna directamente a network.http.user_agent. También se analiza y se asigna a network.http.parsed_user_agent.
UVIndex additional.fields Se agregó como un campo adicional con la clave "UVIndex".
Visibility additional.fields Se agregó como un campo adicional con la clave "Visibilidad".
WindDirection additional.fields Se agregó como un campo adicional con la clave "WindDirection".
WindSpeed additional.fields Se agregó como un campo adicional con la clave "WindSpeed".
_Internal_WorkspaceResourceId additional.fields Se agregó como un campo adicional con la clave "workspace_resource_id".
N/A metadata.event_type Se determina según la lógica basada en OperationName y otros campos. El valor predeterminado es "GENERIC_EVENT" si no coincide con ningún tipo de evento específico. Los valores posibles incluyen "STATUS_SHUTDOWN", "RESOURCE_CREATION", "STATUS_UPDATE", "USER_RESOURCE_DELETION", "RESOURCE_READ", "RESOURCE_WRITTEN", "RESOURCE_DELETION" y "GROUP_MODIFICATION".
N/A metadata.vendor_name Se establece en "Microsoft".
N/A metadata.product_name Se debe establecer en "Azure DevOps".
N/A metadata.log_type Se debe establecer en "AZURE_DEVOPS".
N/A principal.user.account_type Se establece en "SERVICE_ACCOUNT_TYPE" si AuthenticationMechanism contiene "ServicePrincipal". De lo contrario, se establece en "CLOUD_ACCOUNT_TYPE".
N/A target.asset.attribute.cloud.environment Se define en MICROSOFT_AZURE.
N/A security_result.action Se establece en "ALLOW" para las operaciones exitosas (Succeeded, Created, Modified, executed, updated, removed) y en "BLOCK" para las operaciones fallidas (Failed, TimedOut).
N/A extensions.auth.mechanism Se establece en "USERNAME_PASSWORD" si summary es "UserAuthToken".
N/A target.resource.resource_type Se establece en "SETTING" si pipeline_id está presente, en "CREDENTIAL" si authorization_id está presente, en "DEVICE" si agent_id está presente o en "DATABASE" si namespace_id está presente. De lo contrario, en algunos casos, se establece como "STORAGE_BUCKET" según operationName.
N/A target.resource.resource_subtype Se establece en "Canalización" si pipeline_id está presente, en "Token" si authorization_id está presente, en "Agente" si agent_id está presente o en "Espacio de nombres" si namespace_id está presente.

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