Coletar registros do BeyondTrust Endpoint Privilege Management (EPM)
Este documento explica como ingerir registros do BeyondTrust Endpoint Privilege Management (EPM) no Google Security Operations usando o Cloud Storage. O analisador se concentra em transformar dados de registro JSON brutos do BeyondTrust Endpoint em um formato estruturado de acordo com o UDM do Google SecOps. Primeiro, ele inicializa os valores padrão para vários campos e, em seguida, analisa o payload JSON, mapeando campos específicos do registro 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:
- Uma instância do Google SecOps
- Um projeto do Google Cloud com a API Storage Cloud ativada
- Permissões para criar e gerenciar buckets do Cloud Storage
- Permissões para gerenciar políticas do Identity and Access Management (IAM) em buckets do Cloud Storage
- Permissões para criar serviços de função do Cloud Run, tópicos do Pub/Sub e jobs do Cloud Scheduler
- Acesso privilegiado ao locatário ou à API do BeyondTrust Endpoint Privilege Management
Criar um bucket do Cloud Storage
- Acesse o console doGoogle Cloud .
- Selecione um 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, beyondtrust-epm-logs.Tipo de local Escolha de acordo com 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.
Coletar credenciais da API BeyondTrust EPM
- Faça login no console da Web do BeyondTrust Privilege Management como administrador.
- Acesse Configuração > Configurações > Configurações da API.
- Clique em Criar uma conta de API.
- Informe os seguintes detalhes de configuração:
- Nome: insira
Google SecOps Collector. - Acesso à API: ative a opção Relatórios (somente leitura). O endpoint
/management-api/v3/Events/FromStartDateusado por esse coletor pertence à categoria de permissão Relatórios. Ative também a opção Auditoria (somente leitura) se quiser coletar auditorias de atividade do console da Web.
- Nome: insira
- Copie e salve o ID do cliente e a chave secreta do cliente.
Copie o URL de base da API mostrado na parte de cima da página Configurações da API. Normalmente, é
https://<your-tenant>-services.pm.beyondtrustcloud.com. Você vai usar isso comoBPT_API_URL.
Criar uma conta de serviço para a função do Cloud Run
A função do Cloud Run precisa de uma conta de serviço com permissões para gravar no bucket do Cloud Storage e ser invocada pelo Pub/Sub.
Criar a conta de serviço
- No console Google Cloud , acesse IAM e administrador > Contas de serviço.
- Clique em Criar conta de serviço.
- Informe os seguintes detalhes de configuração:
- Nome da conta de serviço: insira
beyondtrust-epm-collector-sa. - Descrição da conta de serviço: insira
Service account for Cloud Run function to collect BeyondTrust EPM logs.
- Nome da conta de serviço: insira
- Clique em Criar e continuar.
- Na seção Conceder acesso a essa conta de serviço ao projeto, adicione os seguintes papéis:
- Clique em Selecionar papel.
- Pesquise e selecione Administrador de objetos do Storage.
- Clique em + Adicionar outro papel.
- Pesquise e selecione Invocador do Cloud Run.
- Clique em + Adicionar outro papel.
- Pesquise e selecione Invocador do Cloud Functions.
- Clique em Continuar.
- Clique em Concluído.
Esses papéis são necessários para:
- Administrador de objetos do Storage: grava registros em um bucket do Cloud Storage e gerencia arquivos de estado.
- Invocador do Cloud Run: permite que o Pub/Sub invoque a função.
- Invocador do Cloud Functions: permite a invocação de funções
Conceder permissões do IAM em um bucket do Cloud Storage
Conceda permissões de gravação à conta de serviço no bucket do Cloud Storage:
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket.
- Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar principais: insira o e-mail da conta de serviço. Por exemplo,
beyondtrust-epm-collector-sa@PROJECT_ID.iam.gserviceaccount.com. - Atribuir papéis: selecione Administrador de objetos do Storage.
- Adicionar principais: insira o e-mail da conta de serviço. Por exemplo,
- Clique em Salvar.
Criar um tópico do Pub/Sub
Crie um tópico do Pub/Sub em que o Cloud Scheduler vai publicar e a função do Cloud Run vai se inscrever.
- No Google Cloud Console, acesse Pub/Sub > Tópicos.
- Selecione Criar tópico.
- Informe os seguintes detalhes de configuração:
- ID do tópico: insira
beyondtrust-epm-trigger. - Não mude as outras configurações.
- ID do tópico: insira
- Clique em Criar.
Criar uma função do Cloud Run para coletar registros
A função do Cloud Run é acionada por mensagens do Pub/Sub do Cloud Scheduler para buscar registros da API EPM do BeyondTrust e gravar no Cloud Storage.
- No Google Cloud console, acesse o Cloud Run.
- Clique em Criar serviço.
- Selecione Função. Use um editor in-line para criar uma função.
Na seção Configurar, forneça os seguintes detalhes de configuração:
Configuração Valor Nome do serviço beyondtrust-epm-collectorRegião Selecione a região correspondente ao seu bucket do Cloud Storage (por exemplo, us-central1).Ambiente de execução Selecione Python 3.12 ou uma versão mais recente. Na seção Acionador (opcional):
- Clique em + Adicionar gatilho.
- Selecione Cloud Pub/Sub.
- Em Selecionar um tópico do Cloud Pub/Sub, escolha o tópico
beyondtrust-epm-trigger. - Clique em Salvar.
Na seção Autenticação:
- Selecione Exigir autenticação.
- Confira o Identity and Access Management (IAM).
Acesse e abra Contêineres, rede, segurança.
Acesse a guia Segurança:
- Conta de serviço: selecione a conta de serviço
beyondtrust-epm-collector-sa.
- Conta de serviço: selecione a conta de serviço
Acesse a guia Contêineres:
- Clique em Variáveis e secrets.
- Clique em + Adicionar variável para cada variável de ambiente:
Nome da variável Valor de exemplo GCS_BUCKETbeyondtrust-epm-logsGCS_PREFIXbeyondtrust-epm/STATE_KEYbeyondtrust-epm-state.jsonBPT_API_URLhttps://yourtenant-services.pm.beyondtrustcloud.comCLIENT_IDyour-client-idCLIENT_SECRETyour-client-secretRECORD_SIZE1000MAX_BATCHES50LOOKBACK_HOURS24RECORD_SIZE: registros por solicitação./Events/FromStartDateaceita valores de 1 a 1.000. A função limita valores mais altos.MAX_BATCHES: limite de segurança para solicitações por execução. Se uma execução atingir esse limite, o cursor ainda vai avançar para o que foi escrito, para que a próxima execução continue de lá em vez de repetir o trabalho.LOOKBACK_HOURS: até quando a primeira execução vai. O BeyondTrust retém eventos passivos (códigos 106, 107, 603, 706) por 30 dias e todos os outros eventos por 90 dias. Portanto, um período de lookback mais longo não retorna nada mais antigo do que isso.LOOKBACK_HOURS: até onde voltar na primeira execução, antes que qualquer cursor exista.
Na guia Variáveis e secrets, acesse Solicitações:
- Tempo limite da solicitação: insira
600segundos (10 minutos).
- Tempo limite da solicitação: insira
Acesse a guia Configurações em Contêineres:
- Na seção Recursos:
- Memória: selecione 512 MiB ou mais.
- CPU: selecione 1.
- Clique em Concluído.
- Na seção Recursos:
Role até Ambiente de execução:
- Selecione Padrão (recomendado).
Na seção Escalonamento de revisão:
- Número mínimo de instâncias: insira
0. - Número máximo de instâncias: insira
100ou ajuste com base na carga esperada.
- Número mínimo de instâncias: insira
Clique em Criar.
Aguarde a criação do serviço (1 a 2 minutos).
Depois que o serviço é criado, o editor de código inline é aberto automaticamente.
Adicionar um código de função
- Insira main em Ponto de entrada da função.
No editor de código em linha, crie dois arquivos:
- Primeiro arquivo:main.py:
import hashlib import json import os import re import time import urllib3 import uuid from datetime import datetime, timedelta, timezone from urllib.parse import urlencode import functions_framework from google.cloud import storage from google.cloud.exceptions import NotFound # Initialize HTTP client with timeouts http = urllib3.PoolManager( timeout=urllib3.Timeout(connect=5.0, read=60.0), retries=False, ) # Initialize Storage client storage_client = storage.Client() TOKEN_PATH = '/oauth/connect/token' # Events/FromStartDate is the endpoint BeyondTrust documents for bulk extraction: # "A new API is exposed to extract the events in bulk." It takes only StartDate and # RecordSize. Events/search is not usable here: it requires an OperatingSystem value, # it is a single string with no documented "all" value, so it can only ever return one # operating system per call. EVENTS_PATH = '/management-api/v3/Events/FromStartDate' OAUTH_SCOPE = 'urn:management:api' # RecordSize accepts 1 to 1000. MAX_RECORD_SIZE = 1000 class FetchError(Exception): """Raised when the BeyondTrust API call fails. The cursor must never advance on a failed fetch, otherwise the events in the failed window are skipped permanently. """ def rfc3339(dt: datetime) -> str: """Render a datetime the way StartDate accepts it: milliseconds and a literal Z.""" return dt.astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z' def parse_iso(stamp: str) -> datetime: """Parse any ISO 8601 timestamp shape the API emits. event.ingested comes back with a +00:00 offset and up to seven fractional digits, e.g. 2026-08-03T13:29:55.1109163+00:00. fromisoformat's tolerance for long fractions varies across Python versions, so the fraction is trimmed to microseconds first. """ text = stamp.strip() if text.endswith('Z'): text = text[:-1] + '+00:00' text = re.sub(r'\.(\d{1,6})\d*', r'.\1', text, count=1) parsed = datetime.fromisoformat(text) if parsed.tzinfo is None: parsed = parsed.replace(tzinfo=timezone.utc) return parsed def canonical(stamp: str) -> str: """Re-render an API timestamp into the one form StartDate accepts. The API returns event.ingested as +00:00-offset ISO 8601 but rejects that same shape as a StartDate value with 400 "Invalid Start date format": it accepts only Z-suffixed values. Every timestamp that came from the API must pass through here before being sent back or persisted. """ return rfc3339(parse_iso(stamp)) def event_id(evt: dict) -> str: """Return the event's identity for deduplication. Falls back to a content hash when event.id is absent, so an id-less event still deduplicates instead of being re-ingested on every boundary re-read. """ explicit = str((evt.get('event') or {}).get('id') or '') if explicit: return explicit digest = hashlib.sha256( json.dumps(evt, sort_keys=True, ensure_ascii=False).encode('utf-8') ).hexdigest() return f'sha256:{digest}' def event_ingested(evt: dict) -> str: """Return the Elastic ingestion timestamp, which is what StartDate filters on.""" return str((evt.get('event') or {}).get('ingested') or '') def next_millisecond(stamp: str) -> str: """Return the canonical timestamp one millisecond later. Used only when a full batch fits inside a single ingestion millisecond. Without this the cursor cannot move and the collector stalls on that timestamp forever. """ return rfc3339(parse_iso(stamp) + timedelta(milliseconds=1)) @functions_framework.cloud_event def main(cloud_event): """Fetch BeyondTrust EPM events and write them to Cloud Storage as NDJSON. Args: cloud_event: CloudEvent object containing the Pub/Sub message. """ bucket_name = os.environ.get('GCS_BUCKET') prefix = os.environ.get('GCS_PREFIX', 'beyondtrust-epm/') state_key = os.environ.get('STATE_KEY', 'beyondtrust-epm-state.json') api_url = (os.environ.get('BPT_API_URL') or '').rstrip('/') client_id = os.environ.get('CLIENT_ID') client_secret = os.environ.get('CLIENT_SECRET') # Clamp both ends: the API rejects RecordSize outside 1 to 1000, and a # misconfigured 0 would otherwise crash-loop on a 400 every run. record_size = min(max(int(os.environ.get('RECORD_SIZE', '1000')), 1), MAX_RECORD_SIZE) max_batches = int(os.environ.get('MAX_BATCHES', '50')) lookback_hours = int(os.environ.get('LOOKBACK_HOURS', '24')) if not all([bucket_name, api_url, client_id, client_secret]): raise RuntimeError( 'Missing required environment variables: ' 'GCS_BUCKET, BPT_API_URL, CLIENT_ID, CLIENT_SECRET' ) bucket = storage_client.bucket(bucket_name) state = load_state(bucket, state_key) # StartDate is a rising cursor on the Elastic ingestion timestamp, not a closed # window. There is no EndDate on this endpoint. if state.get('last_ingested'): # canonical() also repairs state written by the previous script revision, # which persisted the API's raw +00:00 form that StartDate rejects. try: start_date = canonical(state['last_ingested']) except (ValueError, TypeError, AttributeError) as e: raise RuntimeError( f'Unparseable last_ingested in gs://{bucket_name}/{state_key}: ' f'{state["last_ingested"]!r}. Fix or delete that object; deleting ' f'restarts collection from the lookback window.' ) from e else: start_date = rfc3339(datetime.now(timezone.utc) - timedelta(hours=lookback_hours)) seen_ids = set(state.get('seen_ids', [])) print(f'Collecting events ingested from {start_date}') token = get_oauth_token(api_url, client_id, client_secret) fresh, cursor, drained = fetch_events( api_url, token, start_date, record_size, max_batches, seen_ids ) if not fresh: print('No new events. Cursor left unchanged.') return # Everything that can fail is computed before the upload: a crash between the # upload and save_state replays the batch on the next run, so the window where # side effects exist without recorded state must stay minimal. The retained ids # share the cursor millisecond, because those are exactly the ones the # inclusive StartDate will return again. retained = { event_id(e) for e in fresh if event_ingested(e) and canonical(event_ingested(e)) == cursor } if cursor == start_date: # The cursor millisecond did not advance, so ids retained by earlier runs # are still on the boundary; dropping them would re-ingest their events. retained |= seen_ids timestamp = datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ') # The random suffix keeps concurrent executions (Pub/Sub delivers at least # once) from overwriting each other's object within the same second. filename = ( f'{prefix}beyondtrust-epm-events-{timestamp}-' f'{uuid.uuid4().hex[:8]}.ndjson' ) ndjson = '\n'.join(json.dumps(e, ensure_ascii=False) for e in fresh) + '\n' bucket.blob(filename).upload_from_string( ndjson, content_type='application/x-ndjson' ) print(f'Wrote {len(fresh)} events to gs://{bucket_name}/{filename}') save_state(bucket, state_key, { 'last_ingested': cursor, 'seen_ids': sorted(retained), 'updated_at': rfc3339(datetime.now(timezone.utc)), }) if not drained: print( f'Stopped after {max_batches} batches with more events available. ' 'The cursor advanced, so the next run continues from here.' ) def fetch_events(api_url, token, start_date, record_size, max_batches, seen_ids): """Read forward from start_date until the API returns a short batch. The response envelope has no page count and no next-page token, so a batch shorter than record_size is the only documented end-of-data signal. StartDate is inclusive and the cursor lands on the newest event's timestamp, so every batch re-returns the events sharing it. Deduplication by event id therefore has to happen as batches arrive, not only between runs. Returns: Tuple of (new events, cursor to persist, whether the stream was drained). Raises: FetchError: on any API or transport failure, so the caller cannot mistake a failed fetch for an empty result and advance the cursor. """ headers = { 'Authorization': f'Bearer {token}', 'Accept': 'application/json', } all_events = [] seen = set(seen_ids) cursor = start_date for batch in range(1, max_batches + 1): query = urlencode({'StartDate': cursor, 'RecordSize': record_size}) body = request_with_retry(f'{api_url}{EVENTS_PATH}?{query}', headers) events = body.get('events') or [] new = [e for e in events if event_id(e) not in seen] seen.update(event_id(e) for e in events if event_id(e)) all_events.extend(new) print(f'Batch {batch}: {len(events)} events, {len(new)} new') # Termination is judged on what the API returned, not on what survived # deduplication: a batch can be full and still be entirely duplicates. # The newest stamp in the batch, not events[-1]: ordering is a client-side # convention, not a documented guarantee, and a misordered tail would # regress the cursor and re-ingest events already written. stamps = [canonical(s) for s in (event_ingested(e) for e in events) if s] if len(events) < record_size: # Short batch: the stream is drained. if events and not stamps: print( 'Warning: no event in the final batch carries event.ingested; ' 'cursor left unchanged.' ) if stamps: cursor = max(max(stamps), cursor) return all_events, cursor, True if not stamps: raise FetchError( 'No event in a full batch carries event.ingested, ' 'so the cursor cannot advance' ) batch_max = max(stamps) if batch_max <= cursor: # A full batch fits inside one ingestion millisecond. Stepping past it is the only # way to make progress; holding the cursor here stalls collection forever. # Events beyond record_size at that exact millisecond are unreachable, which # needs more than 1000 events in one millisecond. print( f'Warning: a full batch shares ingestion timestamp {batch_max}; ' 'stepping past it. Events beyond RecordSize at that timestamp are skipped.' ) cursor = next_millisecond(cursor) else: cursor = batch_max return all_events, cursor, False def request_with_retry(url, headers, attempts=4): """GET with backoff on 429 and 5xx. The documented rate limit is 1000 requests per 100 seconds. """ backoff = 1.0 for attempt in range(1, attempts + 1): try: response = http.request('GET', url, headers=headers) except Exception as e: raise FetchError(f'Request to {url} failed: {e}') from e if response.status in (429, 500, 502, 503, 504) and attempt < attempts: retry_after = response.headers.get('Retry-After') try: delay = int(retry_after) if retry_after else backoff except (TypeError, ValueError): delay = backoff # Retry-After is server-controlled input: bound it so a bogus value # cannot sleep past the function timeout or crash time.sleep. delay = min(max(delay, 1.0), 60.0) print(f'HTTP {response.status}. Retrying in {delay}s...') time.sleep(delay) backoff = min(backoff * 2, 30.0) continue if response.status != 200: raise FetchError( f'Request failed: {response.status} {response.data.decode("utf-8")}' ) text = response.data.decode('utf-8') # BeyondTrust's sample folds "Owner" into "owner" before parsing, but that # workaround exists for PowerShell's case-insensitive ConvertFrom-Json. # Python parses case-sensitively, and the SecOps parser maps file.Owner.* # and file.owner to different UDM fields, so both keys must survive. try: return json.loads(text) except json.JSONDecodeError as e: raise FetchError(f'Malformed JSON response: {e}') from e raise FetchError(f'Giving up on {url} after {attempts} attempts') def get_oauth_token(api_url, client_id, client_secret): """Get an access token using the OAuth client credentials flow. The token is valid for one hour. """ body = urlencode({ 'grant_type': 'client_credentials', 'client_id': client_id, 'client_secret': client_secret, 'scope': OAUTH_SCOPE, }) response = http.request( 'POST', f'{api_url}{TOKEN_PATH}', body=body, headers={'Content-Type': 'application/x-www-form-urlencoded'}, ) if response.status != 200: raise FetchError( f'Token request failed: {response.status} ' f'{response.data.decode("utf-8")}' ) return json.loads(response.data.decode('utf-8'))['access_token'] def load_state(bucket, key): """Read the collector state from Cloud Storage. Only a missing object is a cold start. Any other error is raised: swallowing it would reset collection to the lookback window and re-ingest that period. """ blob = bucket.blob(key) try: return json.loads(blob.download_as_text()) except NotFound: print('No state file found. Starting from the lookback window.') return {} def save_state(bucket, key, state): """Write the collector state to Cloud Storage. Failures are raised, not logged. A run that cannot record its cursor must fail, otherwise the next run repeats the same window. """ bucket.blob(key).upload_from_string( json.dumps(state, indent=2), content_type='application/json' ) print(f"Saved state: last_ingested={state.get('last_ingested')}")- Segundo arquivo: requirements.txt::
functions-framework==3.* google-cloud-storage==2.* urllib3>=2.0.0Clique em Implantar para salvar e implantar a função.
Aguarde a conclusão da implantação (2 a 3 minutos).
Criar um job do Cloud Scheduler
O Cloud Scheduler publica mensagens no tópico do Pub/Sub em intervalos regulares, acionando a função do Cloud Run.
- No console Google Cloud , acesse Cloud Scheduler.
- Clique em Criar job.
Informe os seguintes detalhes de configuração:
Configuração Valor Nome beyondtrust-epm-collector-hourlyRegião Selecione a mesma região da função do Cloud Run. Frequência 0 * * * *(a cada hora, na hora)Fuso horário Selecione o fuso horário (UTC recomendado) Tipo de destino Pub/Sub Tópico Selecione o tópico beyondtrust-epm-trigger.Corpo da mensagem {}(objeto JSON vazio)Clique em Criar.
Opções de frequência de programação
Escolha a frequência com base no volume de registros e nos requisitos de latência:
| Frequência | Expressão Cron | Caso de uso |
|---|---|---|
| A cada 5 minutos | */5 * * * * |
Alto volume e baixa latência |
| A cada 15 minutos | */15 * * * * |
Volume médio |
| A cada hora | 0 * * * * |
Padrão (recomendado) |
| A cada 6 horas | 0 */6 * * * |
Baixo volume, processamento em lote |
| Diariamente | 0 0 * * * |
Coleta de dados históricos |
Testar o job do programador
- No console do Cloud Scheduler, encontre seu job.
- Clique em Forçar execução para acionar manualmente.
- Aguarde alguns segundos e acesse Cloud Run > Serviços > beyondtrust-epm-collector > Registros.
- Verifique se a função foi executada com sucesso.
- Verifique o bucket do Cloud Storage para confirmar se os registros foram gravados.
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 Cloud Storage. Você precisa conceder a essa conta de serviço acesso ao seu bucket.
Receber o e-mail da conta de serviço
- 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,
BeyondTrust EPM logs). - Selecione Google Cloud Storage V2 como o Tipo de origem.
- Selecione BeyondTrust Endpoint Privilege Management 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 esse endereço de e-mail para usar na próxima etapa.
Conceder permissões do IAM à conta de serviço do Google SecOps
A conta de serviço do Google SecOps precisa de duas funções no seu bucket do Cloud Storage: Leitor de objetos do Storage para ler os objetos de registro e uma função no nível do bucket para ler os metadados dele.
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket.
- Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar principais: cole o e-mail da conta de serviço do Google SecOps.
- Atribuir papéis: selecione as duas opções a seguir:
- Leitor de objetos do Storage: lê os objetos de registro.
- Leitor de bucket legado do Storage: lê os metadados do bucket. Se você selecionou a opção de exclusão Excluir arquivos transferidos e diretórios vazios, escolha Gravador de bucket legado do Storage, que também concede a permissão de exclusão.
Clique em Salvar.
Configurar um feed no Google SecOps para ingerir registros do BeyondTrust EPM
- 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,
BeyondTrust EPM logs). - Selecione Google Cloud Storage V2 como o Tipo de origem.
- Selecione BeyondTrust Endpoint Privilege Management como o Tipo de registro.
- Clique em Próxima.
Especifique valores para os seguintes parâmetros de entrada:
URL do bucket de armazenamento: insira o URI do bucket do Cloud Storage com o caminho do prefixo:
gs://beyondtrust-epm-logs/beyondtrust-epm/Substituir:
beyondtrust-epm-logs: o nome do bucket do Cloud Storage.beyondtrust-epm/: prefixo/caminho da pasta opcional onde os registros são armazenados (deixe em branco para a raiz).
Exemplos:
- Bucket raiz:
gs://beyondtrust-epm-logs/ - Com prefixo:
gs://beyondtrust-epm-logs/beyondtrust-epm/
- Bucket raiz:
Opção de exclusão da fonte: selecione a opção de exclusão de acordo com sua preferência:
- Nunca excluir arquivos: nunca exclua arquivos da origem. Isso é recomendado para fins de teste.
Excluir arquivos transferidos e diretórios vazios: exclui arquivos e diretórios vazios da origem após a conclusão de uma busca bem-sucedida.
Idade máxima do arquivo: inclui arquivos modificados nos últimos 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.
Tabela de mapeamento de UDM
| Campo de registro | Mapeamento do UDM | Lógica |
|---|---|---|
DomainIdentifier_label |
additional.fields |
Mesclado |
WatsonEventType_label |
additional.fields |
Mesclado |
action_label |
additional.fields |
Mesclado |
activity_id_label |
additional.fields |
Mesclado |
app_id_label |
additional.fields |
Mesclado |
app_insights_instrumentation_key_label |
additional.fields |
Mesclado |
asimov_instrumentation_key_label |
additional.fields |
Mesclado |
authorization_request_control_authorization_label |
additional.fields |
Mesclado |
bundle_name_label |
additional.fields |
Mesclado |
changedBy_label |
additional.fields |
Mesclado |
code_signature_subject_name_label |
additional.fields |
Mesclado |
collector_api_key_label |
additional.fields |
Mesclado |
command_label |
additional.fields |
Mesclado |
configuration_application_group_description_label |
additional.fields |
Mesclado |
configuration_application_group_identifier_label |
additional.fields |
Mesclado |
configuration_application_group_name_label |
additional.fields |
Mesclado |
configuration_application_identifier_label |
additional.fields |
Mesclado |
configuration_application_type_label |
additional.fields |
Mesclado |
configuration_identifier_label |
additional.fields |
Mesclado |
configuration_message_identifier_label |
additional.fields |
Mesclado |
configuration_message_name_label |
additional.fields |
Mesclado |
configuration_message_type_label |
additional.fields |
Mesclado |
configuration_name_label |
additional.fields |
Mesclado |
configuration_revision_number_label |
additional.fields |
Mesclado |
configuration_rule_identifier_label |
additional.fields |
Mesclado |
configuration_rule_on_demand_label |
additional.fields |
Mesclado |
configuration_rule_script_outcome_rule_affected_label |
additional.fields |
Mesclado |
configuration_token_identifier_label |
additional.fields |
Mesclado |
configuration_token_name_label |
additional.fields |
Mesclado |
configuration_workstyle_description_label |
additional.fields |
Mesclado |
configuration_workstyle_identifier_label |
additional.fields |
Mesclado |
configuration_workstyle_name_label |
additional.fields |
Mesclado |
content_length_label |
additional.fields |
Mesclado |
content_type_label |
additional.fields |
Mesclado |
domainNetBIOSName_label |
additional.fields |
Mesclado |
domain_label |
additional.fields |
Mesclado |
entity_label |
additional.fields |
Mesclado |
entity_name_label |
additional.fields |
Mesclado |
event_action_label |
additional.fields |
Mesclado |
exitstatus_label |
additional.fields |
Mesclado |
file_hash_md5_label |
additional.fields |
Mesclado |
file_hash_sha1_label |
additional.fields |
Mesclado |
file_hash_sha256_label |
additional.fields |
Mesclado |
file_version_label |
additional.fields |
Mesclado |
gid_label |
additional.fields |
Mesclado |
group_data_id_label |
additional.fields |
Mesclado |
group_id_label |
additional.fields |
Mesclado |
group_label |
additional.fields |
Mesclado |
handle_label |
additional.fields |
Mesclado |
host_name_label |
additional.fields |
Mesclado |
host_uptime_labels |
additional.fields |
Mesclado |
http_host_label |
additional.fields |
Mesclado |
id_label |
additional.fields |
Mesclado |
iolog_label |
additional.fields |
Mesclado |
is_opted_in_label |
additional.fields |
Mesclado |
linenum_label |
additional.fields |
Mesclado |
local_identifier_label |
additional.fields |
Mesclado |
locale_label |
additional.fields |
Mesclado |
master_utcoffset_label |
additional.fields |
Mesclado |
masterlocale_label |
additional.fields |
Mesclado |
owner_identifier_label |
additional.fields |
Mesclado |
parent_entity_id_label |
additional.fields |
Mesclado |
parent_process_exec_label |
additional.fields |
Mesclado |
parent_process_label |
additional.fields |
Mesclado |
pbmasterdnodename_label |
additional.fields |
Mesclado |
pipeName_label |
additional.fields |
Mesclado |
process_entity_id_label |
additional.fields |
Mesclado |
process_hash_label |
additional.fields |
Mesclado |
process_name_label |
additional.fields |
Mesclado |
process_parent_name_label |
additional.fields |
Mesclado |
process_start_time_label |
additional.fields |
Mesclado |
processexe_label |
additional.fields |
Mesclado |
product_label |
additional.fields |
Mesclado |
product_type_label |
additional.fields |
Mesclado |
product_version_label |
additional.fields |
Mesclado |
requestuser_label |
additional.fields |
Mesclado |
runargv_label |
additional.fields |
Mesclado |
runcwd_label |
additional.fields |
Mesclado |
runeffectivegroup_label |
additional.fields |
Mesclado |
runeffectiveuser_label |
additional.fields |
Mesclado |
runhost_label |
additional.fields |
Mesclado |
schema_version_label |
additional.fields |
Mesclado |
sku_name_label |
additional.fields |
Mesclado |
telemetry_level_label |
additional.fields |
Mesclado |
tenant_id_label |
additional.fields |
Mesclado |
type_label |
additional.fields |
Mesclado |
uid_label |
additional.fields |
Mesclado |
user_id_label |
additional.fields |
Mesclado |
user_name_label |
additional.fields |
Mesclado |
vs_exe_version_label |
additional.fields |
Mesclado |
inter_host |
intermediary.hostname |
Mapeado diretamente |
Processes.description |
metadata.description |
Mapeado diretamente |
details |
metadata.description |
Mapeado diretamente |
event_data.reason |
metadata.description |
Mapeado diretamente |
file.pe.description |
metadata.description |
Mapeado diretamente |
created |
metadata.event_timestamp |
Analisado como ISO8601 |
datetime |
metadata.event_timestamp |
Analisado como MMM dd HH:mm:ss |
has_principal |
metadata.event_type |
Mapeado: true → STATUS_UPDATE |
has_user |
metadata.event_type |
Mapeado: true → USER_UNCATEGORIZED |
parent_working_directory_label |
metadata.ingestion_labels |
Mesclado |
working_directory_label |
metadata.ingestion_labels |
Mesclado |
auditType |
metadata.product_event_type |
Mapeado diretamente |
event_datas.ActionId |
metadata.product_log_id |
Mapeado diretamente |
labels.related_item_id |
metadata.product_log_id |
Mapeado diretamente |
uniqueid |
metadata.product_log_id |
Mapeado diretamente |
masterdversion |
metadata.product_version |
Mapeado diretamente |
headers.http_version |
network.application_protocol_version |
Mapeado diretamente |
headers.request_method |
network.http.method |
Mapeado diretamente |
host.os.platform |
principal.administrative_domain |
Mapeado diretamente |
Processes.process |
principal.application |
Mapeado diretamente |
agent_ephemeral_id_label |
principal.asset.attribute.labels |
Mesclado |
agent_id_label |
principal.asset.attribute.labels |
Mesclado |
agent_version_label |
principal.asset.attribute.labels |
Mesclado |
ecs_version_label |
principal.asset.attribute.labels |
Mesclado |
_hardware |
principal.asset.hardware |
Mesclado |
host.hostname |
principal.asset.hostname |
Mapeado diretamente |
submithost |
principal.asset.hostname |
Mapeado diretamente |
ip_address |
principal.asset.ip |
Mesclado |
masterhostip |
principal.asset.ip |
Mesclado |
submithostip |
principal.asset.ip |
Mesclado |
file.path |
principal.file.full_path |
Mapeado diretamente |
lineinfile |
principal.file.full_path |
Mapeado diretamente |
host.hostname |
principal.hostname |
Mapeado diretamente |
submithost |
principal.hostname |
Mapeado diretamente |
ip_address |
principal.ip |
Mesclado |
masterhostip |
principal.ip |
Mesclado |
submithostip |
principal.ip |
Mesclado |
mac |
principal.mac |
Mesclado |
host.os.name |
principal.platform_version |
Mapeado diretamente |
host.os.version |
principal.platform_version |
Mapeado diretamente |
process.command_line |
principal.process.command_line |
Mapeado diretamente |
runcommand |
principal.process.command_line |
Mapeado diretamente |
process.executable |
principal.process.file.full_path |
Mapeado diretamente |
cmd |
principal.process.parent_process.command_line |
Mapeado diretamente |
Processes.process_path |
principal.process.parent_process.file.full_path |
Mapeado diretamente |
process.parent.executable |
principal.process.parent_process.file.full_path |
Mapeado diretamente |
Processes.parent_process_id |
principal.process.parent_process.pid |
Mapeado diretamente |
Processes.process_id |
principal.process.pid |
Mapeado diretamente |
logpid |
principal.process.pid |
Mapeado diretamente |
file.Owner.DomainName |
principal.user.company_name |
Mapeado diretamente |
file.Owner.Name |
principal.user.user_display_name |
Mapeado diretamente |
runuser |
principal.user.user_display_name |
Mapeado diretamente |
userName |
principal.user.user_display_name |
Mapeado diretamente |
Processes.user |
principal.user.userid |
Mapeado diretamente |
userId |
principal.user.userid |
Mapeado diretamente |
userid |
principal.user.userid |
Mapeado diretamente |
Processes.user_id |
principal.user.windows_sid |
Mapeado diretamente |
EPMWinMac.Configuration.Rule.Action |
security_result.action |
Mesclado |
security_result_action |
security_result.action |
Mesclado |
event_data.outcome |
security_result.category_details |
Mesclado |
host.os.version |
security_result.category_details |
Mesclado |
EPMWinMac.Configuration.Application.Description |
security_result.description |
Mapeado diretamente |
EPMWinMac.Configuration.Message.Description |
security_result.description |
Mapeado diretamente |
host.os.type |
src.administrative_domain |
Mapeado diretamente |
file.name |
src.file.names |
Mesclado |
host.os.full |
src.platform_version |
Mapeado diretamente |
host.os.family |
target.administrative_domain |
Mapeado diretamente |
Processes.dest |
target.asset.hostname |
Mapeado diretamente |
file.extension |
target.file.mime_type |
Mapeado diretamente |
Processes.dest |
target.hostname |
Mapeado diretamente |
host.domain |
target.hostname |
Mapeado diretamente |
file_DriveType_label |
target.resource.attribute.labels |
Mesclado |
file_drive_letter_label |
target.resource.attribute.labels |
Mesclado |
owner_label |
target.resource.attribute.labels |
Mesclado |
| N/A | metadata.event_type |
Constante: USER_UNCATEGORIZED |
| N/A | metadata.product_name |
Constante: Beyondtrust Privilege Management |
| N/A | metadata.vendor_name |
Constante: Beyondtrust Privilege Management |
| N/A | network.application_protocol |
Constante: HTTP |
| N/A | principal.platform |
Constante: MAC |
Registro de alterações
Ver o registro de alterações deste analisador
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.