Recolha registos de auditoria do Tines

Compatível com:

Este documento explica como carregar registos de auditoria do Tines para o Google Security Operations através do Amazon S3.

Antes de começar

Certifique-se de que cumpre os seguintes pré-requisitos:

  • Uma instância do Google SecOps.
  • Acesso privilegiado ao Tines.
  • Acesso privilegiado à AWS (S3, Identity and Access Management [IAM], Lambda e EventBridge).

Obtenha o URL do Tines

  1. No navegador, abra a IU do Tines para o seu inquilino.
  2. Copie o domínio da barra de endereço. Vai usá-lo como TINES_BASE_URL.
    • Formato: https://<tenant-domain> (por exemplo, https://<tenant-domain>.tines.com).

Valores a guardar para passos posteriores:

  • TINES_BASE_URL — Por exemplo, https://<domain>.tines.com
  • TINES_API_KEY — O token que cria nos passos seguintes
  1. Aceda ao menu de navegação > Chaves de API.
  2. Clique em + Nova chave.
  3. Selecione Chave da API de serviço.
  4. Introduza um nome descritivo (por exemplo, SecOps Audit Logs).
  5. Clique em Criar.
  6. Copie imediatamente o token gerado e guarde-o em segurança. Vai usá-lo como TINES_API_KEY.

Opção 2: chave da API pessoal (se as chaves de serviço não estiverem disponíveis)

  1. Aceda ao menu de navegação > Chaves de API.
  2. Clique em + Nova chave.
  3. Selecione Chave da API pessoal.
  4. Introduza um nome descritivo.
  5. Clique em Criar.
  6. Copie o token gerado e guarde-o de forma segura.

Conceda a autorização de leitura do registo de auditoria

  1. Inicie sessão como proprietário do inquilino (ou peça a um proprietário do inquilino que o faça).
  2. Aceda a Definições > Administração > Administração de utilizadores (ou clique no nome da sua equipa no menu superior esquerdo e selecione Utilizadores).
  3. Encontre o utilizador da conta de serviço associado à sua chave da API de serviço (tem o mesmo nome que a sua chave da API).
    • Se estiver a usar uma chave da API pessoal, encontre a sua própria conta de utilizador.
  4. Clique no utilizador para abrir o respetivo perfil.
  5. Na secção Autorizações do inquilino, ative a opção AUDIT_LOG_READ.
  6. Clique em Guardar.

(Opcional) Valide o acesso à API

  1. Teste o ponto final com curl ou qualquer cliente HTTP:

    curl -X GET "https://<tenant-domain>/api/v1/audit_logs?per_page=1" \
        -H "Authorization: Bearer <TINES_API_KEY>" \
        -H "Content-Type: application/json"
    
  2. Deve receber uma resposta JSON com entradas do registo de auditoria.

  3. Também pode verificar se existem registos de auditoria navegando para Definições > Monitorização > Registos de auditoria na IU (requer a autorização AUDIT_LOG_READ).

Configure o contentor do AWS S3

  1. Crie um contentor do Amazon S3 seguindo este guia do utilizador: Criar um contentor
  2. Guarde o nome e a região do contentor para referência futura (por exemplo, tines-audit-logs).

Configure a política e a função de IAM para carregamentos do Lambda S3

  1. Na consola da AWS, aceda a IAM > Políticas > Criar política > separador JSON.
  2. Copie e cole a seguinte política.
  3. JSON da política (substitua tines-audit-logs se tiver introduzido um nome de contentor diferente):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowPutObjects",
          "Effect": "Allow",
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::tines-audit-logs/*"
        },
        {
          "Sid": "AllowGetStateObject",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::tines-audit-logs/tines/audit/state.json"
        }
      ]
    }
    
  4. Clique em Seguinte > Criar política.

  5. Atribua um nome à política TinesLambdaS3Policy.

  6. Aceda a IAM > Funções > Criar função > Serviço AWS > Lambda.

  7. Anexe o TinesLambdaS3Policy que acabou de criar.

  8. Dê o nome TinesAuditToS3Role à função e clique em Criar função.

Crie a função Lambda

  1. Na consola da AWS, aceda a Lambda > Functions > Create function.
  2. Clique em Criar do zero.
  3. Faculte os seguintes detalhes de configuração:

    Definição Valor
    Nome tines_audit_to_s3
    Runtime Python 3.13
    Arquitetura x86_64
    Função de execução TinesAuditToS3Role
  4. Depois de criar a função, abra o separador Código, elimine o fragmento e cole o seguinte código (tines_audit_to_s3.py).

    #!/usr/bin/env python3
    # Lambda: Pull Tines Audit Logs to S3 (no transform)
    
    import os, json, time, urllib.parse
    from urllib.request import Request, urlopen
    from urllib.error import HTTPError, URLError
    import boto3
    
    S3_BUCKET      = os.environ["S3_BUCKET"]
    S3_PREFIX      = os.environ.get("S3_PREFIX", "tines/audit/")
    STATE_KEY      = os.environ.get("STATE_KEY", "tines/audit/state.json")
    LOOKBACK_SEC   = int(os.environ.get("LOOKBACK_SECONDS", "3600"))  # default 1h
    PAGE_SIZE      = int(os.environ.get("PAGE_SIZE", "500"))  # Max is 500 for Tines
    MAX_PAGES      = int(os.environ.get("MAX_PAGES", "20"))
    TIMEOUT        = int(os.environ.get("HTTP_TIMEOUT", "60"))
    HTTP_RETRIES   = int(os.environ.get("HTTP_RETRIES", "3"))
    TINES_BASE_URL = os.environ["TINES_BASE_URL"]
    TINES_API_KEY  = os.environ["TINES_API_KEY"]
    
    s3 = boto3.client("s3")
    
    def _iso(ts: float) -> str:
        return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(ts))
    
    def _load_state() -> dict:
        try:
            obj = s3.get_object(Bucket=S3_BUCKET, Key=STATE_KEY)
            b = obj["Body"].read()
            return json.loads(b) if b else {}
        except Exception:
            return {}
    
    def _save_state(st: dict) -> None:
        s3.put_object(
            Bucket=S3_BUCKET, Key=STATE_KEY,
            Body=json.dumps(st, separators=(",", ":")).encode("utf-8"),
            ContentType="application/json",
        )
    
    def _req(url: str) -> dict:
        attempt = 0
        while True:
            try:
                req = Request(url, method="GET")
                req.add_header("Authorization", f"Bearer {TINES_API_KEY}")
                req.add_header("Accept", "application/json")
                req.add_header("Content-Type", "application/json")
                with urlopen(req, timeout=TIMEOUT) as r:
                    data = r.read()
                return json.loads(data.decode("utf-8"))
            except HTTPError as e:
                if e.code in (429, 500, 502, 503, 504) and attempt < HTTP_RETRIES:
                    retry_after = 1 + attempt
                    try:
                        retry_after = int(e.headers.get("Retry-After", retry_after))
                    except Exception:
                        pass
                    time.sleep(max(1, retry_after))
                    attempt += 1
                    continue
                raise
            except URLError:
                if attempt < HTTP_RETRIES:
                    time.sleep(1 + attempt)
                    attempt += 1
                    continue
                raise
    
    def _write(payload, page: int) -> str:
        ts = time.gmtime()
        key = f"{S3_PREFIX}{time.strftime('%Y/%m/%d/%H%M%S', ts)}-tines-audit-{page:05d}.json"
        s3.put_object(
            Bucket=S3_BUCKET, Key=key,
            Body=json.dumps(payload, separators=(",", ":")).encode("utf-8"),
            ContentType="application/json",
        )
        return key
    
    def _extract_items(payload) -> list:
        if isinstance(payload, list):
            return payload
        if isinstance(payload, dict):
            audit_logs = payload.get("audit_logs")
            if isinstance(audit_logs, list):
                return audit_logs
        return []
    
    def _extract_newest_ts(items: list, current: str | None) -> str | None:
        newest = current
        for it in items:
            # Use created_at as the timestamp field
            t = it.get("created_at")
            if isinstance(t, str) and (newest is None or t > newest):
                newest = t
        return newest
    
    def lambda_handler(event=None, context=None):
        st = _load_state()
        since = st.get("since") or _iso(time.time() - LOOKBACK_SEC)
    
        page = 1
        pages = 0
        total = 0
        newest_ts = since
    
        while pages < MAX_PAGES:
            # Build URL with query parameters
            # Note: Tines audit logs API uses 'after' parameter for filtering
            base_url = f"{TINES_BASE_URL.rstrip('/')}/api/v1/audit_logs"
            params = {
                "after": since,  # Filter for logs created after this timestamp
                "page": page,
                "per_page": PAGE_SIZE
            }
            url = f"{base_url}?{urllib.parse.urlencode(params)}"
    
            payload = _req(url)
            _write(payload, page)
            items = _extract_items(payload)
            total += len(items)
            newest_ts = _extract_newest_ts(items, newest_ts)
            pages += 1
    
            # Check if there's a next page using meta.next_page_number
            meta = payload.get("meta") or {}
            next_page = meta.get("next_page_number")
    
            if not next_page:
                break
            page = next_page
    
        if newest_ts and newest_ts != since:
            st["since"] = newest_ts
            _save_state(st)
    
        return {"ok": True, "pages": pages, "items": total, "since": st.get("since")}
    
    if __name__ == "__main__":
        print(lambda_handler())
    
  5. Aceda a Configuração > Variáveis de ambiente.

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

  7. Introduza as variáveis de ambiente fornecidas na tabela seguinte, substituindo os valores de exemplo pelos seus valores.

    Variáveis de ambiente

    Chave Valor de exemplo
    S3_BUCKET tines-audit-logs
    S3_PREFIX tines/audit/
    STATE_KEY tines/audit/state.json
    TINES_BASE_URL https://your-tenant.tines.com
    TINES_API_KEY your-tines-api-key
    LOOKBACK_SECONDS 3600
    PAGE_SIZE 500
    MAX_PAGES 20
    HTTP_TIMEOUT 60
    HTTP_RETRIES 3
  8. Depois de criar a função, permaneça na respetiva página (ou abra Lambda > Functions > a sua função).

  9. Selecione o separador Configuração.

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

  11. Altere Tempo limite para 5 minutos (300 segundos) e clique em Guardar.

Crie um horário do EventBridge

  1. Aceda a Amazon EventBridge > Scheduler > Create schedule.
  2. Indique os seguintes detalhes de configuração:
    • Agenda recorrente: Taxa (1 hour).
    • Destino: a sua função Lambda tines_audit_to_s3.
    • Nome: tines-audit-1h.
  3. Clique em Criar programação.

Crie um utilizador e chaves da IAM só de leitura para o Google SecOps

  1. Na consola da AWS, aceda a IAM > Utilizadores.
  2. Clique em Adicionar utilizadores.
  3. Indique os seguintes detalhes de configuração:
    • Utilizador: introduza secops-reader.
    • Tipo de acesso: selecione Chave de acesso – Acesso programático.
  4. Clique em Criar utilizador.
  5. Anexe a política de leitura mínima (personalizada): Users > secops-reader > Permissions > Add permissions > Attach policies directly > Create policy.
  6. JSON:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": "arn:aws:s3:::tines-audit-logs/*"
        },
        {
          "Effect": "Allow",
          "Action": ["s3:ListBucket"],
          "Resource": "arn:aws:s3:::tines-audit-logs"
        }
      ]
    }
    
  7. Nome = secops-reader-policy.

  8. Clique em Criar política > procure/selecione > Seguinte > Adicionar autorizações.

  9. Crie uma chave de acesso para secops-reader: Credenciais de segurança > Chaves de acesso.

  10. Clique em Criar chave de acesso.

  11. Transfira o .CSV. (Vai colar estes valores no feed).

Configure um feed no Google SecOps para carregar registos de auditoria do Tines

  1. Aceda a Definições do SIEM > Feeds.
  2. Clique em + Adicionar novo feed.
  3. No campo Nome do feed, introduza um nome para o feed (por exemplo, Tines Audit Logs).
  4. Selecione Amazon S3 V2 como o Tipo de origem.
  5. Selecione Tines como o Tipo de registo.
  6. Clicar em Seguinte.
  7. Especifique valores para os seguintes parâmetros de entrada:
    • URI do S3: s3://tines-audit-logs/tines/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: inclua ficheiros modificados no último número de dias. A predefinição é 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 aplicada aos eventos deste feed.
  8. Clicar em Seguinte.
  9. 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.