Recolha registos de auditoria do Azure DevOps
Vista geral
Este analisador processa registos de auditoria do Azure DevOps no formato JSON. Extrai campos de estruturas JSON aninhadas e de nível superior, mapeando-os para o UDM. A lógica condicional baseada em valores de campos específicos categoriza os eventos e enriquece o resultado com informações de segurança relevantes. O analisador também processa mensagens com formatação não JSON tentando extrair um payload JSON através de padrões grok.
Antes de começar
Certifique-se de que cumpre os seguintes pré-requisitos:
- Instância do Google SecOps
- Uma organização ativa do Azure DevOps
- Acesso privilegiado à organização do Azure DevOps e ao Azure
Configure feeds
Existem dois pontos de entrada diferentes para configurar feeds na plataforma Google SecOps:
- Definições do SIEM > Feeds > Adicionar novo
- Content Hub > Pacotes de conteúdo > Começar
Como configurar o feed de auditoria do Azure DevOps
- Clique no pacote Plataforma Azure.
- Localize o tipo de registo Azure DevOps audit e clique em Adicionar novo feed.
Especifique valores para os seguintes campos:
- Source Type: Microsoft Azure Blob Storage V2.
- URI do Azure: o URL do ponto final do blob.
ENDPOINT_URL/BLOB_NAME
- Substitua o seguinte:
ENDPOINT_URL
: o URL do ponto final do blob (https://<storageaccountname>.blob.core.windows.net
)BLOB_NAME
: o nome do blob (por exemplo,insights-logs-<logname>
)
- Substitua o seguinte:
Opções de eliminação de origens: selecione a opção de eliminação de acordo com as suas preferências de carregamento.
Idade máxima do ficheiro: inclui ficheiros modificados no último número de dias. A predefinição é 180 dias.
Chave partilhada: a chave partilhada (uma string aleatória de 512 bits na codificação base-64) usada para aceder aos recursos do Azure.
Opções avançadas
- Nome do feed: um valor pré-preenchido que identifica o feed.
- Espaço de nomes do recurso: o espaço de nomes do recurso.
- Etiquetas de carregamento: a etiqueta aplicada aos eventos deste feed.
Clique em Criar feed.
Para mais informações sobre a configuração de vários feeds para diferentes tipos de registos nesta família de produtos, consulte o artigo Configure feeds por produto.
Crie uma chave da API para o feed de webhook
Aceda à Google Cloud consola > Credenciais.
Clique em Criar credenciais e, de seguida, selecione Chave de API.
Restrinja o acesso da chave de API à API Google Security Operations.
Especifique o URL do ponto final
- Na aplicação cliente, especifique o URL do ponto final HTTPS fornecido no feed do webhook.
Ative a autenticação especificando a chave da 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 da API como um cabeçalho em vez de a especificar no URL. Se o seu cliente de webhook não suportar cabeçalhos personalizados, pode especificar a chave da API e a chave secreta através de parâmetros de consulta no seguinte formato:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Substitua o seguinte:
ENDPOINT_URL
: o URL do ponto final do feed.API_KEY
: a chave da API para autenticar no Google Security Operations.SECRET
: a chave secreta que gerou para autenticar o feed.
Configure a funcionalidade de auditoria no Azure DevOps
- Inicie sessão na sua organização (
https://dev.azure.com/{yourorganization}
). - Selecione o ícone de roda dentada para Definições da organização.
- Selecione Políticas em Segurança.
- Ative o botão Registar eventos de auditoria.
Configure um tópico do Event Grid no Azure
- Inicie sessão no portal do Azure.
- Pesquise e aceda à Event Grid.
- Localize Tópicos em Eventos personalizados.
- Clique em + Criar.
- Selecione a sua Subscrição e Grupo de recursos. Indique um nome (por exemplo,
DevopsAuditLog
) e selecione a região. Clique em Rever e criar. - Aceda ao novo Tópico e copie o URL do ponto final do tópico.
- Aceda a Definições > Chaves de acesso e copie a Chave 1.
Configure a stream de registos do Azure DevOps para a grelha de eventos
- Inicie sessão na sua organização (
https://dev.azure.com/{yourorganization}
). - Selecione o ícone de roda dentada para Definições da organização.
- Selecione Auditoria.
- Aceda ao separador Streams e selecione Nova stream > Event Grid.
- Introduza o ponto final do tópico e a chave de acesso criados em Configure um tópico do Event Grid no Azure.
Configure um webhook no Azure DevOps para o Google SecOps
- No portal do Azure, pesquise e aceda ao Event Grid.
- Selecione um tópico criado anteriormente.
- Aceda a Entidades > Subscrição de eventos.
- Clique em + Subscrição de eventos.
- Indique um nome descritivo (por exemplo, *
Google SecOps Integration
). - Selecione Web Hook e clique em Configurar um ponto final.
- Configure o ponto final:
- Ponto final do subscritor: introduza o URL do ponto final da API Google SecOps.
- Na secção Cabeçalhos HTTP, adicione os seguintes cabeçalhos:
- Header 1:
- Chave:
X-goog-api-key
- Valor: a chave da API que criou na secção Crie uma chave da API para o feed de webhook.
- Chave:
- Header 2:
- Chave:
X-Webhook-Access-Key
- Valor: a chave secreta que gerou na secção Configure um feed no Google SecOps para carregar os registos do Azure DevOps.
- Chave:
- Header 1:
- Defina o cabeçalho Content-Type como
application/json
.
- Clique em Criar.
Tabela de mapeamento da UDM
Campo de registo | Mapeamento de UDM | Lógica |
---|---|---|
ActivityId |
metadata.product_log_id |
Mapeado diretamente a partir do campo Id no registo não processado quando o campo records não está presente ou a partir do campo ActivityId no objeto data quando records está presente. |
ActionId |
metadata.product_event_type |
Mapeado diretamente a partir do campo ActionId no objeto data . |
ActorCUID |
additional.fields |
Incluído como um campo adicional com a chave "Actor CUID". |
ActorDisplayName |
principal.user.user_display_name |
Mapeado diretamente a partir do campo ActorDisplayName se não for "Azure DevOps Service". Se for "Azure DevOps Service", é adicionado como uma etiqueta a principal.resource.attribute.labels . |
ActorUPN |
principal.user.email_addresses |
Mapeado diretamente a partir do campo ActorUPN se corresponder a um padrão de endereço de email. |
ActorUserId |
principal.user.userid |
Mapeado diretamente a partir do campo ActorUserId . |
Area |
target.application |
Usado para construir o campo target.application antepondo "DevOps " ao valor Area . |
AuthenticationMechanism |
extensions.auth.auth_details , security_result.rule_id |
Analisado para extrair os detalhes de autenticação e o ID da regra. Os detalhes de autenticação estã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 a partir do campo City . |
Conditions |
additional.fields |
Adicionado como um campo adicional com a chave "Condições". |
Country |
principal.location.country_or_region |
Mapeado diretamente a partir do campo Country . |
Data.* |
Vários | Os campos no objeto Data são mapeados para diferentes campos da UDM com base nos respetivos nomes e contexto. Veja abaixo exemplos específicos. |
Data.AccessLevel |
target.resource.attribute.labels |
Adicionada como uma etiqueta 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 adicional com a chave "ConnectionId". |
Data.ConnectionName |
additional.fields |
Adicionado como um campo adicional com a chave "ConnectionName". |
Data.ConnectionType |
additional.fields |
Adicionado como um campo adicional com a chave "ConnectionType". |
Data.DefinitionId |
additional.fields |
Adicionado como um campo adicional 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 adicional com a chave "EndpointIdList". |
Data.EnvironmentName |
additional.fields |
Adicionado como um campo adicional com a chave "EnvironmentName". |
Data.Filter.continuationToken |
target.resource.attribute.labels |
Adicionado como uma etiqueta com a chave "continuation_token". |
Data.Filter.endTime |
target.resource.attribute.labels |
Adicionado como uma etiqueta com a chave "filter_end_time". |
Data.Filter.startTime |
target.resource.attribute.labels |
Adicionado como uma etiqueta com a chave "filter_start_time". |
Data.FinishTime |
additional.fields |
Adicionado como um campo adicional 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 uma etiqueta com a chave "PipelineRevision". |
Data.PipelineScope |
target.resource.attribute.labels |
Adicionado como uma etiqueta com a chave "PipelineScope". |
Data.PlanType |
additional.fields |
Adicionado como um campo adicional com a chave "PlanType". |
Data.PreviousAccessLevel |
target.resource.attribute.labels |
Adicionada como uma etiqueta com a chave "PreviousAccessLevel". |
Data.PublisherName |
target.resource.attribute.labels |
Adicionado como uma etiqueta com a chave "PublisherName". |
Data.Reason |
additional.fields |
Adicionado como um campo adicional com a chave "Reason". |
Data.ReleaseId |
additional.fields |
Adicionado como um campo adicional com a chave "ReleaseId". |
Data.ReleaseName |
additional.fields |
Adicionado como um campo adicional 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 adicional com a chave "RetentionLeaseId". |
Data.RetentionOwnerId |
additional.fields |
Adicionado como um campo adicional com a chave "RetentionOwnerId". |
Data.RunName |
additional.fields |
Adicionado como um campo adicional com a chave "RunName". |
Data.Scopes |
target.resource.attribute.labels |
Adicionadas como etiquetas com a chave "Âmbito". |
Data.StageName |
additional.fields |
Adicionado como um campo adicional com a chave "StageName". |
Data.StartTime |
additional.fields |
Adicionado como um campo adicional 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 uma etiqueta 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 uma etiqueta com a chave "ValidFrom". |
Data.ValidTo |
target.resource.attribute.labels |
Adicionado como uma etiqueta com a chave "ValidTo". |
DewPoint |
additional.fields |
Adicionado como um campo adicional com a chave "DewPoint". |
Details |
metadata.description |
Mapeado diretamente para metadata.description . |
Humidity |
additional.fields |
Adicionado como um campo adicional com a chave "Humidade". |
Icon |
additional.fields |
Adicionado como um campo adicional 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 adicional com a chave "MoonPhase". |
Moonrise |
additional.fields |
Adicionado como um campo adicional com a chave "Moonrise". |
Moonset |
additional.fields |
Adicionado como um campo adicional com a chave "Moonset". |
OperationName |
metadata.product_event_type |
Mapeado diretamente para metadata.product_event_type . |
Precipitation |
additional.fields |
Adicionado como um campo adicional com a chave "Precipitation" (Precipitação). |
Pressure |
additional.fields |
Adicionado como um campo adicional com a chave "Pressure". |
ProjectId |
target.resource_ancestors.product_object_id |
Usado para preencher o campo product_object_id em target.resource_ancestors quando o elemento principal é 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 elemento principal é do tipo CLOUD_PROJECT . Também adicionado como etiqueta 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 elemento principal é 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 elemento principal é do tipo CLOUD_ORGANIZATION . |
ScopeType |
additional.fields |
Adicionado como um campo adicional com a chave "ScopeType". |
Sunrise |
additional.fields |
Adicionado como um campo adicional com a chave "Sunrise". |
Sunset |
additional.fields |
Adicionado como um campo adicional com a chave "Sunset". |
Temperature |
additional.fields |
Adicionado como um campo adicional com a chave "Temperatura". |
TenantId |
metadata.product_deployment_id , additional.fields |
Mapeado diretamente para metadata.product_deployment_id . Também é 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 adicional com a chave "Visibilidade". |
WindDirection |
additional.fields |
Adicionado como um campo adicional com a chave "WindDirection". |
WindSpeed |
additional.fields |
Adicionado como um campo adicional 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 noutros campos. A predefinição é "GENERIC_EVENT" se não for encontrado nenhum tipo de evento específico. 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 |
Definido como "Microsoft". |
N/A | metadata.product_name |
Definido como "Azure DevOps". |
N/A | metadata.log_type |
Definido 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 |
Definido como MICROSOFT_AZURE . |
N/A | security_result.action |
Definido como "ALLOW" para operações bem-sucedidas (Succeeded, Created, Modified, executed, updated, removed) e "BLOCK" para operações com falhas (Failed, TimedOut). |
N/A | extensions.auth.mechanism |
Definido como "USERNAME_PASSWORD" se summary for "UserAuthToken". |
N/A | target.resource.resource_type |
Definido 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, é definido como "STORAGE_BUCKET" em alguns casos com base em operationName . |
N/A | target.resource.resource_subtype |
Definido como "Pipeline" se pipeline_id estiver presente, "Token" se authorization_id estiver presente, "Agent" se agent_id estiver presente ou "Namespace" se namespace_id estiver presente. |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.