Coletar registros do BeyondTrust Endpoint Privilege Management

Compatível com:

Este documento explica como ingerir registros do BeyondTrust Endpoint Privilege Management (EPM) no Google Security Operations usando o AWS S3. O analisador se concentra em transformar dados de registro JSON brutos do BeyondTrust Endpoint em um formato estruturado de acordo com o Modelo de Dados Unificado (UDM). Primeiro, ele inicializa os valores padrão para vários campos e, em seguida, analisa o payload JSON, mapeando campos específicos do log bruto para os campos correspondentes da UDM no objeto event.idm.read_only_udm.

Antes de começar

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

  • Instância do Google SecOps
  • Acesso privilegiado à AWS
  • Acesso privilegiado ao BeyondTrust Endpoint Privilege Management

Configurar o IAM da AWS para a ingestão do Google SecOps

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

Configurar o BeyondTrust EPM para acesso à API

  1. Faça login no console da Web do BeyondTrust Privilege Management como administrador.
  2. Acesse Configuração do sistema > API REST > Tokens.
  3. Clique em Adicionar token.
  4. Informe os seguintes detalhes de configuração:
    • Nome: insira Google SecOps Collector.
    • Escopos: selecione Audit:Read e outros escopos conforme necessário.
  5. Salve e copie o valor do token (esse será seu BPT_API_TOKEN).
  6. Copie o URL de base da API. Normalmente, ele é https://<your-epm-server>/api/v3 ou /api/v2, dependendo da sua versão. Use esse URL como BPT_API_URL.

Criar um bucket do AWS S3

  1. Faça login no Console de Gerenciamento da AWS.
  2. Acesse Console da AWS > Serviços > S3 > Criar bucket.
  3. Informe os seguintes detalhes de configuração:
    • Nome do bucket: my-beyondtrust-logs.
    • Região: [sua escolha] > Criar.

Criar um papel do IAM para o EC2

  1. Faça login no Console de Gerenciamento da AWS.
  2. Acesse Console da AWS > Serviços > IAM > Funções > Criar função.
  3. Informe os seguintes detalhes de configuração:
    • Entidade confiável: Serviço da AWS > EC2 > Próxima.
    • Anexar permissão: AmazonS3FullAccess (ou uma política com escopo para seu bucket) > Próxima.
    • Nome da função: EC2-S3-BPT-Writer > Criar função.

Opcional: inicie e configure a VM do coletor do EC2

  1. Faça login no Console de Gerenciamento da AWS.
  2. Acesse Serviços.
  3. Na barra de pesquisa, digite EC2 e selecione essa opção.
  4. No painel do EC2, clique em Instâncias.
  5. Clique em Iniciar instâncias.
  6. Informe os seguintes detalhes de configuração:
    • Nome: insira BPT-Log-Collector.
    • AMI: selecione Ubuntu Server 22.04 LTS.
    • Tipo de instância: t3.micro (ou maior) e clique em Próxima.
    • Rede: verifique se a configuração de rede está definida como sua VPC padrão.
    • Função do IAM: selecione a função do IAM EC2-S3-BPT-Writer no menu.
    • Atribuir IP público automaticamente: Ativar (ou verifique se é possível acessar usando VPN) > Próxima.
    • Adicionar armazenamento: deixe a configuração de armazenamento padrão (8 GiB) e clique em Próxima.
    • Selecione Criar um novo grupo de segurança.
    • Regra de entrada: clique em Adicionar regra.
    • Tipo: selecione SSH.
    • Porta: 22.
    • Origem: seu IP
    • Clique em Revisar e iniciar.
    • Selecione ou crie um par de chaves.
    • Clique em Fazer o download do par de chaves.
    • Salve o arquivo PEM baixado. Você vai precisar desse arquivo para se conectar à instância usando SSH.
  7. Conecte-se à sua máquina virtual (VM) usando SSH:

    chmod 400 ~/Downloads/your-key.pem
    ssh -i ~/Downloads/your-key.pem ubuntu@<EC2_PUBLIC_IP>
    

Instalar os pré-requisitos do coletor

  1. Execute este comando:

    # Update OS
    sudo apt update && sudo apt upgrade -y
    
    # Install Python, Git
    sudo apt install -y python3 python3-venv python3-pip git
    
    # Create & activate virtualenv
    python3 -m venv ~/bpt-venv
    source ~/bpt-venv/bin/activate
    
    # Install libraries
    pip install requests boto3
    
  2. Crie um diretório e um arquivo de estado:

    sudo mkdir -p /var/lib/bpt-collector
    sudo touch /var/lib/bpt-collector/last_run.txt
    sudo chown ubuntu:ubuntu /var/lib/bpt-collector/last_run.txt
    
  3. Inicialize-o (por exemplo, para 1 hora atrás):

    echo "$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)" > /var/lib/bpt-collector/last_run.txt
    

Implantar o script do coletor da Armis

  1. Crie uma pasta para o projeto:

    mkdir ~/bpt-collector && cd ~/bpt-collector
    
  2. Exporte as variáveis de ambiente necessárias (por exemplo, em ~/.bashrc):

    export BPT_API_URL="https://<your-subdomain>-services.pm.beyondtrustcloud.com"
    export BPT_CLIENT_ID="your-client-id"
    export BPT_CLIENT_SECRET="your-client-secret"
    export S3_BUCKET="my-bpt-logs"
    export S3_PREFIX="bpt/"
    export STATE_FILE="/var/lib/bpt-collector/last_run.txt"
    export PAGE_SIZE="100"
    
  3. Crie collector_bpt.py e insira o seguinte código:

    #!/usr/bin/env python3
    import os, sys, json, boto3, requests
    from datetime import datetime, timezone, timedelta
    
    # ── UTILS ─────────────────────────────────────────────────────────────────
    def must_env(var):
        val = os.getenv(var)
        if not val:
            print(f"ERROR: environment variable {var} is required", file=sys.stderr)
            sys.exit(1)
        return val
    
    def ensure_state_file(path):
        d = os.path.dirname(path)
        if not os.path.isdir(d):
            os.makedirs(d, exist_ok=True)
        if not os.path.isfile(path):
            ts = (datetime.now(timezone.utc) - timedelta(hours=1))\
                .strftime("%Y-%m-%dT%H:%M:%SZ")
            with open(path, "w") as f:
                f.write(ts)
    
    # ── CONFIG ─────────────────────────────────────────────────────────────────
    BPT_API_URL    = must_env("BPT_API_URL")       # for example, https://subdomain-services.pm.beyondtrustcloud.com
    CLIENT_ID      = must_env("BPT_CLIENT_ID")
    CLIENT_SECRET  = must_env("BPT_CLIENT_SECRET")
    S3_BUCKET      = must_env("S3_BUCKET")
    S3_PREFIX      = os.getenv("S3_PREFIX", "")    # for example, "bpt/"
    STATE_FILE     = os.getenv("STATE_FILE", "/var/lib/bpt-collector/last_run.txt")
    PAGE_SIZE      = int(os.getenv("PAGE_SIZE", "100"))
    # ── END CONFIG ─────────────────────────────────────────────────────────────
    
    ensure_state_file(STATE_FILE)
    
    def read_last_run():
        with open(STATE_FILE, "r") as f:
            ts = f.read().strip()
        return datetime.fromisoformat(ts.replace("Z", "+00:00"))
    
    def write_last_run(dt):
        with open(STATE_FILE, "w") as f:
            f.write(dt.strftime("%Y-%m-%dT%H:%M:%SZ"))
    
    def get_oauth_token():
        resp = requests.post(
            f"{BPT_API_URL}/oauth/connect/token",
            headers={"Content-Type": "application/x-www-form-urlencoded"},
            data={
                "grant_type":    "client_credentials",
                "client_id":     CLIENT_ID,
                "client_secret": CLIENT_SECRET
            }
        )
        resp.raise_for_status()
        return resp.json()["access_token"]
    
    def fetch_events(token, start, end):
        headers = {"Authorization": f"Bearer {token}"}
        offset = 0
        while True:
            params = {
                "startTime": start,
                "endTime":   end,
                "limit":     PAGE_SIZE,
                "offset":    offset
            }
            resp = requests.get(
                f"{BPT_API_URL}/management-api/v1/Audit/Events",
                headers=headers, params=params
            )
            resp.raise_for_status()
            events = resp.json().get("events", [])
            if not events:
                break
            for e in events:
                yield e
            offset += PAGE_SIZE
    
    def upload_to_s3(obj, key):
        boto3.client("s3").put_object(
            Bucket=S3_BUCKET, Key=key,
            Body=json.dumps(obj).encode("utf-8")
        )
    
    def main():
        # 1) determine window
        start_dt = read_last_run()
        end_dt   = datetime.now(timezone.utc)
        START = start_dt.strftime("%Y-%m-%dT%H:%M:%SZ")
        END   = end_dt.strftime("%Y-%m-%dT%H:%M:%SZ")
        print(f"Fetching events from {START} to {END}")
    
        # 2) authenticate and fetch
        token = get_oauth_token()
        count = 0
        for idx, evt in enumerate(fetch_events(token, START, END), start=1):
            key = f"{S3_PREFIX}{end_dt.strftime('%Y/%m/%d')}/evt_{int(end_dt.timestamp())}_{idx}.json"
            upload_to_s3(evt, key)
            count += 1
        print(f"Uploaded {count} events")
    
        # 3) persist state
        write_last_run(end_dt)
    
    if __name__ == "__main__":
        main()
    
  4. Torne-o executável:

    chmod +x collector_bpt.py
    

Programar diariamente com o Cron

  1. Execute este comando:

    crontab -e
    
  2. Adicione o job diário à meia-noite UTC:

    0 0 * * * cd ~/bpt-collector && source ~/bpt-venv/bin/activate && ./collector_bpt.py >> ~/bpt-collector/bpt.log 2>&1
    

Configurar feeds

Há dois pontos de entrada diferentes para configurar feeds na plataforma do Google SecOps:

  • Configurações do SIEM > Feeds
  • Central de conteúdo > Pacotes de conteúdo

Configure feeds em "Configurações do SIEM" > "Feeds".

Para configurar um feed, siga estas etapas:

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em Adicionar novo feed.
  3. Na próxima página, clique em Configurar um único feed.
  4. No campo Nome do feed, insira um nome para o feed (por exemplo, Registros do BeyondTrust EPM).
  5. Selecione Amazon S3 como o Tipo de origem.
  6. Selecione Beyondtrust Endpoint Privilege Management como o Tipo de registro.
  7. Clique em Próxima.
  8. Especifique valores para os seguintes parâmetros de entrada:

    • Região: a região em que o bucket do Amazon S3 está localizado.
    • URI do S3: o URI do bucket. O formato precisa ser s3://your-log-bucket-name/. Substitua o seguinte:
      • your-log-bucket-name: o nome do bucket
    • O URI é um: selecione Diretório ou Diretório que inclui subdiretórios.
    • Opções de exclusão de fontes: selecione a opção de exclusão de acordo com sua preferência.
    • ID da chave de acesso: a chave de acesso do usuário com acesso ao bucket do S3.
    • Chave de acesso secreta: a chave secreta do usuário com acesso ao bucket do S3.
  9. Clique em Próxima.

  10. Revise a nova configuração do feed na tela Finalizar e clique em Enviar.

Configurar feeds na Central de conteúdo

Especifique valores para os seguintes campos:

  • Região: a região em que o bucket do Amazon S3 está localizado.

    • URI do S3: o URI do bucket. O formato precisa ser s3://your-log-bucket-name/. Substitua o seguinte:
      • your-log-bucket-name: o nome do bucket
    • O URI é um: selecione Diretório ou Diretório que inclui subdiretórios.
    • Opções de exclusão de fontes: selecione a opção de exclusão de acordo com sua preferência.
    • ID da chave de acesso: a chave de acesso do usuário com acesso ao bucket do S3.
    • Chave de acesso secreta: a chave secreta do usuário com acesso ao bucket do S3.

Opções avançadas

  • Nome do feed: um valor pré-preenchido que identifica o feed.
  • Tipo de origem: método usado para coletar registros no Google SecOps.
  • Namespace do recurso: namespace associado ao feed.
  • Rótulos de ingestão: rótulos aplicados a todos os eventos deste feed.

Tabela de mapeamento da UDM

Campo de registro Mapeamento da UDM Lógica
agent.id principal.asset.attribute.labels.value O valor é extraído do campo agent.id no registro bruto e mapeado para um rótulo com a chave agent_id na matriz principal.asset.attribute.labels na UDM.
agent.version principal.asset.attribute.labels.value O valor é extraído do campo agent.version no registro bruto e mapeado para um rótulo com a chave agent_version na matriz principal.asset.attribute.labels na UDM.
ecs.version principal.asset.attribute.labels.value O valor é extraído do campo ecs.version no registro bruto e mapeado para um rótulo com a chave ecs_version na matriz principal.asset.attribute.labels na UDM.
event_data.reason metadata.description O valor é extraído do campo event_data.reason no registro bruto e mapeado para o campo description no objeto metadata na UDM.
event_datas.ActionId metadata.product_log_id O valor é extraído do campo event_datas.ActionId no registro bruto e mapeado para o campo product_log_id no objeto metadata na UDM.
file.path principal.file.full_path O valor é extraído do campo file.path no registro bruto e mapeado para o campo full_path no objeto principal.file na UDM.
headers.content_length additional.fields.value.string_value O valor é extraído do campo headers.content_length no registro bruto e mapeado para um rótulo com a chave content_length na matriz additional.fields na UDM.
headers.content_type additional.fields.value.string_value O valor é extraído do campo headers.content_type no registro bruto e mapeado para um rótulo com a chave content_type na matriz additional.fields na UDM.
headers.http_host additional.fields.value.string_value O valor é extraído do campo headers.http_host no registro bruto e mapeado para um rótulo com a chave http_host na matriz additional.fields na UDM.
headers.http_version network.application_protocol_version O valor é extraído do campo headers.http_version no registro bruto e mapeado para o campo application_protocol_version no objeto network na UDM.
headers.request_method network.http.method O valor é extraído do campo headers.request_method no registro bruto e mapeado para o campo method no objeto network.http na UDM.
host.hostname principal.hostname O valor é extraído do campo host.hostname no registro bruto e mapeado para o campo hostname no objeto principal na UDM.
host.hostname principal.asset.hostname O valor é extraído do campo host.hostname no registro bruto e mapeado para o campo hostname no objeto principal.asset na UDM.
host.ip principal.asset.ip O valor é extraído do campo host.ip no registro bruto e adicionado à matriz ip no objeto principal.asset na UDM.
host.ip principal.ip O valor é extraído do campo host.ip no registro bruto e adicionado à matriz ip no objeto principal na UDM.
host.mac principal.mac O valor é extraído do campo host.mac no registro bruto e adicionado à matriz mac no objeto principal na UDM.
host.os.platform principal.platform O valor é definido como MAC se o campo host.os.platform no registro bruto for igual a macOS.
host.os.version principal.platform_version O valor é extraído do campo host.os.version no registro bruto e mapeado para o campo platform_version no objeto principal na UDM.
labels.related_item_id metadata.product_log_id O valor é extraído do campo labels.related_item_id no registro bruto e mapeado para o campo product_log_id no objeto metadata na UDM.
process.command_line principal.process.command_line O valor é extraído do campo process.command_line no registro bruto e mapeado para o campo command_line no objeto principal.process na UDM.
process.name additional.fields.value.string_value O valor é extraído do campo process.name no registro bruto e mapeado para um rótulo com a chave process_name na matriz additional.fields na UDM.
process.parent.name additional.fields.value.string_value O valor é extraído do campo process.parent.name no registro bruto e mapeado para um rótulo com a chave process_parent_name na matriz additional.fields na UDM.
process.parent.pid principal.process.parent_process.pid O valor é extraído do campo process.parent.pid no registro bruto, convertido em string e mapeado para o campo pid no objeto principal.process.parent_process na UDM.
process.pid principal.process.pid O valor é extraído do campo process.pid no registro bruto, convertido em string e mapeado para o campo pid no objeto principal.process na UDM.
user.id principal.user.userid O valor é extraído do campo user.id no registro bruto e mapeado para o campo userid no objeto principal.user na UDM.
user.name principal.user.user_display_name O valor é extraído do campo user.name no registro bruto e mapeado para o campo user_display_name no objeto principal.user na UDM.
N/A metadata.event_timestamp O carimbo de data/hora do evento é definido como o carimbo de data/hora da entrada de registro.
N/A metadata.event_type O tipo de evento é definido como GENERIC_EVENT se nenhum principal for encontrado. Caso contrário, ele será definido como STATUS_UPDATE.
N/A network.application_protocol O protocolo de aplicativo é definido como HTTP se o campo headers.http_version no registro bruto contiver HTTP.

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