Coletar registros do GitLab
Visão geral
Esse analisador extrai campos dos registros JSON do GitLab, os normaliza no modelo de dados unificado (UDM, na sigla em inglês) e enriquece os dados com mais contexto. Ele processa vários tipos de eventos do GitLab, com foco em ações do usuário, acesso a recursos e resultados de segurança, além de processar informações relacionadas à rede e ao aplicativo. O analisador também executa a lógica com base em funções e ações no GitLab, categorizando eventos e atribuindo severidades apropriadas.
Antes de começar
- Verifique se você tem uma instância do Google SecOps.
- Verifique se você tem acesso privilegiado ao GitLab.
Configurar um feed no Google SecOps para processar os registros do GitLab
- Acesse Configurações do SIEM > Feeds.
- Clique em Adicionar novo.
- No campo Nome do feed, insira um nome para o feed (por exemplo, Logs do GitLab).
- Selecione Webhook como o Tipo de origem.
- Selecione Gitlab 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 um webhook no GitLab para o Google SecOps
- Abra o navegador da Web e acesse o projeto do GitLab para o qual você quer configurar o webhook.
- No projeto, acesse Configurações > Webhooks.
- Clique em Adicionar novo webhook.
- No campo URL, cole o URL do endpoint do Google SecOps.
- Clique em Adicionar cabeçalho personalizado.
- Digite X-Webhook-Access-Key no campo Nome do cabeçalho.
- No campo Header Value, copie a chave secreta gerada durante a configuração do feed do Google SecOps.
- Clique em Adicionar cabeçalho personalizado.
- Digite X-goog-api-key no campo Nome do cabeçalho.
- No campo Valor do cabeçalho, copie a chave de API gerada durante a configuração do feed do Google SecOps. Observação: para aumentar a segurança, gere um token secreto e adicione-o à configuração do webhook do GitLab e à configuração correspondente do feed do Google SecOps. Isso ajuda a verificar a autenticidade dos webhooks recebidos.
- Escolha os eventos do GitLab que vão acionar o webhook. Por exemplo, você pode selecionar Eventos de envio para enviar dados ao Google SecOps sempre que o código for enviado ao repositório. Considere cuidadosamente quais eventos são relevantes para suas necessidades de monitoramento de segurança. Muitos eventos podem causar uma carga desnecessária.
- Para entender melhor a finalidade dos webhooks, dê a eles um nome significativo, como Google SecOps Webhook.
- Verifique se a caixa de seleção Ativar verificação SSL está marcada. Isso é crucial para a comunicação segura.
- Clique em Adicionar webhook para salvar a configuração.
Tabela de mapeamento do UDM
Campo de registro | Mapeamento do UDM | Lógica |
---|---|---|
author_id |
principal.user.userid |
Convertido em string. |
author_name |
principal.user.email_addresses |
Se o valor corresponder a uma regex de endereço de e-mail. |
author_name |
principal.user.user_display_name |
Se o valor não corresponder a uma regex de endereço de e-mail. |
details.as |
principal.resource.attribute.labels |
Adicionado como um rótulo com a chave "as". |
details.add |
principal.resource.attribute.labels |
Adicionado como um rótulo com a chave "add". |
details.as |
principal.user.role_name |
O valor do campo de registro bruto. |
details.as |
principal.user.attribute.roles.type |
Defina como "ADMINISTRATOR" se details.as for "Proprietário", "SERVICE_ACCOUNT" se details.as for "Developer", "Maintainer" ou "Reporter" e "TYPE_UNSPECIFIED" se details.as for "Guest". |
details.custom_message |
security_result.description |
O valor do campo de registro bruto. |
details.custom_message.action |
security_result.summary |
O valor do campo de registro bruto. |
details.entity_path |
target.file.full_path |
O valor do campo de registro bruto. |
details.target_id |
target.resource.id |
Convertido em string. |
entity_path |
target.file.full_path |
O valor do campo de registro bruto. |
entity_type |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "Tipo de entidade". |
event_type |
metadata.product_event_type |
O valor do campo de registro bruto. |
insertId |
metadata.product_log_id |
O valor do campo de registro bruto. |
ip_address |
principal.ip , principal.asset.ip |
O valor do campo de registro bruto. |
jsonPayload.action |
additional.fields |
Adicionado como um campo com a chave "action" e o valor da string. |
jsonPayload.controller |
additional.fields |
Adicionado como um campo com a chave "controller" e o valor da string. |
jsonPayload.correlation_id |
principal.asset_id |
Prefixado com "id: ". |
jsonPayload.cpu_s |
additional.fields |
Adicionado como um campo com a chave "cpu_s" e o valor da string. |
jsonPayload.details.custom_message.protocol |
network.application_protocol |
É definido como "UNKNOWN_APPLICATION_PROTOCOL" se o valor for "web". Caso contrário, será convertido em letras maiúsculas. Também é adicionado como um campo extra com a chave "Protocolo do aplicativo" se o valor for "web". |
jsonPayload.mem_total_bytes |
additional.fields |
Adicionado como um campo com a chave "mem_total_bytes" e o valor da string. |
jsonPayload.meta_caller_id |
additional.fields |
Adicionado como um campo com a chave "ID do autor da chamada" e o valor da string. |
jsonPayload.meta_client_id |
target.user.userid |
O valor do campo de registro bruto. |
jsonPayload.meta_feature_category |
additional.fields |
Adicionado como um campo com a chave "Categoria de recurso" e o valor da string. |
jsonPayload.meta_remote_ip |
principal.ip , principal.asset.ip |
O valor do campo de registro bruto, analisado como uma matriz JSON e mesclado nos campos de IP. |
jsonPayload.meta_user |
principal.user.userid |
Usado como fallback se jsonPayload.username estiver vazio. |
jsonPayload.method |
network.http.method |
O valor do campo de registro bruto. |
jsonPayload.path |
target.process.file.full_path |
O valor do campo de registro bruto. |
jsonPayload.pid |
target.process.pid |
Convertido em string. |
jsonPayload.remote_ip |
principal.ip , principal.asset.ip |
O valor do campo de registro bruto. |
jsonPayload.request_urgency |
additional.fields |
Adicionado como um campo com a chave "Urgência da solicitação" e o valor da string. |
jsonPayload.severity |
security_result.severity |
Defina como "INFORMATIONAL" se o valor for "INFO", "ERROR" se o valor for "ERROR" e "MEDIUM" se o valor for "NOTICE". |
jsonPayload.status |
network.http.response_code |
Convertido em número inteiro se não for "ACTIVE". |
jsonPayload.ua |
network.http.user_agent |
O valor do campo de registro bruto. |
jsonPayload.username |
principal.user.userid |
O valor do campo de registro bruto. |
jsonPayload.worker_id |
principal.application |
O valor do campo de registro bruto. |
labels.instance_name |
principal.hostname , principal.asset.hostname |
O valor do campo de registro bruto, usado se a mensagem contiver "Removendo usuário". |
logName |
security_result.category_details |
O valor do campo de registro bruto. |
message |
security_result.summary |
O valor do campo de registro bruto, usado se jsonPayload.severity for "ERROR". |
protoPayload.@type |
additional.fields |
Adicionado como um campo com a chave "protoPayload type" e o valor de string. |
protoPayload.authenticationInfo.principalEmail |
principal.user.email_addresses , principal.user.userid |
O valor do campo de registro bruto. |
protoPayload.authenticationInfo.principalSubject |
additional.fields |
Adicionado como um campo com a chave "authenticationInfo principalSubject" e o valor da string. |
protoPayload.authenticationInfo.serviceAccountKeyName |
additional.fields |
Adicionado como um campo com a chave "authenticationInfo serviceAccountKeyName" e o valor da string. |
protoPayload.authorizationInfo |
target.resource.attribute.labels , security_result.action |
Os valores neste campo são adicionados como rótulos com chaves prefixadas com "authenticationInfo". O security_result.action é definido como "ALLOW" se um valor em granted for verdadeiro e como "BLOCK" se for falso. Campos aninhados, como resourceAttributes , também são adicionados como rótulos com chaves prefixadas com "authenticationInfo_resourceAttributes". |
protoPayload.methodName |
additional.fields |
Adicionado como um campo com a chave "protoPayload methodName" e o valor da string. |
protoPayload.request.@type |
additional.fields |
Adicionado como um campo com a chave "Request Type" e o valor da string. |
protoPayload.request.resource |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "Recurso de solicitação". |
protoPayload.requestMetadata.callerIp |
additional.fields |
Adicionado como um campo com a chave "requestMetadata callerIp" e o valor da string. |
protoPayload.requestMetadata.callerSuppliedUserAgent |
additional.fields |
Adicionado como um campo com a chave "requestMetadata callerSuppliedUserAgent" e o valor da string. |
protoPayload.serviceName |
additional.fields |
Adicionado como um campo com a chave "serviceName" e o valor da string. |
protoPayload.status.code |
additional.fields |
Adicionado como um campo com a chave "protoPayload status code" e o valor da string. |
protoPayload.status.message |
additional.fields , target.user.email_addresses , target.user.userid |
Adicionado como um campo com a chave "protoPayload status message" e o valor da string. Se um endereço de e-mail puder ser extraído da mensagem, ele será adicionado a target.user.email_addresses e target.user.userid . |
receiveTimestamp |
metadata.event_timestamp , timestamp |
Analisado como o carimbo de data/hora do evento. |
resource.labels.project_id |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "ID do projeto". |
resource.labels.zone |
target.cloud.availability_zone |
O valor do campo de registro bruto. |
resource.type |
target.cloud.environment |
Defina como "GOOGLE_CLOUD_PLATFORM" se o valor corresponder a "gce". |
security_result.action |
security_result.action |
Derivado de protoPayload.authorizationInfo.granted . |
security_result.category_details |
security_result.category_details |
Mesclado com logName . |
security_result.description |
security_result.description |
Derivado de jsonPayload.details.custom_message . |
security_result.severity |
security_result.severity |
Derivado de severity ou jsonPayload.severity . |
security_result.summary |
security_result.summary |
Derivado de jsonPayload.details.custom_message.action ou jsonPayload.message . |
severity |
security_result.severity |
Defina como "INFORMATIONAL" se o valor for "INFO", "ERROR" se o valor for "ERROR" e "MEDIUM" se o valor for "NOTICE". |
sourceLocation |
principal.resource.attribute.labels |
Os valores nesse campo são adicionados como rótulos. |
target_details |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "Target Details". |
target_type |
target.resource.attribute.labels |
Adicionado como um rótulo com a chave "tipo de destino". |
timestamp |
timestamp |
O valor do campo de registro bruto. É definido com base na presença de campos principais e de destino. O padrão é "GENERIC_EVENT" se nenhuma condição específica for atendida. Os valores possíveis são "USER_RESOURCE_UPDATE_CONTENT", "USER_RESOURCE_ACCESS" e "USER_UNCATEGORIZED". Defina como "GITLAB". Defina como "GITLAB". |
Alterações
2024-04-08
- "custom_message.action" foi associado a "security_result.summary".
- "ip_address" foi mapeado para "principal.ip".
- "applicationProtocol" foi mapeado para "network.application_protocol".
- "details.author_name" foi associado a "principal.user.email_addresses"
- "author_id" foi associado a "principal.user.userid".
- "target_id" foi mapeado para "target.resource.id".
- "details.entity_path" foi mapeado para "target.file.full_path".
- "event_type" foi associado a "product_event_type".
- Mapeamos "target_type", "entity_type" e "target_details" para "resource.attribute.labels".
2023-10-20
- Mapeou os campos que começam com "db_" para "additional_fields".
- Os campos que começam com "redis_" foram mapeados para "additional_fields".
- Mapeou "severity" ou "jsonPayload.severity" para "security_result.severity" quando o valor é "ERROR" ou "NOTICE".
- "jsonPayload.correlation_id" foi mapeado para "principal.asset_id".
- Os campos "unmapped fields of jsonPayload" foram mapeados para "additional_fields".
- "jsonPayload.worker_id" foi mapeado para "principal.application".
- "jsonPayload.method" foi mapeado para "network.http.method".
- "jsonPayload.pid" foi mapeado para "target.process.pid".
- "jsonPayload.status" foi mapeado para "network.http.response_code".
- "resource.labels.zone" foi mapeado para "target.cloud.availability_zone".
- "resource.type" foi mapeado para "target.cloud.environment".
- "jsonPayload.meta_user" foi associado a "target.user.userid".
- "jsonPayload.username" foi mapeado para "principal.user.userid".
- "jsonPayload.remote_ip" foi mapeado para "principal.ip".
- "jsonPayload.ua" foi associado a "network.http.user_agent".
- "jsonPayload.meta_client_id" foi mapeado para "target.user.userid".
- "jsonPayload.path" foi mapeado para "target.process.file.full_path".
- "protoPayload.authenticationInfo.principalEmail" foi associado a "principal.user.email_addresses".
- Os campos adicionais em "protoPayload" foram mapeados para "additional.fields".
- Fornece uma verificação condicional de que o mapeamento necessário está presente antes de mapear "metadata.event_type".
2023-10-10
- "jsonPayload.details.as" foi associado a "principal.resource.attribute.labels" e "principal.user.role_name".
- Defina "principal_role.type" como "ADMINISTRATOR" para registros com "jsonPayload.details.as" igual a "Proprietário".
- Defina "principal_role.type" como "SERVICE_ACCOUNT" para registros com "jsonPayload.details.as" definido como "Developer", "Maintainer" ou "Reporter".
- Defina "principal_role.type" como "TYPE_UNSPECIFIED" para registros com "jsonPayload.details.as" igual a "Guest".
- "jsonPayload.details.add" foi mapeado para "principal.resource.attribute.labels".
- "jsonPayload.entity_type" foi mapeado para "target.resource.attribute.labels".
2023-08-31
- Parser recém-criado.