Audit Log

The audit log tracks user actions across the system. It can answer questions like when a certain authentication event happened and what actions were taken by whom on instances and disks. The log is accessible to users with the fleet viewer role via the audit_log_list API endpoint.

Overview

Audit log entries correspond one-to-one with API calls that can mutate data. An entry is initialized before the operation begins, and if the initialization fails, the request fails: no mutating operation can proceed without an audit log entry. Each entry includes time_started for when the request came in and time_completed for when the result was recorded. Entries only appear in the audit_log_list response once they are completed.

Audit log entries are immutable: once you can see an entry in the list, fetching it again will never get you a different result. If you fetch the log for a time_completed range that is fully in the past, the resulting list is guaranteed to be complete, i.e., fetching the same timespan again later will always produce the same set of entries. Entries will never be inserted after the fact.

In the rare event that a log entry is initialized but the control plane fails to complete the log entry (see Unknown result), a background task will mark it complete after a timeout (currently four hours). The entry does not appear in the log until it is marked complete. This is required to guarantee the immutability discussed above.

Events logged

The aim is for the audit log to capture any API request that can mutate data. In practice, this means logging all non-GET requests. There are two exceptions:

  • Read-only OxQL endpoints that use POST bodies for queries

  • disk_bulk_write_import: the endpoint used to upload chunks during a disk import. We exclude it from the log because there can be thousands of calls to it during a single image upload. Related API operations before and after the bulk write calls (e.g., disk_bulk_write_import_start) are still logged.

Viewing the log

Use the audit_log_list endpoint or the oxide audit-log list CLI command to fetch the log. Fleet viewer permissions are required. Callers are responsible for filtering, e.g., by operation ID, as there is no filtering built in.

The request requires a start_time (inclusive) and accepts an end_time (exclusive). Results are ordered by time_completed and a unique id, which you can use to deduplicate entries from overlapping time ranges. Results are paginated; use the page_token returned in the response to fetch subsequent pages.

Actor types

The actor field identifies who made the request:

silo_user

A user in a silo, identified by silo_user_id and silo_id

scim

A silo’s SCIM client, identified by silo_id

user_builtin

An internal system user

unauthenticated

No authenticated identity (e.g., login attempts)

user_builtin is an internal actor type included only for completeness; it should never appear in the log because there is no way for built-in users to make an external API request.

Authentication method and credential ID

For authenticated requests, auth_method indicates the type of credential used and credential_id identifies the specific session or token:

session_cookie

Console session

access_token

Device auth / OAuth 2.0 token

scim_token

SCIM client bearer token

Login endpoints (login_local and login_saml) are logged but have no auth_method, credential_id, or identified actor because the login request itself is not authenticated by one of the above methods. In a future release, successful logins will log the actor and resulting session ID.

Success result

{
"id": "224ea169-1b08-42c5-8349-86517083641d",
"time_started": "2025-08-12T00:03:45.439Z",
"time_completed": "2025-08-12T00:03:45.611Z",
"request_id": "e5cb503e-7af6-4620-b3d4-4b683eac2b7d",
"request_uri": "https://corp.sys.oxide.acme.com/v1/projects/hello",
"operation_id": "project_delete",
"source_ip": "172.20.17.118",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0",
"actor": {
"kind": "silo_user",
"silo_user_id": "dcef2ede-a083-4826-805e-b79d05007aec",
"silo_id": "7bd7623a-68ed-4636-8ecb-b59e3b068787"
},
"auth_method": "session_cookie",
"credential_id": "dd423500-8578-47de-897c-20a287559369",
"result": {
"kind": "success",
"http_status_code": 204
}
}

Error result

When the operation fails, the audit log entry looks the same except for the result value.

{
// ...
"result": {
"kind": "error",
"http_status_code": 400,
"error_code": "InvalidRequest",
"error_message": "project to be deleted contains a vpc: default"
}
}

Unknown result

An unknown result kind means an API call took place, but the control plane failed to record the outcome and then a background task marked it complete later, after a timeout (currently four hours). This is expected to be very rare. An unknown result does not mean the operation failed, only that the outcome was not recorded in the audit log.

Because the audit log is designed so that entries in the past never change once fetched, entries cannot appear in the log until they are marked complete — up to four hours after the original request.

{
// ...
"result": {
"kind": "unknown"
}
}

Retention

Audit log entries are retained for 90 days. A background task permanently removes entries older than 90 days. If you need to retain the log for longer, fetch it on a regular interval using the audit_log_list endpoint and store it externally.

Planned features

  • Silo-scoped log list endpoint for silo administrators

  • Log ID of resource created

  • Log more details about changes made in create and update requests