Skip to content

mcm/pydantic-ocsf

Repository files navigation

pydantic-ocsf

Pydantic models for the Open Cybersecurity Schema Framework (OCSF).

Installation

pip install pydantic-ocsf

Version Scheme

Package versions follow semantic versioning and are independent of OCSF schema versions.

  • This package (v2.x) uses OCSF schema version 1.7.0
  • Patch versions fix bugs or update type stubs
  • Minor versions add features
  • Major versions make breaking changes

Quick Start

from ocsf.v1_7_0.objects import File
from ocsf.v1_7_0.events import FileActivity

# Create a file object
file = File(
    name="document.pdf",
    type_id=1,
    size=1024000,
)

# Serialize to JSON
json_str = file.model_dump_json(indent=2)
print(json_str)

# Parse from JSON
parsed = File.model_validate_json(json_str)

# Create an event
event = FileActivity(
    class_uid=1001,
    category_uid=1,
    activity_id=1,
    file=file,
    metadata={"version": "1.7.0"},
)

Namespace Organization

BREAKING CHANGE in v2.0.0: OCSF models are now organized into namespaces to resolve name collisions.

Required Import Pattern

Models must be imported from their respective namespaces:

# Import objects (User, File, Account, etc.)
from ocsf.v1_7_0.objects import User, Account, File

# Import events (FileActivity, ApiActivity, etc.)
from ocsf.v1_7_0.events import FileActivity, ApiActivity

Migration from v1.x

Old style imports NO LONGER WORK:

# ❌ NO LONGER WORKS
from ocsf.v1_7_0 import User, FileActivity

# ✅ Use namespace imports instead
from ocsf.v1_7_0.objects import User
from ocsf.v1_7_0.events import FileActivity

Name Collision Resolution

Some names exist in both namespaces. Import them explicitly with aliases:

from ocsf.v1_7_0.objects import Finding as FindingObject
from ocsf.v1_7_0.events import Finding as FindingEvent
from ocsf.v1_7_0.objects import Application as AppObject
from ocsf.v1_7_0.events import Application as AppEvent

# These are different classes
assert FindingObject is not FindingEvent

Top-Level Imports

For convenience, namespace modules are also accessible from the top level:

from ocsf import objects, events

user = objects.User(name="Alice", uid="123")
activity = events.FileActivity(class_uid=1001, category_uid=1)

OCSF Schema Version

This package uses OCSF schema version 1.7.0 (latest stable release).

The package includes 8 OCSF versions (v1.0.0 through v1.7.0), each organized into objects and events namespaces:

  • 169 objects: User, File, Process, Account, etc.
  • 84 events: FileActivity, ApiActivity, ProcessActivity, etc.

Using Newer Schema Versions

If a newer OCSF schema version is released before this package is updated, you can manually use it by downloading the schema and placing it in the appropriate location.

Step 1: Download the Schema

Download the schema JSON from the OCSF Schema Repository:

# Example: Download schema version 1.8.0
VERSION="1.8.0"
curl -o "src/ocsf/schemas/v${VERSION//./_}.json" \
  "https://raw.githubusercontent.com/ocsf/ocsf-schema/v${VERSION}/exports/schema.json"

Step 2: Regenerate Type Stubs

Generate type stubs for the new schema:

python3 scripts/regenerate_stubs.py

Step 3: Use the New Version

# Import from the new version's namespaces
from ocsf.v1_8_0.objects import File
from ocsf.v1_8_0.events import FileActivity

Note: The package maintainers test and validate each bundled schema version. Manually added schemas may have edge cases that aren't fully supported.

Using Custom Schemas

You can use custom or extended OCSF schemas with this package's JIT (Just-In-Time) model generation system.

Option 1: Fork and Modify

The simplest approach for custom schemas is to fork this repository:

  1. Fork the repository
  2. Replace src/ocsf/schemas/v1_7_0.json with your custom schema
  3. Run python3 scripts/regenerate_stubs.py
  4. Install from your fork: pip install git+https://github.com/yourname/pydantic-ocsf.git

Option 2: Use the Model Factory Directly

For advanced use cases, you can use the internal model factory with your own schema:

from pathlib import Path
import json
from ocsf._model_factory import ModelFactory
from ocsf._version_module import OCSFVersionModule
import sys

# Load your custom schema
with open("path/to/your/custom_schema.json") as f:
    custom_schema = json.load(f)

# Create a version module with your schema
custom_module = OCSFVersionModule("ocsf.custom", "custom")
custom_module.schema = custom_schema
custom_module.factory = ModelFactory(custom_schema, "custom")

# Register it so imports work
sys.modules["ocsf.custom"] = custom_module

# Now you can use it with namespaces
from ocsf.custom.objects import File
from ocsf.custom.events import FileActivity

Custom Schema Requirements

Your custom schema must follow the OCSF schema structure:

  • Top-level keys: objects, events, dictionary
  • Each object/event must have attributes and optional extends
  • Attributes must specify type (e.g., string_t, integer_t) and optionally requirement (required or optional)

See the OCSF Schema Documentation for details on the schema format.

Contributing New Schema Versions

Maintainers and contributors can add new OCSF schema versions to the released library by following these steps:

1. Update the Version List

Edit scripts/download_schemas.py and add the new version:

VERSIONS = [
    "1.7.0",
    "1.8.0",  # Add new version here
]

2. Download and Validate the Schema

Run the download script to fetch the new schema:

# First, ensure the schema exists in the .schema_cache directory
# (You may need to manually download it first)

python3 scripts/download_schemas.py

This will:

  • Copy the schema from .schema_cache/ to src/ocsf/schemas/
  • Compute and store the checksum in checksums.json
  • Validate that the schema has the expected structure

3. Generate Type Stubs

Generate type stub files for the new version:

python3 scripts/regenerate_stubs.py

This creates src/ocsf/v1_8_0/__init__.pyi with type hints for all models.

4. Test the New Version

Create tests for the new version:

# tests/test_v1_8_0.py
def test_import_v1_8_0():
    """Test that v1.8.0 imports work."""
    from ocsf.v1_8_0.objects import File
    from ocsf.v1_8_0.events import FileActivity

    assert FileActivity is not None
    assert File is not None

def test_v1_8_0_basic_usage():
    """Test basic model creation with v1.8.0."""
    from ocsf.v1_8_0.objects import File

    file = File(name="test.txt", type_id=1)
    assert file.name == "test.txt"

Run all tests to ensure nothing broke:

pytest tests/ -v

5. Update Documentation

Update the README.md and CLAUDE.md:

## OCSF Schema Versions

This package supports OCSF schema versions:
- v1.7.0 (stable)
- v1.8.0 (latest)

6. Run Quality Checks

Ensure all quality checks pass:

just check
# Or manually:
ruff format src/ tests/ scripts/
ruff check src/ tests/ scripts/
mypy src/ocsf/ --ignore-missing-imports
pytest tests/ -v --cov=ocsf

7. Create a Pull Request

  1. Commit your changes with a descriptive message:

    git add .
    git commit -m "Add support for OCSF schema v1.8.0"
  2. Push to your fork and create a pull request

  3. Include in your PR description:

    • OCSF schema version added
    • Link to the OCSF schema release notes
    • Any breaking changes or schema differences
    • Test coverage for the new version

Schema Source

Schemas are typically downloaded from:

  • Official releases: https://github.com/ocsf/ocsf-schema/releases
  • Schema exports: https://raw.githubusercontent.com/ocsf/ocsf-schema/v{VERSION}/exports/schema.json

Versioning Guidelines

When adding a new schema version, consider the package versioning:

  • Patch version (2.0.x → 2.0.y): Bug fixes, type stub updates for existing versions
  • Minor version (2.0.x → 2.1.0): Adding new schema versions (backward compatible)
  • Major version (2.x → 3.0): Removing old schema versions or breaking API changes

Note: v2.0.0 introduced namespace organization (breaking change from v1.x)

License

Apache 2.0

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages