diff --git a/docs.json b/docs.json index 9b0eef6..f3d9ee9 100644 --- a/docs.json +++ b/docs.json @@ -116,6 +116,7 @@ ] }, "info/api-keys", + "info/audit-logs", "browsers/file-io", "browsers/curl", "browsers/ssh", diff --git a/info/audit-logs.mdx b/info/audit-logs.mdx new file mode 100644 index 0000000..f93dbe4 --- /dev/null +++ b/info/audit-logs.mdx @@ -0,0 +1,196 @@ +--- +title: "Audit Logs" +description: "List organization API request audit events" +--- + +Audit logs record authenticated API requests for your organization. Use them to review who called Kernel, which endpoint they called, when the request happened, and how the request completed. + +Audit logs are ordered newest first. The `start` timestamp is inclusive, the `end` timestamp is exclusive, and each request can cover up to 30 days. Each page returns up to 100 events. + +Keep each audit log request to a 30-day range or less. For longer investigations, split the query into multiple time windows. + +## List audit logs + +Use the SDKs to page through logs for a time window. + + +```typescript TypeScript +import Kernel from '@onkernel/sdk'; + +const kernel = new Kernel({ + apiKey: process.env.KERNEL_API_KEY, +}); + +for await (const event of kernel.auditLogs.list({ + start: '2026-06-01T00:00:00Z', + end: '2026-06-02T00:00:00Z', + limit: 100, + method: 'POST', +})) { + console.log(event.timestamp, event.method, event.path, event.status); +} +``` + +```python Python +import os +from kernel import Kernel + +client = Kernel(api_key=os.environ["KERNEL_API_KEY"]) + +for event in client.audit_logs.list( + start="2026-06-01T00:00:00Z", + end="2026-06-02T00:00:00Z", + limit=100, + method="POST", +): + print(event.timestamp, event.method, event.path, event.status) +``` + +```go Go +package main + +import ( + "context" + "fmt" + "time" + + "github.com/kernel/kernel-go-sdk" +) + +func main() { + ctx := context.Background() + client := kernel.NewClient() + + pager := client.AuditLogs.ListAutoPaging(ctx, kernel.AuditLogListParams{ + Start: time.Date(2026, time.June, 1, 0, 0, 0, 0, time.UTC), + End: time.Date(2026, time.June, 2, 0, 0, 0, 0, time.UTC), + Limit: kernel.Int(100), + Method: kernel.String("POST"), + }) + for pager.Next() { + event := pager.Current() + fmt.Println(event.Timestamp, event.Method, event.Path, event.Status) + } + if err := pager.Err(); err != nil { + panic(err) + } +} +``` + + +## Filter audit logs + +Use filters to narrow results to the events you need: + +- `auth_strategy` filters by authentication method, such as `api_key`, `dashboard`, or `oauth`. +- `service` filters by the service that emitted the audit event. +- `method` filters by HTTP method. +- `exclude_method` excludes a single HTTP method. +- `search` matches path, user ID, email, client IP, and status. +- `search_user_id` adds one or more user IDs to the search. + + +```typescript TypeScript +const logs = kernel.auditLogs.list({ + start: '2026-06-01T00:00:00Z', + end: '2026-06-08T00:00:00Z', + limit: 50, + auth_strategy: 'api_key', + exclude_method: 'GET', + search: '/browsers', +}); + +for await (const event of logs) { + console.log(event.email, event.client_ip, event.user_agent); +} +``` + +```python Python +logs = client.audit_logs.list( + start="2026-06-01T00:00:00Z", + end="2026-06-08T00:00:00Z", + limit=50, + auth_strategy="api_key", + exclude_method="GET", + search="/browsers", +) + +for event in logs: + print(event.email, event.client_ip, event.user_agent) +``` + +```go Go +package main + +import ( + "context" + "fmt" + "time" + + "github.com/kernel/kernel-go-sdk" +) + +func main() { + ctx := context.Background() + client := kernel.NewClient() + + pager := client.AuditLogs.ListAutoPaging(ctx, kernel.AuditLogListParams{ + Start: time.Date(2026, time.June, 1, 0, 0, 0, 0, time.UTC), + End: time.Date(2026, time.June, 8, 0, 0, 0, 0, time.UTC), + Limit: kernel.Int(50), + AuthStrategy: kernel.String("api_key"), + ExcludeMethod: kernel.String("GET"), + Search: kernel.String("/browsers"), + }) + for pager.Next() { + event := pager.Current() + fmt.Println(event.Email, event.ClientIP, event.UserAgent) + } + if err := pager.Err(); err != nil { + panic(err) + } +} +``` + + +## Page with HTTP + +The API returns the next cursor in the `X-Next-Page-Token` response header. Pass it back as `page_token` to read the next page. + +```bash +curl --include --get https://api.onkernel.com/audit-logs \ + --header "Authorization: Bearer $KERNEL_API_KEY" \ + --data-urlencode "start=2026-06-01T00:00:00Z" \ + --data-urlencode "end=2026-06-02T00:00:00Z" \ + --data-urlencode "limit=100" +``` + +```bash +curl --include --get https://api.onkernel.com/audit-logs \ + --header "Authorization: Bearer $KERNEL_API_KEY" \ + --data-urlencode "start=2026-06-01T00:00:00Z" \ + --data-urlencode "end=2026-06-02T00:00:00Z" \ + --data-urlencode "limit=100" \ + --data-urlencode "page_token=eyJ0IjoiMjAyNi0wNi0wMVQyMzo1OTo1OS43NDUxMjNaIn0" +``` + +Use `X-Has-More: true` to decide whether to continue paging. Page tokens are opaque; store and pass them exactly as returned. + +## Response fields + +Each audit log entry includes: + +- `timestamp` +- `auth_strategy` +- `user_id` +- `email` +- `status` +- `method` +- `path` +- `route` +- `domain` +- `duration_ms` +- `client_ip` +- `user_agent` + +See the [API reference](https://kernel.sh/docs/api-reference/audit-logs/list-audit-logs) for the full request and response schema.