Recolha registos de auditoria da Harness IO
Este documento explica como carregar registos de auditoria do Harness IO para o Google Security Operations através do Amazon S3.
Antes de começar
- Instância do Google SecOps
- Acesso privilegiado ao Harness (ID da conta e chave da API)
- Acesso privilegiado à AWS (S3, IAM, Lambda, EventBridge)
Obtenha a chave da API e o ID da conta do Harness para uma conta pessoal
- Inicie sessão na IU Web do Harness.
- Aceda ao seu perfil de utilizador > As minhas chaves da API.
- Selecione Chave da API.
- Introduza um Nome para a chave da API.
- Clique em Guardar.
- Selecione Token na nova chave da API.
- Introduza um Nome para o token.
- Clique em Gerar token.
- Copie e guarde o token num local seguro.
- Copie e guarde o ID da conta (apresentado no URL do Harness e nas Definições da conta).
Opcional: obtenha a chave da API e o ID da conta do Harness para uma conta de serviço
- Inicie sessão na IU Web do Harness.
- Crie uma conta de serviço
- Aceda a Account Settings > Access Control (Definições da conta > Controlo de acesso).
- Selecione Contas de serviço > selecione a conta de serviço para a qual quer criar uma chave da API.
- Em Chaves da API, selecione Chave da API.
- Introduza um Nome para a chave da API.
- Clique em Guardar.
- Selecione Token na nova chave da API.
- Introduza um nome para o token.
- Clique em Gerar token.
- Copie e guarde o token num local seguro.
- Copie e guarde o ID da conta (apresentado no URL do Harness e nas Definições da conta).
Configure o contentor do AWS S3 e o IAM para o Google SecOps
- Crie um contentor do Amazon S3 seguindo este manual do utilizador: Criar um contentor
- Guarde o nome e a região do contentor para referência futura (por exemplo,
harness-io
). - Crie um utilizador seguindo este guia do utilizador: Criar um utilizador do IAM.
- Selecione o utilizador criado.
- Selecione o separador Credenciais de segurança.
- Clique em Criar chave de acesso na secção Chaves de acesso.
- Selecione Serviço de terceiros como o Exemplo de utilização.
- Clicar em Seguinte.
- Opcional: adicione uma etiqueta de descrição.
- Clique em Criar chave de acesso.
- Clique em Transferir ficheiro CSV para guardar a chave de acesso e a chave de acesso secreta para utilização posterior.
- Clique em Concluído.
- Selecione o separador Autorizações.
- Clique em Adicionar autorizações na secção Políticas de autorizações.
- Selecione Adicionar autorizações.
- Selecione Anexar políticas diretamente
- Pesquise e selecione a política AmazonS3FullAccess.
- Clicar em Seguinte.
- Clique em Adicionar autorizações.
Configure a política e a função de IAM para carregamentos do S3
- Na consola da AWS, aceda a IAM > Políticas > Criar política > separador JSON.
Introduza a seguinte política:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutHarnessObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::harness-io/*" }, { "Sid": "AllowGetStateObject", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::harness-io/harness/audit/state.json" } ] }
- Substitua
harness-io
se tiver introduzido um nome de contentor diferente):
- Substitua
Clique em Seguinte > Criar política.
Aceda a IAM > Funções > Criar função > Serviço AWS > Lambda.
Anexe a política criada recentemente.
Dê o nome
WriteHarnessToS3Role
à função e clique em Criar função.
Crie a função Lambda
- Na consola da AWS, aceda a Lambda > Functions > Create function.
- Clique em Criar do zero.
Faculte os seguintes detalhes de configuração:
Definição Valor Nome harness_io_to_s3
Runtime Python 3.13 Arquitetura x86_64 Função de execução WriteHarnessToS3Role
Depois de criar a função, abra o separador Código, elimine o fragmento de código e introduza o seguinte código (
harness_io_to_s3.py
).#!/usr/bin/env python3 import os, json, time, urllib.parse from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError import boto3 API_BASE = os.environ.get("HARNESS_API_BASE", "https://app.harness.io").rstrip("/") ACCOUNT_ID = os.environ["HARNESS_ACCOUNT_ID"] API_KEY = os.environ["HARNESS_API_KEY"] # x-api-key token BUCKET = os.environ["S3_BUCKET"] PREFIX = os.environ.get("S3_PREFIX", "harness/audit/").strip("/") STATE_KEY = os.environ.get("STATE_KEY", "harness/audit/state.json") PAGE_SIZE = min(int(os.environ.get("PAGE_SIZE", "100")), 100) # <=100 START_MINUTES_BACK = int(os.environ.get("START_MINUTES_BACK", "60")) s3 = boto3.client("s3") HDRS = {"x-api-key": API_KEY, "Content-Type": "application/json", "Accept": "application/json"} def _read_state(): try: obj = s3.get_object(Bucket=BUCKET, Key=STATE_KEY) j = json.loads(obj["Body"].read()) return j.get("since"), j.get("pageToken") except Exception: return None, None def _write_state(since_ms: int, page_token: str | None): body = json.dumps({"since": since_ms, "pageToken": page_token}).encode("utf-8") s3.put_object(Bucket=BUCKET, Key=STATE_KEY, Body=body, ContentType="application/json") def _http_post(path: str, body: dict, query: dict, timeout: int = 60, max_retries: int = 5) -> dict: qs = urllib.parse.urlencode(query) url = f"{API_BASE}{path}?{qs}" data = json.dumps(body).encode("utf-8") attempt, backoff = 0, 1.0 while True: req = Request(url, data=data, method="POST") for k, v in HDRS.items(): req.add_header(k, v) try: with urlopen(req, timeout=timeout) as r: return json.loads(r.read().decode("utf-8")) except HTTPError as e: if (e.code == 429 or 500 <= e.code <= 599) and attempt < max_retries: time.sleep(backoff) attempt += 1 backoff *= 2 continue raise except URLError: if attempt < max_retries: time.sleep(backoff) attempt += 1 backoff *= 2 continue raise def _write_page(obj: dict, now: float, page_index: int) -> str: ts = time.strftime("%Y/%m/%d/%H%M%S", time.gmtime(now)) key = f"{PREFIX}/{ts}-page{page_index:05d}.json" s3.put_object( Bucket=BUCKET, Key=key, Body=json.dumps(obj, separators=(",", ":")).encode("utf-8"), ContentType="application/json", ) return key def fetch_and_store(): now_s = time.time() since_ms, page_token = _read_state() if since_ms is None: since_ms = int((now_s - START_MINUTES_BACK * 60) * 1000) until_ms = int(now_s * 1000) page_index = 0 total = 0 while True: body = {"startTime": since_ms, "endTime": until_ms} query = {"accountIdentifier": ACCOUNT_ID, "pageSize": PAGE_SIZE} if page_token: query["pageToken"] = page_token else: query["pageIndex"] = page_index data = _http_post("/audit/api/audits/listV2", body, query) _write_page(data, now_s, page_index) entries = [] for key in ("data", "content", "response", "resource", "resources", "items"): if isinstance(data.get(key), list): entries = data[key] break total += len(entries) if isinstance(entries, list) else 0 next_token = ( data.get("pageToken") or (isinstance(data.get("meta"), dict) and data["meta"].get("pageToken")) or (isinstance(data.get("metadata"), dict) and data["metadata"].get("pageToken")) ) if next_token: page_token = next_token page_index += 1 continue if len(entries) < PAGE_SIZE: break page_index += 1 _write_state(until_ms, None) return {"pages": page_index + 1, "objects_estimate": total} def lambda_handler(event=None, context=None): return fetch_and_store() if __name__ == "__main__": print(lambda_handler())
Aceda a Configuração > Variáveis de ambiente > Editar > Adicionar nova variável de ambiente.
Introduza as seguintes variáveis de ambiente, substituindo-as pelos seus valores:
Chave Exemplo S3_BUCKET
harness-io
S3_PREFIX
harness/audit/
STATE_KEY
harness/audit/state.json
HARNESS_ACCOUNT_ID
123456789
HARNESS_API_KEY
harness_xxx_token
HARNESS_API_BASE
https://app.harness.io
PAGE_SIZE
100
START_MINUTES_BACK
60
Depois de criar a função, permaneça na respetiva página (ou abra Lambda > Functions > your‑function).
Selecione o separador Configuração.
No painel Configuração geral, clique em Editar.
Altere Tempo limite para 5 minutos (300 segundos) e clique em Guardar.
Crie um horário do EventBridge
- Aceda a Amazon EventBridge > Scheduler > Create schedule.
Faculte os seguintes detalhes de configuração:
- Agenda recorrente: Taxa (
1 hour
). - Alvo: a sua função Lambda.
- Nome:
harness-io-1h
.
- Agenda recorrente: Taxa (
Clique em Criar programação.
Crie um utilizador e chaves da IAM só de leitura para o Google SecOps
- Na consola da AWS, aceda a IAM > Users e, de seguida, clique em Add users.
- Indique os seguintes detalhes de configuração:
- Utilizador: introduza um nome único (por exemplo,
secops-reader
) - Tipo de acesso: selecione Chave de acesso – Acesso programático
- Clique em Criar utilizador.
- Utilizador: introduza um nome único (por exemplo,
- Anexe a política de leitura mínima (personalizada): Utilizadores > selecione
secops-reader
> Autorizações > Adicionar autorizações > Anexar políticas diretamente > Criar política No editor JSON, introduza a seguinte política:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::<your-bucket>/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::<your-bucket>" } ] }
Defina o nome como
secops-reader-policy
.Aceda a Criar política > pesquise/selecione > Seguinte > Adicionar autorizações.
Aceda a Credenciais de segurança > Chaves de acesso > Criar chave de acesso.
Transfira o CSV (estes valores são introduzidos no feed).
Configure um feed no Google SecOps para carregar registos do Harness IO
- Aceda a Definições do SIEM > Feeds.
- Clique em Adicionar novo feed.
- No campo Nome do feed, introduza um nome para o feed (por exemplo,
Harness IO
). - Selecione Amazon S3 V2 como o Tipo de origem.
- Selecione Harness IO como o Tipo de registo.
- Clicar em Seguinte.
- Especifique valores para os seguintes parâmetros de entrada:
- URI do S3:
s3://harness-io/harness/audit/
- Opções de eliminação de origens: selecione a opção de eliminação de acordo com a sua preferência.
- Idade máxima do ficheiro: predefinição de 180 dias.
- ID da chave de acesso: chave de acesso do utilizador com acesso ao contentor do S3.
- Chave de acesso secreta: chave secreta do utilizador com acesso ao contentor do S3.
- Espaço de nomes do recurso: o espaço de nomes do recurso.
- Etiquetas de carregamento: a etiqueta a aplicar aos eventos deste feed.
- URI do S3:
- Clicar em Seguinte.
- Reveja a nova configuração do feed no ecrã Finalizar e, de seguida, clique em Enviar.
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.