Skip to content

Send audit logs to a SIEM

Dew delivers its audit log to a SIEM in two ways, with the same records either way. Pick the one your SIEM supports:

  • Poll the feed: your SIEM calls Dew over HTTPS with an API token and asks for new events. Works with any SIEM that has an HTTP or REST poller, including QRadar’s Universal Cloud REST API protocol. Nothing to install on the Dew server.
  • Read the log file: Dew writes every event to audit.log on the server, and a collector next to Dew forwards it. Use it for Splunk Universal Forwarder, Filebeat or Elastic Agent, or a syslog forwarder.

You need an Enterprise plan and an admin account on Dew. For the file option, you also need access to the Docker host Dew runs on.

  1. Open System → Integrations and click New service account.

  2. Name it SIEM collector, choose any domain, and under Permissions select only Monitoring: Audit log. It lets the account read and export the audit log and nothing else. Click Create service account.

  3. On the account’s page, click New token and give it a name such as Production.

  4. Under Expires, keep the default date or choose Never expires. When the token expires, the feed stops answering; Dew alerts admins a week before.

  5. Click Create token and copy the token, which starts with dewsa_. Dew shows it only once.

Your SIEM calls this address with the token in the Authorization header:

curl -s -H "Authorization: Bearer dewsa_<token>" "https://files.example.com/api/admin/audit-logs/feed?after_id=0&limit=1000"

The response looks like this, shortened here to an empty entries list. In a real response, entries holds the events oldest first, each with the fields in the event reference.

{ "success": true, "data": { "entries": [], "next_after_id": 1532, "has_more": true } }

Set up the poller to:

  1. Start with after_id=0 to fetch all stored history.
  2. Store next_after_id from each response and send it as after_id in the next call.
  3. Call again straight away while has_more is true, then poll on your usual interval.

limit is 1 to 1000 events per call. The feed has no rate limit; polling every minute is plenty. The feed never skips an event, and polling isn’t recorded in the audit log.

Dew appends every event to audit.log in its log folder, one JSON record per line. At midnight UTC the file is renamed audit-YYYY-MM-DD.log, compressed to .log.gz a day later, and deleted after 90 days.

The collector receives events from the day it starts reading. Older days are compressed or deleted, and collectors skip compressed files. To load earlier history, poll the feed once from after_id=0 (see Option A).

1. Give the collector access to the log folder

Section titled “1. Give the collector access to the log folder”

The log folder is data/logs in the folder that holds Dew’s compose.yaml. If the collector runs in a container, mount that folder into it read-only, for example in the collector’s compose file:

    volumes:
      - /path/to/dew/data/logs:/dew-logs:ro

A collector installed directly on the host can read the folder where it is.

Have the collector read audit.log and audit-*.log, and skip *.gz.

The examples below assume the log folder is at /dew-logs. For a collector on the host, use the folder’s real path instead.

Splunk Universal Forwarder. In inputs.conf:

[monitor:///dew-logs/audit*.log]
sourcetype = dew:audit
index = <your index>

In props.conf on the forwarder:

[dew:audit]
INDEXED_EXTRACTIONS = json
TIMESTAMP_FIELDS = timestamp
TIME_FORMAT = %Y-%m-%dT%H:%M:%S.%6NZ
TZ = UTC
TRUNCATE = 0

In props.conf on the search head, add KV_MODE = none to the [dew:audit] stanza, otherwise every field shows twice.

Filebeat or Elastic Agent (filestream input):

- type: filestream
  id: dew-audit
  paths: ["/dew-logs/audit.log", "/dew-logs/audit-*.log"]
  prospector.scanner.exclude_files: ['\.gz$']
  file_identity.fingerprint: ~
  prospector.scanner.fingerprint:
    enabled: true
    length: 64
  parsers:
    - ndjson:
        target: "dew"
        add_error_key: true
  processors:
    - timestamp:
        field: dew.timestamp
        layouts: ["2006-01-02T15:04:05.000000Z"]
    - copy_fields:
        fields: [{from: dew.event_id, to: "@metadata._id"}]

Keep the fingerprint settings: from Filebeat 9, files under 1 KB are skipped by default, so a quiet day’s file would never be read. @metadata._id makes a repeated line replace its document instead of adding a duplicate.

Syslog SIEMs (QRadar, ArcSight and others). Dew doesn’t send syslog itself. Run a forwarder next to Dew that reads the file and holds events on disk while the SIEM is unreachable, for example rsyslog:

global(maxMessageSize="64k")
module(load="imfile")
input(type="imfile" File="/dew-logs/audit.log" Tag="dew-audit" Severity="info" Facility="local4")
local4.* action(type="omfwd" Target="siem.example.com" Port="6514" Protocol="tcp"
  StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="x509/name"
  queue.type="LinkedList" queue.filename="dew-audit" queue.saveOnShutdown="on")

Each message carries one JSON record. Set your SIEM’s line or message limit to at least 64 KB: an event that lists many recipients can exceed 10,000 bytes.

Events don’t include the server’s name, so set it in your ingest pipeline: observer.name in Elastic, dest in Splunk, Dvc in Sentinel. Events about files and file requests carry the hostname they happened on in the top-level domain field.

For field-by-field mappings to Elastic ECS, Splunk CIM and Microsoft Sentinel ASIM, see Map to SIEM schemas.

  1. Sign in to Dew in a private browser window.
  2. Within one polling interval, or a few seconds for the log file, your SIEM shows an auth.signed_in event with your email and IP address.
  3. Open Activity → Audit logs in Dew and compare: the event’s event_id matches.
  • Remove duplicates by event_id. After a crash, the log file can repeat a line (it never misses one). The Filebeat example above already does this; in Splunk, add | dedup event_id to your searches.
  • Watch for gaps after retention. Each cleanup is recorded as an audit.purged event. If your stored after_id is below its metadata.last_deleted_id, events were deleted before your SIEM read them. Poll more often or raise Audit log retention.
  • After restoring an older database backup:
    • Feed: reset your stored after_id to the newest id the restored database holds. Otherwise new events have IDs your SIEM has already passed, and are skipped.
    • Log file: before starting Dew, move every audit file out of the log folder: audit.log, audit-*.log and audit-*.log.gz. Dew then writes audit.log again from the oldest stored event.
  • Gaps in id are normal. They never mean an event was deleted.
What you see What to do
The feed answers 401 The token is wrong, has expired or was revoked. Create a new one on the service account’s page in System → Integrations.
The feed answers 403 The service account lacks the Monitoring: Audit log permission, the SIEM’s IP address isn’t on the Admin pages IP allowlist (if you use one), or the server’s plan doesn’t include audit logs (check System → System → License).
audit.log doesn’t exist The license doesn’t include audit logs, or the collector is reading the wrong folder (it should be data/logs next to compose.yaml). Dew adds all stored events once audit logs are licensed.
A day’s rotated file is never read by Filebeat Add the fingerprint settings from the example above.
Events are cut off in the SIEM Raise the SIEM’s line or message limit to at least 64 KB. In Splunk, keep TRUNCATE = 0.
Every event has the same IP address Dew is behind a reverse proxy it doesn’t trust. See Tell Dew about the proxy.