Coletar registros do Cisco AMP para Endpoints

Compatível com:

Este documento explica como ingerir registros do Cisco AMP for Endpoints no Google Security Operations usando o Amazon S3. O analisador transforma registros brutos formatados em JSON em um formato estruturado de acordo com o UDM do Chronicle. Ele extrai campos de objetos JSON aninhados, mapeia-os para o esquema UDM, identifica categorias de eventos, atribui níveis de gravidade e gera uma saída de evento unificada, sinalizando alertas de segurança quando condições específicas são atendidas.

Antes de começar

  • Uma instância do Google SecOps
  • Acesso privilegiado ao console do Cisco AMP for Endpoints.
  • Acesso privilegiado à AWS (S3, IAM, Lambda, EventBridge)

Coletar os pré-requisitos do Cisco AMP for Endpoints (IDs, chaves de API, IDs da organização, tokens)

  1. Faça login no console do Cisco AMP for Endpoints.
  2. Acesse Contas > Credenciais da API.
  3. Clique em Nova credencial de API para criar uma chave de API e um ID do cliente.
  4. Informe os seguintes detalhes de configuração:
    • Nome do aplicativo: insira um nome (por exemplo, Chronicle SecOps Integration).
    • Escopo: selecione Somente leitura para sondagem básica de eventos ou Leitura e gravação se você planeja criar fluxos de eventos.
  5. Clique em Criar.
  6. Copie e salve em um local seguro os seguintes detalhes:
    • ID do cliente da API de terceiros
    • Chave de API
    • URL base da API: dependendo da sua região:
      • EUA: https://api.amp.cisco.com
      • UE: https://api.eu.amp.cisco.com
      • APJC: https://api.apjc.amp.cisco.com

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, cisco-amp-logs).
  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 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 referência futura.
  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 a política AmazonS3FullAccess.
  18. Selecione a política.
  19. Clique em Próxima.
  20. Clique em Adicionar permissões

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

  1. No console da AWS, acesse IAM > Políticas.
  2. Clique em Criar política > guia JSON.
  3. Insira a seguinte política:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowPutObjects",
          "Effect": "Allow",
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::cisco-amp-logs/*"
        },
        {
          "Sid": "AllowGetStateObject",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::cisco-amp-logs/cisco-amp-events/state.json"
        }
      ]
    }
    
    • Substitua cisco-amp-logs se você tiver inserido um nome de bucket diferente.
  4. Clique em Próxima > Criar política.

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

  6. Anexe a política recém-criada.

  7. Nomeie a função como cisco-amp-lambda-role e clique em Criar função.

Criar a função Lambda

  1. No console da AWS, acesse Lambda > Functions > Create function.
  2. Clique em Criar do zero.
  3. Informe os seguintes detalhes de configuração:

    Configuração Valor
    Nome cisco-amp-events-collector
    Ambiente de execução Python 3.13
    Arquitetura x86_64
    Função de execução cisco-amp-lambda-role
  4. Depois que a função for criada, abra a guia Código, exclua o stub e insira o seguinte código (cisco-amp-events-collector.py):

    import json
    import boto3
    import urllib3
    import base64
    from datetime import datetime, timedelta
    import os
    import logging
    
    # Configure logging
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    # AWS S3 client and HTTP pool manager
    s3_client = boto3.client('s3')
    http = urllib3.PoolManager()
    
    def lambda_handler(event, context):
        """
        AWS Lambda handler to fetch Cisco AMP events and store them in S3
        """
    
        try:
            # Get environment variables
            s3_bucket = os.environ['S3_BUCKET']
            s3_prefix = os.environ['S3_PREFIX']
            state_key = os.environ['STATE_KEY']
            api_client_id = os.environ['AMP_CLIENT_ID']
            api_key = os.environ['AMP_API_KEY']
            api_base = os.environ['API_BASE']
    
            # Optional parameters
            page_size = int(os.environ.get('PAGE_SIZE', '500'))
            max_pages = int(os.environ.get('MAX_PAGES', '10'))
    
            logger.info(f"Starting Cisco AMP events collection for bucket: {s3_bucket}")
    
            # Get last run timestamp from state file
            last_timestamp = get_last_timestamp(s3_bucket, state_key)
            if not last_timestamp:
                last_timestamp = (datetime.utcnow() - timedelta(days=1)).isoformat() + 'Z'
    
            # Create Basic Auth header
            auth_header = base64.b64encode(f"{api_client_id}:{api_key}".encode()).decode()
            headers = {
                'Authorization': f'Basic {auth_header}',
                'Accept': 'application/json'
            }
    
            # Build initial API URL
            base_url = f"{api_base}/v1/events"
            next_url = f"{base_url}?limit={page_size}&start_date={last_timestamp}"
    
            all_events = []
            page_count = 0
    
            while next_url and page_count < max_pages:
                logger.info(f"Fetching page {page_count + 1} from: {next_url}")
    
                # Make API request using urllib3
                response = http.request('GET', next_url, headers=headers, timeout=60)
    
                if response.status != 200:
                    raise RuntimeError(f"API request failed: {response.status} {response.data[:256]!r}")
    
                data = json.loads(response.data.decode('utf-8'))
    
                # Extract events from response
                events = data.get('data', [])
                if events:
                    all_events.extend(events)
                    logger.info(f"Collected {len(events)} events from page {page_count + 1}")
    
                    # Check for next page
                    next_url = data.get('metadata', {}).get('links', {}).get('next')
                    page_count += 1
                else:
                    logger.info("No events found on current page")
                    break
    
            logger.info(f"Total events collected: {len(all_events)}")
    
            # Store events in S3 if any were collected
            if all_events:
                timestamp_str = datetime.utcnow().strftime('%Y%m%d_%H%M%S')
                s3_key = f"{s3_prefix}cisco_amp_events_{timestamp_str}.ndjson"
    
                # Convert events to NDJSON format (one JSON object per line)
                ndjson_content = 'n'.join(json.dumps(event) for event in all_events)
    
                # Upload to S3
                s3_client.put_object(
                    Bucket=s3_bucket,
                    Key=s3_key,
                    Body=ndjson_content.encode('utf-8'),
                    ContentType='application/x-ndjson'
                )
    
                logger.info(f"Uploaded {len(all_events)} events to s3://{s3_bucket}/{s3_key}")
    
            # Update state file with current timestamp
            current_timestamp = datetime.utcnow().isoformat() + 'Z'
            update_state(s3_bucket, state_key, current_timestamp)
    
            return {
                'statusCode': 200,
                'body': json.dumps({
                    'message': 'Success',
                    'events_collected': len(all_events),
                    'pages_processed': page_count
                })
            }
    
        except Exception as e:
            logger.error(f"Error in lambda_handler: {str(e)}")
            return {
                'statusCode': 500,
                'body': json.dumps({
                    'error': str(e)
                })
            }
    
    def get_last_timestamp(bucket, state_key):
        """
        Get the last run timestamp from S3 state file
        """
        try:
            response = s3_client.get_object(Bucket=bucket, Key=state_key)
            state_data = json.loads(response['Body'].read().decode('utf-8'))
            return state_data.get('last_timestamp')
        except s3_client.exceptions.NoSuchKey:
            logger.info("No state file found, starting from 24 hours ago")
            return None
        except Exception as e:
            logger.warning(f"Error reading state file: {str(e)}")
            return None
    
    def update_state(bucket, state_key, timestamp):
        """
        Update the state file with the current timestamp
        """
        try:
            state_data = {
                'last_timestamp': timestamp,
                'updated_at': datetime.utcnow().isoformat() + 'Z'
            }
    
            s3_client.put_object(
                Bucket=bucket,
                Key=state_key,
                Body=json.dumps(state_data).encode('utf-8'),
                ContentType='application/json'
            )
    
            logger.info(f"Updated state file with timestamp: {timestamp}")
    
        except Exception as e:
            logger.error(f"Error updating state file: {str(e)}")
    
  5. Acesse Configuração > Variáveis de ambiente.

  6. Clique em Editar > Adicionar nova variável de ambiente.

  7. Insira as variáveis de ambiente a seguir, substituindo pelos seus valores.

    Chave Valor de exemplo
    S3_BUCKET cisco-amp-logs
    S3_PREFIX cisco-amp-events/
    STATE_KEY cisco-amp-events/state.json
    AMP_CLIENT_ID <your-client-id>
    AMP_API_KEY <your-api-key>
    API_BASE https://api.amp.cisco.com (ou o URL da sua região)
    PAGE_SIZE 500
    MAX_PAGES 10
  8. Depois que a função for criada, permaneça na página dela ou abra Lambda > Functions > cisco-amp-events-collector.

  9. Selecione a guia Configuração.

  10. No painel Configuração geral, clique em Editar.

  11. Mude Tempo limite para 5 minutos (300 segundos) e clique em Salvar.

Criar uma programação do EventBridge

  1. Acesse Amazon EventBridge > Scheduler > Criar programação.
  2. Informe os seguintes detalhes de configuração:
    • Programação recorrente: Taxa (1 hour).
    • Destino: sua função Lambda cisco-amp-events-collector.
    • Nome: cisco-amp-events-collector-1h.
  3. Clique em Criar programação.

Opcional: criar um usuário e chaves do IAM somente leitura para o Google SecOps

  1. Acesse Console da AWS > IAM > Usuários > Adicionar usuários.
  2. Clique em Add users.
  3. Informe os seguintes detalhes de configuração:
    • Usuário: insira secops-reader.
    • Tipo de acesso: selecione Chave de acesso – Acesso programático.
  4. Clique em Criar usuário.
  5. Anexe a política de leitura mínima (personalizada): Usuários > secops-reader > Permissões > Adicionar permissões > Anexar políticas diretamente > Criar política.
  6. No editor JSON, insira a seguinte política:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": "arn:aws:s3:::cisco-amp-logs/*"
        },
        {
          "Effect": "Allow",
          "Action": ["s3:ListBucket"],
          "Resource": "arn:aws:s3:::cisco-amp-logs"
        }
      ]
    }
    
  7. Defina o nome como secops-reader-policy.

  8. Acesse Criar política > pesquise/selecione > Próxima > Adicionar permissões.

  9. Acesse Credenciais de segurança > Chaves de acesso > Criar chave de acesso.

  10. Faça o download do CSV (esses valores são inseridos no feed).

Configurar um feed no Google SecOps para ingerir registros do Cisco AMP for Endpoints

  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, Cisco AMP for Endpoints logs).
  4. Selecione Amazon S3 V2 como o Tipo de origem.
  5. Selecione Cisco AMP como o Tipo de registro.
  6. Clique em Próxima.
  7. Especifique valores para os seguintes parâmetros de entrada:
    • URI do S3: s3://cisco-amp-logs/cisco-amp-events/
    • Opções de exclusão de fontes: selecione a opção de exclusão de acordo com sua preferê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: chave de acesso do usuário com acesso ao bucket do S3.
    • Chave de acesso secreta: chave secreta do usuário com acesso ao bucket do S3.
    • Namespace do recurso: o namespace do recurso.
    • Rótulos de ingestão: o rótulo aplicado aos eventos deste feed.
  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
ativo read_only_udm.principal.asset.active Mapeado diretamente de computer.active
connector_guid read_only_udm.principal.asset.uuid Mapeado diretamente de computer.connector_guid
data read_only_udm.metadata.event_timestamp.seconds Mapeado diretamente de date após a conversão para carimbo de data/hora
por IA read_only_udm.security_result.threat_name Mapeado diretamente de detection
detection_id read_only_udm.security_result.detection_fields.value Mapeado diretamente de detection_id
disposition read_only_udm.security_result.description Mapeado diretamente de file.disposition
error.error_code read_only_udm.security_result.detection_fields.value Mapeado diretamente de error.error_code
error.description read_only_udm.security_result.detection_fields.value Mapeado diretamente de error.description
event_type read_only_udm.metadata.product_event_type Mapeado diretamente de event_type
event_type_id read_only_udm.metadata.product_log_id Mapeado diretamente de event_type_id
external_ip read_only_udm.principal.asset.external_ip Mapeado diretamente de computer.external_ip
file.file_name read_only_udm.target.file.names Mapeado diretamente de file.file_name
file.file_path read_only_udm.target.file.full_path Mapeado diretamente de file.file_path
file.identity.md5 read_only_udm.security_result.about.file.md5 Mapeado diretamente de file.identity.md5
file.identity.md5 read_only_udm.target.file.md5 Mapeado diretamente de file.identity.md5
file.identity.sha1 read_only_udm.security_result.about.file.sha1 Mapeado diretamente de file.identity.sha1
file.identity.sha1 read_only_udm.target.file.sha1 Mapeado diretamente de file.identity.sha1
file.identity.sha256 read_only_udm.security_result.about.file.sha256 Mapeado diretamente de file.identity.sha256
file.identity.sha256 read_only_udm.target.file.sha256 Mapeado diretamente de file.identity.sha256
file.parent.disposition read_only_udm.target.resource.attribute.labels.value Mapeado diretamente de file.parent.disposition
file.parent.file_name read_only_udm.target.resource.attribute.labels.value Mapeado diretamente de file.parent.file_name
file.parent.identity.md5 read_only_udm.target.resource.attribute.labels.value Mapeado diretamente de file.parent.identity.md5
file.parent.identity.sha1 read_only_udm.target.resource.attribute.labels.value Mapeado diretamente de file.parent.identity.sha1
file.parent.identity.sha256 read_only_udm.target.resource.attribute.labels.value Mapeado diretamente de file.parent.identity.sha256
file.parent.process_id read_only_udm.security_result.about.process.parent_process.pid Mapeado diretamente de file.parent.process_id
file.parent.process_id read_only_udm.target.process.parent_process.pid Mapeado diretamente de file.parent.process_id
nome do host read_only_udm.principal.asset.hostname Mapeado diretamente de computer.hostname
nome do host read_only_udm.target.hostname Mapeado diretamente de computer.hostname
nome do host read_only_udm.target.asset.hostname Mapeado diretamente de computer.hostname
ip read_only_udm.principal.asset.ip Mapeado diretamente de computer.network_addresses.ip
ip read_only_udm.principal.ip Mapeado diretamente de computer.network_addresses.ip
ip read_only_udm.security_result.about.ip Mapeado diretamente de computer.network_addresses.ip
mac read_only_udm.principal.mac Mapeado diretamente de computer.network_addresses.mac
mac read_only_udm.security_result.about.mac Mapeado diretamente de computer.network_addresses.mac
gravidade, read_only_udm.security_result.severity Mapeado de severity com base na seguinte lógica:
- "Medium" -> "MEDIUM"
- "High" ou "Critical" -> "HIGH"
- "Low" -> "LOW"
- Caso contrário -> "UNKNOWN_SEVERITY"
timestamp read_only_udm.metadata.event_timestamp.seconds Mapeado diretamente de timestamp
usuário read_only_udm.security_result.about.user.user_display_name Mapeado diretamente de computer.user
usuário read_only_udm.target.user.user_display_name Mapeado diretamente de computer.user
vulnerabilities.cve read_only_udm.extensions.vulns.vulnerabilities.cve_id Mapeado diretamente de vulnerabilities.cve
vulnerabilities.name read_only_udm.extensions.vulns.vulnerabilities.name Mapeado diretamente de vulnerabilities.name
vulnerabilities.score read_only_udm.extensions.vulns.vulnerabilities.cvss_base_score Mapeado diretamente de vulnerabilities.score após a conversão para ponto flutuante
vulnerabilities.url read_only_udm.extensions.vulns.vulnerabilities.vendor_knowledge_base_article_id Mapeado diretamente de vulnerabilities.url
vulnerabilities.version read_only_udm.extensions.vulns.vulnerabilities.cvss_version Mapeado diretamente de vulnerabilities.version
is_alert Definido como "true" se event_type for um dos seguintes: "Ameaça detectada", "Prevenção de exploração", "Malware executado", "Possível infecção por dropper", "Vários arquivos infectados", "Aplicativo vulnerável detectado" ou se security_result.severity for "ALTA"
is_significant Definido como "true" se event_type for um dos seguintes: "Ameaça detectada", "Prevenção de exploração", "Malware executado", "Possível infecção por dropper", "Vários arquivos infectados", "Aplicativo vulnerável detectado" ou se security_result.severity for "ALTA"
read_only_udm.metadata.event_type Determinado com base nos valores event_type e security_result.severity.
: se event_type for um dos seguintes: "Malware executado", "Ameaça detectada", "Possível infecção por dropper", "Detecção de recall na nuvem", "Detecção de atividade maliciosa", "Prevenção de exploração", "Vários arquivos infectados", "IOC na nuvem", "Proteção de processos do sistema", "Aplicativo vulnerável detectado", "Ameaça em quarentena", "Execução bloqueada", "Quarentena de recall na nuvem concluída", "Falha na restauração da quarentena de recall na nuvem", "Falha na tentativa de quarentena de recall na nuvem", "Falha na quarentena", o tipo de evento será definido como "SCAN_FILE".
: se security_result.severity for "HIGH", o tipo de evento será definido como "SCAN_FILE".
: se has_principal e has_target forem verdadeiros, o tipo de evento será definido como "SCAN_UNCATEGORIZED".
: caso contrário, o tipo de evento será definido como "GENERIC_EVENT".
read_only_udm.metadata.log_type Definido como "CISCO_AMP"
read_only_udm.metadata.vendor_name Definido como "CISCO_AMP"
read_only_udm.security_result.about.file.full_path Mapeado diretamente de file.file_path
read_only_udm.security_result.about.hostname Mapeado diretamente de computer.hostname
read_only_udm.security_result.about.user.user_display_name Mapeado diretamente de computer.user
read_only_udm.security_result.detection_fields.key Definido como "ID de detecção" para detection_id, "Código de erro" para error.error_code, "Descrição do erro" para error.description, "Disposição principal" para file.parent.disposition, "Nome do arquivo principal" para file.parent.file_name, "MD5 principal" para file.parent.identity.md5, "SHA1 principal" para file.parent.identity.sha1 e "SHA256 principal" para file.parent.identity.sha256.
read_only_udm.security_result.summary Definido como event_type se event_type for um dos seguintes: "Ameaça detectada", "Prevenção de exploração", "Malware executado", "Possível infecção por dropper", "Vários arquivos infectados", "Aplicativo vulnerável detectado" ou se security_result.severity for "ALTA"
read_only_udm.target.asset.ip Mapeado diretamente de computer.network_addresses.ip
read_only_udm.target.resource.attribute.labels.key Definido como "Disposição da matriz" para file.parent.disposition, "Nome do arquivo da matriz" para file.parent.file_name, "MD5 da matriz" para file.parent.identity.md5, "SHA1 da matriz" para file.parent.identity.sha1 e "SHA256 da matriz" para file.parent.identity.sha256
timestamp.seconds Mapeado diretamente de date após a conversão para carimbo de data/hora

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