How to Enrich Existing Veza Entities with Custom Properties

Goal

Attach custom properties (e.g. a company internal ID, a compliance flag, a cost center) to entities that already exist in the Veza graph — such as AwsIamRole, AwsIamUser, or OktaUser discovered by other Veza integrations — without creating new entities.

This uses the Veza Entity Enrichment template.

When to use this

Use Entity Enrichment when:

  • You have data that should appear as searchable metadata on a Veza entity that another integration discovered.

  • You want to keep enrichment data separate from the integration that owns the entity (so re-running the source integration doesn’t overwrite your fields).

  • You do not want to create new entities — only add properties to existing ones.

If you need to create the entities themselves (users, groups, roles, resources), use the CUSTOM_APP, IDP, or HRIS destination type instead.

Prerequisites

  • A config.yaml ready for OAA-runner.

  • The Veza entity_type of the entities you want to enrich (e.g. AwsIamRole).

  • The Veza data_source_id of the datasource that owns those entities (for AWS, this is the account ID combined with the data source type, e.g. "339083562601:awsiam").

  • A list of entity IDs (e.g. role ARNs) and the property values you want to attach.


Steps

1. Set destination_type: ENTITY_ENRICHMENT at the top of the config

version: v2

destination_type: ENTITY_ENRICHMENT

app:
  name: Company Metadata Enrichment

The app.name is used as the Veza provider name. No other app fields (application_type, idp_type, hris_type, …) apply.

2. Configure each source with destination: EnrichedEntity

Each source enriches one Veza entity type. Set entity_type and data_source_id once on the source — they apply to every row.

sources:
  aws_iam_roles:
    destination: EnrichedEntity
    entity_type: AwsIamRole
    data_source_id: "339083562601:awsiam"
    source_type: csv
    csv_filepath: ./data/role_metadata.csv
    field_mapping:
      role_arn:
        destination_field: id
      my_company_id:
        destination_field: my_company_id
        custom_type: STRING
      company_purpose:
        destination_field: company_purpose
        custom_type: STRING
      is_compliance_validated:
        destination_field: is_compliance_validated
        custom_type: BOOLEAN

Source field

Required

Purpose

destination

yes

Must be EnrichedEntity.

entity_type

yes

Veza entity type to enrich (e.g. AwsIamRole, OktaUser).

data_source_id

yes

Veza datasource ID that owns the entities.

field_mapping entry with destination_field: id

yes

The per-row Veza unique ID (for AWS, the ARN).

Any other field_mapping entries with custom_type:

no

Become custom properties on the enriched entity.

3. Run the integration

cd src && uv tool run --from oaa-runner oaa app \
  --config-file path/to/entity-enrichment.yaml \
  run

To preview the payload without pushing to Veza:

cd src && uv tool run --from oaa-runner oaa app \
  --config-file path/to/entity-enrichment.yaml \
  --no-push=True --save-json=True \
  run

The generated JSON contains enriched_entity_property_definitions and enriched_entities — no users/groups/roles keys.


Things to know

Generators are not supported

local_group and local_role generators have no meaning on enriched entities (there are no roles or groups in the enrichment payload). If a source declares generators while destination: EnrichedEntity, OAA-runner logs a prominent error and skips all generators for that source — the rest of the source is still processed.

Multiple entity types

Use one source per Veza entity type. Each source can have its own entity_type and data_source_id. See entity-enrichment.yaml for a two-source example.

Property name validation

Property names must match ^[a-z_][a-z0-9_]*$ — lowercase letters, digits, and underscores only, starting with a letter or underscore. This is enforced by the underlying oaaclient library and applies to the destination_field value of any custom-typed field.