Coletar registros de auditoria do Azure DevOps
Visão geral
Esse analisador processa os registros de auditoria do Azure DevOps no formato JSON. Ele extrai campos de estruturas JSON aninhadas e de nível superior, mapeando-as para o UDM. A lógica condicional com base em valores de campo específicos categoriza eventos e enriquece a saída com informações de segurança relevantes. O analisador também processa mensagens não formatadas em JSON tentando extrair um payload JSON usando padrões grok.
Antes de começar
- Verifique se você tem uma instância do Google SecOps.
- Verifique se você tem uma organização ativa do Azure DevOps.
- Verifique se você tem acesso privilegiado à organização do Azure DevOps e ao Azure.
Configurar um feed no Google SecOps para processar os registros do Azure DevOps
- Acesse Configurações do SIEM > Feeds.
- Clique em Adicionar novo.
- No campo Nome do feed, insira um nome para o feed (por exemplo, Azure Devops Logs).
- Selecione Webhook como o Tipo de origem.
- Selecione Azure Devops como o Tipo de registro.
- Clique em Próxima.
- Opcional: especifique valores para os seguintes parâmetros de entrada:
- Delimitador de divisão: o delimitador usado para separar linhas de registro, como
\n
. - Namespace de recursos: o namespace de recursos.
- Rótulos de ingestão: o rótulo aplicado aos eventos desse feed.
- Delimitador de divisão: o delimitador usado para separar linhas de registro, como
- Clique em Próxima.
- Revise a configuração do feed na tela Finalizar e clique em Enviar.
- Clique em Gerar chave secreta para gerar uma chave secreta para autenticar esse feed.
- Copie e armazene a chave secreta. Não é possível acessar essa chave secreta novamente. Se necessário, você pode gerar uma nova chave secreta, mas essa ação torna a chave secreta anterior obsoleta.
- Na guia Detalhes, copie o URL do endpoint do feed no campo Informações do endpoint. É necessário especificar esse URL de endpoint no aplicativo cliente.
- Clique em Concluído.
Criar uma chave de API para o feed de webhook
Acesse o console do Google Cloud > Credenciais.
Clique em Criar credenciais e, em seguida, selecione Chave de API.
Restrinja o acesso da chave de API à API Google Security Operations.
Especificar o URL do endpoint
- No aplicativo cliente, especifique o URL do endpoint HTTPS fornecido no feed de webhook.
Ative a autenticação especificando a chave de API e a chave secreta como parte do cabeçalho personalizado no seguinte formato:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET
Recomendação: especifique a chave de API como um cabeçalho em vez de especificar no URL. Se o cliente do webhook não tiver suporte a cabeçalhos personalizados, especifique a chave de API e a chave secreta usando parâmetros de consulta no seguinte formato:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Substitua:
ENDPOINT_URL
: o URL do endpoint do feed.API_KEY
: a chave de API para autenticação no Google Security Operations.SECRET
: a chave secreta gerada para autenticar o feed.
Configurar o recurso de auditoria no Azure DevOps
- Faça login na sua organização (
https://dev.azure.com/{yourorganization}
). - Selecione o ícone de engrenagem em Configurações da organização.
- Selecione Políticas em Segurança.
- Defina o botão Registrar eventos de auditoria como Ativado.
Configurar um tópico do Event Grid no Azure
- Faça login no portal do Azure.
- Pesquise e acesse a grade de eventos.
- Localize Tópicos em Eventos personalizados.
- Clique em Criar.
- Selecione sua assinatura e o grupo de recursos. Informe um nome (por exemplo, DevopsAuditLog) e selecione a região. Clique em Revisar e criar.
- Acesse o novo Tópico e copie o URL do endpoint do tópico.
- Acesse Configurações > Chaves de acesso e copie a Chave 1.
Configurar o fluxo de registro do Azure DevOps para o Event Grid
- Faça login na sua organização (
https://dev.azure.com/{yourorganization}
). - Selecione o ícone de engrenagem em Configurações da organização.
- Selecione Auditoria.
- Acesse a guia Streams e selecione New stream > Event Grid.
- Insira o endpoint do tópico e a chave de acesso criados em Configurar um tópico do Event Grid no Azure.
Configurar um webhook no Azure DevOps para o Google SecOps
- No portal do Azure, pesquise e acesse o Event Grid.
- Selecione o Tópico criado anteriormente.
- Acesse Entidades > Assinatura de eventos.
- Clique em + Assinatura de evento.
- Forneça um nome descritivo (por exemplo, Integração do Google SecOps).
- Selecione Gancho da Web e clique em Configurar um endpoint.
- Configure o endpoint:
- Endpoint do assinante: insira o URL do endpoint de API Google SecOps.
- Anexe
?key=<API_KEY>&secret=<SECRET_KEY>
ao URL do payload. - Defina o cabeçalho Content-Type como application/json.
- Clique em Criar.
Tabela de mapeamento do UDM
Campo de registro | Mapeamento do UDM | Lógica |
---|---|---|
ActivityId |
metadata.product_log_id |
Mapeado diretamente do campo Id no registro bruto quando o campo records não está presente ou do campo ActivityId no objeto data quando records está presente. |
ActionId |
metadata.product_event_type |
Mapeado diretamente do campo ActionId no objeto data . |
ActorCUID |
additional.fields |
Incluído como um campo extra com a chave "Actor CUID". |
ActorDisplayName |
principal.user.user_display_name |
Mapeado diretamente do campo ActorDisplayName , se não for "Azure DevOps Service". Se for "Azure DevOps Service", ele será adicionado como um rótulo a principal.resource.attribute.labels . |
ActorUPN |
principal.user.email_addresses |
Mapeado diretamente do campo ActorUPN se ele corresponder a um padrão de endereço de e-mail. |
ActorUserId |
principal.user.userid |
Mapeado diretamente do campo ActorUserId . |
Area |
target.application |
É usado para construir o campo target.application precedido por "DevOps " no valor Area . |
AuthenticationMechanism |
extensions.auth.auth_details , security_result.rule_id |
Analisado para extrair detalhes de autenticação e o ID da regra. Os detalhes de autenticação são mapeados para extensions.auth.auth_details . O ID da regra extraído é mapeado para security_result.rule_id . |
CategoryDisplayName |
security_result.action_details |
Mapeado diretamente para security_result.action_details . |
City |
principal.location.city |
Mapeado diretamente do campo City . |
Conditions |
additional.fields |
Adicionado como um campo extra com a chave "Condições". |
Country |
principal.location.country_or_region |
Mapeado diretamente do campo Country . |
Data.* |
Vários | Os campos no objeto Data são mapeados para diferentes campos do UDM com base nos nomes e no contexto. Confira abaixo exemplos específicos. |
Data.AccessLevel |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "AccessLevel". |
Data.AgentId |
target.resource.product_object_id |
Mapeado para target.resource.product_object_id se PipelineId e AuthorizationId não estiverem presentes. |
Data.AgentName |
target.resource.name |
Mapeado para target.resource.name se PipelineName , NamespaceName e DisplayName não estiverem presentes. |
Data.AuthorizationId |
target.resource.product_object_id |
Mapeado para target.resource.product_object_id se PipelineId não estiver presente. |
Data.CallerProcedure |
additional.fields |
Adicionado como um campo adicional com a chave "CallerProcedure". |
Data.CheckSuiteId |
additional.fields |
Adicionado como um campo adicional com a chave "CheckSuiteId". |
Data.CheckSuiteStatus |
additional.fields |
Adicionado como um campo adicional com a chave "CheckSuiteStatus". |
Data.ConnectionId |
additional.fields |
Adicionado como um campo extra com a chave "ConnectionId". |
Data.ConnectionName |
additional.fields |
Adicionado como um campo extra com a chave "ConnectionName". |
Data.ConnectionType |
additional.fields |
Adicionado como um campo extra com a chave "ConnectionType". |
Data.DefinitionId |
additional.fields |
Adicionado como um campo extra com a chave "DefinitionId". |
Data.DeploymentResult |
additional.fields |
Adicionado como um campo adicional com a chave "DeploymentResult". |
Data.DisplayName |
target.resource.name |
Mapeado para target.resource.name se PipelineName e NamespaceName não estiverem presentes. |
Data.EndpointIdList |
additional.fields |
Adicionado como um campo extra com a chave "EndpointIdList". |
Data.EnvironmentName |
additional.fields |
Adicionado como um campo extra com a chave "EnvironmentName". |
Data.Filter.continuationToken |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "continuation_token". |
Data.Filter.endTime |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "filter_end_time". |
Data.Filter.startTime |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "filter_start_time". |
Data.FinishTime |
additional.fields |
Adicionado como um campo extra com a chave "FinishTime". |
Data.GroupId |
target.group.product_object_id |
Mapeado diretamente para target.group.product_object_id quando Data.Updates.0.GroupId não está presente. |
Data.GroupName |
target.group.group_display_name |
Mapeado diretamente para target.group.group_display_name . |
Data.JobName |
additional.fields |
Adicionado como um campo adicional com a chave "JobName". |
Data.MemberId |
target.user.userid |
Mapeado diretamente para target.user.userid quando Data.Updates.0.MemberId não está presente. |
Data.MemberDisplayName |
target.user.user_display_name |
Mapeado diretamente para target.user.user_display_name . |
Data.NamespaceId |
target.resource.product_object_id |
Mapeado para target.resource.product_object_id se PipelineId , AuthorizationId e AgentId não estiverem presentes. |
Data.NamespaceName |
target.resource.name |
Mapeado para target.resource.name se PipelineName não estiver presente. |
Data.ownerDetails |
additional.fields |
Adicionado como um campo adicional com a chave "OwnerDetails". |
Data.OwnerId |
additional.fields |
Adicionado como um campo adicional com a chave "OwnerId". |
Data.PipelineId |
target.resource.product_object_id |
Mapeado diretamente para target.resource.product_object_id . |
Data.PipelineName |
target.resource.name |
Mapeado diretamente para target.resource.name . |
Data.PipelineRevision |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "PipelineRevision". |
Data.PipelineScope |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "PipelineScope". |
Data.PlanType |
additional.fields |
Adicionado como um campo extra com a chave "PlanType". |
Data.PreviousAccessLevel |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "PreviousAccessLevel". |
Data.PublisherName |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "PublisherName". |
Data.Reason |
additional.fields |
Adicionado como um campo extra com a chave "Reason". |
Data.ReleaseId |
additional.fields |
Adicionado como um campo extra com a chave "ReleaseId". |
Data.ReleaseName |
additional.fields |
Adicionado como um campo extra com a chave "ReleaseName". |
Data.RequesterId |
additional.fields |
Adicionado como um campo adicional com a chave "RequesterId". |
Data.RetentionLeaseId |
additional.fields |
Adicionado como um campo extra com a chave "RetentionLeaseId". |
Data.RetentionOwnerId |
additional.fields |
Adicionado como um campo extra com a chave "RetentionOwnerId". |
Data.RunName |
additional.fields |
Adicionado como um campo extra com a chave "RunName". |
Data.Scopes |
target.resource.attribute.labels |
Adicionados como rótulos com a chave "Escopo". |
Data.StageName |
additional.fields |
Adicionado como um campo extra com a chave "StageName". |
Data.StartTime |
additional.fields |
Adicionado como um campo extra com a chave "StartTime". |
Data.TargetUser |
target.user.userid |
Mapeado diretamente para target.user.userid . |
Data.Timestamp |
metadata.event_timestamp |
Analisado e mapeado para metadata.event_timestamp . |
Data.TokenType |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "TokenType". |
Data.Updates.0.GroupId |
target.group.product_object_id |
Mapeado diretamente para target.group.product_object_id . |
Data.Updates.0.MemberId |
target.user.userid |
Mapeado diretamente para target.user.userid . |
Data.ValidFrom |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "ValidFrom". |
Data.ValidTo |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "ValidTo". |
DewPoint |
additional.fields |
Adicionado como um campo extra com a chave "DewPoint". |
Details |
metadata.description |
Mapeado diretamente para metadata.description . |
Humidity |
additional.fields |
Adicionado como um campo adicional com a chave "Humidity". |
Icon |
additional.fields |
Adicionado como um campo extra com a chave "Ícone". |
Id |
metadata.product_log_id |
Mapeado diretamente para metadata.product_log_id . |
IpAddress |
principal.ip |
Mapeado diretamente para principal.ip . |
MoonPhase |
additional.fields |
Adicionado como um campo extra com a chave "MoonPhase". |
Moonrise |
additional.fields |
Adicionado como um campo extra com a chave "Moonrise". |
Moonset |
additional.fields |
Adicionado como um campo extra com a chave "Moonset". |
OperationName |
metadata.product_event_type |
Mapeado diretamente para metadata.product_event_type . |
Precipitation |
additional.fields |
Adicionado como um campo extra com a chave "Precipitação". |
Pressure |
additional.fields |
Adicionado como um campo extra com a chave "Pressão". |
ProjectId |
target.resource_ancestors.product_object_id |
Usado para preencher o campo product_object_id em target.resource_ancestors quando o ancestral é do tipo CLOUD_PROJECT . |
ProjectName |
target.resource_ancestors.name , target.resource.attribute.labels |
Usado para preencher o campo name em target.resource_ancestors quando o ancestral é do tipo CLOUD_PROJECT . Também adicionado como um rótulo a target.resource.attribute.labels com a chave "ProjectName". |
RoleLocation |
target.location.name |
Mapeado diretamente para target.location.name . |
ScopeDisplayName |
target.resource_ancestors.name |
Usado para preencher o campo name em target.resource_ancestors quando o ancestral é do tipo CLOUD_ORGANIZATION . |
ScopeId |
target.resource_ancestors.product_object_id |
Usado para preencher o campo product_object_id em target.resource_ancestors quando o ancestral é do tipo CLOUD_ORGANIZATION . |
ScopeType |
additional.fields |
Adicionado como um campo extra com a chave "ScopeType". |
Sunrise |
additional.fields |
Adicionado como um campo extra com a chave "Sunrise". |
Sunset |
additional.fields |
Adicionado como um campo extra com a chave "Sunset". |
Temperature |
additional.fields |
Adicionado como um campo adicional com a chave "Temperature". |
TenantId |
metadata.product_deployment_id , additional.fields |
Mapeado diretamente para metadata.product_deployment_id . Também foi adicionado como um campo adicional com a chave "TenantId". |
TimeGenerated |
metadata.event_timestamp |
Analisado e mapeado para metadata.event_timestamp . |
UserAgent |
network.http.user_agent , network.http.parsed_user_agent |
Mapeado diretamente para network.http.user_agent . Também analisado e mapeado para network.http.parsed_user_agent . |
UVIndex |
additional.fields |
Adicionado como um campo adicional com a chave "UVIndex". |
Visibility |
additional.fields |
Adicionado como um campo extra com a chave "Visibilidade". |
WindDirection |
additional.fields |
Adicionado como um campo adicional com a chave "WindDirection". |
WindSpeed |
additional.fields |
Adicionado como um campo extra com a chave "WindSpeed". |
_Internal_WorkspaceResourceId |
additional.fields |
Adicionado como um campo adicional com a chave "workspace_resource_id". |
N/A | metadata.event_type |
Determinado pela lógica com base no OperationName e em outros campos. O padrão é "GENERIC_EVENT" se nenhum tipo de evento específico for correspondido. Os valores possíveis incluem "STATUS_SHUTDOWN", "RESOURCE_CREATION", "STATUS_UPDATE", "USER_RESOURCE_DELETION", "RESOURCE_READ", "RESOURCE_WRITTEN", "RESOURCE_DELETION" e "GROUP_MODIFICATION". |
N/A | metadata.vendor_name |
Defina como "Microsoft". |
N/A | metadata.product_name |
Defina como "Azure DevOps". |
N/A | metadata.log_type |
Defina como "AZURE_DEVOPS". |
N/A | principal.user.account_type |
Defina como "SERVICE_ACCOUNT_TYPE" se AuthenticationMechanism contiver "ServicePrincipal". Caso contrário, defina como "CLOUD_ACCOUNT_TYPE". |
N/A | target.asset.attribute.cloud.environment |
Defina como MICROSOFT_AZURE . |
N/A | security_result.action |
Defina como "PERMITIR" para operações bem-sucedidas (sucedidas, criadas, modificadas, executadas, atualizadas, removidas) e "BLOQUEAR" para operações com falha (falha, tempo limite). |
N/A | extensions.auth.mechanism |
Defina como "USERNAME_PASSWORD" se summary for "UserAuthToken". |
N/A | target.resource.resource_type |
Defina como "SETTING" se pipeline_id estiver presente, "CREDENTIAL" se authorization_id estiver presente, "DEVICE" se agent_id estiver presente ou "DATABASE" se namespace_id estiver presente. Caso contrário, ele será definido como "STORAGE_BUCKET" em alguns casos com base em operationName . |
N/A | target.resource.resource_subtype |
Defina como "Pipeline" se pipeline_id estiver presente, "Token" se authorization_id estiver presente, "Agente" se agent_id estiver presente ou "Namespace" se namespace_id estiver presente. |
Alterações
2024-01-19
- O valor "metadata.eventtype" foi alterado de "SERVICE*" para "USER_RESOURCE_UPDATE_CONTENT" se os dados do usuário principal e do recurso de destino estiverem presentes.
- O mapeamento de "IpAddress" mudou de "target.ip" para "principal.ip".
- O mapeamento de "ActorCUID" foi alterado de "principal.user.product_object_id" para "additional.fields".
- O mapeamento de "ScopeId" mudou de "principal.asset_id" para "resource_ancestors.product_object_id".
- O mapeamento de "_Internal_WorkspaceResourceId" foi alterado de "target.resource.product_object_id" para "additional.fields".
- O mapeamento de "ProjectId" mudou de "target.resource.attribute.labels" para "target.resource_ancestors.product_object_id".
- O mapeamento de "AuthenticationMechanism" mudou de "security_result.summary" para "extensions.auth.auth_details".
- O mapeamento de "CorrelationId" mudou de "network.session_id" para "additional.fields".
- O mapeamento de "ScopeDisplayName" mudou de "additional.fields" para "target.resource_ancestors.name".
- O mapeamento de "PipelineId" foi alterado de "additional.fields" para "target.resource.product_object_id".
- O mapeamento de "PipelineName" mudou de "additional.fields" para "target.resource.name".
- O mapeamento de "PipelineScope" mudou de "additional.fields" para "target.resource.attribute.labels".
- O mapeamento de "PipelineRevision" mudou de "additional.fields" para "target.resource.attribute.labels".
- O mapeamento de "ProjectId" mudou de "target.resource.resource.attribute.labels" para "target.resource_ancestors.product_object_id".
- O mapeamento de "Área" foi alterado de "additional.fields" para "target.application".
- O valor "MICROSOFT_AZURE" foi mapeado para "target.asset.attribute.cloud.environment".
- Quando "AuthenticationMechanism" tiver o valor "ServicePrincipal", defina "SERVICE_ACCOUNT_TYPE" como "principal.user.account_type". Caso contrário, defina "CLOUD_ACCOUNT_TYPE" como "principal.user.account_type".
- Mapeamos "Categoria" para "security_result.action_details".
- "ALLOW" ou "BLOCK" foram mapeados para "security_result.action" com base no campo "Details".
- "ActivityId" foi mapeado para "additional.fields".
2024-01-09
- Foram adicionados Grok e gsub para analisar os registros JSON não analisados.
- Mapeou "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" para "security_result.detection_fields".
- "resultSignature.label", "rec.resultType", "Visibility", "Humidity", "Precipitation","MoonPhase", "Moonrise", "Moonset", "Pressure", "WindSpeed", "UVIndex", "DewPoint", "WindDirection", "Sunrise", "Sunset", "Temperature", "Icon", "Conditions" foram mapeados para "additional.fields".
- "level" foi mapeado para "security_result.severity".
- Mapeamos "appname" para "target.application".
- "category.details" foi associado a "security.result.category.details".
- "rec.resourceId" foi mapeado para "target.resource.id".
- "res.extensionResourceName" foi mapeado para "principal.hostname".
2023-11-23
- Adição de suporte a um novo padrão de registros JSON.
- "data.TimeGenerated" foi associado a "metadata.event_timestamp".
- Quando "_Internal_WorkspaceResourceId" está ausente, "topic" é mapeado para "target.resource.product_object_id".
- "data.Data.ConnectionId" foi mapeado para "additional.fields".
- "data.Data.ownerDetails" foi associado a "additional.fields".
- "data.Data.DeploymentResult" foi mapeado para "additional.fields".
- "data.Data.EnvironmentName" foi associado a "additional.fields".
- Mapeamos "data.Data.JobName" para "additional.fields".
- "data.Data.StageName" foi associado a "additional.fields".
- "data.Data.RunName" foi mapeado para "additional.fields".
- "data.Data.RetentionLeaseId" foi mapeado para "additional.fields".
- "data.Data.CheckSuiteId" foi mapeado para "additional.fields".
- "data.Data.CheckSuiteStatus" foi mapeado para "additional.fields".
- "data.Data.ApprovalRequest" foi associado a "additional.fields".
- "data.Data.ApprovalType" foi mapeado para "additional.fields".
- "subject" foi mapeado para "additional.fields".
- "data.ActorUserId" foi mapeado para "principal.user.userid".
- "data.ActorDisplayName" foi mapeado para "principal.user.user_display_name".
- "data.ActorCUID" foi associado a "principal.user.product_object_id".
- "data.ActorUPN" foi associado a "principal.user.email_addresses".
- "data.ScopeId" foi mapeado para "principal.asset_id".
- "data.CorrelationId" foi mapeado para "network.session_id".
- "data.UserAgent" foi associado a "network.http.user_agent".
- "data.ProjectId" foi mapeado para "target.resource.attribute.labels".
- "data.ScopeType" foi mapeado para "additional.fields".
- Mapeamos "data.ProjectName" para "target.resource.attribute.labels".
- "data.Details" foi associado a "metadata.description".
- "data.CategoryDisplayName" foi mapeado para "security_result.rule_name".
- Mapeamos "data.Area" para "additional.fields".
- Mapeamos "data.Id" para "metadata.product_log_id".
- Mapeamos "data.ActionId" para "metadata.product_event_type".
- "data.Timestamp" foi mapeado para "metadata.event_timestamp".
2022-06-28
- Parser recém-criado