Coletar registros do Google App Engine

Compatível com:

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

  1. Acesse o Console do Google Cloud.
  2. Selecione seu projeto ou crie um novo.
  3. No menu de navegação, acesse Cloud Storage > Buckets.
  4. Clique em Criar bucket.
  5. 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
  6. 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

  1. No Console do Google Cloud, acesse Logging > Roteador de registros.
  2. Clique em Criar coletor.
  3. 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.
  4. Clique em Próxima.
  5. 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-export no menu suspenso.
  6. Clique em Próxima.
  7. 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_ID pelo ID do projeto do GCP.

  8. Clique em Próxima.

  9. 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

  1. Na página Roteador de registros, localize o coletor recém-criado.
  2. Clique no ícone de menu (três pontos verticais) ao lado do nome do coletor.
  3. Selecione Ver detalhes do coletor.
  4. Copie a Identidade do gravador (e-mail da conta de serviço).
  5. Acesse Cloud Storage > Buckets.
  6. Clique no nome do bucket (appengine-logs-export).
  7. Acesse a guia Permissões.
  8. Clique em Conceder acesso.
  9. 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.
  10. 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

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Clique em Configurar um único feed.
  4. No campo Nome do feed, insira um nome para o feed (por exemplo, App Engine Logs).
  5. Selecione Google Cloud Storage V2 como o Tipo de origem.
  6. Selecione GCP_APP_ENGINE como o Tipo de registro.

  7. Clique em Receber conta de serviço.

  8. Um e-mail exclusivo da conta de serviço será exibido, por exemplo:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  9. Copie o endereço de e-mail. Você vai usá-la na próxima etapa.

  10. Clique em Próxima.

  11. 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.

  12. Clique em Próxima.

  13. 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.

  1. Acesse Cloud Storage > Buckets.
  2. Clique no nome do bucket (appengine-logs-export).
  3. Acesse a guia Permissões.
  4. Clique em Conceder acesso.
  5. 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.
  6. 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.