# OCSF Standardization

### Description

The OCSF Standardization processor transforms log data into [Open Cybersecurity Schema Framework (OCSF)](https://schema.ocsf.io/) compliant events. It maps fields from incoming logs to the appropriate OCSF class structure using

### Use

Use the OCSF Standardization processor to normalize security logs from diverse sources into a common OCSF schema before routing them to a security destination. The processor replaces the **log body** with an OCSF-compliant JSON structure. The original log attributes and resource fields are preserved. Destinations such as AWS Security Lake and [Google SecOps](https://docs.bindplane.com/integrations/destinations/google-secops-chronicle) both support forwarding just the log body, making them well-suited for use downstream of this processor.

### Supported Types

| Metrics | Logs | Traces |
| ------- | ---- | ------ |
|         | ✓    |        |

### Configuration

| Field              | Required | Type                | Description                                                                                                    |
| ------------------ | -------- | ------------------- | -------------------------------------------------------------------------------------------------------------- |
| Telemetry Types    | Yes      | `telemetrySelector` | The types of telemetry to apply the processor to. Only Logs are supported.                                     |
| OCSF Version       | Yes      | `enum`              | The version of the OCSF specification to use for standardization. Supported versions: `1.0.0` through `1.7.0`. |
| Runtime Validation | Yes      | `bool`              | Enable runtime validation of OCSF events against the schema. Logs that fail validation will be dropped.        |
| Event Mappings     | Yes      | `ocsfEventMappings` | One or more mappings that define how incoming logs are transformed into OCSF events. See Event Mappings below. |

#### Event Mappings

Each event mapping defines the rules for transforming a matched log into a specific OCSF event class. Multiple mappings can be configured to handle different log types within the same processor. The first mapping whose filter condition matches a given log record is applied.

| Field          | Required | Type                 | Description                                                                                                                                            |
| -------------- | -------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Class ID       | Yes      | `int`                | The OCSF class ID for the target event type (e.g., `3002` for Authentication Activity).                                                                |
| Filter         | No       | `string`             | A condition expression that determines which logs this mapping applies to. If omitted, the mapping applies to all logs.                                |
| Profiles       | No       | `string[]`           | One or more OCSF profiles to apply to this event mapping. Each profile adds additional required and optional fields to the output. See Profiles below. |
| Field Mappings | Yes      | `ocsfFieldMapping[]` | A list of individual field mappings that copy or set values in the OCSF output body.                                                                   |

#### **Event Mapping Fields**

Each entry in the field mappings list defines how a single OCSF field is populated.

| Field   | Required | Type     | Description                                                                                         |
| ------- | -------- | -------- | --------------------------------------------------------------------------------------------------- |
| To      | Yes      | `string` | The target OCSF field path. Dot notation is used for nested fields (e.g., `actor.user.name`).       |
| From    | No\*     | `string` | An expression that extracts a value from the source log (e.g., `body["EventData"]["IpAddress"]`).   |
| Default | No\*     | `any`    | A static default value to use when the source field is absent or the `From` expression returns nil. |

\*At least one of `From` or `Default` must be provided for each field mapping.

### Automatically Populated Fields

In addition to fields defined in your event mappings, the processor automatically populates the following fields in the log body for every processed record:

| Field              | Description                                           |
| ------------------ | ----------------------------------------------------- |
| `class_uid`        | Set to the Class ID of the matched event mapping.     |
| `category_uid`     | Derived from the Class ID as `class_id / 1000`.       |
| `metadata.version` | Set to the configured OCSF version (e.g., `"1.7.0"`). |
| `type_uid`         | Calculated as `class_uid * 100 + activity_id`.        |

The processor also adds an `ocsf.class_uid` attribute to the log record (outside the body) for use in downstream routing and filtering.

### Type Coercion

The processor automatically coerces mapped values to match the target OCSF field's schema type. If a value cannot be coerced, it is passed through unchanged.

| OCSF Type   | Accepted Input Types                                                 | Output                     |
| ----------- | -------------------------------------------------------------------- | -------------------------- |
| `integer`   | `int`, `int64`, `float64`, `string` (numeric), `bool`                | `int`                      |
| `long`      | `int`, `int64`, `float64`, `string` (numeric), `bool`                | `int64`                    |
| `float`     | `int`, `int64`, `float64`, `string` (numeric)                        | `float64`                  |
| `boolean`   | `bool`, `string` (`"true"`/`"false"`), `int`, `int64`, `float64`     | `bool`                     |
| `timestamp` | `int`, `int64`, `float64`, `string` (numeric or RFC3339/RFC3339Nano) | `int64` epoch milliseconds |
| `datetime`  | `int`, `int64`, `float64` (epoch ms), `string`                       | `string` RFC3339           |
| `string`    | Any                                                                  | Unchanged                  |

### OCSF Profiles

Profiles are standardized field groups that can be applied to an event to extend it with a predefined set of related attributes. When a profile is selected, its required fields must be mapped. Profiles are selected per event mapping using a multi-select dropdown.

Not all profiles are available for every class. The profile dropdown automatically filters to show only profiles that are valid for the selected class and OCSF version.

### Example Configuration

#### **Map Windows Logon Events to OCSF Authentication Activity**

In this example, Windows Security Event ID `4624` (Successful Logon) is mapped to the OCSF class `3002` (Authentication). The filter ensures this mapping applies only to matching log records. Field mappings populate all required fields for the Authentication class, including the target user, event time, severity, and source network details.

<figure><img src="https://1405008107-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgmiOMzBfoNFwmKJFHMcJ%2Fuploads%2FN6XGvVzRHsDBCVGX2Dh9%2Fbpss_Screenshot%202026-03-27%20at%203.18.10%E2%80%AFPM.png?alt=media&#x26;token=2a6feb3f-88a7-47cf-a88e-1e1e1eb3b0f1" alt=""><figcaption></figcaption></figure>

#### **Standalone Processor**

```yaml
apiVersion: bindplane.observiq.com/v1
kind: Processor
metadata:
  id: ocsf_standardization
  name: ocsf_standardization
spec:
  type: ocsf_standardization
  parameters:
    - name: telemetry_types
      value:
        - Logs
    - name: ocsf_version
      value: '1.3.0'
    - name: runtime_validation
      value: true
    - name: event_mappings
      value:
        - classId: 3002
          filter: 'body["System"]["EventID"] == 4624'
          fieldMappings:
            - to: 'user.name'
              from: 'body["EventData"]["TargetUserName"]'
            - to: 'user.domain'
              from: 'body["EventData"]["TargetDomainName"]'
            - to: 'time'
              from: 'body["System"]["TimeCreated"]["SystemTime"]'
            - to: 'severity_id'
              default: 1
            - to: 'activity_id'
              default: 1
            - to: 'status_id'
              default: 1
            - to: 'src_endpoint.ip'
              from: 'body["EventData"]["IpAddress"]'
            - to: 'src_endpoint.hostname'
              from: 'body["EventData"]["WorkstationName"]'
            - to: 'actor.user.name'
              from: 'body["EventData"]["SubjectUserName"]'
            - to: 'actor.user.domain'
              from: 'body["EventData"]["SubjectDomainName"]'
```

The resulting log body will conform to the OCSF Authentication schema (class `3002`). The table below shows all populated fields, including those automatically added by the processor:

| OCSF Field              | Source        | Value                                                                         |
| ----------------------- | ------------- | ----------------------------------------------------------------------------- |
| `class_uid`             | Auto          | `3002`                                                                        |
| `category_uid`          | Auto          | `3`                                                                           |
| `metadata.version`      | Auto          | `"1.3.0"`                                                                     |
| `type_uid`              | Auto          | `300201`                                                                      |
| `user.name`             | Field mapping | Value from `body["EventData"]["TargetUserName"]`                              |
| `user.domain`           | Field mapping | Value from `body["EventData"]["TargetDomainName"]`                            |
| `time`                  | Field mapping | Value from `body["System"]["TimeCreated"]["SystemTime"]`, coerced to epoch ms |
| `severity_id`           | Field mapping | `1` (Informational)                                                           |
| `activity_id`           | Field mapping | `1` (Logon)                                                                   |
| `status_id`             | Field mapping | `1` (Success)                                                                 |
| `src_endpoint.ip`       | Field mapping | Value from `body["EventData"]["IpAddress"]`                                   |
| `src_endpoint.hostname` | Field mapping | Value from `body["EventData"]["WorkstationName"]`                             |
| `actor.user.name`       | Field mapping | Value from `body["EventData"]["SubjectUserName"]`                             |
| `actor.user.domain`     | Field mapping | Value from `body["EventData"]["SubjectDomainName"]`                           |

The log record attribute `ocsf.class_uid` will also be set to `3002`.

### Schema Validation

#### Configuration-time Validation

When the processor is saved, Bindplane validates it against the OCSF schema. Configuration-time validation checks:

* The selected OCSF version is supported.
* Each event mapping has a valid Class ID.
* All filter and from expressions are syntactically valid.
* Any selected profiles are valid for the chosen class and version.
* Field coverage - all required fields for the class (and any selected profiles) have a corresponding field mapping. The auto-populated fields (`class_uid`, `category_uid`, `metadata.version`, `type_uid`) are counted toward coverage automatically.

Configuration validation does not verify that mapped values will be the correct type at runtime. A field mapping that references the wrong source field or provides a default of the wrong type will pass configuration validation but may fail at runtime if Runtime Validation is enabled.

#### Runtime Validation

When Runtime Validation is enabled (the default), each processed log record is validated against the full OCSF schema after all field mappings are applied. Log records that fail validation are dropped and logged as errors. Validation checks include:

* Required fields - all required fields for the class and selected profiles are present.
* Enum values - integer and string enum fields contain a valid value from the allowed set.
* String length - string fields do not exceed their maximum allowed length.
* Pattern constraints - fields with format requirements (such as IP addresses, email addresses, hostnames, UUIDs, and datetime strings) match the expected pattern.

Disable runtime validation during initial configuration to allow logs through while you iterate on your field mappings. Re-enable it once the output is confirmed correct to ensure that all log bodies sent to your destination are OCSF-compliant.
