Coletar registros do Google App Engine
Este documento explica como ingerir registros do Google App Engine no Google Security Operations usando o Google Cloud Storage V2.
O Google App Engine é uma plataforma sem servidor totalmente gerenciada para criar e implantar aplicativos da Web e APIs. O App Engine gera automaticamente registros de solicitação para solicitações HTTP e registros de aplicativo do seu código. Esses registros são enviados ao Cloud Logging e podem ser exportados para o Cloud Storage para ingestão no Google Security Operations.
Antes de começar
Verifique se você atende os seguintes pré-requisitos:
- Uma instância do Google SecOps
- Um projeto do GCP com a API Cloud Storage ativada
- Permissões para criar e gerenciar buckets do GCS
- Permissões para gerenciar políticas do IAM em buckets do GCS
- Permissões para criar coletores do Cloud Logging (roles/logging.configWriter)
- Um aplicativo do App Engine ativo (ambiente padrão ou flexível)
Criar um bucket do Google Cloud Storage
- Acesse o Console do Google Cloud.
- Selecione seu projeto ou crie um novo.
- No menu de navegação, acesse Cloud Storage > Buckets.
- Clique em Criar bucket.
Informe os seguintes detalhes de configuração:
Configuração Valor Nomeie seu bucket Insira um nome exclusivo globalmente, por exemplo, appengine-logs-export.Tipo de local Escolha com base nas suas necessidades (região, birregional, multirregional) Local Selecione o local (por exemplo, us-central1).Classe de armazenamento Padrão (recomendado para registros acessados com frequência) Controle de acesso Uniforme (recomendado) Ferramentas de proteção Opcional: ativar o controle de versões de objetos ou a política de retenção Clique em Criar.
Configurar o Cloud Logging para exportar registros do App Engine para o GCS
O Cloud Logging usa coletores de registros para encaminhar entradas de registro para destinos compatíveis, incluindo buckets do Cloud Storage. A identidade do gravador do coletor exige o papel de criador de objetos do Storage (roles/storage.objectCreator) no bucket de destino.
Criar um coletor do Cloud Logging
- No Console do Google Cloud, acesse Logging > Roteador de registros.
- Clique em Criar coletor.
- Informe os seguintes detalhes de configuração:
- Nome do coletor: insira um nome descritivo (por exemplo,
appengine-to-gcs). - Descrição do coletor: descrição opcional.
- Nome do coletor: insira um nome descritivo (por exemplo,
- Clique em Próxima.
- Na seção Selecionar serviço do coletor:
- Serviço de coletor: selecione Bucket do Cloud Storage.
- Selecionar bucket do Cloud Storage: selecione
appengine-logs-exportno menu suspenso.
- Clique em Próxima.
Na seção Escolher registros para incluir no coletor, insira uma consulta de filtro para selecionar os registros do App Engine. O tipo de recurso precisa ser exatamente "gae_app".
Para todos os registros do App Engine (de solicitação e de aplicativo):
resource.type="gae_app"Somente para registros de solicitação do App Engine:
resource.type="gae_app" logName="projects/PROJECT_ID/logs/appengine.googleapis.com/request_log"Para registros de aplicativos do App Engine (stdout/stderr):
resource.type="gae_app" (logName="projects/PROJECT_ID/logs/stdout" OR logName="projects/PROJECT_ID/logs/stderr")Substitua
PROJECT_IDpelo ID do projeto do GCP.Clique em Próxima.
Revise a configuração e clique em Criar coletor.
Conceder permissões à identidade de gravador do coletor
Depois de criar o coletor, conceda à identidade do gravador o papel de criador de objetos do Storage no bucket de destino. A identidade do gravador da conta de serviço é semelhante a: serviceAccount:service-123456789012@gcp-sa-logging.iam.gserviceaccount.com
- Na página Roteador de registros, localize o coletor recém-criado.
- Clique no ícone de menu (três pontos verticais) ao lado do nome do coletor.
- Selecione Ver detalhes do coletor.
- Copie a Identidade do gravador (e-mail da conta de serviço).
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket (
appengine-logs-export). - Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar principais: cole a identidade do gravador do coletor (e-mail da conta de serviço).
- Atribuir papéis: selecione Criador de objetos do Storage.
- Clique em Salvar.
Recuperar a conta de serviço do Google SecOps
O Google SecOps usa uma conta de serviço exclusiva para ler dados do seu bucket do GCS. Você precisa conceder a essa conta de serviço acesso ao seu bucket.
Configurar um feed no Google SecOps para ingerir registros do App Engine
- Acesse Configurações do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Clique em Configurar um único feed.
- No campo Nome do feed, insira um nome para o feed (por exemplo,
App Engine Logs). - Selecione Google Cloud Storage V2 como o Tipo de origem.
Selecione GCP_APP_ENGINE como o Tipo de registro.
Clique em Receber conta de serviço.
Um e-mail exclusivo da conta de serviço será exibido, por exemplo:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comCopie o endereço de e-mail. Você vai usá-la na próxima etapa.
Clique em Próxima.
Especifique valores para os seguintes parâmetros de entrada:
URL do bucket de armazenamento: insira o URI do bucket do GCS com o caminho do prefixo:
gs://appengine-logs-export/O Cloud Logging organiza os arquivos de registro exportados em hierarquias de diretório por tipo de registro e data. O tipo de registro pode ser um nome composto, como appengine.googleapis.com/request_log. Os arquivos são fragmentados e nomeados com períodos (por exemplo, 08:00:00_08:59:59_S0.json).
Opção de exclusão da fonte: selecione a opção de exclusão de acordo com sua preferência:
- Nunca: nunca exclui arquivos após as transferências (recomendado para testes).
- Excluir arquivos transferidos: exclui os arquivos após a transferência bem-sucedida.
- Excluir arquivos transferidos e diretórios vazios: exclui arquivos e diretórios vazios após a transferência bem-sucedida.
Idade máxima do arquivo: inclui arquivos modificados no último número de dias. O padrão é de 180 dias.
Namespace do recurso: o namespace do recurso.
Rótulos de ingestão: o rótulo a ser aplicado aos eventos deste feed.
Clique em Próxima.
Revise a nova configuração do feed na tela Finalizar e clique em Enviar.
Conceder permissões do IAM à conta de serviço do Google SecOps
A conta de serviço do Google SecOps precisa do papel de Leitor de objetos do Storage no seu bucket do GCS.
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket (
appengine-logs-export). - Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar participantes: cole o e-mail da conta de serviço do Google SecOps.
- Atribuir papéis: selecione Leitor de objetos do Storage.
Clique em Salvar.
Noções básicas sobre a estrutura de registros do App Engine
O App Engine envia automaticamente os registros de solicitação e de aplicativos para o Cloud Logging. O App Engine emite registros automaticamente para solicitações enviadas ao aplicativo. Portanto, não é necessário gravar registros de solicitação. Esta seção aborda como gravar registros de apps.
Os registros de solicitação do App Engine têm entradas de registro que contêm campos protoPayload com objetos do tipo RequestLog com @type "type.googleapis.com/google.appengine.logging.v1.RequestLog". O tipo de recurso é "gae_app".
Por padrão, o payload do registro é uma string de texto armazenada no campo textPayload da entrada de registro. As strings aparecem como mensagens no Explorador de registros e são associadas ao serviço e à versão do App Engine que as emitiu.
Para gravar registros estruturados, escreva os registros em uma única linha de JSON serializado. Quando você fornece um registro estruturado como um dicionário JSON, alguns campos especiais são removidos do jsonPayload e gravados no campo correspondente no LogEntry gerado. Por exemplo, se o JSON incluir uma propriedade de gravidade, ela será removida do jsonPayload e aparecerá como a gravidade da entrada de registro.
Limitações conhecidas
Quando você encaminha registros do coletor de registros para o Cloud Storage, o destino do Cloud Storage contém apenas registros de solicitação. O App Engine grava os registros de aplicativos em pastas diferentes.
As entradas de registro encaminhadas são salvas em lotes a cada hora nos buckets do Cloud Storage. Pode ser necessário aguardar de duas a três horas até que as primeiras entradas comecem a aparecer.
No ambiente flexível do App Engine, a geração de registros funciona automaticamente. No entanto, os registros são coletados em um formato diferente. Os registros não serão agrupados por solicitações, e os registros de stdout e stderr serão coletados separadamente.
Tabela de mapeamento do UDM
| Campo de registro | Mapeamento do UDM | Lógica |
|---|---|---|
| jsonPayload.logger, taskTypeName, jsonPayload.@type, jsonPayload.backendTargetProjectNumber, jsonPayload.cacheDecision, resource.labels.version_id, resource.labels.module_id, logName, spanId, trace, protoPayload.@type, labels.clone_id, operation.producer | additional.fields | Combinados com rótulos de valor-chave criados em cada campo |
| metadados | metadados | Renomeado de metadados |
| receiveTimestamp | metadata.collected_timestamp | Analisado usando o filtro de data com RFC3339 |
| metadata.event_type | Definido como "USER_LOGIN" se has_principal, has_target, has_principal_user; "NETWORK_CONNECTION" se has_principal e has_target; "USER_UNCATEGORIZED" se não has_principal e has_target; "STATUS_UPDATE" se has_principal; "USER_UNCATEGORIZED" se has_principal_user; caso contrário, "GENERIC_EVENT" | |
| metadata.extensions.auth.type | Defina como "AUTHTYPE_UNSPECIFIED" se has_principal, has_target, has_principal_user | |
| insertId | metadata.product_log_id | Valor copiado diretamente |
| httpRequest.requestMethod,protoPayload.method | network.http.method | Valor de httpRequest.requestMethod se não estiver vazio, caso contrário, protoPayload.method |
| httpRequest.userAgent | network.http.parsed_user_agent | Convertido para parseduseragent |
| httpRequest.status | network.http.response_code | Convertido para string e depois para número inteiro |
| httpRequest.userAgent | network.http.user_agent | Valor copiado diretamente |
| httpRequest.responseSize | network.received_bytes | Convertido para uinteger |
| httpRequest.requestSize | network.sent_bytes | Convertido para uinteger |
| participante | participante | Renomeado de principal se não estiver vazio |
| protoPayload.host | principal.asset.hostname | Valor copiado diretamente |
| httpRequest.serverIp, protoPayload.ip | principal.asset.ip | Mesclado com server_ip de httpRequest.serverIp ou protoPayload.ip |
| protoPayload.host | principal.hostname | Valor copiado diretamente |
| httpRequest.serverIp, protoPayload.ip | principal.ip | Mesclado com server_ip de httpRequest.serverIp ou protoPayload.ip |
| protoPayload.appId | principal.resource.attribute.labels | Mesclado com appId_label contendo a chave "appId" e o valor do campo |
| requestUser | principal.user.email_addresses | Mesclado com requestUser se corresponder ao padrão de e-mail |
| security_result | security_result | Mesclado de security_result |
| resource.labels.forwarding_rule_name | security_result.rule_labels | Unido a "rule_label", que contém a chave "forwarding_rule_name" e o valor do campo |
| gravidade, | security_result.severity | Definido como "severity" se corresponder a (?i)ERROR|CRITICAL, "INFORMATIONAL" se corresponder a (?i)INFO, "MEDIUM" se corresponder a (?i)WARN, "LOW" se corresponder a (?i)DEBUG ou "UNKNOWN_SEVERITY" |
| jsonPayload.statusDetails | security_result.summary | Valor copiado diretamente |
| target | target | Renomeado da meta se não estiver vazio |
| resource.labels.backend_service_name | target.application | Valor copiado diretamente |
| httpRequest.remoteIp, jsonPayload.remoteIp | target.asset.ip | Mesclado com remote_ip extraído de httpRequest.remoteIp ou jsonPayload.remoteIp |
| resource.labels.project_id | target.cloud.project.name | Valor copiado diretamente |
| httpRequest.remoteIp, jsonPayload.remoteIp | target.ip | Mesclado com remote_ip extraído de httpRequest.remoteIp ou jsonPayload.remoteIp |
| resource.labels.zone | target.resource.attribute.cloud.availability_zone | Valor copiado diretamente |
| resource.labels.target_proxy_name, resource.labels.url_map_name | target.resource.attribute.labels | Combinados com rótulos de cada fonte |
| resource.type | target.resource.type | Valor copiado diretamente |
| httpRequest.requestUrl | target.url | Valor copiado diretamente |
| metadata.product_name | Defina como "GCP_APP_ENGINE" | |
| metadata.vendor_name | Defina como "GCP". |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.