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 a la UDM. La lógica condicional basada en valores de campos específicos clasifica los eventos y enriquece el resultado con información de seguridad relevante. El analizador también controla los mensajes con formato que no son JSON, ya que intenta extraer una carga útil JSON con patrones de grok.

Antes de comenzar

  • Asegúrate de tener una instancia de Google SecOps.
  • Asegúrate de tener una organización de Azure DevOps activa.
  • Asegúrate de tener acceso con privilegios a la organización de Azure DevOps y a Azure.

Configura un feed en Google SecOps para transferir los registros de Azure DevOps

  1. Ve a Configuración de SIEM > Feeds.
  2. Haz clic en Agregar nueva.
  3. En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, Registros de Azure Devops).
  4. Selecciona Webhook como el Tipo de origen.
  5. Selecciona Azure Devops como el Tipo de registro.
  6. Haz clic en Siguiente.
  7. 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 de recursos: Es el espacio de nombres de recursos.
    • Etiquetas de transferencia: Es la etiqueta que se aplica a los eventos de este feed.
  8. Haz clic en Siguiente.
  9. Revisa la configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.
  10. Haz clic en Generate Secret Key para generar una clave secreta que autentique este feed.
  11. Copia y almacena la clave secreta. No podrás volver a ver esta clave secreta. Si es necesario, puedes volver a generar una clave secreta nueva, pero esta acción hace que la clave secreta anterior quede obsoleta.
  12. 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.
  13. Haz clic en Listo.

Crea una clave de API para el feed de webhook

  1. Ve a consola de Google Cloud > Credenciales.

    Ir a Credenciales

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

  3. Restringe el acceso de 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. Habilita la autenticación especificando la clave de API y la clave secreta como parte del encabezado personalizado en 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 consulta 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 acceder a la Configuración de la organización.
  3. Selecciona Políticas en Seguridad.
  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. Busca Temas en Eventos personalizados.
  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 > Llaves de acceso y copia la Clave 1.

Configura la transmisión de registros de Azure DevOps a Event Grid

  1. Accede a tu organización (https://dev.azure.com/{yourorganization}).
  2. Selecciona el ícono de ajustes para acceder a la Configuración de la organización.
  3. Selecciona Auditoría.
  4. Ve a la pestaña Transmisiones y selecciona Nueva transmisión > Cuadrícula de eventos.
  5. Ingresa el extremo del tema y la clave de acceso que creaste en Cómo configurar 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 que creaste anteriormente.
  3. Ve a Entidades > Suscripción a eventos.
  4. Haz clic en + Suscripción a eventos.
  5. Proporciona un nombre descriptivo (p. ej., Integración de Google SecOps).
  6. Selecciona Webhook y haz clic en Configurar un extremo.
  7. Configura el extremo:
    • Extremo del suscriptor: Ingresa la URL del extremo de API de Google SecOps.
    • Agrega ?key=<API_KEY>&secret=<SECRET_KEY> a la URL de la carga útil.
    • Establece el encabezado Content-Type en 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 asignan directamente desde el campo Id en el registro sin procesar cuando no está presente el campo records, 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 “Servicio de Azure DevOps”, 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 agregando "DevOps " al principio del valor 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 la regla extraída se asigna a security_result.rule_id.
CategoryDisplayName security_result.action_details Se asignan 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 "Condiciones".
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 de la AUA según sus nombres y contexto. Consulta los ejemplos específicos que aparecen 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 asignan 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 asignan 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 asignan directamente a target.resource.product_object_id.
Data.PipelineName target.resource.name Se asignan 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 "Motivo".
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 agregaron como etiquetas con la clave "Alcance".
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 asignan directamente a target.user.userid.
Data.Timestamp metadata.event_timestamp Se analiza y se asigna 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 asignan directamente a target.group.product_object_id.
Data.Updates.0.MemberId target.user.userid Se asignan 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 etiqueta con la clave "ValidTo".
DewPoint additional.fields Se agregó como un campo adicional con la clave "DewPoint".
Details metadata.description Se asignan directamente a metadata.description.
Humidity additional.fields Se agregó como un campo adicional con la clave "Humidity".
Icon additional.fields Se agregó como un campo adicional con la clave "Icon".
Id metadata.product_log_id Se asignan directamente a metadata.product_log_id.
IpAddress principal.ip Se asignan 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 "Amanecer lunar".
Moonset additional.fields Se agregó como un campo adicional con la clave "Puesta de la luna".
OperationName metadata.product_event_type Se asignan directamente a metadata.product_event_type.
Precipitation additional.fields Se agregó como un campo adicional con la clave "Precipitación".
Pressure additional.fields Se agregó como un campo adicional con la clave "Presión".
ProjectId target.resource_ancestors.product_object_id Se usa para propagar el campo product_object_id dentro de target.resource_ancestors cuando el ancestro es de tipo CLOUD_PROJECT.
ProjectName target.resource_ancestors.name, target.resource.attribute.labels Se usa para propagar el campo name dentro de target.resource_ancestors cuando el ancestro 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 asignan directamente a target.location.name.
ScopeDisplayName target.resource_ancestors.name Se usa para propagar el campo name dentro de target.resource_ancestors cuando el ancestro es de tipo CLOUD_ORGANIZATION.
ScopeId target.resource_ancestors.product_object_id Se usa para propagar el campo product_object_id dentro de target.resource_ancestors cuando el ancestro 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 "Amanecer".
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 asignan directamente a metadata.product_deployment_id. También se agregó como un campo adicional con la clave "TenantId".
TimeGenerated metadata.event_timestamp Se analiza y se asigna a metadata.event_timestamp.
UserAgent network.http.user_agent, network.http.parsed_user_agent Se asignan 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 mediante una lógica basada en OperationName y otros campos. El valor predeterminado es "GENERIC_EVENT" si no se encuentra ningún tipo de evento específico. Los valores posibles son "STATUS_SHUTDOWN", "RESOURCE_CREATION", "STATUS_UPDATE", "USER_RESOURCE_DELETION", "RESOURCE_READ", "RESOURCE_WRITTEN", "RESOURCE_DELETION" y "GROUP_MODIFICATION".
N/A metadata.vendor_name Establece el valor en “Microsoft”.
N/A metadata.product_name Establece la opción en "Azure DevOps".
N/A metadata.log_type Establece el valor en "AZURE_DEVOPS".
N/A principal.user.account_type Establece en "SERVICE_ACCOUNT_TYPE" si AuthenticationMechanism contiene "ServicePrincipal"; de lo contrario, configúralo en "CLOUD_ACCOUNT_TYPE".
N/A target.asset.attribute.cloud.environment Se define en MICROSOFT_AZURE.
N/A security_result.action Establece el valor en "ALLOW" para las operaciones que se realizan correctamente (Succeeded, Created, Modified, executed, updated, removed) y en "BLOCK" para las operaciones que fallan (Failed, TimedOut).
N/A extensions.auth.mechanism Establece en "USERNAME_PASSWORD" si summary es "UserAuthToken".
N/A target.resource.resource_type Se establece en "SETTING" si pipeline_id está presente, "CREDENTIAL" si authorization_id está presente, "DEVICE" si agent_id está presente o "DATABASE" si namespace_id está presente. De lo contrario, se establece como "STORAGE_BUCKET" en algunos casos 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.

Cambios

2024-01-19

  • Se cambió el valor de "metadata.eventtype" de "SERVICE*" a "USER_RESOURCE_UPDATE_CONTENT" si están presentes los datos del usuario principal y los datos del recurso de destino.
  • Se cambió la asignación de "IpAddress" de "target.ip" a "principal.ip".
  • Se cambió la asignación de "ActorCUID" de "principal.user.product_object_id" a "additional.fields".
  • Se cambió la asignación de "ScopeId" de "principal.asset_id" a "resource_ancestors.product_object_id".
  • Se cambió la asignación de "_Internal_WorkspaceResourceId" de "target.resource.product_object_id" a "additional.fields".
  • Se cambió la asignación de "ProjectId" de "target.resource.attribute.labels" a "target.resource_ancestors.product_object_id".
  • Se cambió la asignación de "AuthenticationMechanism" de "security_result.summary" a "extensions.auth.auth_details".
  • Se cambió la asignación de "CorrelationId" de "network.session_id" a "additional.fields".
  • Se cambió la asignación de "ScopeDisplayName" de "additional.fields" a "target.resource_ancestors.name".
  • Se cambió la asignación de "PipelineId" de "additional.fields" a "target.resource.product_object_id".
  • Se cambió la asignación de "PipelineName" de "additional.fields" a "target.resource.name".
  • Se cambió la asignación de "PipelineScope" de "additional.fields" a "target.resource.attribute.labels".
  • Se cambió la asignación de "PipelineRevision" de "additional.fields" a "target.resource.attribute.labels".
  • Se cambió la asignación de "ProjectId" de "target.resource.resource.attribute.labels" a "target.resource_ancestors.product_object_id".
  • Se cambió la asignación de "Area" de "additional.fields" a "target.application".
  • Se asignó el valor "MICROSOFT_AZURE" a "target.asset.attribute.cloud.environment".
  • Cuando "AuthenticationMechanism" tenga el valor "ServicePrincipal", establece "SERVICE_ACCOUNT_TYPE" en "principal.user.account_type". De lo contrario, establece "CLOUD_ACCOUNT_TYPE" en "principal.user.account_type".
  • Se asignó "Category" a "security_result.action_details".
  • Se asignó “ALLOW” o “BLOCK” a “security_result.action” según el campo “Details”.
  • Se asignó "ActivityId" a "additional.fields".

2024-01-09

  • Se agregaron Grok y gsub para analizar los registros JSON sin analizar.
  • Se asignaron "rec.correlationId", "properties.currentHealthStatus", "properties.previousHealthStatus", "properties.type", "properties.cause", "properties.title", "properties.details", "properties.recommendationType", "properties.recommendationCategory", "properties.recommendationImpact", "properties.recommendationName", "properties.recommendationResourceLink", "properties.recommendationSchemaVersion", "properties.eventCategory", "properties.hierarchy", "properties.message", "properties.entity", "identity.claims.xms.tcdt", "identity.claims.aio", "identity.claims.appid", "identity.claims.appidacr", "identity.claims.aud", "identity.claims.exp", "identity.claims.iat", "identity.claims.idtyp", "identity.claims.iss", "identity.claims.uti", "identity.claims.rh", "identity.claims.ver", "identity.claims.nbf", "identity.authorization.evidence.roleAssignmentId", "identity.authorization.evidence.principalType", "identity.authorization.evidence.principalId", "identity.authorization.evidence.roleAssignmentScope", "identity.authorization.evidence.roleDefinitionId" a "security_result.detection_fields".
  • Se asignaron "resultSignature.label", "rec.resultType", "Visibility", "Humidity", "Precipitation","MoonPhase", "Moonrise", "Moonset", "Pressure", "WindSpeed", "UVIndex", "DewPoint", "WindDirection", "Sunrise", "Sunset", "Temperature", "Icon", "Conditions" a "additional.fields".
  • Se asignó "level" a "security_result.severity".
  • Se asignó "appname" a "target.application".
  • Se asignó "category.details" a "security.result.category.details".
  • Se asignó "rec.resourceId" a "target.resource.id".
  • Se asignó "res.extensionResourceName" a "principal.hostname".

2023-11-23

  • Se agregó compatibilidad con un nuevo patrón de registros JSON.
  • Se asignó "data.TimeGenerated" a "metadata.event_timestamp".
  • Cuando falta "_Internal_WorkspaceResourceId", se asigna "topic" a "target.resource.product_object_id".
  • Se asignó "data.Data.ConnectionId" a "additional.fields".
  • Se asignó "data.Data.ownerDetails" a "additional.fields".
  • Se asignó "data.Data.DeploymentResult" a "additional.fields".
  • Se asignó "data.Data.EnvironmentName" a "additional.fields".
  • Se asignó "data.Data.JobName" a "additional.fields".
  • Se asignó "data.Data.StageName" a "additional.fields".
  • Se asignó "data.Data.RunName" a "additional.fields".
  • Se asignó "data.Data.RetentionLeaseId" a "additional.fields".
  • Se asignó "data.Data.CheckSuiteId" a "additional.fields".
  • Se asignó "data.Data.CheckSuiteStatus" a "additional.fields".
  • Se asignó "data.Data.ApprovalRequest" a "additional.fields".
  • Se asignó "data.Data.ApprovalType" a "additional.fields".
  • Se asignó "subject" a "additional.fields".
  • Se asignó "data.ActorUserId" a "principal.user.userid".
  • Se asignó "data.ActorDisplayName" a "principal.user.user_display_name".
  • Se asignó "data.ActorCUID" a "principal.user.product_object_id".
  • Se asignó "data.ActorUPN" a "principal.user.email_addresses".
  • Se asignó "data.ScopeId" a "principal.asset_id".
  • Se asignó "data.CorrelationId" a "network.session_id".
  • Se asignó "data.UserAgent" a "network.http.user_agent".
  • Se asignó "data.ProjectId" a "target.resource.attribute.labels".
  • Se asignó "data.ScopeType" a "additional.fields".
  • Se asignó "data.ProjectName" a "target.resource.attribute.labels".
  • Se asignó "data.Details" a "metadata.description".
  • Se asignó "data.CategoryDisplayName" a "security_result.rule_name".
  • Se asignó "data.Area" a "additional.fields".
  • Se asignó "data.Id" a "metadata.product_log_id".
  • Se asignó "data.ActionId" a "metadata.product_event_type".
  • Se asignó "data.Timestamp" a "metadata.event_timestamp".

2022-06-28

  • Analizador creado recientemente