# OpenAI Logs (Beta)

## Overview

{% hint style="info" %}
OpenAI log ingestion is in [open beta](https://docs.panther.com/resources/help/glossary#beta-features) starting with Panther version 1.117, and is available to all customers. Please share any bug reports and feature requests with your Panther support team.
{% endhint %}

Panther has the ability to fetch [OpenAI](https://platform.openai.com/docs/overview) audit logs by querying the [OpenAI Audit Logs API](https://platform.openai.com/docs/api-reference/audit-logs). Panther queries the Audit Logs API every one minute. In order for Panther to access the API, you need to create a new OpenAI API key with appropriate permissions.

### Common OpenAI audit log event types

See a full list of audit log event types [here](https://platform.openai.com/docs/api-reference/audit-logs/object). Common events include:

* `api_key.created`
* `api_key.updated`
* `api_key.deleted`
* `project.created`
* `project.updated`
* `project.deleted`
* `user.added`
* `user.updated`
* `user.deleted`
* `service_account.created`
* `service_account.updated`
* `service_account.deleted`

## How to onboard OpenAI logs to Panther

### Prerequisites

* You are logged into OpenAI as an organization owner or administrator. This is required to complete Step 1.
* Audit Logging must be enabled in OpenAI organization settings:
  1. Navigate to **Organization** > **Data controls** > **Data retention** in your OpenAI account: [Organization data retention settings](https://platform.openai.com/settings/organization/data-controls/data-retention)
  2. Enable **Audit Logging**.
     * When successfully enabled, the option will read **Active** with a green check.

### Step 1: Create a new OpenAI API key

{% hint style="info" %}
It's recommended to use an API key with read-only permissions for audit logs, following the principle of least privilege.
{% endhint %}

1. In your OpenAI account, navigate to **Settings** > **Organization** > **API keys**.
2. Click **Create new secret key**.
3. Enter a descriptive name for your key, e.g., `Panther Audit Log Access`.
4. Configure the key permissions:
   * **Permissions**: Set to **Read-only** (or ensure the key has read access to audit logs).
   * Ensure the key has access to the **Audit Logs** resource.
5. Copy the **API key value** and store it in a secure location. You will need it in the next step.
   * OpenAI will not display this value again.

### Step 2: Create a new OpenAI source in Panther

1. In the left-hand navigation bar of your Panther Console, click **Configure** > **Log Sources**.
2. Click **Create New.**
3. Search for "OpenAI," then click its tile.
4. On the slide-out panel, click **Start Setup**.
5. On the **Configuration** page, enter a descriptive **Name**, e.g., `My OpenAI Audit Logs`.
   * The **Log Types** read-only dropdown will have an `OpenAI.Audit` value.
6. Click **Setup**.
7. On the **Credentials** page, fill in the **API Key** field with the key you generated in Step 1.
8. Click **Setup**.
   * You will be directed to a verification screen that confirms Panther can successfully connect to the OpenAI API.
     * You can optionally enable one or more Detection Packs.
     * The **Trigger an alert when no events are processed** setting defaults to **YES**. We recommend leaving this enabled, as you will be alerted if data stops flowing from the log source after a certain period of time. The timeframe is configurable, with a default of 24 hours.

## Custom detection patterns

### API key creation monitoring example

Monitor when new API keys are created in your OpenAI organization:

```python
def rule(event):
    return event.get('type') == 'api_key.created'

def title(event):
    actor_email = event.deep_get('actor', 'user', 'email', default='Unknown')
    return f'New OpenAI API key created by {actor_email}'
```

### Administrative user changes example

Detect when users are added or their roles are modified:

```python
def rule(event):
    event_type = event.get('type', '')
    return event_type in ['user.added', 'user.updated']

def severity(event):
    # Higher severity for role changes
    if event.get('type') == 'user.updated':
        return 'MEDIUM'
    return 'INFO'
```

### Project deletion monitoring example

Alert when projects are deleted:

```python
def rule(event):
    return event.get('type') == 'project.deleted'

def alert_context(event):
    return {
        'actor_email': event.deep_get('actor', 'user', 'email'),
        'project_id': event.deep_get('project', 'id'),
        'project_name': event.deep_get('project', 'name'),
        'timestamp': event.get('effective_at')
    }
```

## Supported log types

### OpenAI.AuditLogs

OpenAI audit logs track administrative and security-related events within your OpenAI organization, including API key management, project changes, user actions, and access control modifications.

Reference: [OpenAI Audit Logs API Documentation](https://platform.openai.com/docs/api-reference/audit-logs)

```yaml
schema: OpenAI.Audit
description: |
    OpenAI audit logs provide visibility into administrative actions and security events within your OpenAI organization. These logs help track API key usage, project management, and user access control.
referenceURL: https://platform.openai.com/docs/api-reference/audit-logs
fields:
    - name: id
      required: true
      description: Unique identifier for the audit log event
      type: string
    - name: type
      required: true
      description: The type of event that occurred
      type: string
    - name: effective_at
      required: true
      description: Unix timestamp (in seconds) when the event occurred
      type: timestamp
      timeFormat: unix
      isEventTime: true
    - name: actor
      description: The entity that performed the action
      type: object
      fields:
        - name: type
          description: The type of actor (e.g., user, service_account, system)
          type: string
        - name: user
          description: Details about the user who performed the action
          type: object
          fields:
            - name: id
              description: The user's unique identifier
              type: string
            - name: email
              description: The user's email address
              type: string
              indicators:
                - email
        - name: service_account
          description: Details about the service account that performed the action
          type: object
          fields:
            - name: id
              description: The service account's unique identifier
              type: string
        - name: api_key
          description: Details about the API key used to perform the action
          type: object
          fields:
            - name: id
              description: The API key's unique identifier
              type: string
            - name: type
              description: The type of API key
              type: string
            - name: user
              description: The user associated with the API key
              type: object
              fields:
                - name: id
                  description: The user's unique identifier
                  type: string
                - name: email
                  description: The user's email address
                  type: string
                  indicators:
                    - email
            - name: service_account
              description: The service account associated with the API key
              type: object
              fields:
                - name: id
                  description: The service account's unique identifier
                  type: string
    - name: project
      description: Details about the project affected by the action
      type: object
      fields:
        - name: id
          description: The project's unique identifier
          type: string
        - name: name
          description: The project's name
          type: string
    - name: api_key
      description: Details about the API key affected by the action
      type: object
      fields:
        - name: id
          description: The API key's unique identifier
          type: string
        - name: type
          description: The type of API key
          type: string
        - name: user
          description: The user associated with the API key
          type: object
          fields:
            - name: id
              description: The user's unique identifier
              type: string
            - name: email
              description: The user's email address
              type: string
              indicators:
                - email
        - name: service_account
          description: The service account associated with the API key
          type: object
          fields:
            - name: id
              description: The service account's unique identifier
              type: string
    - name: user
      description: Details about the user affected by the action
      type: object
      fields:
        - name: id
          description: The user's unique identifier
          type: string
        - name: email
          description: The user's email address
          type: string
          indicators:
            - email
        - name: role
          description: The user's role in the organization
          type: string
    - name: service_account
      description: Details about the service account affected by the action
      type: object
      fields:
        - name: id
          description: The service account's unique identifier
          type: string
        - name: name
          description: The service account's name
          type: string
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.panther.com/data-onboarding/supported-logs/openai.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
