SecuAAS Docs

Log Collection and Ingestion

SecuSiem — Log Collection and Ingestion

Log Collection and Ingestion

Log Collection and Ingestion

Overview

SecuSiem collects logs from client applications and infrastructure through the ingestion-api service, which acts as a Loki-compatible proxy with multi-tenant isolation.

Ingestion Architecture

Client Application / Agent
        |
        | HTTPS + Bearer Token (sk_live_xxx)
        v
+-------------------+
|  ingestion-api    |
|  (Port 8000)      |
+-------------------+
        |
        | Internal HTTP + X-Scope-OrgID header
        v
+-------------------+
|  Grafana Loki 3.0 |
|  (Port 3100)      |
+-------------------+
        |
        v
  Filesystem / S3 Storage

Supported Log Sources

SourceProtocolDescription
Application SDKHTTPS POSTDirect API calls with Loki-format JSON
SyslogSyslog -> Promtail -> LokiTraditional syslog forwarding via Promtail
KubernetesPromtail DaemonSetAutomatic pod log collection
Custom agentsHTTPS POSTAny HTTP client sending Loki-format data

Sending Logs (SDK / API)

Authentication

Every request must include a valid API key:

Authorization: Bearer sk_live_AbCdEfGh...

API keys are generated per tenant via the tenant-manager API.

Log Format (Loki Push API)

{
  "streams": [
    {
      "stream": {
        "job": "web-api",
        "app": "conformvault",
        "environment": "production",
        "level": "error"
      },
      "values": [
        ["1738000000000000000", "Error processing request: connection timeout"],
        ["1738000001000000000", "Retrying connection to database"]
      ]
    }
  ]
}
  • stream: Label key-value pairs for indexing and querying
  • values: Array of [timestamp_nanoseconds, log_line] pairs
  • Timestamps must be in nanoseconds (Unix epoch * 10^9)

Example: Python Client

import httpx
import time

SECUSIEM_URL = "https://ingestion.secusiem.secuaas.dev"
API_KEY = "sk_live_AbCdEfGh..."

async def send_logs(logs: list[str]):
    timestamp_ns = str(int(time.time() * 1e9))
    
    payload = {
        "streams": [{
            "stream": {
                "job": "my-app",
                "app": "web-api",
                "environment": "production",
                "level": "info"
            },
            "values": [[timestamp_ns, log] for log in logs]
        }]
    }
    
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{SECUSIEM_URL}/loki/api/v1/push",
            headers={
                "Authorization": f"Bearer {API_KEY}",
                "Content-Type": "application/json"
            },
            json=payload
        )
        assert response.status_code == 204

Example: cURL

curl -X POST https://ingestion.secusiem.secuaas.dev/loki/api/v1/push \
  -H "Authorization: Bearer sk_live_AbCdEfGh..." \
  -H "Content-Type: application/json" \
  -d '{
    "streams": [{
      "stream": {"job": "syslog", "level": "warning"},
      "values": [["'$(date +%s)000000000'", "Failed login attempt from 10.0.0.1"]]
    }]
  }'

Multi-tenant Flow

  1. Client sends logs with Bearer token
  2. ingestion-api validates the API key
  3. Tenant is identified from the API key
  4. Loki X-Scope-OrgID header is set to tenant-{slug}
  5. Logs are forwarded to Loki with tenant isolation
  6. Each tenant's logs are stored in separate Loki streams

Rate Limiting

Rate limiting is configured per API key via the rate_limit_rpm field:

PlanDefault Rate Limit
Starter100 requests/min
Pro500 requests/min
Business2,000 requests/min
Enterprise10,000 requests/min

Rate limiting is enforced via Redis counters in the ingestion-api.

Loki Storage Configuration

Development

  • Mode: SingleBinary
  • Storage: Filesystem (local PVC)
  • Retention: Default Loki retention
  • Replication: 1 replica

Production (planned)

  • Mode: Distributed (read/write/backend)
  • Storage: OVH S3 Object Storage
  • Retention: Per-tenant lifecycle policies
  • Replication: 3 replicas for high availability

On this page