Coletar registros do Akamai Cloud Monitor

Compatível com:

Este documento explica como ingerir registros do Akamai Cloud Monitor (balanceador de carga, modelador de tráfego, ADC) no Google Security Operations usando o AWS S3. A Akamai envia eventos JSON para seu endpoint HTTPS. Um receptor API Gateway + Lambda grava os eventos no S3 (JSONL, gz). O analisador transforma os registros JSON em UDM. Ele extrai campos do payload JSON, realiza conversões de tipo de dados, renomeia campos para corresponder ao esquema da UDM e processa lógica específica para campos personalizados e construção de URL. Ele também incorpora tratamento de erros e lógica condicional com base na presença de campos.

Antes de começar

Verifique se você tem os pré-requisitos a seguir:

  • Instância do Google SecOps
  • Acesso privilegiado ao Akamai Control Center e ao Property Manager.
  • Acesso privilegiado à AWS (S3, IAM, Lambda, API Gateway)

Configurar o bucket do AWS S3 e o IAM para o Google SecOps

  1. Crie um bucket do Amazon S3 seguindo este guia do usuário: Como criar um bucket
  2. Salve o Nome e a Região do bucket para referência futura (por exemplo, akamai-cloud-monitor).
  3. Crie um usuário seguindo este guia: Como criar um usuário do IAM.
  4. Selecione o usuário criado.
  5. Selecione a guia Credenciais de segurança.
  6. Clique em Criar chave de acesso na seção Chaves de acesso.
  7. Selecione Serviço de terceiros como o Caso de uso.
  8. Clique em Próxima.
  9. Opcional: adicione uma tag de descrição.
  10. Clique em Criar chave de acesso.
  11. Clique em Fazer o download do arquivo CSV para salvar a chave de acesso e a chave de acesso secreta para uso posterior.
  12. Clique em Concluído.
  13. Selecione a guia Permissões.
  14. Clique em Adicionar permissões na seção Políticas de permissões.
  15. Selecione Adicionar permissões.
  16. Selecione Anexar políticas diretamente.
  17. Pesquise e selecione a política AmazonS3FullAccess.
  18. Clique em Próxima.
  19. Clique em Adicionar permissões

Configurar a política e o papel do IAM para uploads do S3 (Lambda)

  1. No console da AWS, acesse IAM > Políticas > Criar política > JSON e cole a política abaixo.
  2. Política JSON (substitua akamai-cloud-monitor pelo nome do seu bucket do S3):

    {
    "Version": "2012-10-17",
    "Statement": [
        {
        "Sid": "AllowPutAkamaiObjects",
        "Effect": "Allow",
        "Action": ["s3:PutObject"],
        "Resource": "arn:aws:s3:::akamai-cloud-monitor/*"
        }
    ]
    }
    
  3. Clique em Próxima > Criar política.

  4. Acesse IAM > Funções > Criar função > Serviço da AWS > Lambda.

  5. Anexe a política JSON.

  6. Nomeie a função como WriteAkamaiCMToS3Role e clique em Criar função.

Criar a função Lambda

Configuração Valor
Nome akamai_cloud_monitor_to_s3
Ambiente de execução Python 3.13
Arquitetura x86_64
Função de execução WriteAkamaiCMToS3Role
  1. Depois que a função for criada, abra a guia Código, exclua o stub e insira o seguinte código (akamai_cloud_monitor_to_s3.py):

    #!/usr/bin/env python3
    # Lambda: Receive Akamai Cloud Monitor POST, write JSONL (gz) to S3
    
    import os, json, gzip, io, uuid, base64, datetime as dt
    import boto3
    
    S3_BUCKET  = os.environ["S3_BUCKET_NAME"]
    S3_PREFIX  = os.environ.get("S3_PREFIX", "akamai/cloud-monitor/json/").strip("/") + "/"
    INGEST_TOKEN = os.environ.get("INGEST_TOKEN")  # optional shared secret in URL query (?token=...)
    
    s3 = boto3.client("s3")
    
    def _write_jsonl_gz(objs: list) -> str:
        key = f"{dt.datetime.utcnow():%Y/%m/%d}/akamai-cloud-monitor-{uuid.uuid4()}.json.gz"
        buf = io.BytesIO()
        with gzip.GzipFile(fileobj=buf, mode="w") as gz:
            for o in objs:
                gz.write((json.dumps(o, separators=(",", ":")) + "n").encode())
        buf.seek(0)
        s3.upload_fileobj(
            buf,
            S3_BUCKET,
            f"{S3_PREFIX}{key}",
            ExtraArgs={
                "ContentType": "application/json",
                "ContentEncoding": "gzip",
            },
        )
        return f"s3://{S3_BUCKET}/{S3_PREFIX}{key}"
    
    def _parse_records_from_event(event) -> list:
        # HTTP API (Lambda proxy) event: body is a JSON string
        body = event.get("body") or ""
        if event.get("isBase64Encoded"):
            body = base64.b64decode(body).decode("utf-8", "replace")
        try:
            data = json.loads(body)
        except Exception:
            # accept line-delimited JSON as pass-through
            try:
                return [json.loads(line) for line in body.splitlines() if line.strip()]
            except Exception:
                return []
        if isinstance(data, list):
            return data
        if isinstance(data, dict):
            return [data]
        return []
    
    def lambda_handler(event, context=None):
        # Optional shared-secret verification via query parameter (?token=...)
        if INGEST_TOKEN:
            qs = event.get("queryStringParameters") or {}
            token = qs.get("token")
            if token != INGEST_TOKEN:
                return {"statusCode": 403, "body": "forbidden"}
    
        records = _parse_records_from_event(event)
        if not records:
            return {"statusCode": 204, "body": "no content"}
    
        key = _write_jsonl_gz(records)
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"ok": True, "s3_key": key, "count": len(records)}),
        }
    
  2. Acesse Configuração > Variáveis de ambiente > Editar.

  3. Clique em Adicionar nova variável de ambiente e defina os seguintes valores:

    Variáveis de ambiente

    Chave Exemplo
    S3_BUCKET_NAME akamai-cloud-monitor
    S3_PREFIX akamai/cloud-monitor/json/
    INGEST_TOKEN random-shared-secret
  4. Acesse Configuração > Configuração geral.

  5. Clique em Editar e defina Tempo limite como 5 minutos (300 segundos).

  6. Clique em Salvar.

Criar o Amazon API Gateway (endpoint HTTPS para Akamai)

  1. No console da AWS, acesse API Gateway > Criar API.
  2. Selecione API HTTP > Build.
  3. Informe os seguintes detalhes de configuração:
    • Integrações: escolha Lambda e selecione akamai_cloud_monitor_to_s3.
    • Rotas: adicione ANY /{proxy+} ou crie uma rota específica (por exemplo, POST /akamai/cloud-monitor).
    • Etapas: crie ou use $default.
  4. Implante a API e copie o URL de invocação (por exemplo, https://abc123.execute-api.<region>.amazonaws.com).

Configurar o Akamai Cloud Monitor para enviar registros

  1. No Akamai Control Center, abra sua Propriedade no Property Manager.
  2. Clique em Adicionar regra > escolha Gerenciamento na nuvem.
  3. Adicione Instrumentação do Cloud Monitoring e selecione os Conjuntos de dados necessários.
  4. Adicione Entrega de dados do Cloud Monitoring.
    • Nome do host de entrega: insira o URL de invocação do API Gateway (por exemplo, abc123.execute-api.<region>.amazonaws.com).
    • Caminho do URL de exibição: sua rota mais um token de consulta opcional, por exemplo: /akamai/cloud-monitor?token=<INGEST_TOKEN>.
  5. Salve e ative a versão da propriedade.

Configurar um feed no Google SecOps para ingerir o Akamai Cloud Monitor (JSON do S3)

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. No campo Nome do feed, insira um nome para o feed (por exemplo, Akamai Cloud Monitor — S3).
  4. Selecione Amazon S3 V2 como o Tipo de origem.
  5. Selecione Akamai Cloud Monitor como o Tipo de registro.
  6. Clique em Próxima.
  7. Especifique valores para os seguintes parâmetros de entrada:
    • URI do S3: s3://akamai-cloud-monitor/akamai/cloud-monitor/json/
    • Opções de exclusão de origem: se você quer excluir arquivos e/ou diretórios após a transferência.
    • Idade máxima do arquivo: inclui arquivos modificados no último número de dias. O padrão é de 180 dias.
    • ID da chave de acesso: uma chave de acesso alfanumérica de 20 caracteres (por exemplo, AKIAIOSFODNN7EXAMPLE).
    • Chave de acesso secreta: uma chave de acesso secreta alfanumérica de 40 caracteres (por exemplo, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY).
    • Namespace do recurso: akamai.cloud_monitor
    • Rótulos de ingestão: são adicionados a todos os eventos desse feed (por exemplo, source=akamai_cloud_monitor, format=json).
  8. Clique em Próxima.
  9. Revise a nova configuração do feed na tela Finalizar e clique em Enviar.

Tabela de mapeamento do UDM

Campo de registro Mapeamento do UDM Lógica
accLang network.http.user_agent Mapeado diretamente se não for "-" ou uma string vazia.
city principal.location.city Mapeado diretamente se não for "-" ou uma string vazia.
cliIP principal.ip Mapeado diretamente se não for uma string vazia.
country principal.location.country_or_region Mapeado diretamente se não for "-" ou uma string vazia.
cp additional.fields Mapeado como um par de chave-valor com a chave "cp".
customField about.ip, about.labels, src.ip Analisados como pares de chave-valor. Tratamento especial para "eIp" e "pIp" para mapear para src.ip e about.ip, respectivamente. Outras chaves são mapeadas como rótulos em about.
errorCode security_result.summary, security_result.severity Se presente, define security_result.severity como "ERROR" e mapeia o valor para security_result.summary.
geo.city principal.location.city Mapeado diretamente se city for "-" ou uma string vazia.
geo.country principal.location.country_or_region Mapeado diretamente se country for "-" ou uma string vazia.
geo.lat principal.location.region_latitude Mapeado diretamente, convertido em ponto flutuante.
geo.long principal.location.region_longitude Mapeado diretamente, convertido em ponto flutuante.
geo.region principal.location.state Mapeado diretamente.
id metadata.product_log_id Mapeado diretamente se não for uma string vazia.
message.cliIP principal.ip Mapeado diretamente se cliIP for uma string vazia.
message.fwdHost principal.hostname Mapeado diretamente.
message.reqHost target.hostname, target.url Usado para criar target.url e extrair target.hostname.
message.reqLen network.sent_bytes Mapeado diretamente, convertido em número inteiro sem sinal se totalBytes estiver vazio ou for "-".
message.reqMethod network.http.method Mapeado diretamente se reqMethod for uma string vazia.
message.reqPath target.url Adicionado a target.url.
message.reqPort target.port Mapeado diretamente, convertido em número inteiro se reqPort for uma string vazia.
message.respLen network.received_bytes Mapeado diretamente, convertido para número inteiro sem sinal.
message.sslVer network.tls.version Mapeado diretamente.
message.status network.http.response_code Mapeado diretamente, convertido em número inteiro se statusCode estiver vazio ou for "-".
message.UA network.http.user_agent Mapeado diretamente se UA for "-" ou uma string vazia.
network.asnum additional.fields Mapeado como um par de chave-valor com a chave "asnum".
network.edgeIP intermediary.ip Mapeado diretamente.
network.network additional.fields Mapeado como um par de chave-valor com a chave "network".
network.networkType additional.fields Mapeado como um par de chave-valor com a chave "networkType".
proto network.application_protocol Usado para determinar network.application_protocol.
queryStr target.url Adicionado a target.url se não for "-" ou uma string vazia.
referer network.http.referral_url, about.hostname Mapeado diretamente se não for "-". O nome do host extraído é mapeado para about.hostname.
reqHost target.hostname, target.url Usado para criar target.url e extrair target.hostname.
reqId metadata.product_log_id, network.session_id Mapeado diretamente se id for uma string vazia. Também mapeado para network.session_id.
reqMethod network.http.method Mapeado diretamente se não for uma string vazia.
reqPath target.url Adicionado a target.url se não for "-".
reqPort target.port Mapeado diretamente, convertido em número inteiro.
reqTimeSec metadata.event_timestamp, timestamp Usado para definir o carimbo de data/hora do evento.
start metadata.event_timestamp, timestamp Usado para definir o carimbo de data/hora do evento se reqTimeSec for uma string vazia.
statusCode network.http.response_code Mapeado diretamente, convertido em número inteiro se não for "-" ou uma string vazia.
tlsVersion network.tls.version Mapeado diretamente.
totalBytes network.sent_bytes Mapeado diretamente, convertido em número inteiro sem sinal se não estiver vazio ou "-".
type metadata.product_event_type Mapeado diretamente.
UA network.http.user_agent Mapeado diretamente se não for "-" ou uma string vazia.
version metadata.product_version Mapeado diretamente.
xForwardedFor principal.ip Mapeado diretamente se não for "-" ou uma string vazia.
(Lógica do analisador) metadata.vendor_name Defina como "Akamai".
(Lógica do analisador) metadata.product_name Defina como "DataStream".
(Lógica do analisador) metadata.event_type Defina como "NETWORK_HTTP".
(Lógica do analisador) metadata.product_version Defina como "2" se version for uma string vazia.
(Lógica do analisador) metadata.log_type Defina como "AKAMAI_CLOUD_MONITOR".
(Lógica do analisador) network.application_protocol Determinado por proto ou message.proto. Defina como "HTTPS" se um dos dois contiver "HTTPS" (sem diferenciação de maiúsculas e minúsculas) ou "HTTP" caso contrário.
(Lógica do analisador) security_result.severity Defina como "INFORMATIONAL" se errorCode for "-" ou uma string vazia.
(Lógica do analisador) target.url Construído com base em protocol, reqHost (ou message.reqHost), reqPath (ou message.reqPath) e queryStr.

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.