What are Veza Custom Properties?

Overview

Custom properties allow you to extend OAA templates with additional fields beyond the standard Veza properties. Any field in your source data that doesn’t map to a predefined OAA field can be added as a custom property.

Use the custom_type parameter in field mappings to specify the data type for your custom property:

field_mapping:
  department:
    destination_field: department
    custom_type: STRING  # Custom field of type STRING
  
  is_contractor:
    destination_field: is_contractor
    custom_type: BOOLEAN  # Custom field of type BOOLEAN

Available Data Types

All custom properties must have one of the following custom_type values:

Type

Description

Valid Values

Example

STRING

Text values

Any string

"Engineering", "Active", "john@example.com"

BOOLEAN

True/False values

true, false

true, false

NUMBER

Numeric values (integer or decimal)

Any number

42, 3.14, -100

STRING_LIST

Array/list of strings

JSON array of strings

["admin", "user"], ["read", "write"]

TIMESTAMP

Date/time in ISO 8601 format

ISO 8601 or supported formats (see below)

"2024-01-15T10:30:00Z"

TIMESTAMP_AD

Active Directory timestamp (Windows filetime)

64-bit integer

133456789012345678

⚠️ Critical: custom_type is ONLY for Custom Properties

custom_type must ONLY be used on fields that are not built-in to the OAA entity type. Applying custom_type to built-in fields causes validation errors.

Built-in LocalUser Fields (do NOT use custom_type)

These fields are built-in to LocalUser and should never use custom_type:

  • Required: unique_id

  • Identity: name, email

  • Status: is_active, user_type

  • Timestamps: last_login_at, created_at, deactivated_at, password_last_changed_at

Incorrect:

field_mapping:
  email_address:
    destination_field: email
    custom_type: STRING    # ❌ email is built-in; do not add custom_type
  
  username:
    destination_field: unique_id
    custom_type: STRING    # ❌ unique_id is built-in; do not add custom_type

Correct:

field_mapping:
  email_address:
    destination_field: email    # ✓ No custom_type needed (built-in field)
  
  username:
    destination_field: unique_id    # ✓ No custom_type needed (built-in field)
  
  department_code:
    destination_field: department    # ✓ Custom field; use custom_type
    custom_type: STRING
  
  hire_date:
    destination_field: hire_date    # ✓ Custom field; use custom_type
    custom_type: TIMESTAMP

Refer to the OAA Provider Object reference for a complete list of built-in fields per entity type (LocalGroup, LocalRole, etc.).

Field Type Examples

STRING

field_mapping:
  department:
    destination_field: department
    custom_type: STRING
  
  office_location:
    destination_field: office_location
    custom_type: STRING
  
  employee_id:
    destination_field: employee_id
    custom_type: STRING  # Keep as string, not number

BOOLEAN

field_mapping:
  is_active:
    destination_field: is_active
    custom_type: BOOLEAN
  
  is_manager:
    destination_field: is_manager
    custom_type: BOOLEAN
  
  has_mfa:
    destination_field: has_mfa
    custom_type: BOOLEAN

NUMBER

field_mapping:
  salary:
    destination_field: salary
    custom_type: NUMBER
  
  years_of_service:
    destination_field: years_of_service
    custom_type: NUMBER
  
  performance_rating:
    destination_field: performance_rating
    custom_type: NUMBER

STRING_LIST

field_mapping:
  certifications:
    destination_field: certifications
    custom_type: STRING_LIST
  
  access_groups:
    destination_field: access_groups
    custom_type: STRING_LIST
  
  assigned_roles:
    destination_field: assigned_roles
    custom_type: STRING_LIST

TIMESTAMP

field_mapping:
  hire_date:
    destination_field: hire_date
    custom_type: TIMESTAMP
  
  last_login:
    destination_field: last_login
    custom_type: TIMESTAMP
  
  password_last_changed:
    destination_field: password_last_changed
    custom_type: TIMESTAMP

TIMESTAMP_AD

field_mapping:
  ad_last_logon:
    destination_field: ad_last_logon
    custom_type: TIMESTAMP_AD
  
  ad_pwd_last_set:
    destination_field: ad_pwd_last_set
    custom_type: TIMESTAMP_AD

Timestamp Formats

Veza OAA accepts multiple timestamp input formats and converts them to ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ).

Input Formats Accepted

Use the date_convert transform to automatically convert various date formats:

field_mapping:
  hire_date:
    destination_field: hire_date
    custom_type: TIMESTAMP
    transforms:
      - name: date_convert

Supported Timestamp Formats

Input Format

Example Input

Output (ISO 8601)

MM-DD-YYYY

01-15-2024

2024-01-15T00:00:00Z

MM/DD/YYYY

01/15/2024

2024-01-15T00:00:00Z

MM-DD-YY

01-15-24

2024-01-15T00:00:00Z

MM/DD/YY

01/15/24

2024-01-15T00:00:00Z

YYYY-MM-DD

2024-01-15

2024-01-15T00:00:00Z

YYYY-MM-DDTHH:MM

2024-01-15T10:30

2024-01-15T10:30:00Z

ISO 8601

2024-01-15T10:30:00Z

2024-01-15T10:30:00Z (no conversion needed)

Timestamp Examples

Converting Multiple Formats

sources:
  employees:
    destination: LocalUser
    field_mapping:
      user_id:
        destination_field: unique_id
      
      # Handles: "01-15-2024", "01/15/2024", etc.
      hire_date:
        destination_field: hire_date
        custom_type: TIMESTAMP
        transforms:
          - name: date_convert
      
      # Already in ISO format, no conversion needed
      last_login:
        destination_field: last_login
        custom_type: TIMESTAMP

Windows Active Directory Timestamp

field_mapping:
  ad_last_logon:
    destination_field: ad_last_logon
    custom_type: TIMESTAMP_AD
    # No conversion needed - send as-is (integer value)
    # Example: 133456789012345678

Important Considerations

Data Type Consistency

Ensure your source data values match the custom_type you specify:

# ✅ CORRECT - Value is boolean
field_mapping:
  is_active:
    destination_field: is_active
    custom_type: BOOLEAN
    # Data: true, false

# ❌ WRONG - String value for BOOLEAN type
field_mapping:
  is_active:
    destination_field: is_active
    custom_type: BOOLEAN
    # Data: "true", "false" (strings, not booleans)

⚠️ Critical: Empty String vs. Null for Timestamp Fields

Built-in timestamp fields (last_login_at, created_at, deactivated_at, password_last_changed_at) require valid RFC3339 format or NULL. An empty string is rejected by Veza.

The Problem:

OAA field mapping converts None (NULL) → "" (empty string) for all built-in fields. If your source has NULL values, they become empty strings, which Veza rejects.

Solution: Clean empty strings in PRE_PUSH_OAA hook

from oaa.hooks import hook, OAAHookEvent

@hook(event=OAAHookEvent.PRE_PUSH_OAA)
def clean_empty_timestamps(provider=None, **kwargs):
    """Replace empty strings with None for timestamp fields."""
    for user in provider.local_users.values():
        for field in ["last_login_at", "created_at", 
                      "deactivated_at", "password_last_changed_at"]:
            if getattr(user, field, None) == "":
                setattr(user, field, None)

Or skip unmapped fields entirely at the source level:

def fetch(**kwargs):
    def clean_record(record):
        # Only include last_login_at if it has a valid ISO timestamp
        if record.get("last_login") and is_valid_timestamp(record["last_login"]):
            record["last_login_at"] = record["last_login"]
        else:
            record["last_login_at"] = None  # Explicitly None, not empty
        return record
    
    return lazy_dict_table(
        (clean_record(r) for r in users_generator()),
        header=["id", "email", "last_login_at", ...]
    )

Recommendation: Always validate timestamp fields in PRE_PUSH_OAA before pushing to Veza.

Other NULL/Empty Values

  • Empty strings and null values in custom properties are handled gracefully

  • Veza will display them appropriately in the UI

  • Optional custom fields can remain empty

Timestamp Best Practices

  • Always use ISO 8601 format when possible: YYYY-MM-DDTHH:MM:SSZ

  • Use date_convert transform for non-standard formats

  • Ensure timezone information is included when available

  • For AD timestamps, use TIMESTAMP_AD type (requires Windows filetime integer format)

Complete Example

sources:
  users:
    destination: LocalUser
    field_mapping:
      # Standard OAA fields
      user_id:
        destination_field: unique_id
      email:
        destination_field: email
      name:
        destination_field: name
      
      # Custom STRING fields
      department:
        destination_field: department
        custom_type: STRING
      
      office_location:
        destination_field: office_location
        custom_type: STRING
      
      # Custom BOOLEAN fields
      is_contractor:
        destination_field: is_contractor
        custom_type: BOOLEAN
      
      has_mfa_enabled:
        destination_field: has_mfa_enabled
        custom_type: BOOLEAN
      
      # Custom NUMBER fields
      salary:
        destination_field: salary
        custom_type: NUMBER
      
      # Custom TIMESTAMP fields (with format conversion)
      hire_date:
        destination_field: hire_date
        custom_type: TIMESTAMP
        transforms:
          - name: date_convert
      
      # Custom STRING_LIST fields
      certifications:
        destination_field: certifications
        custom_type: STRING_LIST

See Also