All pages
Powered by GitBook
1 of 30

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Core Concepts

Strategies and best practices for OAA connector development

See the included topics for more information about developing an Open Authorization API connector.

Connector Requirements
Using OAA Templates
Providers, Data Sources, Names and Types
Sourcing and Extracting Metadata
Naming and Identifying OAA Entities
Modeling Users, Permissions, and Roles
Custom Properties
Tagging with OAA
Cross Service IdP Connections

Providers, Data Sources, Names and Types

Naming, typing, and searching for top OAA entities

Custom providers and data sources

Before uploading entity metadata for an OAA integration, you must create a custom provider and at least one data source under that provider. The provider represents the type of application (such as "Jira Server") and determines the template used for all data sources (e.g."dev", "prod")created under that provider.

The OAA payload is pushed to a specific data source and updates the existing data.

A display icon can be set for the provider, shown throughout the Veza UI to identify the integration and its entities.

Naming the provider and data source is an important step in integration creation. In general,

  • The provider name should be unique to the integration. Avoid common terms such as "application". Separating providers for systems with several instances such as "production" and "development" can be a good idea.

  • The provider or data source value should be unique to the integration and incorporate an identifier such as hostname or other instance ID. This ensures that multiple instances of the integration can be separated if necessary.

  • Do not user random or date values in provider or data source names. Each run of the connector should result in the same provider and data source name, based on discovered values or a configuration parameter.

Custom application names and types

Each OAA Template supports a concept of name and type. The type enables search for all instances of a specific entity. For example, the Application Type identifies application entities such as users, groups, roles, and resources. It will enable search for all entities in an application. Setting the application type to Zendesk will allow for search Zendesk Users, Zendesk Groups, and other entity types:

The app name appears when searching for individual entities, and, to differentiate more than one instances of the same system. For example two instances of an application "Portal - Production" and "Portal - Development".

Open Authorization API

Using Veza APIs to add custom data and identity providers to the Veza Entity Catalog

Several community connectors built on OAA are already available for immediate use, enabling easy connection to SaaS providers such as GitHub, SalesForce, and others. You can also develop a custom connector using the Veza-provided Python SDK oaaclient or your language of choice.

To integrate a custom application using OAA, you will typically rely on an API (or another method) to list identities and resources within the host system, and retrieve entity and authorization metadata such as permissions, roles, and activity status. You must then structure this information according to one of the supported OAA templates. Once you have assembled the JSON payload, you can publish it using REST API calls or the oaaclient CLI.

Use Cases

Customers have utilized the Open Authorization API to accommodate many different scenarios. A few use cases include:

  • Using the GitHub connector to ensure that repositories holding critical source code are correctly configured.

  • Collecting infrastructure-as-a-code (IaC) configurations to audit which users can log in to important hosts.

  • Auditing the permissions granted by an internal developer portal.

First Steps

Alternatively, you can parse a data source, compile the JSON payload, and publish it using your language of choice. For detailed documentation on the OAA schema and API operations, see:

Using OAA Templates

How to use the Application Template to represent various types of application

The OAA Application template allows for representing the basic elements of an application and is flexible to allow for multiple different patterns.

The custom application template provides a framework for describing:

  • Who: Users, Groups, and other identities

  • What: Application, resources, sub-resources

  • How: Permissions, canonical mappings, roles, authorization

Application

The Application itself is the first entity as part of the Application submission. The application has a name and a type. The name can be specific such as "West Production" and the type is typically the vendor, technology, or product such as "GitLab". Veza will group the rest of the entities by the application type such as "GitLab Users" across all instances of an application type, however, entities will only be directly associated with the application they are submitted with. Applications additionally can have custom properties assigned to further enrich the data. This can be especially useful to distinguish between multiple instances of an application type.

Local Users

The Local User object represents the local user of the application. It can store application-specific information such as the identifier, name, active status, last login time, and custom properties specific to the application. An external Identity can be associated with the user, enabling Veza to connect the source Identity Provider (IdP). This creates a connection in the Authorization Graph between the application user and a source identity such as Okta or Active Directory. Users can be added to groups, or have roles and permissions directly assigned.

Local Groups

Local Groups represent a collection of users. Groups can store additional metadata about the group to support search and filters. Groups can also contain other groups, to model applications that support nested groups. Groups can have role and permission assignments in the application.

Local Roles

Local Roles represent a collection of permissions within an application. When a user or group is assigned a role, that user or group is assigned all the permissions from the role. Like other entities, roles can contain additional properties to enrich the metadata of the role, such as description or application-specific attributes.

Permissions

OAA allows for expressing the permissions of the application in its own terms. In the Application Template, permissions are defined by application-specific terms such as "Close Ticket" or "Approve User". These permissions will also allow for setting corresponding Veza Canonical Permissions such as "Data Read", "Data Write", or "Metadata Read". This enables search and filters across permissions using CRUD-like equivalents.

Available Canonical Permissions: - DataRead - DataWrite - DataCreate - DataDelete - MetadataRead - MetadataWrite - MetadataCreate - MetadataDelete - NonData - Uncategorized

Resources

Resources can be used to model components within applications that users can be assigned roles or permissions on. For example, an OAA resource may be used to model a Project in an application like Jira. Users can have different roles in different projects, by assigning the correct users or groups their respective roles on the resources. Each resource has a Type which Veza uses when displaying and searching the resources for an application. Applications can have multiple types of Resources. Like other entities, resources can have properties containing additional resource metadata.

Examples

Below are some examples of how applications may be modeled in OAA. These examples have all been implemented using the Application template.

PagerDuty

PagerDuty is an example of an application where users can have roles at the application level (global roles) but also within the PageDuty Teams that a user is a member of. Understanding which Users are part of which Teams and what level of access they have in those Teams is important for reviewing access in an application like PagerDuty. The OAA Application template can be used to model this type of application using the following mappings.

With this model, Veza can show the levels of access users have within the overall Application and their individual Teams. In this example, we can see the User Gary Ward has the Role "Restricted Access" in the PagerDuty Application, and the "Observer" Role in the "Support" Team Resource.

GitLab

GitLab is a good example of a more complex application that can be modeled using the Veza OAA Application Template. By correctly modeling the applications, Veza can show which users have access to GitLab Groups and Projects to show details beyond just "who has access to GitLab?"

  • Each GitLab User is represented with the Application Local User. GitLab assigns each user a unique ID number to each user, using this as the ID for the Local User makes it easier when associating groups and roles to Projects later. The Local User also allows for setting properties to represent the user's state such as is_active or last_login_at, custom properties to represent GitLab-specific properties can also be utilized like if the user is licensed or not. The identity for the Local User is set to enable OAA connection to source Identity Providers configured in Veza.

  • A GitLab Group represents both a collection of Users, a collection of Projects, and possibly other sub-groups. This is a good example of where some mapping needs to be done to represent GitLab using the Application Template. Since GitLab Users have a specific role in the GitLab Group, it is correct to represent the GitLab Group as an OAA Resource. Members are assigned an OAA Local Role to the Resource that represents the GitLab Group, denoting their level of access (Owner, Developer, Guest, and so on). Veza can return all the members of a GitLab Group by querying for the relation between the OAA User and the OAA Resource. Additionally, the role within the GitLab Group is preserved by the OAA Role.

  • GitLab Projects are also represented as an OAA Sub-Resource with the type set to Project. The Project Sub-Resource is added to the corresponding Group resource. Local User and Local Groups can be assigned roles on the project based on their direct assignments. In the case of GitLab, permissions can be inherited from above. This is an optional behavior for permissions, which can be set to automatically apply to sub-resources, or only apply directly to the assigned resources. Additionally, permissions can be set to apply to certain types of resources so that roles can be used across resources and only the correct permissions will be applied.

Getting Started

Overview and first steps for building an Open Authorization API connector

A built-in Veza integration or OAA connector might not be available for an application or identity provider you want to connect to Veza. However, you can still use the Open Authorization API to integrate compatible applications and identity providers with the rest of your Veza data catalog.

The adaptable OAA schema can model a wide range of authorization models and resource hierarchies, and you will typically have several options for sourcing authorization metadata from the application provider. To integrate a custom application with Veza, you will need to be able to:

1. Extracting metadata from the source application

Typically, the required information will be available from an API, but you should consult the provider's documentation to ensure the information is available, and consider an alternative method for sourcing the data, if not.

2. Generating a sample payload

Most programming languages offer ways to populate and manipulate a JSON schema. You can also use the Python SDK for prebuilt functions:

Custom Application Payload

Custom Properties

3. Creating and Updating Custom Providers and Data Sources

You will use the Veza REST API to create, delete, and update a custom data source under v1/providers/custom/{provider_id}/{datasource_id}. Before you can push an OAA payload, you will need to:

  • Add a custom Provider to represent the generic application provider (such as "GitHub"), and set the name and template (application or IdP).

  • Bind a custom Data Source to the new custom Provider (such as "GitHub Organization") to activate it in the data pipeline. The data source will be the destination for future pushes and updates, and should usually represent the top-level instance of the modeled application.

  • Push the payload to populate the Veza Access Graph with new entities and metadata for the custom data source.

Updates

To update the data, push a new payload to the original provider ID and data source ID. By default, Veza will overwrite any existing data. The previous state will be available in the graph history, based on Veza's snapshot retention schedule.

Using oaaclient

Notes

  • Typically, the provider should represent the provider name (such as "CustomSCM"). Any payload pushes will target the data source ("CustomSCMInstance") under the custom provider. The pushed payload can include many nested resources (such as multiple repositories). The template also supports resources with a variety of different types within a single application.

  • The data source and provider name are primarily for internal use. The application_type specified in the template is used when viewing and searching the custom app from the Veza UI.

Troubleshooting

Veza enforces strict validation of the json_data field containing the OAA payload. Three checks are performed:

  1. All required fields must be present.

  2. String fields must be valid UTF-8 strings, no larger than 256 characters.

Warnings

  • To validate an AzureAD or other type of user, go to the Authorization Graph, search for the node of interest, select Show Details, and confirm the principal name is correct.

  • To validate the identifier for a group, find the node for the group and verify the name is as expected.

Veza will always return the warnings key in the response. If a response is empty, there are no warnings.

Errors

  1. The field in which the error occurs

  2. The detailed reason for the error

Connector Requirements

Choosing your development environment and deploying an OAA connector

The Open Authorization API enables developers to push metadata to the Veza Authorization Graph using a standard JSON schema. To automate this process, you will need a way to periodically query the data source you want to integrate, populate the schema, and publish the populated template payload to your Veza instance using API calls.

You can interact with the Veza API from your client or language of choice. OAA connectors can (and have) been developed in a variety of languages. The only requirements are the ability to:

  • assemble a dict or similar data structure and convert to JSON

  • make REST API calls to publish the payload

Deploying your connector

You can run OAAClient as a manual CLI tool for trial purposes, but should automate any long-running OAA implementation. A DevOps or SecOps team is typically responsible for establishing continuous integration of a Veza connector.

Customers are responsible for running their own connectors. The frequency your app must run will depend on use case, ranging from daily to hourly. Veza typically refreshes metadata for built-in integrations on an hourly basis. However, you can decide to publish OAA payloads on any schedule.

At a minimum, a deployed OAA connector should be able to:

  • Parse the data source and push an updated payload on a schedule

  • Securely handle secrets such as API keys

Teams should follow their preferred processes and use familiar or existing platforms. Some options include:

  • AWS Lambda function

  • Docker/k8s-based container

  • cron task

  • GitHub action

Choosing between full push and incremental updates

Veza expects the default push to contain a full payload. This will overwrite all information in the updated data source.

During development, it is usually most efficient to design your parser for a full discovery. It will be easiest to design the connector to assemble and push the full payload, and use the same code to publish updates.

To use incremental updates:

  • Set the is_incremental flag in the payload to true

  • Add an add, modify or delete operation to all entities

Sourcing and Extracting Metadata

Strategies for extracting authorization, identity, and resource metadata

When planning an OAA connector, consider how you will gather the information you want to import into Veza. Refer to the application’s documentation to confirm you can obtain the required metadata from the host application.

Ideally, you will be able to list and collect metadata for:

  • User records

  • Group memberships

  • User roles and permissions

  • Resource names and metadata

For example, the Veza-GitHub connector utilizes the following endpoints (in addition to basic authentication and authorization APIs):

Web-based APIs are a common solution for SaaS apps, but not required for an OAA integration. Just because an endpoint exists does not mean that it returns useful information (some APIs are more designed for client automation than audits). Possible choices for sourcing metadata include:

  • From a database: Is data for a hosted app available in a database your connector can query?

  • File-based extraction: is the metadata available in source code or a configuration file, or an exportable report (such as CSV)?

  • Other options: does the provider have an SDK or CLI interface you can use to retrieve data?

If no machine-readable data is readily available, even screen scraping could be a solution. There are many creative options for extracting the information to populate the template, although an API will typically be the most usable option.

Naming and Identifying OAA Entities

Setting unique identifiers and human-readable names using OAA templates

By default the templates use the name field for this purpose. However, names are not unique within some applications. In this case the templates offer an optional id as a unique identifier, allowing name to function as a non-unique display name.

Custom Application

Local User, Local Group and Local Role have an optional value id that can be provided for each entity that serves as the unique identifier.

  • To use id all Local Users, Local Groups and Local Roles must be defined with an ID. The name and id can be the same value as long it is unique for the entity type. For example a local role can have admin for both the name and id.

  • The id value becomes the key for referencing local users, groups and roles in the identity_to_permissions section of the payload and for referencing group memberships.

Using ids for mapping, instead of name is recommended in most cases, especially if any of the following are true:

  • Entity names aren't unique in the application (if two users can have the name "Joe Doe" but each have a unique user id such as email or login or the applications unique id).

  • The API references users, resources, and other entities by an ID instead of name. Using the same ID for the OAA payload will limit scenarios where you need to maintain a mapping of id to name in your connector.

For Custom Application to use id for Local Users, Groups and Roles all entities must use the id field. To use the id field for Resources all Resources and Sub-Resources must have an id

Resources

Resources and Sub-resource each can have an optional id value. When provided, the resource name does not need to be unique. To use id, all resources and sub-resources must be defined with a unique ID. The id value will be used to assign resource permissions in identity_to_permissions.

Custom IdP

Custom IdP also supports a optional unique identifier value identity for Users and Groups. If not used, the entity name must be unique and will be the primary identifier.

Tagging with OAA

Tags are applied by providing a key and an optional value for each. A new tag will be created if a matching one doesn't already exist.

Due to superior integration with other Veza functionality and ease of updates, custom properties are recommended as the best approach for adding metadata to OAA entities, unless tagging is required as part of a larger campaign.

Modifying Tags with Incremental Updates

The operation field indicates the change to make. Valid operations are:

  • "add", "modify", "delete" to create, change, or remove an entity.

  • "add_tag", "delete_tag" to update a tag without altering the entity.

Custom Properties

Applying additional metadata to OAA entities

In addition to built-in fields such as last_login_at, OAA supports custom-named properties for users, resources, groups, and other entities in a payload. Custom properties are validated against a set of custom property definitions as part of the JSON payload.

To use custom properties:

  1. Include a definition of all properties as part of the payload push. The definition sets the type for the property.

  2. Set the custom properties for each object.

Use cases

If a built-in property doesn’t exist for the provider you are modeling, you can define custom properties in the OAA payload. This can enable sophisticated queries on many possible fields (such as encryption_enabled, password_last_used_at). Custom properties have a declared data type and are indexed and filterable, like any built-in property.

For example, you could use the custom string property "state" for an app that can be either "active," "suspended," or "disabled." If there's only one state, you could instead use a boolean ("active": "false").

Custom property types

Custom Properties are defined as part of the custom_property_definition section and require a type. Typing the data allows Veza to provide a better index and search experience. For example, the TIMESTAMP type enables date-relative filters such as "in the last 30 days."

Allowed types are NUMBER, STRING, STRING_LIST, TIMESTAMP, and BOOLEAN.

  • A type is required and permanent.

  • The maximum length of a string is 4096 characters.

In the Veza UI, underscores in property names are replaced by spaces, and first letters are capitalized (is_licensed > Is Licensed).

If a custom property name collides with an existing built-in property, Veza will add the "Custom" prefix (ID > Custom Id).

In the Query Builder API, custom properties are prefixed with custom_ in responses and must be prefixed with custom_ when used in filter statements.

Modifying custom properties

Once pushed, properties and types can't be altered. You can re-submit the payload with additional custom property definitions to add new properties.

  • The provider must be deleted and pushed again to remove properties from a definition or change their types.

  • The original custom property definition is not required in future submissions but should be saved for later reference.

OAA custom property examples

Custom properties with oaaclient Python SDK

Custom properties for a custom application

A custom property definition sets possible properties, their types, and the application or resource type they can apply to. The following entities can have custom properties:

The following example shows a custom property definition for GitLab:

Properties are set on users and resources in custom_properties:

Custom properties for a custom identity provider

Modeling Users, Permissions, and Roles

Using local roles, local users, and canonical permissions to describe access

Using local_users to describe local and federated identities and service accounts

Most applications will have some concept of a “local user” that can have varying permissions to data and metadata. Most modern cloud applications offer some form of single sign-on. In some cases, local user accounts correspond to an external federated identity, or even only exist ephemerally.

The Open Authorization API is able to represent local users, local groups, and external identities. An external identity could be an user connecting directly to a resource through Single Sign On, or an SSO group. A local user could be a just-in-time account created when an IdP user first connects.

  • The OAA template supports direct permissions from IdP users to resources. However, including a local user entity in your OAA mapping strategy is still recommended when possible.

Map provider permissions to Veza canonical permissions

Veza understands an identity's level access to a resource in terms of raw system permissions in the provider's terms (such as AWS IAM s3:DeleteBucket), and canonical permissions (such asDATA DELETE). This allows Veza to answer the questions: "Who has MERGE permission on production repositories?" and "who can read data from any resource flagged for PII compliance?".

OAA requires you to map each granular application permission (like "view ticket" or "close ticket") to its corresponding C/R/U/D permission. This enables search and audit of effective and configured access.

Modeling role-based access control

SaaS apps tend to be role-based, and organizations that follow security best practices will typically restrict the assignment of permissions directly to users. Following standard RBAC concepts, an OAA role represents a collection of permissions which can be scoped to individual resources or specific resource types.

If permissions granted by a role only apply to specific resource types or sub-resources, create the custom permissions individually and add them to the role in a list:

Under the custom application OAA schema, users can have direct permissions and role-based permissions to resources. Modeling these role-based permission assignments will enable searches such as "show all users with the maintain role in GitHub."

Note that “roles” in some apps actually function more like groups (lists of users), in which case they should be modeled using local_groups.

For payloads where permissions apply for the entire application, you can create a single custom permission for a role, containing all the associated canonical permissions:

As demonstrated in the OAA PagerDuty connector, this is a quick way to model authorization structures such as:

The Open Authorization API (OAA) is used to publish information about identities, authorization, and resources to the Veza , making custom-built or otherwise-unsupported applications available for search, workflows, and monitoring. A typical motivation for using OAA is the need to integrate with enterprise applications that don't have an official Veza integration, such as a custom identity broker or source control management system.

Each built-in Veza has a fixed schema unique to the provider. Integrations created with OAA can use either the Custom Identity Provider or Custom Application schema, both of which are flexible enough to model a wide range of data and identity sources.

introduces important OAA workflows, the custom application template, and common API operations. When planning your connector, you may also want to review the for more information about naming considerations, mapping custom applications to the OAA schema, and other topics.

Veza provides a and , which you can download using GitHub or pip install oaaclient. Examples and documentation are included with the source code.

- suitable for most applications

- for custom Identity Providers

- operations for creating, updating, and deleting OAA providers and data sources

PagerDuty Entity
OAA Application
Notes

Python Code for the can be referenced on the Veza GitHub

GitLab
OAA Application

GitLab Roles are assigned to users or Groups as part of a Group or Project. GitLab is an example of an application with fixed roles where the roles and behaviors are coded directly into the application. For the OAA Application Template, the corresponding Local Roles are also coded directly into the connector by reviewing the on available roles and the permissions associated with the roles. It is not always necessary to capture every Permission as part of the Local Role. Which permissions are important and how much detail is needed will be determined by the queries you intend to run, and the scope of Access Reviews that will be conducted in Veza.

Python Code for the can be referenced on the Veza GitHub

using an API, command line, or another method to collect the needed authorization-related data. Depending on the application, this could include data resources and sub-resources as well as local users, groups, roles, permissions, and correlation to federated identities or external IDs.

describing the users, resources, and permissions, according to a standard JSON schema. The payload can describe any number of application resources and sub-resources, along with information about identities, groups, permissions, and relationships to other graph entities.

for processing using Veza APIs (after registering a new custom provider and data source if they don't already exist).

You can use the to simplify the process of populating the payload, connecting to Veza, and managing OAA providers and data sources.

The process of retrieving user records, along with lists of resources, group and permissions information, will be unique to each technology and OAA connector. You may also need to consider how to adapt the application's implementation of roles, federated identities, and resource hierarchies to fit the .

Before building a connector, you should read the best practices for and , or see the current list of for real-world examples.

Below is an example of a populated application template. It demonstrates the basic principles of modeling local user permissions on application resources. For more details on all the available entities and properties see the full reference.

In addition to built-in properties such as department or last_login_at, most entities can have additional user-defined custom properties. Using enables integrations to capture application-specific data that can be useful for reporting and provide additional insight during investigations.

You can also apply to entities within the payload.

Optionally, subsequent changes can be , where the payload only contains entities to modify, add, or remove.

You can use GET to retrieve any existing provider and data source IDs. For more information about managing Providers and Data Sources see .

The module can be used to instantiate a Veza connection and manage OAA providers:

See for additional documentation.

Alternatively, you can make the required REST API calls using the client of your choice or by invoking oaaclient as a .

The maximum payload size is 100MB. If you need to compress the payload, you can enable the option when .

A successful response may include warnings for issues that didn't prevent the processing of OAA data but should still be investigated. When mapping identities to an , a warning will be raised if a matching IdP group name or user principal name can't be found.

For all Veza APIs, include an error code (in standard gRPC error, such as 3 for Invalid Argument) and a descriptive error message. The error message consists of two parts:

query the source application (or , or another method) to collect identity, resource, and authorization metadata

Veza provides a Python SDK . This package provides functions for generating and submitting the JSON payload. The Veza developed community connectors use this toolkit, along with all integrations built by active customer developers.

OAA does support as an optional behavior–if your custom data source or identity provider provides a way to get individual changes over time, you could design your connector to parse only new or changed entities, and push updates individually (perhaps in response to detected changes). However, this approach will be more complicated. A full parse-and-push will be more efficient, unless there's a method to query the provider for differences since the last push.

Veza requires each entity to have a unique identifier, used within the template to reference entities (which groups a user is a member of) and for Veza to use to track and display the entity. This is true for both the and templates

Both custom properties and can be used to add rich metadata and apply labeling strategies across entities in the Veza data catalog. Both can be viewed by checking an entity's details from tables view or Authorization Graph, and are fully available when searching and filtering results.

Veza tags can be assigned to objects in an OAA payload. One typical use case for tagging within the OAA payload is assigning using Veza SYSTEM_resource_managers tags.

Note that while tags can be removed using the tags applied within the template are persistent: an existing tag won't be deleted when pushing a payload with a new tag or empty tag.

After the initial metadata push (which must contain the full payload), you can modify, add, or remove the domain, users, and groups without resubmitting other entities. An is enabled by setting "incremental_change": true in the json_data push payload, and specifying the update operation for each entity to change.

Built-in properties (such as last_login, created_at, and is_active for local users) enrich Veza graph entities with additional metadata. These built-in properties are described in the template documentation for and .

Dates must be in , which can include a timezone offset or use UTC (2021-01-01T22:47:31-07:00, 2021-01-01T22:47:31Z).

Property values on entities can be modified by pushing a complete payload with new custom_properties or using operations.

Here are some example custom property definitions for the and templates.

The also supports creating and setting custom properties.

Entity
Key
Notes
Entity
Key

You should represent system users using objects, even for apps that are SSO-enabled. The local user object is able to contain useful attributes such as activity status and timestamps, enabling rich search on those entities. A local user can also reference a federated identity, creating graph relationships between IdP entities and local users and groups when the payload is parsed. Veza handles these cross service connections similarly to built-in integrations such as Snowflake.

Users can also be grouped and assigned permissions with .

Raw ("System") Permission
Canonical Permission
Custom Application Role
Custom App Permission
Canonical Permission
Access Graph
integration
Getting Started
Core Concepts
Python SDK
working example connectors
Custom Application Template
Custom Identity Provider Template
API reference

User

Local User

Team

Local Group

To group the Users

Application Role

Local Role

Applied to the Application

Team

Local Resource

To represent the User's role in the Team

Team Role

Local Role

Applied to the Team Resource

User

Local User

Group

Resource

Project

Sub Resource

custom_app.add_custom_permission("owner", [OAAPermission.DataRead, OAAPermission.DataWrite])
jane = custom_app.add_local_user("jane", identities="jane@example.com")
resource1 = custom_app.add_resource(name="customers", resource_type="database")
jane.add_permission(permission="owner", resources=[customers])
{
  "applications": [
    {
      "name": "Support Portal",
      "application_type": "support_portal",
      "description": "Our customer support portal",
      "local_users": [
        {
          "name": "bob",
          "identities": [
            "bob@example.com"
          ],
          "groups": [
            "admins"
          ],
          "is_active": true,
          "last_login_at": "2022-03-21T18:56:38Z"
        },
        {
          "name": "sue",
          "identities": [
            "sue@example.com"
          ]        }
      ],
      "local_groups": [
        {
          "name": "admins"
        }
      ]
    }
  ],
  "permissions": [
    {
      "name": "admin",
      "permission_type": [
        "DataWrite",
        "DataRead",
        "DataDelete",
        "MetadataWrite",
        "MetadataRead"
      ]
    },
    {
      "name": "login",
      "permission_type": [
        "DataRead",
        "MetadataRead"
      ]
    }
  ],
  "identity_to_permissions": [
    {
      "identity": "bob",
      "identity_type": "local_user",
      "application_permissions": [
        {
          "application": "Support Portal",
          "permission": "login"

        }
      ]
    },
    {
      "identity": "sue",
      "identity_type": "local_user",
      "application_permissions": [
        {
          "application": "Support Portal",
          "permission": "login"

        }
      ]
    },
    {
      "identity": "admins",
      "identity_type": "local_group",
      "application_permissions": [
        {
          "application": "Support Portal",
          "permission": "admin"
        }
      ]
    }
  ]
}
from oaaclient.client import OAAClient
from oaaclient.templates import CustomApplication, OAAPermission

# creates a connection class to communicate with Veza
veza_con = OAAClient(url=veza_url, token=veza_api_key)

# creates a new Custom Application model
custom_app = CustomApplication(name="Sample App", application_type="sample")
{
  "warnings": [
    {
      "message": "Cannot find identity by names (values: unknown_user@veza.com)"
    }
  ]
}
- orgs/{org_name} - Get Organization information
- orgs/{org_name}/members - List members for an organization
- orgs/{org_name}/teams - List teams for an organization
- orgs/{org_name}/teams/{team}/members - List members for a given team
- orgs/{org_name}/repos - List organization repositories
- repos/{org_name}/{repo}/teams - List Team permissions for repository
- repos/{org_name}/{repo}/collaborators?affiliation=direct - List team members with direct permissions
{
  "resource_type": "Cluster",
  "description": "release staging cluster",
  "sub_resources": [],
  "tags": [
    {
      "key": "environment",
      "value": "development"
    }
  ]
}
...
"local_groups": [
    {
      "name": "LGroup1",
      "identities": [
        "localgroup1@company.com"
      ],
      "tags": [
        {
          "key": "NewTag2Key",
          "value": "NewTag2Value"
        }
      ],
      "operation": "add_tag"
    }
]
...
app = CustomApplication(name="Demo", application_type="Demo")
# Define a new local user string property `email`
app.property_definitions.define_local_user_property("email", OAAPropertyType.STRING)

local_user = app.add_local_user(name="name", unique_id="user_id")
# set the property by name
local_user.set_property("email", "user@example.com")

Custom Application

application_properties

Scoped by application_type

Custom User

local_user_properties

Custom Group

local_group_properties

Custom Role

local_role_properties

Custom Resource

resources

Scoped by resource_type

  "custom_property_definition": {
    "applications": [
      {
        "application_type": "GitLab",
        "application_properties": {},
        "local_user_properties": {
          "id": "NUMBER",
          "bot": "BOOLEAN",
          "is_licensed": "BOOLEAN",
          "state": "STRING"
        },
        "local_group_properties": {},
        "local_role_properties": {},
        "resources": [
          {
            "resource_type": "project",
            "properties": {
              "id": "NUMBER",
              "visibility": "STRING"
            }
          }
        ]
      }
    ]
  }
{
  "name": "support-bot",
  "identities": ["support@cookie.ai"],
  "groups": null,
  "is_active": true,
  "created_at": "2022-01-25T18:55:19.146Z",
  "last_login_at": null,
  "deactivated_at": null,
  "password_last_changed_at": null,
  "tags": [],
  "custom_properties": {
    "id": 7,
    "is_licensed": false,
    "state": "active",
    "bot": true
  }
}

Custom IdP Domain

domain_properties

Custom IdP User

user_properties

Custom IdP Group

group_properties

{
  "custom_property_definition": {
    "domain_properties": null,
    "group_properties": {
      "group_lead": "STRING"
    },
    "user_properties": {
      "birthday": "TIMESTAMP",
      "description": "STRING",
      "last_login": "TIMESTAMP",
      "is_licensed": "BOOLEAN",
      "region": "STRING"
    }
  },
  "name": "My IdP",
  "id": "custom_idp",
  "domains": [
    {
      "name": "domain.biz"
    }
  ],
  "users": [
    {
      "name": "Colby Smith",
      "custom_properties": {
        "is_licensed": false,
        "region": "US-West"
      }
    }
  ]
}

Manage Access

Metadata Write

Merge

Data Write

Pull

Data Read

self.app.add_local_role("Write", ["Pull", "Fork", "Push", "Merge"])
self.app.add_custom_permission("limited_user", permissions=[OAAPermission.DataRead, OAAPermission.MetadataRead])
self.app.add_local_role("Responder", unique_id="limited_user", permissions=["limited_user"])

Account Owner

owner

Data Write, Data Read, Data Delete, Metadata Read, Metadata Write

Responder

limited_user

Data Read, Metadata Read

Observer

limited_user

Data Read, Metadata Read

PagerDuty connector
GitLab documentation
GitLab connector
Python SDK
OAA template
Custom Application
custom properties
Veza tags
incremental updates
REST API Operations
oaaclient.client
Client
command-line tool
external id
error messages
read a data file
oaaclient
incremental update
Application
IdP
Veza Tags
resource managers
Tags API,
incremental update
applications
identity providers
RFC3339 format
incremental update
custom application
custom identity provider
Python SDK
Extract metadata from the source application
Generate a payload
Publish the payload
creating the OAA data source

OAA Operations

API calls for managing and updating custom data sources

Use these REST API calls to manage and update custom providers and data sources with Open Authorization API.

Create Custom Provider

Creates a custom provider and returns the provider ID.

List Custom Providers

Lists all configured custom providers.

Get Custom Provider by ID

Returns details for an individual custom provider.

Delete Custom Provider

Delete a custom provider by ID.

List Custom Provider Datasources

Return all data sources for a Custom Provider ID.

You can constrain large responses by adding a filter to the request query string. Include the operator (eq), and value, for example:

CURL <VEZA_URL>/api/v1/providers/custom?filter=name eq "GitHub"&order_by=state

Veza expects that spaces in URLS are encoded as "+" (for example?name+eq+"GitHub"&order_by=state). Note that some libraries and clients will encode spaces as "%2B" by default, which will cause errors unless you override this behavior.

Create Custom Provider Datasource

Register a new datasource for a custom provider. There can be more than one datasource for a single provider.

Get Datasource by ID

Returns details for a single datasource.

Delete Custom Provider Datasource

Unbind a datasource from a custom provider, and delete it.

Push Custom Provider Datasource

To push authorization metadata for a custom datasource, you can specify the source and provider IDs, and upload a payload with the entities and permissions in JSON format.

A warning is returned for any non-critical errors during payload processing. These can indicate incomplete or inaccurate data in the payload that do not prevent processing, but may warrant attention.

Push Custom Provider Datasource CSV

CSV data must base64 encoded into the JSON body of the request.

{
    "csv_data": "abc123="
}
CSV_PAYLOAD=$(cat my_app_data.csv | base64)
curl --location https://example.vezacloud.com/api/v1/providers/custom/40bdd318-d320-4574-be90-ca556d59889a/datasources/9bc29dc6-8cd0-4926-992e-7d720305ae2f:push_csv \
--request POST \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $VEZA_API_KEY" \
--data "{\"csv_data\": \"${CSV_PAYLOAD}\"}"

Compression

The populated template can be compressed and encoded, for significantly reduced payload size.

  • Specify the compression_type. Currently supported: GZIP.

  • If compression is selected, Veza will expect the payload json_data as a compressed, base64-encoded string.

To compress using shell commands:

cat app_payload.json | gzip | base64 -o json_data.b64

Size is typically not an issue when updating custom datasources. However, you may want to compress large payloads. The maximum body size is 100MB (compressed or uncompressed).

Escaping unsafe characters

Veza expects the populated template as a single JSON string, enclosed in the request body json_data field. Any "s and non-ASCII characters must be escaped.

To convert a template to JSON string using Python, the json.dumps() method could be used:

payload = {"id": provider_id,
           "data_source_id": data_source_id,
           "json_data": json.dumps(template_contents)
           }

Custom Provider Icons

You can optionally add an icon for your custom provider by uploading a PNG or SVG file (less than 64kb) as a base64-encoded string:

curl -X POST '{{VezaURL}}/api/v1/providers/custom/962d5eff-285c-4b08-a54e-400eead1e680:icon' \
-H "authorization: Bearer $API_KEY" \
-d '{"icon_base64": "PHN2ZyBmaWxsPSIjMDAwMDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciICB2aWV3Qm94PSIwIDAgNjQgNjQiIHdpZHRoPSIzMnB4IiBoZWlnaHQ9IjMycHgiPjxwYXRoIGQ9Ik0zMiA2QzE3LjY0MSA2IDYgMTcuNjQxIDYgMzJjMCAxMi4yNzcgOC41MTIgMjIuNTYgMTkuOTU1IDI1LjI4Ni0uNTkyLS4xNDEtMS4xNzktLjI5OS0xLjc1NS0uNDc5VjUwLjg1YzAgMC0uOTc1LjMyNS0yLjI3NS4zMjUtMy42MzcgMC01LjE0OC0zLjI0NS01LjUyNS00Ljg3NS0uMjI5LS45OTMtLjgyNy0xLjkzNC0xLjQ2OS0yLjUwOS0uNzY3LS42ODQtMS4xMjYtLjY4Ni0xLjEzMS0uOTItLjAxLS40OTEuNjU4LS40NzEuOTc1LS40NzEgMS42MjUgMCAyLjg1NyAxLjcyOSAzLjQyOSAyLjYyMyAxLjQxNyAyLjIwNyAyLjkzOCAyLjU3NyAzLjcyMSAyLjU3Ny45NzUgMCAxLjgxNy0uMTQ2IDIuMzk3LS40MjYuMjY4LTEuODg4IDEuMTA4LTMuNTcgMi40NzgtNC43NzQtNi4wOTctMS4yMTktMTAuNC00LjcxNi0xMC40LTEwLjQgMC0yLjkyOCAxLjE3NS01LjYxOSAzLjEzMy03Ljc5MkMxOS4zMzMgMjMuNjQxIDE5IDIyLjQ5NCAxOSAyMC42MjVjMC0xLjIzNS4wODYtMi43NTEuNjUtNC4yMjUgMCAwIDMuNzA4LjAyNiA3LjIwNSAzLjMzOEMyOC40NjkgMTkuMjY4IDMwLjE5NiAxOSAzMiAxOXMzLjUzMS4yNjggNS4xNDUuNzM4YzMuNDk3LTMuMzEyIDcuMjA1LTMuMzM4IDcuMjA1LTMuMzM4LjU2NyAxLjQ3NC42NSAyLjk5LjY1IDQuMjI1IDAgMi4wMTUtLjI2OCAzLjE5LS40MzIgMy42OTdDNDYuNDY2IDI2LjQ3NSA0Ny42IDI5LjEyNCA0Ny42IDMyYzAgNS42ODQtNC4zMDMgOS4xODEtMTAuNCAxMC40IDEuNjI4IDEuNDMgMi42IDMuNTEzIDIuNiA1Ljg1djguNTU3Yy0uNTc2LjE4MS0xLjE2Mi4zMzgtMS43NTUuNDc5QzQ5LjQ4OCA1NC41NiA1OCA0NC4yNzcgNTggMzIgNTggMTcuNjQxIDQ2LjM1OSA2IDMyIDZ6TTMzLjgxMyA1Ny45M0MzMy4yMTQgNTcuOTcyIDMyLjYxIDU4IDMyIDU4IDMyLjYxIDU4IDMzLjIxMyA1Ny45NzEgMzMuODEzIDU3Ljkzek0zNy43ODYgNTcuMzQ2Yy0xLjE2NC4yNjUtMi4zNTcuNDUxLTMuNTc1LjU1NEMzNS40MjkgNTcuNzk3IDM2LjYyMiA1Ny42MSAzNy43ODYgNTcuMzQ2ek0zMiA1OGMtLjYxIDAtMS4yMTQtLjAyOC0xLjgxMy0uMDdDMzAuNzg3IDU3Ljk3MSAzMS4zOSA1OCAzMiA1OHpNMjkuNzg4IDU3LjljLTEuMjE3LS4xMDMtMi40MTEtLjI4OS0zLjU3NC0uNTU0QzI3LjM3OCA1Ny42MSAyOC41NzEgNTcuNzk3IDI5Ljc4OCA1Ny45eiIvPjwvc3ZnPg=="}'

Create Custom Provider Icon

Upload a custom icon to display for an OAA provider.

Get Custom Provider Icon

Return the type and string-encoded icon for a custom provider.

Delete Custom Provider Icon

Delete the icon associated with an OAA provider.

OAA Templates

JSON schemas for describing custom applications and identity providers

OAA utilizes templates (JSON schema) for structuring authorization and identity metadata, combined with a REST API to register, update and manage the data. Once uploaded, Veza processes the template payload and incorporates the entities and permissions into the Authorization Metadata Graph.

Choosing the appropriate template (application or identity provider) is the first step in creating a new integration with OAA. The template provides a schema for describing the identities, resources, and authorization relationships local to the OAA data source.

Custom Application

A custom application is structured with the following main entities:

  • Application

    • Resource

      • Sub-resource

        • Sub-resource

          • Additional sub-resources

    • Local Users

    • Local Groups

    • Local Roles

  • Local Permissions

  • Identity-to-permissions binding

Custom Identity Provider

A Custom Identity Provider can have the following entities:

  • Domains

  • Users

  • Groups

The Custom IdP template also includes the option to define AWS Roles that are assumable by users and groups and can work with Access Review Workflows to auto-assign resource managers.

Custom Application

Template for pushing custom data source entities and authorization

Overview

The Custom Application Template can be used to model most applications and services. It can describe many common entity types (such as users, groups, and resources), and should be the starting point for most custom connectors.

The template has three primary elements, covered in detail in this document:

  • Applications - describes one or more application instances for the custom data source. An application may consist of any of the following entities:

    • Local Users - defines the users of the application. The local user entity can be used to store the properties of the user specific to the application (such as last_login_at) and can be linked to a source identity like Okta or AzureAD.

    • Local Groups - defines a group of users, permissions to the application or resources can be assigned to a group.

    • Local Roles - defines a collection of permissions. A role can be used to link an identity (local user, group, or IdP) to an application or resource. An identity assigned to a role will be assigned all permissions from that role.

    • Resources - for more fine grain authorization tracking resources can be used to represent components of the application that have their own authorization. Users and groups can be assigned permission or roles to resources.

      • Sub Resources - resources can additionally have sub-resources for additional levels of depth.

  • Permissions - define the applications specific permissions and map to Veza canonical permissions.

  • Identity to Permissions - Assign local and federated users and groups to permissions or roles to the application and resources.

To use the generic app template, set the template type to application when creating a new data provider:

Sample Payload

Simple Custom Application

This example demonstrates using local users and groups to assign permissions directly to the application and resources.

Sample Application using Roles

Custom Properties and Tags

Define custom properties

Set custom properties

In the rest of the payload, for each object that should have additional properties, add a custom_properties array containing the property keys and values:

Validation and Troubleshooting

The API response will provide information for invalid data submission. You can check Veza events for updates on parsing status. Errors won't typically occur during parsing, as the metadata is validated upon push. To ensure a valid payload, you should:

  • Confirm all string fields are are valid UTF-8 strings no larger than 256 bytes.

  • Check that all required fields are present. Tags and properties are optional. You can null empty groups, roles, and other "empty" but required keys.

  • A 200 OK response may include warnings when matching IDP identities can't be found

Applications

The OAA payload must contain at least one top-level application. To model data systems with multiple components (such as different servers or repositories), applications can have resources and sub-resources.

You can also specify more than one application in the OAA payload, each with its own identities, permissions, roles, and resources.

The application_typeis applied to all application resources and identities, and can be used as a filterable property in Veza search.

Application Properties

Optional fields: some values in the schema are optional. When submitting a payload without a required field, an error message will help identify the issue. The following guidelines apply:

  • Any type of data in a JSON payload can be null (not set).

  • Unused optional arrays and objects should be empty {} or [].

  • Unused optional strings, numbers, and booleans should be null.

  • Strings and string lists intended to have constant values (enums) such as identity_type may have a default value when not set.

Resources

Each application can contain one or more resources that users can access. Resources can have additional searchable properties and may contain additional sub-resources.

Sub-resources describe additional layers of the application principals can have authorization to, and support the same properties as resources, including additionally nested sub-resources.

Resource Properties

An application can have any number of nested sub resources.

* A specific resource type must have only resources with an id, or only resources without an id. When used identity_to_permissions assignments are made by the id value and name functions as a display name.

Resource Connections

In the system being modeled, application resources and sub-resources (such as virtual machines or Looker views) have access to other entities in the Veza authorization graph.

If an application resource or sub-resource is able to assume the permissions of a local user, IAM role, or Enterprise application, you can specify the connections to another graph entity node_type and id:

The following node types are currently available:

  • SnowflakeUser

  • GoogleCloudServiceAccount

  • AwsIamRole

  • AzureADEnterpriseApplication

  • TrinoUser

Identities

Applications can have local users and groups for identities. For users and groups that correlate to an external Identity Provider (for example accounts automatically provisioned by the IdP), you can map the principal to the IdP entity name or login email in identities.

Local Users

Contains any users whose profiles and authentication are handled and stored by the custom application. Local users include their group assignments and any federated identities that should be mapped to the local user:

local Groups

If the application has any groups, describe each one in the local_groups array.

Group assignments for entities are defined in identity_to_permissions.

*Must match a discovered Okta or Azure entity Name, PrincipalName, or Identity

Local Roles

Local roles define collections of local permissions that can be assigned to multiple resources. In the applications section, roles are named and mapped to permissions. Role assignments are defined in identity_to_permissions.

permissions

Bind local permissions to the corresponding Veza canonical permission(s). Each native application permission should be included as an object, mapped to the corresponding data/non-data actions it allows.

Canonical permission types are:

  • DataRead

  • DataWrite

  • MetadataRead

  • MetadataWrite

  • NonData

  • DataCreate

  • DataDelete

  • MetadataCreate

  • MetadataDelete

  • Uncategorized

To better model systems where roles can contain different permissions to different types of resources, permissions can apply to individual resource_types.

  • When the payload is parsed, individual permissions are created for each type of resource the permission applies to.

  • Without resource_types specified, the permission will function normally. When directly connecting principals and resources, resource_type is ignored.

identity_to_permissions

Contains an object for each local and IdP identity, and the individual permissions to applications and resources.

  • You can bind permissions to federated users and groups by providing the principal’s IDP login email or group name as the identity, and setting the identity_type to idp.

  • Permissions and role assignments can apply to the entire application or scoped to specific resources.

  • For each identity (matching a local user, group, or IdP identity), state the identity type and add the assigned permissions/roles:

  • Each identity can be either a local_user, local_role, or local_group name, or the identifier of an IdP user, group, or role (email address or group name).

  • identity_type must be one of (idp (default), local_group, local_role, or local_user.

application_permissions

Binds the identity (IdP entity, local user, or local group) to local permission, by application and resources.

role_assignments

Local roles are assigned to identities in the role_assignments array. Roles can apply to the entire application or only to specific (sub) resources.

Identities to Permissions mapping

Custom Identity Provider

Template for pushing IdP domain, user, and group metadata

Veza will handle federated identities just as those in supported IdPs such as Okta or Entra ID, enabling search and access review for OAA entities alongside the rest of your data catalog.

Sample Template and Features

The metadata payload describes the Identity Provider domain, users, and groups to add to the Veza authorization graph:

Modeling Assumable Amazon Web Services Roles

For cases where federated IdP entities are granted AWS permissions via IAM roles, the template supports defining assumable roles per-user. Binding a custom IdP user or group to an AWS role or group ARN enables Veza to parse and display the resource-level actions permitted within AWS.

Source Identity Assignments

For use cases where a custom IdP is federated with another identity provider user identities can be linked between the two. Authorizations granted to the user will also be granted the source identity. The link is created by providing the unique identity ID and provider type as part of the user entry.

For provider_type the following values are accepted:

Resource Manager Assignments

New in Veza release 2022.2.1

To assign an IdP user or group as the manager of any resource Veza has discovered, list the node type and node id in the entities_owned field, for example:

When parsing the payload, resources in the data catalog will be updated with a SYSTEM_resource_managers tag to enable entitlement reviews. The owner(s) will be suggested as reviewers for Veza Workflows that target an individual named resource with the correct tag.

Manager Assignments

Users and groups can be mapped to the identity of another user they report to. When configured, the manager will be suggested as a review for Workflow certifications where the assigned reporter is the single query target "named entity."

Custom Properties and Tags

Incremental Updates

Custom Identity Provider definition

The identity provider object models one instance of the custom IdP:

IdP Domain

One domain is supported for each custom IdP. Users and groups are mapped to the IdP domain, and connected in Veza Search:

IdP Users

Each IdP user object contains the display name, login email, and identity, along with other identity-related properties:

IdP Groups

Add a group by name in the groups section of the template to enable mapping IdP users to those groups:

IdP Apps

Use the apps section to define any applications used to manage access within the identity provider. Apps can be associated with users and groups to model application assignments across your organization.

Users and Groups can be assigned to an application by setting the app_assignments in the user or group.

Creating and Updating a Custom Identity Provider

The steps to add a custom IdP are the same as for any other OAA provider: you will need to register the new provider and data source, and then push the domain, user, and group descriptions in a JSON payload.

Register a custom identity provider

To create a new custom provider using the identity_provider template, POST the name and template type to /providers/custom:

The response will return the custom IdP ID, which you will need when pushing the metadata payload:

Push a data source for the custom identity provider

Note that the provider id is required in both the path and body of the request. The response will include the new data source ID.

Push metadata for the data source

The payload file must contain the provider and data source ID, and the authorization metadata as a single string, for example:

Identity Mapping Configuration

The identity_mapping_configuration parameter defines rules for connecting users in a custom IdP to users from other data sources in the Veza graph.

This is useful when:

  • The connected data source does not natively support returning information about external identities

  • A correlation between IdP identities and local users can be assumed based on values like username, email, or another property value.

The identity_mapping_configuration is a top-level property of the Custom IDP submission, and is optional. The mapping configuration can include multiple mappings to connect IDP users to users from different data source types, each based on its own mappings.

Identity Mapping Configuration

Identity Mapping Submission

Supported transformations:

  • IGNORE_SPECIAL: Ignore special characters (_, -, .) when matching identities

  • IGNORE_DOMAIN: Match identities after removing domain portions (e.g., "@example.com")

IdentityMappingPropertyMatchersSubmission

Custom HRIS Provider

OAA Template for Human Resources Information Systems

Overview

Use this Open Authorization API template to publish employee metadata for Human Resources Information Systems (HRIS) platforms, typically used by organizations as a single source of truth for employee information.

Unlike an Identity Provider, HR platforms typically do not provide access to other systems. Employee profiles within an HRIS platform are instead used to store important details such as employment status, who individuals report to, department, and country. Veza can use this metadata to:

  • Correlate employees in the HRIS system with identities in your identity provider (IdP).

  • Enrich Access Reviews with details about linked HRIS employees for users under review.

The template supports:

  • A top-level System entity representing the HRIS tenant, organization, or account.

  • Employee entities representing current and inactive workers

  • Group entities representing teams, departments, cost centers, or other units to which users are assigned.

HRIS template example

Custom properties

Identity mappings

Veza maps HRIS employees to identities from integrated Identity Providers (IdPs) such as Okta by matching the idp_id, email, or id value in the HRIS payload with the IdP entity's Name, Principal Name, or Identity. The matching process checks these fields in the following sequence:

  1. idp_id

  2. email

  3. id

If the idp_id is unset, Veza uses the email field for matching. If the email field is also absent, the id is used. Veza issues a warning if no matching entity is found.

Custom HRIS System

The account/tenant/etc. that contains the HR information.

Custom HRIS Employee

Used to represent any person who has been employed by a company.

Custom HRIS Group

Used to represent any subset of employees, such as PayGroup or Team. Employees can be in multiple Groups.

Cross Service IdP Connections

Mapping OAA objects to external and federated identities

In Veza, the Identity Provider (IdP) serves as the representation of the source of an identity (human or otherwise). That identity can have access to many applications, clouds and other data sources. By connecting OAA entities to source IdP identities, Veza can show all the access for that identity. This can also enable powerful correlation queries such as finding deactivated Okta Users with active application accounts.

Veza makes these connections based on the identity information provided in the OAA payload.

Veza Supports Mapping for the following Identity Providers:

  • Active Directory

  • Azure AD

  • Custom IdP

  • Google Workspace

  • Okta

  • OneLogin

For all Identity Providers, the IdP Unique ID and email attributes are used to match the source identity to an OAA principal. Some entity types have additional properties usable for identity mapping:

  • Active Directory

    • Account Name

    • Distinguished Name

  • Azure AD

    • Principal Name

    • On Premises SAM Account Name

  • Okta

    • User Login

Application Template

The Application Template's Local User entity represents a user within the application. That Local User can map to an Identity Provider (IdP) by setting the identity value(s) in the Local Users identities array. Veza will use these identities to create an association between the IdP Identity and the Local User.

Setting external IdP Group identities is also supported on Local Groups. This should be used when there are no Local User records in the application that correlate to the external user identities. Veza will create a connection between the IdP Group and the Local Group, indicating that all IdP users from that group will have the access granted to the Local Group.

Unknown identities set on users will result in a warning that the identity can not be found. The OAA Local User will still be successfully created.

Note on Identity Mapping from the IdP: You can confirm these values by finding the corresponding entity in Veza search or the data catalog and checking the identities Idp Unique Id and other fields in the details view. Identities that cannot be resolved are returned as warnings when the application payload is pushed.

Identity Provider (IdP) Template

Human Resources Information System (HRIS) Template

Veza will automatically correlate HRIS Employee records and IdP identities based on the HRIS employee's email property. The HRIS employee has an optional parameter for identity_id if the required value is different from the user's email.

Incremental Updates

Modifying custom providers using a partial OAA payload

When developing your OAA integration, whether to implement incremental updates depends on your use case. If you don't have a convenient way to track provider-side changes, it is typically easier to do a full extraction and metadata push, to not miss changes within the app or IdP.

After the initial metadata push, you can modify, add, or remove OAA entities, permissions, and properties without needing to submit the full payload each time. A first push can't be an incremental update.

An incremental update is specified by setting "incremental_change": true in the json_data push payload and adding an update operation for each entity to change. Most payload objects support incremental update operations:

The operation field indicates the change to make. Valid operations are:

  • "add", "modify", "delete" to create, change, or remove an entity.

  • "add_resource", "delete_resource" to modify resources in applications, permissions and role scopes.

  • "add_tag", "delete_tag" to update a tag without altering the entity.

The object to update must contain an ID (name or identity) and the properties to create or modify. An error response will provide more details if an operation is invalid or unavailable.

Notes

  • When modifying dynamic properties, all five properties must be present.

  • add and modify can't be used on the same object. For example, to update both tags and properties on an entity, use:

Sample payload

sourcing metadata
naming conventions

For , this endpoint pushes CSV data to an existing datasource. Typically, you will first create the integration and define column mappings using the "Add Integration" flow in Veza.

For most applications, SaaS Apps and systems the provides a generic and flexible model to capture authorization data for users and groups to the system and its resources.

Intended for modeling sources of users, group, and federated identity metadata, the can be used to enumerate users and groups that access other external applications and resources, similar to built-in connectors for Okta and AzureAD. These users and groups typically represent the top-level corporate identities within an organization.

Additionally, a may describe user-configured key:pair values that can be applied to entities in the payload.

and can be applied to most objects in the OAA payload: the application and its local_users, local_groups, local_roles and resources/sub_resources.

Use incremental updates to remove tags: Resubmitting a payload with different tags will apply any new tags, but not remove existing ones. To remove a tag already applied to an entity, you will need to use the remove_tag operation.

Field
Type
Description

OAA apps need to contain at least one identity, which could be a local_group, local_role, or an IdP identity. Role assignments are made in the section.

Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description

Use this template to model authorization metadata for custom identity providers using the .

This document includes an example template and notes for designing and a model of your IdP.

A can define additional properties, used to add supplemental metadata to entities in the payload.

Simple Custom Identity Provider

Custom IdP users and groups can be assigned permissions in other OAA applications by setting the principal type to idp in identity_to_permissions in the payload.

are the recommended method for adding additional metadata to custom identities and resources.

Additionally, can be applied to the IdP domain, users, and groups:

Use incremental updates to remove tags: Resubmitting a payload with different tags will apply any new tags, but not remove existing ones. To remove a tag already applied to an entity, you will need to use the remove_tag operation.

After the initial metadata push (which must contain the full payload), you can modify, add, or remove the domain, users, and groups without resubmitting other entities. An is enabled by setting "incremental_change": true in the json_data push payload, and specifying the update operation for each entity to change.

Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description

IdP entities can be granted permissions on custom applications in the identity_to_permissions section of the .

Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description
Field
Type
Description

Trigger events when there is a change in the integrated HRIS data source.

To enable this payload format, specify the hris custom template when with the API.

The HRIS template supports . After specifying a custom property definition in the payload, you can assign additional attributes to entities. These enable attribute filters for searches and access reviews in Veza, and enrich results with entity metadata unique to the source system or your organization.

Property
Type
Required
Unique
Description
Property
Type
Required
Unique
Description
Property
Type
Required
Unique
Description

OAA Identity Provider Users can be connected to other IdPs by using the source_identity property on the IdP users. For details see

Custom Application
Custom Identity Provider

See the sample payload below for .

The following JSON example for includes a range of update operations. Note that when modifying tags, only include the identity and tags (no other properties such as manager_id can be present).

CSV Upload Integrations
curl -X POST "https://{VEZA_URL}/api/v1/providers/custom" \
-H "authorization: Bearer {API_KEY}" \
--compressed --data-binary '{"name":"DemoApp","custom_template":"application"}'
{
  "custom_property_definition": {
    "applications": [
      {
        "application_type": "sample",
        "application_properties": {},
        "local_user_properties": {},
        "local_group_properties": {},
        "local_role_properties": {},
        "resources": []
      }
    ]
  },
  "applications": [
    {
      "name": "Sample App",
      "application_type": "sample",
      "description": "This is a sample app",
      "local_users": [
        {
          "name": "bob",
          "identities": [
            "bob@example.com"
          ],
          "is_active": true,
          "created_at": "2022-01-26T20:48:12.460Z",
          "id": "0000000001"
        },
        {
          "name": "jane",
          "identities": [
            "jane@example.com"
          ],
          "groups": [
            "admins"
          ],
          "created_at": "2021-08-13T06:28:13.250Z",
          "id": "0000000002"
        }
      ],
      "local_groups": [
        {
          "name": "admins"
        }
      ],
      "local_roles": [],
      "tags": [],
      "custom_properties": {},
      "resources": [
        {
          "id": "0001",
          "name": "Entity1",
          "resource_type": "thing",
          "description": "Some entity in the application",
          "sub_resources": [
            {
              "name": "Child 1",
              "resource_type": "child",
              "description": "My information about resource"
            }
          ]
        },
        {
          "id": "0002",
          "name": "Entity2",
          "resource_type": "thing",
          "description": "Another entity in the application"
        }
      ]
    }
  ],
  "permissions": [
    {
      "name": "admin",
      "permission_type": [
        "DataRead",
        "DataWrite"
      ],
      "apply_to_sub_resources": false,
      "resource_types": []
    },
    {
      "name": "operator",
      "permission_type": [
        "DataRead",
        "MetadataRead"
      ],
      "apply_to_sub_resources": false,
      "resource_types": []
    },
    {
      "name": "manager",
      "permission_type": [
        "MetadataWrite"
      ],
      "apply_to_sub_resources": false,
      "resource_types": []
    }
  ],
  "identity_to_permissions": [
    {
      "identity": "0000000001",
      "identity_type": "local_user",
      "application_permissions": [
        {
          "application": "Sample App",
          "permission": "operator",
          "apply_to_application": true
        },
        {
          "application": "Sample App",
          "resources": [
            "0001"
          ],
          "permission": "manager"
        }
      ]
    },
    {
      "identity": "admins",
      "identity_type": "local_group",
      "application_permissions": [
        {
          "application": "Sample App",
          "permission": "admin",
          "apply_to_application": true
        }
      ]
    }
  ]
}
{
  "applications": [
    {
      "name": "Sample App",
      "application_type": "sample",
      "description": "This is a sample app",
      "local_users": [
        {
          "name": "bob",
          "identities": [
            "bob@example.com"
          ],
          "is_active": true,
          "created_at": "2022-01-26T20:48:12.460Z",
          "id": "0000000001"
        },
        {
          "name": "jane",
          "identities": [
            "jane@example.com"
          ],
          "created_at": "2021-08-13T06:28:13.250Z",
          "id": "0000000002"
        }
      ],
      "local_groups": [],
      "local_roles": [
        {
          "name": "admin",
          "permissions": [
            "manage_users"
          ],
          "tags": [],
          "custom_properties": {}
        },
        {
          "name": "user",
          "permissions": [
            "view_tickets",
            "close_tickets"
          ],
          "tags": [],
          "custom_properties": {}
        }
      ],
      "tags": [],
      "custom_properties": {},
      "resources": []
    }
  ],
  "permissions": [
    {
      "name": "manage_users",
      "permission_type": [
        "MetadataWrite"
      ],
      "apply_to_sub_resources": false,
      "resource_types": []
    },
    {
      "name": "view_tickets",
      "permission_type": [
        "DataRead"
      ],
      "apply_to_sub_resources": false,
      "resource_types": []
    },
    {
      "name": "close_tickets",
      "permission_type": [
        "MetadataWrite"
      ],
      "apply_to_sub_resources": false,
      "resource_types": []
    }
  ],
  "identity_to_permissions": [
    {
      "identity": "0000000001",
      "identity_type": "local_user",
      "role_assignments": [
        {
          "application": "Sample App",
          "role": "user",
          "apply_to_application": true,
          "resources": []
        }
      ]
    },
    {
      "identity": "0000000002",
      "identity_type": "local_user",
      "role_assignments": [
        {
          "application": "Sample App",
          "role": "user",
          "apply_to_application": true,
          "resources": []
        },
        {
          "application": "Sample App",
          "role": "admin",
          "apply_to_application": true,
          "resources": []
        }
      ]
    }
  ]
}
  "custom_property_definition": {
    "applications": [
      {
        "application_type": "sample",
        "application_properties": {},
        "local_user_properties": {
          "license_type": "STRING",
          "license_expires": "TIMESTAMP"
        },
        "local_group_properties": {},
        "local_role_properties": {},
        "resources": []
      }
    ]
  }
      "local_users": [
        {
          "name": "bob",
          "identities": [
            "bob@example.com"
          ],
          "groups": null,
          "is_active": true,
          "created_at": "2022-01-26T20:48:12.460Z",
          "last_login_at": null,
          "deactivated_at": null,
          "password_last_changed_at": null,
          "tags": [],
          "custom_properties": {
            "license_type": "pro",
            "license_expires": "2023-01-01T00:00:00.000Z"
          }
        }
      ]
{
  "applications": [
    {
      "name": "Custom App",
      "application_type": "Source Control",
      "description": "Has a resource for each repository",
      "custom_properties": {},
      "tags": [],
      "local_users": [],
      "local_groups": [],
      "local_roles": [],
      "resources": []
    }
  ]
}
"resources": [
  {
    "name": "Entity1",
    "id": "Unique ID",
    "resource_type": "thing",
    "description": "Some entity in the application",
    "sub_resources": [
      {
        "name": "Child 1",
        "resource_type": "child",
        "description": "My information about resource",
        "sub_resources": [],
        "custom_properties": {},
        "tags": []
      }
    ],
    "custom_properties": {},
    "tags": []
  },
  {
    "name": "Entity2",
    "id": "Another Unique ID",
    "resource_type": "thing",
    "description": "Another entity in the application",
    "sub_resources": [],
    "custom_properties": {},
    "tags": []
  }
]
{
  "name": "cog1",
  "resource_type": "cog",
  "connections": [
    {
      "id": "service_account@some-project.iam.gserviceaccount.com",
      "node_type": "GoogleCloudServiceAccount"
     }
  ]
}
"local_users": [
  {
    "name": "Evan Gray",
    "unique_id": "egray",
    "identities": ["egray@idp.net"],
    "groups": ["contractors"],
    "is_active": true,
    "created_at": "2020-12-19T16:39:57-08:00",
    "last_login_at": "2021-11-19T14:19:30-08:00",
    "password_last_changed_at": null,
    "deactivated_at": null,
    "custom_properties": {},
    "tags": []
   }
]
"local_groups": [
  {
    "name": "US Contractors",
    "unique_id": "us-contractors",
    "identities": ["user1@company.com"],
    "groups": [
      "all-contractors",
      "all-workers"
    ],
    "tags": []
  }
]
"local_roles": [
    {
        "name": "administrator",
        "unique_id": "0001",
        "permissions": ["create","destroy"]
    },
    {
        "name": "operator",
        "permissions": ["pull", "read"],
        "tags": []
    }
]

name

string

Name of the local role. Primary ID for mapping role to permissions.

unique_id

string

Optional identifier to use for permissions mapping

permissions

array

Permissions associated with the role. Must exist in permissions

tags

array

Specify tags with a key and optional value (optional)

"permissions": [
   {
     "name": "Admin",
     "permission_type": [
       "DataRead",
       "DataWrite",
       "MetadataRead",
       "MetadataWrite"
     ]
   },
   {
     "name": "Operator",
     "permission_type": [
       "MetadataRead",
       "DataRead"
     ]
   },
   {
     "name": "Inactive",
     "permission_type": [
       "NonData"
     ]
   }
 ]

name

string

Native permission name, such as “Push” (used to bind local and IdP identities to native permissions).

permission_type

enum

List of canonical privilege(s) the permission represents.

application_type

enum

Optional list of custom application application_type the permission applies to.

apply_to_sub_resources

bool

To more accurately model applications where permissions should apply to any children of a resource, set TRUE to define the permission as inheritable. This eliminates the need to include the permission at each sub level.

"identity_to_permissions": [
     {
       "identity": "Evan Gray",
       "identity_type": "local_user",
       "application_permissions": [
          {
           "application": "Veza AI",
           "resources": ["terraform-dev", "prod"],
           "permission": "pull"
         },
         {
           "application": "Veza AI",
           "resources": ["terraform-dev", "prod"],
           "permission": "push"
         }
       ]
     }
   ]

identity

string

Principal name or email address. Maps to IdP login email or group name.

identity_type

string

Sets whether the identity corresponds to an IdP identity, or is local to the application

application_permissions

array

List each local permission available to the identity (must be a valid permission name from the previous section).

role_assignments

array

Any roles assigned to the identity, and the resources they apply to (role/resource must exist in applications).

{
    "identity": "idpuser@org.co",
    "identity_type": "idp",
    "application_permissions":
    [
        {
            "application": "source control",
            "resources": ["util-tools", "terraform"],
            "apply_to_application": false,
            "permission": "write"
        },
        {
            "application": "source control",
            "resources": [],
            "apply_to_application": true,
            "permission": "read"
        }
    ]
}

application

string

Maps to an application name from the first section. Must exist in applications

resources

array

List of application resource or sub-resource names to apply the permission. Must exist in applications

apply_to_application

boolean

Set to true to model environments where permissions apply to the top-level application as well as its resources.

permission

string

Maps to a permission name from the second section. Must exist in permissions

{
    "identity": "john_smith",
    "identity_type": "local_user",
    "role_assignments":[
        {
            "application": "custom application",
            "role": "administrator",
            "apply_to_application": true,
            "resources": []
        },
        {
            "application": "custom application",
            "role": "ops",
            "apply_to_application": false,
            "resources": ["oaa-vm-1"]
        }
    ]
}

application

string

The application where the role applies. Must exist in applications

role

string

The role name. Must exist in local_roles

apply_to_application

boolean

Set to true to model environments where the role applies to the top-level application and all its resources.

resources

array

List of resources and sub-resources where the role applies. Must exist in applications

  "identity_to_permissions": [
    {
      "identity": "0000000001",
      "identity_type": "local_user",
      "role_assignments": [
        {
          "application": "Sample App",
          "role": "user",
          "apply_to_application": true,
          "resources": []
        }
      ]
    },
    {
      "identity": "0000000002",
      "identity_type": "local_user",
      "role_assignments": [
        {
          "application": "Sample App",
          "role": "user",
          "apply_to_application": true,
          "resources": []
        },
        {
          "application": "Sample App",
          "role": "admin",
          "apply_to_application": true,
          "resources": []
        }
      ]
    }
  ]
local_user
local_groups
{
  "name": "My IdP",
  "idp_type": "custom_idp",
  "domains": [
    {
      "name": "example.com",
      "tags": [],
    }
  ],
  "users": [
    {
      "name": "m_richardson",
      "email": "mrichardson@example.com",
      "identity": "m_richardson",
      "full_name": "Michelle Richardson",
      "department": null,
      "is_active": true,
      "is_guest": false,
      "groups": [
        {
          "identity": "everyone"
        },
        {
          "identity": "developers"
        }
      ],
      "assumed_role_arns": [
        {
          "identity": "arn:aws:iam::123456789012:role/role001"
        },
        {
          "identity": "arn:aws:iam::123456789012:role/role002"
        }
      ],
      "tags": [],
    },
    {
      "name": "evargas",
      "email": "evargas@example.com",
      "identity": "evargas",
      "full_name": "Elizabeth Vargas",
      "department": null,
      "is_active": true,
      "is_guest": false,
      "groups": [
        {
          "identity": "everyone"
        },
        {
          "identity": "developers"
        },
        {
          "identity": "sec-ops"
        }
      ],
      "assumed_role_arns": [],
      "tags": [],
    },
    {
      "name": "willis",
      "email": "willis@example.com",
      "identity": "c_williams",
      "full_name": null,
      "department": null,
      "is_active": true,
      "is_guest": false,
      "groups": [
        {
          "identity": "everyone"
        }
      ],
      "assumed_role_arns": [],
      "tags": []
    }
  ],
  "groups": [
    {
      "name": "developers",
      "identity": "developers",
      "full_name": null,
      "is_security_group": null,
      "tags": []
    },
    {
      "name": "sec-ops",
      "identity": "sec-ops",
      "full_name": null,
      "is_security_group": null,
      "tags": []
    },
    {
      "name": "everyone",
      "identity": "everyone",
      "full_name": "All Company Employees",
      "is_security_group": null,
      "tags": []
    }
  ],
  "identity_mapping_configuration": {
    "mappings": [
      {
        "destination_datasource_type": "GITHUB_USERS",
        "property_matchers": [
          {
            "source_property": "EMAIL",
            "destination_property": "UNIQUE_ID"
          }
        ]
      },
      {
        "destination_datasource_type": "SQL_SERVER",
        "property_matchers": [
          {
            "source_property": "EMAIL",
            "destination_property": "EMAIL"
          }
        ],
        "transformations": [
          "IGNORE_DOMAIN"
        ]
      }
    ]
  }
}
{
      "name": "Custom User",
      "assumed_role_arns": {
        "identity": [
          "arn:aws:iam::123456789012:role/S3Access"
          ]
        },
    }
{
  "name": "Custom User",
  "identity": "00001",
  "source_identity": {
    "identity": "user0001@corp.example.com",
    "provider_type": "okta"
  }
}

Provider

provider_type string

Active Directory

active_directory

Any

any

AzureAD

azure_ad

OAA

custom

Google Workspace

google_workspace

Okta

okta

One Login

one_login

{
  "name": "Custom User",
  "identity": "000011",
  "entities_owned": [
    {
      "node_type": "S3Bucket",
      "id": "arn:aws:s3:::amazon-connect-53f87966654d"
    }
  ]
}
{
  "name": "Custom User",
  "identity": "000013",
  "manager_id": "000011"
}
"tags": [
  {
    "key": "Tag1key",
    "value": "optional_Tag1Val"
  }
]
{
      "name": "willis",
      "email": "willis@example.com",
      "identity": "000001",
      "full_name": "Charles Willis",
      "department": "Sales",
      "is_active": true,
      "is_guest": false,
      "groups": [
        {
          "identity": "everyone"
        }
      ],
      "assumed_role_arns": {
        "identity": [
          "arn:aws:iam::123456789012:role/S3Access"
          ]
      },
      "source_identity": {
        "identity": "user0001@corp.example.com",
        "provider_type": "okta"
      },
      "tags": [],
      "custom_properties": {},
      "manager_id": "string",
      "entities_owned": {
        "node_type": "S3Bucket",
        "id": "arn:aws:s3:::amazon-connect-53f87966654d"
        }
    }
"groups": [
  {
    "name": "developers",
    "identity": "developers",
    "full_name": null,
    "is_security_group": null,
    "assumed_role_arns": {
      "identity": ["arn:aws:iam::123456789012:role/S3Access"]
    },
    "tags": [],
    "groups": [
      { "group_1_identity": "parent" },
      { "group_2_identity": "parent" }
    ],
    "custom_properties": {}
  }
]
  "apps": [
    {
      "id": "app1",
      "name": "Application 1",
      "description": "This is a sample application",
      "assumed_role_arns": [
        {
          "identity": "arn:aws:iam::1234567890:role/DevAppRole"
        }
      ],
      "custom_properties": {
        "owner_org": "engineering"
      },
      "tags": []
    }
  ]
    {
      "name": "willis",
      "email": "willis@example.com",
      "identity": "cwilliams",
      "groups": [
        {
          "identity": "everyone"
        }
      ],
      "custom_properties": {
        "region": "NorthAmerica",
        "is_contractor": true
      },
      "app_assignments": [
        {
          "id": "assignment1",
          "name": "Assignment",
          "app_id": "app1",
          "custom_properties": {
            "assigned_on": "2024-12-05T12:42:25+00:00"
          }
        }
      ]
    }
curl -X POST 'https://<veza_url>/api/v1/providers/custom' \
-H 'authorization: Bearer '<access_token> \
--data-binary '{"name":"SimpleIdP","custom_template":"identity_provider"}'
{
  "value": {
    "id": "532f6fe3-189f-4576-afdf-8913088961e4",
    "name": "Simple IdP",
    "custom_template": "identity_provider",
    "state": "ENABLED",
    "application_types": [],
    "resource_types": [],
    "idp_types": []
  }
}
curl -X POST 'https://<veza_url>/api/v1/providers/custom/532f6fe3-189f-4576-afdf-8913088961e4/datasources' \
-H 'authorization: Bearer '<access_token> \
--data-binary '{"id":"532f6fe3-189f-4576-afdf-8913088961e4", "name":"SimpleDataSource"}'
{"value":{"id":"b6a32af6-b854-47e1-8325-e5984f78bb4d","name":"SimpleDataSource"}}
curl -X POST 'https://<veza_url>/api/v1/providers/custom/532f6fe3-189f-4576-afdf-8913088961e4/datasources/b6a32af6-b854-47e1-8325-e5984f78bb4d:push' \
-H 'authorization: Bearer '<access_token> \
--compressed --data-binary @payload.json
payload.json
{
  "id": "532f6fe3-189f-4576-afdf-8913088961e4",
  "data_source_id": "b6a32af6-b854-47e1-8325-e5984f78bb4d",
  "json_data": "{\n\"name\":\"CustomIdentityProvider\",\n\"idp_type\": ... "
}
{
  "identity_mapping_configuration": {
    "mappings": [
      {
        "destination_datasource_type": "OKTA",
        "property_matchers": [
          {
            "source_property": "EMAIL",
            "destination_property": "EMAIL"
          }
        ],
        "transformations": [
          "IGNORE_SPECIAL"
        ]
      },
      {
        "destination_datasource_type": "AZURE_AD",
        "property_matchers": [
          {
            "source_property": "EMAIL",
            "destination_property": "EMAIL"
          }
        ],
        "transformations": [
          "IGNORE_DOMAIN"
        ]
      },
      {
        "destination_datasource_type": "GITHUB_USERS",
        "property_matchers": [
          {
            "source_property": "EMAIL",
            "destination_property": "UNIQUE_ID"
          }
        ]
      }
    ]
  }
}

destination_datasource_type

string

Veza Type for the destination data source, GITHUB_USERS, SQL_SERVER, CUSTOM_APPLICATION

destination_datasource_oaa_app_type

string

Optional specifically for mapping to OAA Custom Application to provide a specific App Type

property_matchers

IdentityMappingPropertyMatchersSubmission

List of properties to match on

transformations

list enum

Optional transformations to perform on the property values, available values: ignore_special, ignore_domain

source_property

enum

IDP User property to match on, unique_id, email, property or custom_property

destination_property

enum

Destination User property to match on, unique_id, email, property or custom_property

custom_source_property

string

When using property or custom_propert the property name to match on

custom_destination_property

string

When using property or custom_propert the property name to match on

{
  "System": {
    "URL": "https://examplehris.com"
  },
  "Employees": [
    {
      "Employee Number": "123456",
      "Company": "Example Corp",
      "First Name": "John",
      "Last Name": "Doe",
      "Preferred Name": "Johnny",
      "Display Full Name": "Johnny Doe",
      "Canonical Name": "John Doe",
      "Username": "john.doe",
      "Email": "john.doe@examplecorp.com",
      "IDP ID": "1234-5678-9012",
      "Personal Email": "johndoe@gmail.com",
      "Home Location": "City A",
      "Work Location": "City B",
      "Cost Center": "001",
      "Department": "002",
      "Managers": ["987654"],
      "Groups": ["team-1", "dept-1"],
      "Employment Status": "ACTIVE",
      "Is Active": true,
      "Start Date": "2021-05-01T00:00:00Z",
      "Termination Date": null,
      "Job Title": "Software Engineer",
      "Employment Types": ["FULL_TIME"],
      "Primary Time Zone": "America/New_York"
    }
  ],
  "Groups": [
    {
      "Group Type": "TEAM",
      "Parent": "dept-1"
    }
  ]
}
{
  "name": "BambooHR",
  "hris_type": "BambooHR",
  "custom_property_definition": {
    "employee_properties": {
      "division": "STRING",
      "office_extension": "STRING"
    },
    "group_properties": {
      "headquarters_location": "STRING"
    }
  },
  "system": {
    "name": "BambooHR",
    "id": "BambooHR",
    "url": "https://vezai.bamboohr.com",
    "idp_providers": ["okta"]
  },
  "employees": [
    {
      "name": "Charlotte Abbott",
      "id": "1",
      "custom_properties": {
        "division": "North America",
        "office_extension": "1234"
      },
      "employee_number": "1",
      "email": "cabbott@efficientoffice.com",
      "work_location": "Lindon, Utah",
      "job_title": "Sr. HR Administrator"
    },
    {
      "name": "Cheryl Barnet",
      "id": "10",
      "custom_properties": {
        "division": "North America",
        "office_extension": "5678"
      },
      "employee_number": "10",
      "email": "cbarnet@efficientoffice.com",
      "work_location": "Lindon, Utah",
      "job_title": "VP of Customer Success"
    }
  ],
  "groups": [
    {
      "name": "North America-Human Resources",
      "id": "North America-Human Resources",
      "group_type": "Department",
      "custom_properties": {
        "headquarters_location": "Lindon, Utah"
      }
    }
  ]
}

URL

String

Y

N

The url for this HRIS system.

Employee Number

String

Y

Y

The employee's number that appears in the third-party integration.

Company

String

N

N

The company (or subsidiary) the employee works for.

First Name

String

Y

N

The employee's first name

Last Name

String

Y

N

The employee's last name

Preferred Name

String

N

N

The employee's preferred first name.

Display Full Name

String

N

N

The employee's full name, to use for display purposes. If a preferred first name is available, the full name will include the preferred first name.

Canonical Name

String

N

N

The employee's canonical name.

Username

String

N

N

The employee's username that appears in the integration UI.

Email

String

N

Y

The employee's work email.

IDP ID

String

N

N

The ID for this employee on the destination IDP provider used to automatically connect to it, if not supplied email is used

Personal Email

String

N

N

The employee's personal email.

Home Location

String

N

N

The employee's home location.

Work Location

String

N

N

The employee's work location.

Cost Center

String

N

N

The cost center ID (Group ID) that the employee is in.

Department

String

N

N

The department ID (Group ID) that the employee is in.

Managers

STRINGLIST

N

N

The employee IDs of the employee's managers.

Groups

STRINGLIST

N

N

The IDs of groups this user is in

Employment Status

String

Y

N

The employment status of the employee. Possible values include - ACTIVE, PENDING, INACTIVE.

Is Active

BOOLEAN

Y

N

If the employee is active or not.

Start Date

TIMESTAMP

N

N

The date that the employee started working. If an employee was rehired, the most recent start date will be returned.

Termination Date

TIMESTAMP

N

N

The employee's termination date.

Job Title

String

N

N

The title of the employee.

Employment Types

STRINGLIST

N

N

The employee's type of employment. Possible values include - FULL_TIME, PART_TIME, INTERN, CONTRACTOR, FREELANCE.

Primary Time Zone

String

N

N

The time zone which the employee primarily lives.

Group Type

String

Y

N

The type of group, possible values include - TEAM, DEPARTMENT, COST_CENTER, BUSINESS_UNIT, GROUP. This is intended as to not have each type as their own nodes.

Parent

String

N

N

The group ID of its parent group.

application, user, group, role, permission, role_assignments

domain, group, user

  "resources": [
    {
      "name": "resource1",
      "resource_type": "type1",
      "tags": [
        {
          "key": "keyDelta1",
          "value": "valDelta1"
        }
      ],
      "operation": "add_tag"
    },
    {
      "name": "resource1",
      "resource_type": "type1",
      "operation": "modify"
    }
  ]
{
  "incremental_change": true,
  "applications": [
    {
      "name": "Controller1",
      "application_type": "WebServer",
      "description": "The base web server",
      "local_users": [
        {
          "name": "LUser1",
          "identities": [
            "localuser1@company.com"
          ],
          "operation": "delete"
        },
        {
          "name": "LUser1",
          "identities": [
            "localuser1Mod@company.com"
          ],
          "operation": "add"
        }
      ],
      "local_groups": [
        {
          "name": "LGroup1",
          "identities": [
            "localgroup1@company.com"
          ],
          "tags": [
            {
              "key": "groupTag2Key",
              "value": "groupTag2Value"
            }
          ],
          "operation": "add_tag"
        }
      ],
      "local_roles": [
        {
          "name": "LRole2",
          "permissions": [
            "FULL"
          ],
          "operation": "delete"
        }
      ],
      "resources": [
        {
          "name": "resource1",
          "sub_resources": [
            {
              "name": "sub1b",
              "operation": "delete"
            }
          ],
          "operation": "modify"
        }
      ]
    }
  ],
  "permissions": [
    {
      "name": "Just Access",
      "operation": "modify"
    },
    {
      "name": "NonData",
      "PermissionType": [
        "NonData"
      ],
      "operation": "add"
    },
    {
      "name": "READ",
      "permission_type": [
        "DataRead"
      ],
      "operation": "delete"
    },
    {
      "name": "READ",
      "permission_type": [
        "DataRead"
      ],
      "operation": "add"
    }
  ],
  "identity_to_permissions": [
    {
      "identity": "testuser1@company.com",
      "identity_type": "IDP",
      "role_assignments": [
        {
          "application": "Controller1",
          "role": "LRole1",
          "apply_to_application": true,
          "operation": "delete"
        },
        {
          "application": "Controller1",
          "role": "LRole2",
          "resources": [
            "resource1",
            "resource1.sub1a.sub2b"
          ],
          "operation": "add"
        }
      ]
    },
    {
      "identity": "testuser3@company.com",
      "identity_type": "IDP",
      "role_assignments": [
        {
          "application": "Controller1",
          "role": "LRole1",
          "resources": [
            "resource1.sub1b",
            "resource1.sub1c"
          ],
          "operation": "delete_resource"
        },
        {
          "application": "Controller1",
          "role": "LRole1",
          "resources": [
            "resource1.sub1a"
          ],
          "operation": "add_resource"
        }
      ],
      "application_permissions": [
        {
          "application": "WebServer2",
          "permission": "Just Access",
          "operation": "delete"
        }
      ]
    }
  ]
}

Structures

Copyright 2023 Veza Technologies Inc.

Use of this source code is governed by the MIT license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.


class CaseInsensitiveDict

Case Insensitive Key Dictionary

Dictionary like object with case insensitive keys for types that support .lower() such as strings.

Keys do not have to be strings, in the case where the key type does not support .lower() such as integers the value is used as is.

Example: from oaaclient.structures import CaseInsensitiveDict >>> x = CaseInsensitiveDict() >>> x["User"] = "value" >>> x.get("user") 'value' >>> "USER" in x True >>> print(x) {'user': 'value'} >>> x CaseInsensitiveDict({'user': 'value'})

method __init__

__init__(data=None, **kwargs) → None

Templates

Classes for constructing an OAA JSON payload (Custom "Application" or "IdP").

Copyright 2022 Veza Technologies Inc.

Use of this source code is governed by the MIT license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.

Global Variables


  • PROPERTY_NAME_REGEX


function append_helper

append_helper(base, addition)

Helper function to simplify appending.

Handles multiple cases:

  • base is None: starts a list

  • addition is list: extends base with list

  • addition is anything else: append element to list

Args:

  • base (List or None): base list to append to, can be None

  • addition (*): What to append to the list

Returns:

  • list: will always return a list


function unique_strs

unique_strs(input: 'list') → list

Returns a list of unique strings from input list case insensitive

Returns the unique list of strings from input list in a case insensitive manner. For duplicate strings with different cast (e.g. "STRING" and "string") the case of the first occurrence is returned.

Args:

  • input (list): list of strings

Returns:

  • list: list of unique strings


class OAATemplateException

General exception used for violations of the template schema.

method __init__

__init__(message)

class OAAPermission

Canonical permissions used by Veza Authorization Framework.

Used to describe the raw data or metadata permissions granted by CustomPermission


class OAAIdentityType

Types of identities for permission mapping.


class Provider

Base class for CustomProvider.

method __init__

__init__(name, custom_template)

method serialize

serialize()

class Application

Base class for CustomApplication.

method __init__

__init__(name, application_type, description=None)

class CustomApplication

Class for modeling application authorization using the OAA Application template.

CustomApplication class consists of identities, resources and permissions and produces the OAA JSON payload for the custom application template.

Class uses dictionaries to track most entities that can be referenced after creation. Dictionaries keys are case insensitive of the entity identifier (name or id). This applies to local_users, local_groups, local_roles, idp_identities, resources and custom_permissions.

Args:

  • name (str): Name of custom application

  • application_type (str): Searchable property, can be unique or shared across multiple applications

  • description (str, optional): Description for application. Defaults to None.

Attributes:

  • application_type (str): Searchable application type

  • custom_permissions (dict[OAAPermission]): Dictionary of class instances

  • description (str): Description for application

  • identity_to_permissions (dict): Mapping of authorizations for identities to resources

  • idp_identities (dict[IdPIdentity]): Contains federated identities without a corresponding local account

  • local_groups (dict[LocalGroup]): Contains application groups (collections of users)

  • local_roles (dict[LocalRole]): Contains application roles (collections of permissions)

  • local_users (dict[LocalUser]): Contains users local to the application and their properties

  • name (str): Name of custom application

  • properties (dict): key value pairs of property values, property keys must be defined as part of the property_definitions

  • property_definitions (ApplicationPropertyDefinitions): Custom property names and types for the application

  • resources (dict[CustomResource]): Contains data resources and subresources within the application

method __init__

__init__(name: 'str', application_type: 'str', description: 'str' = None) → None

method add_access

add_access(identity, identity_type, permission, resource=None)

Legacy method for backwards compatibility.

.. deprecated:


---



### <kbd>method</kbd> `add_access_cred`

```python
add_access_cred(unique_id: 'str', name: 'str') → AccessCred

Create an Access Credential

Access creds can be used to represent alternative access methods such as API keys or application integrations.

Access creds can be assigned roles and permissions similar to local users. Access credentials can exist independently for use cases such as administratively created integrations or can be assigned to a local user for use cases like personal access tokens.

Args:

  • unique_id (str): unique identifier for access cred

  • name (str): name for access cred

Raises:

  • OAATemplateException: Access credential with unique ID already exists

Returns:

  • AccessCred: New access cred


method add_custom_permission

add_custom_permission(
    name: 'str',
    permissions: 'List[OAAPermission]',
    apply_to_sub_resources: 'bool' = False,
    resource_types: 'List[str]' = None
) → CustomPermission

Create a new custom permission.

Creates a new CustomPermission object for the application that can be used to authorize identities to the application, resources/sub-resource or as part of a role.

Args:

  • name (str): Name of the permission

  • permissions (list[OAAPermission]): Canonical permissions the custom permission represents

  • apply_to_sub_resources (bool, optional): If true, when permission is applied to the application or resource, identity also has permission to all children of application/resource. Defaults to False.

  • resource_types (list, optional): List of resource types as strings that the permission relates to. Defaults to empty list.

Returns: CustomPermission


method add_idp_identity

add_idp_identity(name: 'str') → IdPIdentity

Create an IdP principal identity.

IdP users and groups can be authorized directly to applications and resources by associating custom application permissions and roles with an IdP identity's name or email.

Args:

  • name (str): IdP unique identifier for user or group.

Returns: IdPIdentity


method add_local_group

add_local_group(
    name: 'str',
    identities: 'List[str]' = None,
    unique_id: 'str' = None
) → LocalGroup

Create a new local group.

Groups can be associated to resources via permissions or roles. All users in the local group are granted the group's authorization.

Local groups will be identified by name by default, if unique_id is provided it will be used as the identifier instead

Local groups can be referenced after creation using .local_groups dictionary attribute. Dictionary is case insensitive keyed by unique_id or name if not using unique_id.

Args:

  • name (str): Display name for group

  • identities (list): List of IdP identities to associate group with.

  • unique_id (str, optional): Unique identifier for group for reference by ID

Returns: LocalGroup


method add_local_role

add_local_role(
    name: 'str',
    permissions: 'List[str]' = None,
    unique_id: 'str' = None
) → LocalRole

Create a new local role.

  • A local role represents a collection of permissions.

  • Identities (local user, group, idp user) can be assigned a role to the application or resource, granting the role's permissions.

  • Local roles will be identified by name by default, if unique_id is provided it will be used as the identifier instead.

  • Local roles can be referenced after creation if needed through .local_roles case insensitive dictionary attribute.

  • When a permission that has resource_types is added to a role, it will only apply to resources with a matching resource_type

Args:

  • name (str): Display name for role

  • permissions (list): List of Custom Permission names to include in role. CustomPermission must be created separately.

  • unique_id (str, optional): Unique identifier for role for reference by ID

Returns: LocalRole


method add_local_user

add_local_user(
    name: 'str',
    identities: 'List[str]' = None,
    groups: 'List[str]' = None,
    unique_id: 'str' = None
) → LocalUser

Create a new local user for application.

Local users can be assigned to groups and associated with resources via permissions or roles. Groups and identities can be provided at creation or added later. See Identity and LocalUser class for operations.

Local users will be identified by name by default, if unique_id is provided it will be used as the identifier instead.

Local users can be referenced after creation using the .local_users dictionary attribute. Dictionary is case insensitivekeyed by unique_id or name if not using unique_id.

Use unique_id when name is not guaranteed to be unique. All permission, group and role assignments will be referenced by unique_id.

Args:

  • name (str): Display name for user

  • identities (list): List of identities as strings (usually email) for local user. Used to map local user to discovered IdP identities.

  • groups (list[LocalGroup]): List of group names (as string) to add user to

  • unique_id (str, optional): Unique identifier for user for reference by ID

Returns: LocalUser


method add_resource

add_resource(
    name: 'str',
    resource_type: 'str',
    description: 'str' = None,
    unique_id: 'str' = None
) → CustomResource

Create a new resource under the application.

Resource type is used to group and filter application resources. It should be consistent for all common resources of an application.

Returns new resource object.

Resource is identified by name by default unless unique_id is provided. name must be unique if not using unique_id.

Resources can be referenced after creation using the .resources dictionary attribute. Dictionary is keyed by unique_id or name if not using unique_id. Use unique_id when name is not guaranteed to be unique.

Args:

  • name (str): Name of resources

  • resource_type (str): Type for resource

  • description (str, optional): Description of resources. Defaults to None.

  • unique_id (str, optional): Unique identifier for resource. defaults to None.

Returns: CustomResource


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a tag to the Application

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method app_dict

app_dict() → dict

Return the 'applications' section of the payload as serializable dictionary.


method define_custom_permission

define_custom_permission(
    custom_permission: 'CustomPermission'
) → CustomPermission

Add a custom permission to the application.

.. deprecated: ``` See CustomApplication.add_custom_permission()



**Args:**

 - <b>`custom_permission`</b> (CustomPermission):  CustomPermission class



**Raises:**

 - <b>`Exception`</b>:  Duplicate Keys



**Returns:**

 - <b>`CustomPermission`</b>:  The defined custom Permission

---


### <kbd>method</kbd> `get_identity_to_permissions`

```python
get_identity_to_permissions() → list

Collect authorizations for all identities into a single list.


method get_payload

get_payload() → dict

Get the OAA payload.

Returns the complete OAA template payload for application as serializable dictionary

Returns:

  • dict: OAA payload as dictionary


method permissions_dict

permissions_dict() → dict

Return the 'permissions' section of the payload as serializable dictionary.


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set a custom property value for the application.

Property name must be defined for CustomApplication before calling set_property. See example below and ApplicationPropertyDefinitions.define_application_property for more information on defining properties.

Args:

  • property_name (str): Name of property to set value for, property names must be defined as part of the application property_definitions

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property name is not defined

Example: app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_application_property(name="my_property", property_type=OAAPropertyType.STRING) >>> app.set_property("my_property", "property value")


class CustomResource

Class for resources and sub-resources.

Should be used for representing components of the application to which authorization is granted. Each resource has a name and a type. The type can be used for grouping and filtering.

Arguments:

  • name (str): display name for resource, must be unique to parent application or resource unless using unique_id

  • resource_type (str): type for resource

  • description (str): description for resource

  • application_name (str): name of parent application

  • resource_key (str, optional): for sub-resources the full unique identifier required for identity_to_permissions section. Defaults to name or unique_id if not provided.

  • property_definitions (ApplicationPropertyDefinitions, optional): Property definitions structure for the resource

  • unique_id (str, optional): Optional unique identifier for the resource. Defaults to None.

Attributes:

  • name (str): display name for resource, must be unique to parent application or resource

  • unique_id (str): resource's unique identifier if provided.

  • resource_type (str): type for resource

  • application_name (str): name of parent application

  • resource_key (str): for sub-resources represents the sub-resource's parent path

  • sub_resources (dict): dictionary of sub-resources keyed by name

  • properties (dict): dictionary of properties set for resource

  • tags (list[Tag]): list of tags

method __init__

__init__(
    name: 'str',
    resource_type: 'str',
    description: 'str',
    application_name: 'str',
    resource_key: 'str' = None,
    property_definitions: 'ApplicationPropertyDefinitions' = None,
    unique_id: 'str' = None
) → None

method add_access

add_access(identity, identity_type, permission)

No longer supported, access should be added through identity (local_user, local_group, idp)


method add_resource_connection

add_resource_connection(id: 'str', node_type: 'str') → None

Add an external connection to the resource.

Used to add a relationship to another entity discovered by Veza such as a service account or AWS IAM role.

Args:

  • id (str): Unique identifier for connection entity

  • node_type (str): Veza type for connecting node


method add_sub_resource

add_sub_resource(
    name: 'str',
    resource_type: 'str',
    description: 'str' = None,
    unique_id: 'str' = None
) → CustomResource

Create a new sub-resource under current resource

Args:

  • name (str): display name for resource

  • resource_type (str): type for resource

  • description (str, optional): String description. Defaults to None.

  • unique_id (str, optional): Unique identifier for new subresource, Defaults to name.

Returns: CustomResource


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to resource.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set the value for a custom property on a resource or sub-resource.

Property name must be defined for resource type before calling set_property(). See example below and ApplicationPropertyDefinitions.define_resource_property for more information on defining properties.

Args:

  • property_name (str): Name of property to set value for

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property_name is not defined

Example: app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_resource_property(resource_type="cog", name="my_property", property_type=OAAPropertyType.STRING) >>> cog1 = app.add_resource(name="cog1", resource_type="cog") >>> cog1.set_property("my_property", "this value")


method to_dict

to_dict() → dict

Return the dictionary representation of resource.


class Identity

Base class for deriving all identity types (should not be used directly).

Args:

  • name (str): name of identity

  • identity_type (OAAIdentityType): Veza Identity Type (local_user, local_group, idp)

  • unique_id (str, optional): ID of entity for reference by ID

Attributes:

  • name (str): name of identity

  • identity_type (OAAIdentityType): Veza Identity Type (local_user, local_group, idp)

  • application_permissions (list[CustomPermission]): List of permissions identity has directly to custom application

  • resource_permissions (dict): Dictionary of custom permissions associated with resources and sub-resources. Key is permission, value is list of resource keys

  • application_roles (LocalRole): List of roles identity has directly to custom application

  • resource_roles (dict): Dictionary of local_roles for resources and sub-resources. Key is roles, value is list of resource keys

  • properties (dict): Dictionary of properties for identity, allowed values will vary by identity type

  • tags (list[Tag]): List of tags

method __init__

__init__(
    name: 'str',
    identity_type: 'OAAIdentityType',
    unique_id: 'str' = None,
    property_definitions: 'ApplicationPropertyDefinitions' = None
) → None

method add_permission

add_permission(
    permission: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'bool' = False
) → None

Add a permission to an identity.

Permission can apply to either the application or application resource/sub-resources

Args:

  • permissions ([str]): List of strings representing the permission names

  • resource (CustomResource, optional): Custom resource, if None permission is applied to application. Defaults to None.

  • apply_to_application (bool): Apply permission to application when True, defaults to False


method add_role

add_role(
    role: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'Optional[bool]' = None,
    assignment_properties: 'Optional[dict]' = None
) → None

Add a role to an identity.

Role to authorize identity to either the application or application resource/sub-resource based on role's permissions.

Role assignment properties can be set with the assignment_properties dictionary parameter with property names as the keys. Role assignment properties types must be defined on the application prior to setting.

Args:

  • role (str): Name of role as string

  • resources (List[CustomResource], optional): Custom resource, if None role is applied to application. Defaults to None.

  • apply_to_application (bool, optional): Apply permission to application when True, False will replace existing value, None will leave previous setting if any

  • assignment_properties (dict, optional): Custom properties for the role assignment. Defaults to no properties.


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to identity.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method get_identity_to_permissions

get_identity_to_permissions(application_name: 'str') → dict

Get a JSON serializable dictionary of all the identity's permissions and roles.

Formats the identity's permissions and roles for the Custom Application template payload

Returns:

  • dict: JSON serializable dictionary of all the identity's permissions and roles


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set a custom defined property to a specific value on an identity.

Property name must be defined for identity type before calling set_property(). See example below for LocalUser and ApplicationPropertyDefinitions.define_local_user_property for more information on defining properties. Property must be defined for the correct Identity type (LocalUser or LocalGroup, IdPIdentity does not support custom properties).

Args:

  • property_name (str): Name of property to set value for

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example:

app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_local_user_property(name="my_property", property_type=OAAPropertyType.STRING) >>> user1 = app.add_local_user(name="user1") >>> user1.set_property("my_property", "value for user1")


class LocalUserType

Enum for


class LocalUser

LocalUser identity, derived from Identity base class.

Used to model an application user. Can be associated with an external IdP user, or represent a local account.

Args:

  • name (str): name of identity

  • identities (list): list of strings for IdP identity association

  • groups (list[LocalGroup]): list of group names as strings to add user too

  • unique_id (string, optional): For reference by ID

Attributes:

  • name (str): name of identity

  • id (str): ID of entity for ID based reference

  • email (string): Users email address

  • identities (list): list of strings for IdP identity association

  • groups (list[LocalGroup]): list of group names as strings to add user too

  • identity_type (OAAIdentityType): Veza Identity Type (local_user)

  • application_permissions (list[CustomPermission]): Permissions identity has directly to custom application

  • resource_permissions (dict): Dictionary of custom permissions associated with resources and sub-resources. Key is permission, value is list of resource keys

  • application_roles (list[LocalRole]): Custom application roles assigned directly to the identity

  • resource_roles (dict): Dictionary of local_roles for resources and sub-resources. Key is roles, value is list of resource keys

  • properties (dict): Dictionary of properties for identity, allowed values will vary by identity type

  • tags (list[Tag]): List of tags

  • is_active (bool): Defaults to None for unset

  • created_at (str): RFC3339 time stamp for user creation

  • last_login_at (str): RFC3339 time stamp for last login

  • deactivated_at (str): RFC3339 for user deactivate time

  • password_last_changed_at (str): RFC3339 time stamp for last password change

  • user_type (LocalUserType): Set the local user account type

method __init__

__init__(
    name: 'str',
    identities: 'List[str]' = None,
    groups: 'List[str]' = None,
    unique_id: 'str' = None,
    property_definitions: 'ApplicationPropertyDefinitions' = None
) → None

method add_access_cred

add_access_cred(access_cred: 'str') → None

Add access cred to user (access cred must be created separately)

Args:

  • access_cred (str): unique identifier of access cred


method add_group

add_group(group: 'str') → None

Add user to local group (group must be created separately).

Args:

  • group (str): identifier of local group


method add_identities

add_identities(identities: 'List[str]') → None

Add multiple identities to a local user from a list.

Args:

  • identities (list[str]): list of identities to add to user


method add_identity

add_identity(identity: 'str') → None

Add an identity to user.

Identity should match the email address or another principal identifier for an IdP user (Okta, Azure, ect). Veza will create a connection from the application local user to IdP identity.

Args:

  • identity (str): email or identifier for IdP user


method add_permission

add_permission(
    permission: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'bool' = False
) → None

Add a permission to an identity.

Permission can apply to either the application or application resource/sub-resources

Args:

  • permissions ([str]): List of strings representing the permission names

  • resource (CustomResource, optional): Custom resource, if None permission is applied to application. Defaults to None.

  • apply_to_application (bool): Apply permission to application when True, defaults to False


method add_role

add_role(
    role: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'Optional[bool]' = None,
    assignment_properties: 'Optional[dict]' = None
) → None

Add a role to an identity.

Role to authorize identity to either the application or application resource/sub-resource based on role's permissions.

Role assignment properties can be set with the assignment_properties dictionary parameter with property names as the keys. Role assignment properties types must be defined on the application prior to setting.

Args:

  • role (str): Name of role as string

  • resources (List[CustomResource], optional): Custom resource, if None role is applied to application. Defaults to None.

  • apply_to_application (bool, optional): Apply permission to application when True, False will replace existing value, None will leave previous setting if any

  • assignment_properties (dict, optional): Custom properties for the role assignment. Defaults to no properties.


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to identity.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method get_identity_to_permissions

get_identity_to_permissions(application_name: 'str') → dict

Get a JSON serializable dictionary of all the identity's permissions and roles.

Formats the identity's permissions and roles for the Custom Application template payload

Returns:

  • dict: JSON serializable dictionary of all the identity's permissions and roles


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set a custom defined property to a specific value on an identity.

Property name must be defined for identity type before calling set_property(). See example below for LocalUser and ApplicationPropertyDefinitions.define_local_user_property for more information on defining properties. Property must be defined for the correct Identity type (LocalUser or LocalGroup, IdPIdentity does not support custom properties).

Args:

  • property_name (str): Name of property to set value for

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example:

app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_local_user_property(name="my_property", property_type=OAAPropertyType.STRING) >>> user1 = app.add_local_user(name="user1") >>> user1.set_property("my_property", "value for user1")


method to_dict

to_dict() → dict

Output user to dictionary for payload.


class LocalGroup

LocalGroup identity.

Derived from Identity base class. Used to represent groups of local users for application.

Args:

  • name (str): name of group

  • identities (list): list of strings for IdP identity association

  • unique_id (string, optional): Unique identifier for group

Attributes:

  • name (str): name of identity

  • identities (list): list of strings for IdP identity association

  • groups (list[LocalGroup]): list of group names as strings that group is member of for nested groups

  • identity_type (OAAIdentityType): Veza Identity Type, local_group

  • application_permissions (list[CustomPermission]): permissions identity has directly to custom application

  • resource_permissions (dict): Dictionary of custom permissions associated with resources and sub-resources. Key is permission, value is list of resource keys

  • application_roles (list[LocalRole]): list of roles identity has directly to custom application

  • resource_roles (dict): Dictionary of local_roles for resources and sub-resources. Key is roles, value is list of resource keys

  • properties (dict): Dictionary of properties for identity, allowed values will vary by identity type

  • tags (list[Tag]): List of tags

  • created_at (str): RFC3339 time stamp for group creation time

method __init__

__init__(
    name,
    identities=None,
    unique_id: 'str' = None,
    property_definitions: 'ApplicationPropertyDefinitions' = None
)

method add_group

add_group(group: 'str') → None

Add a nested group to local group (group must be created separately).

Args:

  • group (str): identifier of local group


method add_identity

add_identity(identity: 'str') → None

Add an identity to group.

The email address or another valid identifier should match that of an IdP principal (Okta, Azure, ect). Veza will create a connection from the application local group to IdP identity.

Args:

  • identity (str): primary IdP identifier for group to associate


method add_permission

add_permission(
    permission: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'bool' = False
) → None

Add a permission to an identity.

Permission can apply to either the application or application resource/sub-resources

Args:

  • permissions ([str]): List of strings representing the permission names

  • resource (CustomResource, optional): Custom resource, if None permission is applied to application. Defaults to None.

  • apply_to_application (bool): Apply permission to application when True, defaults to False


method add_role

add_role(
    role: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'Optional[bool]' = None,
    assignment_properties: 'Optional[dict]' = None
) → None

Add a role to an identity.

Role to authorize identity to either the application or application resource/sub-resource based on role's permissions.

Role assignment properties can be set with the assignment_properties dictionary parameter with property names as the keys. Role assignment properties types must be defined on the application prior to setting.

Args:

  • role (str): Name of role as string

  • resources (List[CustomResource], optional): Custom resource, if None role is applied to application. Defaults to None.

  • apply_to_application (bool, optional): Apply permission to application when True, False will replace existing value, None will leave previous setting if any

  • assignment_properties (dict, optional): Custom properties for the role assignment. Defaults to no properties.


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to identity.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method get_identity_to_permissions

get_identity_to_permissions(application_name: 'str') → dict

Get a JSON serializable dictionary of all the identity's permissions and roles.

Formats the identity's permissions and roles for the Custom Application template payload

Returns:

  • dict: JSON serializable dictionary of all the identity's permissions and roles


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set a custom defined property to a specific value on an identity.

Property name must be defined for identity type before calling set_property(). See example below for LocalUser and ApplicationPropertyDefinitions.define_local_user_property for more information on defining properties. Property must be defined for the correct Identity type (LocalUser or LocalGroup, IdPIdentity does not support custom properties).

Args:

  • property_name (str): Name of property to set value for

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example:

app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_local_user_property(name="my_property", property_type=OAAPropertyType.STRING) >>> user1 = app.add_local_user(name="user1") >>> user1.set_property("my_property", "value for user1")


method to_dict

to_dict() → dict

Output group to dictionary for payload.


class IdPIdentity

IdP identity derived from Identity base class.

Used to associate IdP identities (users or groups) directly to resource where concept of local users/groups doesn't apply to application.

Args:

  • name (str): Primary IdP identifier for identity (email, group name, etc)

Attributes:

  • name (str): name of identity

  • identity_type (OAAIdentityType): Veza Identity Type, (idp)

  • application_permissions (list[CustomPermission]): permissions identity has directly to custom application

  • resource_permissions (dict): Dictionary of custom permissions associated with resources and sub-resources. Key is permission, value is list of resource keys

  • application_roles (list[LocalRole]): roles identity has directly to custom application

  • resource_roles (dict): Dictionary of local_roles for resources and sub-resources. Key is roles, value is list of resource keys

  • properties (dict): Dictionary of properties for identity, allowed values will vary by identity type

  • tags (list[Tag]): List of tags

method __init__

__init__(name: 'str') → None

method add_permission

add_permission(
    permission: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'bool' = False
) → None

Add a permission to an identity.

Permission can apply to either the application or application resource/sub-resources

Args:

  • permissions ([str]): List of strings representing the permission names

  • resource (CustomResource, optional): Custom resource, if None permission is applied to application. Defaults to None.

  • apply_to_application (bool): Apply permission to application when True, defaults to False


method add_role

add_role(
    role: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'Optional[bool]' = None,
    assignment_properties: 'Optional[dict]' = None
) → None

Add a role to an identity.

Role to authorize identity to either the application or application resource/sub-resource based on role's permissions.

Role assignment properties can be set with the assignment_properties dictionary parameter with property names as the keys. Role assignment properties types must be defined on the application prior to setting.

Args:

  • role (str): Name of role as string

  • resources (List[CustomResource], optional): Custom resource, if None role is applied to application. Defaults to None.

  • apply_to_application (bool, optional): Apply permission to application when True, False will replace existing value, None will leave previous setting if any

  • assignment_properties (dict, optional): Custom properties for the role assignment. Defaults to no properties.


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to identity.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method get_identity_to_permissions

get_identity_to_permissions(application_name: 'str') → dict

Get a JSON serializable dictionary of all the identity's permissions and roles.

Formats the identity's permissions and roles for the Custom Application template payload

Returns:

  • dict: JSON serializable dictionary of all the identity's permissions and roles


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set custom IdP property (no functionality).

IdP identities do not support custom properties since the identity is discovered through the provider (Okta, Azure, etc)


class AccessCred

Access Credential derived from Identity base class.

Access Creds can be used to represent non-user based methods that grant access such as API keys or integrations.

AccessCreds can be assigned roles or permissions to an application or resource. An AccessCred can stand-alone or be associated to a local user.

Args:

  • unique_id (str): Unique identifier for access cred

  • name (str): Name for access cred, does not need to be unique

Attributes:

  • unique_id (str): Unique identifier for access cred

  • name (str): Name for access cred, does not need to be unique

  • is_active (bool): Indicate if credential is active, defaults to True

  • created_at (str): Time access cred was created at as RFC3339 timestampe, defaults to empty

  • expires_at (str): Time access cred was created at as RFC3339 timestampe, defaults to empty

  • last_used_at (str): Time access cred was created at as RFC3339 timestampe, defaults to empty

  • can_expire (bool): Boolean to indicate if credential type can exipre, defaults to unset

method __init__

__init__(
    unique_id: 'str',
    name: 'str',
    property_definitions: 'ApplicationPropertyDefinitions' = None
) → None

method add_permission

add_permission(
    permission: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'bool' = False
) → None

Add a permission to an identity.

Permission can apply to either the application or application resource/sub-resources

Args:

  • permissions ([str]): List of strings representing the permission names

  • resource (CustomResource, optional): Custom resource, if None permission is applied to application. Defaults to None.

  • apply_to_application (bool): Apply permission to application when True, defaults to False


method add_role

add_role(
    role: 'str',
    resources: 'List[CustomResource]' = None,
    apply_to_application: 'Optional[bool]' = None,
    assignment_properties: 'Optional[dict]' = None
) → None

Add a role to an identity.

Role to authorize identity to either the application or application resource/sub-resource based on role's permissions.

Role assignment properties can be set with the assignment_properties dictionary parameter with property names as the keys. Role assignment properties types must be defined on the application prior to setting.

Args:

  • role (str): Name of role as string

  • resources (List[CustomResource], optional): Custom resource, if None role is applied to application. Defaults to None.

  • apply_to_application (bool, optional): Apply permission to application when True, False will replace existing value, None will leave previous setting if any

  • assignment_properties (dict, optional): Custom properties for the role assignment. Defaults to no properties.


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to identity.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method get_identity_to_permissions

get_identity_to_permissions(application_name: 'str') → dict

Get a JSON serializable dictionary of all the identity's permissions and roles.

Formats the identity's permissions and roles for the Custom Application template payload

Returns:

  • dict: JSON serializable dictionary of all the identity's permissions and roles


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set a custom defined property to a specific value on an access credential.

Property name must be defined for access credentials before calling set_property(). See example below and ApplicationPropertyDefinitions.define_access_cred_property for more information on defining properties.

Args:

  • property_name (str): Name of property to set value for

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example:

app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_access_cred_property(name="my_property", property_type=OAAPropertyType.STRING) >>> cred1 = app.add_access_cred(unique_id="cred001", name="Cred 001") >>> cred1.set_property("my_property", "value for cred001")


method to_dict

to_dict() → dict

Output Access credential dictionary for payload


class LocalRole

Represent a Custom Application Local Role.

Local Roles are a collection of permissions (as CustomPermission). Roles can be used to associate a local user, group or IdP identity to an application, resource or sub-resource.

Permissions can either be assigned at creation and/or added later.

If the CustomPermission definition includes resource types in the resource_types list, the permission will only be assigned to resources/sub-resources that match that type as part of an assignment.

Args:

  • name (str): name of local role

  • permissions (list[CustomPermission], optional): List of custom permission names (strings) to associate with the role. Defaults to empty list.

  • unique_id (string, optional): Unique identifier for role for identification by ID

Attributes:

  • name (str): name of local role

  • unique_id (str): Unique identifier for role for identification by ID

  • permissions (list[CustomPermission]): list of custom permission names (strings) to associate with the role

  • roles (list[LocalRole]): list of roles nested inside the role

  • tags (list[Tag]): list of Tags instances

method __init__

__init__(
    name: 'str',
    permissions: 'List[str]' = None,
    unique_id: 'str' = None,
    property_definitions: 'ApplicationPropertyDefinitions' = None
) → None

method add_permissions

add_permissions(permissions: 'List[str]') → None

Add a permission to the role.

Args:

  • permissions (list): List of permission names (strings) to add to role


method add_role

add_role(role: 'str') → None

Add a nested sub-role to the role (nested role must be created separately)

Args:

  • role (str): identifier of the local role to nest inside this role


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to role.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set the value for custom property on a local role.

Property name must be defined for local roles before calling set_property(). See example below and ApplicationPropertyDefinitions.define_local_role_property for more information on defining properties.

Args:

  • property_name (str): Name of property to set value for

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property name is not defined.

Example: app = CustomApplication("App", application_type="example") >>> app.property_definitions.define_local_role_property(name="my_property", property_type=OAAPropertyType.STRING) >>> role1 = app.add_local_role(name="role1") >>> role1.set_property(property_name="my_property", property_value="role1s value")


method to_dict

to_dict() → dict

Convert role to dictionary for inclusion in JSON payload.

Returns:

  • dict: serializable dictionary of role


class CustomPermission

CustomPermission class for defining CustomApplication permissions.

  • Custom permissions represent the named permissions for the application in its terms (e.g. "Admin" or "PUSH") and define the Veza canonical mapping (e.g. DataRead, MetadataRead, DataWrite).

  • A permission can either be applied directly to an application or resource or assigned as part of a role.

  • Optionally, when permissions are used as part of a role, if the resource_types list is populated the permission will only be applied to resources who's type is in the resource_types list when the role is applied to a resource.

Args:

  • name (str): Display name for permission

  • permissions (list): List of OAAPermission enums that represent the canonical permissions

  • apply_to_sub_resources (bool, optional): If true, when permission is applied to the application or resource, identity also has permission to all children of application/resource. Defaults to False.

  • resource_types (list, optional): List of resource types as strings that the permission relates to. Defaults to empty list.

Attributes:

  • name (str): Display name for permission

  • permissions (list[OAAPermission]): List of OAAPermission enums that represent the canonical permissions

  • apply_to_sub_resources (bool): If true, when permission is applied to the application or resource, identity also has permission to all children of application/resource.

  • resource_types (list): List of resource types as strings that the permission relates to.

method __init__

__init__(
    name: 'str',
    permissions: 'List[OAAPermission]',
    apply_to_sub_resources: 'bool' = False,
    resource_types: 'list' = None
) → None

method add_resource_type

add_resource_type(resource_type: 'str') → None

Add a resource type to the resource_types list.

Extends the list of resource types permission applies to when used in role assignment.

Args:

  • resource_type (str): The resource type string value


method to_dict

to_dict() → dict

Returns dictionary representation for payload.


class OAAPropertyType

Supported types for custom properties on OAA entities such as application, resource, and identity.


class ApplicationPropertyDefinitions

Model for defining custom properties for application and its entities (users, groups, roles, resources).

Property definitions define the names for additional entity properties and the expected type.

Args:

  • application_type (str): type of custom application property definitions apply to

Attributes:

  • application_properties (dict): property definitions for application

  • local_user_properties (dict): property definitions for local users

  • local_group_properties (dict): property definitions for local groups

  • local_role_properties (dict): property definitions for local roles

  • resources (dict): property definitions for resources keyed by resource type

method __init__

__init__(application_type: 'str') → None

method define_access_cred_property

define_access_cred_property(
    name: 'str',
    property_type: 'OAAPropertyType'
) → None

Define an access cred property.

Args:

  • name (str): name for property

  • property_type (OAAPropertyType): type for property


method define_application_property

define_application_property(
    name: 'str',
    property_type: 'OAAPropertyType'
) → None

Define an application property.

Args:

  • name (str): name for property

  • property_type (OAAPropertyType): type for property


method define_local_group_property

define_local_group_property(
    name: 'str',
    property_type: 'OAAPropertyType'
) → None

Define a local group property.

Args:

  • name (str): name for property

  • property_type (OAAPropertyType): type for property


method define_local_role_property

define_local_role_property(name: 'str', property_type: 'OAAPropertyType') → None

Define a local role property.

Args:

  • name (str): name for property

  • property_type (OAAPropertyType): type for property


method define_local_user_property

define_local_user_property(name: 'str', property_type: 'OAAPropertyType') → None

Define a local user property.

Args:

  • name (str): name for property

  • property_type (OAAPropertyType): type for property


method define_resource_property

define_resource_property(
    resource_type: 'str',
    name: 'str',
    property_type: 'OAAPropertyType'
) → None

Define a property for a resource by type of resource.

Args:

  • resource_type (str): type of resource property definition is for

  • name (str): property name

  • property_type (OAAPropertyType): type for property


method define_role_assignment_property

define_role_assignment_property(
    name: 'str',
    property_type: 'OAAPropertyType'
) → None

method to_dict

to_dict() → dict

Return property definitions as dictionary ready for OAA payload


method validate_name

validate_name(name: 'str') → None

Check property name for valid characters

Raises an exception if the name string does not match required pattern. Name must start with a character and can only contain letters and _ character.

Args:

  • name (str): name of property to validate

Raises:

  • OAATemplateException: Name is not a string

  • OAATemplateException: Name contains invalid characters or does not start with a letter


method validate_property_name

validate_property_name(
    property_name: 'str',
    entity_type: 'str',
    resource_type: 'str' = None
) → bool

Validate that a property name has been defined for given resource type.

Args:

  • property_name (str): name of property to validate

  • entity_type (str): type of entity custom property is for (application, local_user, local_group, local_role, resource)

  • resource_type (str): (optional) type for validating resource property names, only applicable to entity_type resource

Raises:

  • OAATemplateException: If property name has not been previously defined for entity


class IdPEntityType

IdP entity types.


class IdPProviderType

Veza supported IdP provider types.


class CustomIdPProvider

CustomIdPProvider class for modeling Identity Providers (IdP) using OAA Custom Identity Provider Template.

CustomIdPProvider class consists of IdP domain information, user, group and external associations for identities like AWS Roles.

Classes uses dictionaries to track most components, dictionaries are all keyed by string of the entity name

Args:

  • name (str): Name of IdP

  • idp_type (str): Type descriptor for IdP, can be unique or share across multiple IdP e.g. ldap, IPA

  • domain (str): IdP domain name

  • description (str, optional): Description for IdP. Defaults to None.

Attributes:

  • name (str): Name of custom IdP

  • idp_type (str): Type for IdP

  • description (str): Description for IdP

  • domain (CustomIdPDomain): Domain model, created with domain name at init

  • users (dict[CustomIdPUser]): Dictionary of CustomIdPUser class instances

  • groups (dict[CustomIdPGroup]): Dictionary of CustomIdPGroup class instances

  • property_definitions (IdPPropertyDefinitions): Custom Property definitions for IdP instance

method __init__

__init__(
    name: 'str',
    idp_type: 'str',
    domain: 'str',
    description: 'str' = None
) → None

method add_app

add_app(id: 'str', name: 'str') → CustomIdPApp

summary

Args:

  • id (str): description

  • name (str): description

Raises:

Returns:

  • CustomIdPApp: description


method add_group

add_group(
    name: 'str',
    full_name: 'str' = None,
    identity: 'str' = None
) → CustomIdPGroup

Add group to IdP.

Arguments:

  • name (str): primary ID for group

  • full_name (str): optional display name for group

  • identity (str): optional unique identifier for group, if None name is used as identity


method add_user

add_user(
    name: 'str',
    full_name: 'str' = None,
    email: 'str' = None,
    identity: 'str' = None
) → CustomIdPUser

Add user to IdP

if no identity is set name will be used as identity

Arguments:

  • name (str): primary ID for user

  • full_name (str): optional full name for display

  • email (str): optional email for user

  • identity (str): optional unique identifier for user, if None name is used as identity

Returns: CustomIdPUser


method get_payload

get_payload() → dict

Return formatted payload as dictionary for JSON conversion and upload


class CustomIdPDomain

Domain model for Custom IdP provider.

Args:

  • name (str): domain name

Attributes:

  • name (str): domain name

method __init__

__init__(
    name: 'str',
    property_definitions: 'IdPPropertyDefinitions' = None
) → None

method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to IdP Domain.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set custom property value for domain.

Property name must be defined for domain before calling set_property(). See example below and IdPPropertyDefinitions.define_domain_property for more information.

Args:

  • property_name (str): Name of property

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example: idp = CustomIdPProvider(name="Example IdP", idp_type="example", domain="example.com") >>> idp.property_definitions.define_domain_property(name="my_property", property_type=OAAPropertyType.STRING) >>> idp.domain.set_property(property_name="my_property", property_value="domain property value")


method to_dict

to_dict() → dict

Output function for payload.


class CustomIdPUser

User model for CustomIdPProvider.

Args:

  • name (str): username for identity

  • email (str): primary email for user

  • full_name (str): Display name for user

  • identity (str): unique identifier for user (may be same as username or email, or another unique ID like employee number)

Attributes:

  • name (str): username for identity

  • email (str): primary email for user

  • full_name (str): display name for user

  • identity (str): unique identifier for user (may be same as username or email, or another unique ID like employee number)

  • department (str): department name for user

  • is_active (bool): if user is active, defaults to None

  • is_guest (bool): if user is a guest type user, defaults to None

  • manager_id (str, optional): CustomIdPUser.identity of manager, defaults to None

method __init__

__init__(
    name: 'str',
    email: 'str' = None,
    full_name: 'str' = None,
    identity: 'str' = None,
    property_definitions: 'IdPPropertyDefinitions' = None
) → None

method add_app_assignment

add_app_assignment(
    id: 'str',
    name: 'str',
    app_id: 'str',
    assignment_properties: 'Optional[dict]' = None
) → None

Create App assignment for user

Args:

  • id (str): ID of App assignment, must be unique for user

  • name (str): Name of assignment

  • app_id (str): App ID, must exist in list of Apps for IDP

  • assignment_properties (Optional[dict], optional): Optional custom properties to set. Property names must be defined first. Defaults to None.

Raises:

  • OAATemplateException: Duplicate assignment ID

  • OAATemplateException: Unknown assignment property name


method add_assumed_role_arns

add_assumed_role_arns(arns: 'List[str]') → None

Add AWS Roles to list of roles user can assume by ARN.

Args:

  • arns (list): list of role ARNs as strings that the user is allowed to assume


method add_groups

add_groups(group_identities: 'List[str]') → None

Add user to group(s) by group name

Args:

  • group_identities (list): list of strings for group identities to add user to


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to IdP User.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set custom property value for user.

Property name must be defined for users before calling set_property(). See example below and IdPPropertyDefinitions.define_user_property for more information.

Args:

  • property_name (str): Name of property

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example: idp = CustomIdPProvider(name="Example IdP", idp_type="example", domain="example.com") >>> idp.property_definitions.define_user_property(name="my_property", property_type=OAAPropertyType.STRING) >>> user1 = idp.add_user(name="User 1") >>> user1.set_property("my_property", "user1 value")


method set_source_identity

set_source_identity(identity: 'str', provider_type: 'IdPProviderType') → None

Set an source external identity for user.

  • source_identity will connect CustomIdP user to a Veza graph IdP user.

  • provider_type limits scope for finding matching IdP identities

  • search all providers with IdPProviderType.ANY.

Args:

  • identity (str): Unique Identity of the source identity

  • provider_type (IdPProviderType): Type for provider to match source identity from


method to_dict

to_dict() → dict

Function to prepare user entity for payload


class CustomIdPGroup

Group model for CustomIdPProvider.

Args:

  • name (str): name of group

  • full_name (str): optional full name for group

  • identity (str): optional identifier for group if name is not reference identifier

Parameters:

  • name (str): name of group

  • full_name (str): optional full name for group

  • identity (str): optional identifier for group, if None name is used as identity

  • is_security_group (bool): Property for group, defaults to None (unset)

method __init__

__init__(
    name: 'str',
    full_name: 'str' = None,
    identity: 'str' = None,
    property_definitions: 'IdPPropertyDefinitions' = None
) → None

method add_app_assignment

add_app_assignment(
    id: 'str',
    name: 'str',
    app_id: 'str',
    assignment_properties: 'Optional[dict]' = None
) → None

Create App assignment for group

Args:

  • id (str): ID of App assignment, must be unique for group

  • name (str): Name of assignment

  • app_id (str): App ID, must exist in list of Apps for IDP

  • assignment_properties (Optional[dict], optional): Optional custom properties to set. Property names must be defined first. Defaults to None.

Raises:

  • OAATemplateException: Duplicate assignment ID

  • OAATemplateException: Unknown assignment property name


method add_assumed_role_arns

add_assumed_role_arns(arns: 'List[str]') → None

Add AWS Roles to list of roles group members can assume by ARN.

Args:

  • arns (list): list of role ARNs as strings that the group members are allowed to assume


method add_groups

add_groups(group_identities: 'List[str]') → None

Add group to group(s) by group name

Adds current group to another parent group by the group identifier

Args:

  • group_identities (list): list of strings for group identities to add group to


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to IdP Group.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set custom property value for group.

Property name must be defined for groups before calling set_property(). See example below and IdPPropertyDefinitions.define_group_property for more information.

Args:

  • property_name (str): Name of property

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example: idp = CustomIdPProvider(name="Example IdP", idp_type="example", domain="example.com") >>> idp.property_definitions.define_group_property(name="my_property", property_type=OAAPropertyType.STRING) >>> group1 = idp.add_group(name="Group 1") >>> group1.set_property("my_property", "group1 value")


method to_dict

to_dict() → None

Function to prepare user entity for payload.


class CustomIdPApp

App model for CustomIdPProvider

Args:

  • id (str): ID for App, must be unique

  • name (str): Name for App

  • property_definitions (IdPPropertyDefinitions, optional): Custom property definitions, required to set custom properties. Defaults to None.

Attributes:

  • id (str): ID for App, must be unique

  • name (str): Name for App

  • description (str): Description property for App

method __init__

__init__(
    id: 'str',
    name: 'str',
    property_definitions: 'IdPPropertyDefinitions' = None
) → None

method add_assumed_role_arns

add_assumed_role_arns(arns: 'List[str]') → None

Add AWS Roles to list of roles App can assume by ARN. Any Users or Groups assigned to the App are represented as being able to assume the roles.

Args:

  • arns (list): list of role ARNs as strings that the user is allowed to assume


method add_tag

add_tag(key: 'str', value: 'str' = '') → None

Add a new tag to IdP User.

Args:

  • key (str): Key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for Tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only. Defaults to "".


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set custom property value for app.

Property name must be defined for app before calling set_property(). See example below and IdPPropertyDefinitions.define_app_property for more information.

Args:

  • property_name (str): Name of property

  • property_value (Any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.

Example: idp = CustomIdPProvider(name="Example IdP", idp_type="example", domain="example.com") >>> idp.property_definitions.define_app_property(name="my_property", property_type=OAAPropertyType.STRING) >>> app1 = idp.add_app(id="app1", ="App 1") >>> app1.set_property("my_property", "app1 value")


method to_dict

to_dict() → dict

class IdPPropertyDefinitions

Model for defining custom properties for CustomIdPProvider and its entities (users, groups, domain).

Property definitions define the names for additional entity properties and the expected type.

Attributes:

  • domain_properties (dict): property definitions for IdP Domain

  • user_properties (dict): property definitions for IdP users

  • group_properties (dict): property definitions for IdP groups

method __init__

__init__() → None

method define_app_assignment_property

define_app_assignment_property(
    name: 'str',
    property_type: 'OAAPropertyType'
) → None

Define an app assignment custom property

Args:

  • name (str): name of property

  • property_type (OAAPropertyType): type for property


method define_app_property

define_app_property(name: 'str', property_type: 'OAAPropertyType') → None

Define an app custom property

Args:

  • name (str): name of property

  • property_type (OAAPropertyType): type for property


method define_domain_property

define_domain_property(name: 'str', property_type: 'OAAPropertyType') → None

Define a domain custom property.

Args:

  • name (str): name of property

  • property_type (OAAPropertyType): type for property


method define_group_property

define_group_property(name: 'str', property_type: 'OAAPropertyType') → None

Define a group custom property.

Args:

  • name (str): name of property

  • property_type (OAAPropertyType): type for property


method define_user_property

define_user_property(name: 'str', property_type: 'OAAPropertyType') → None

Define a user custom property.

Args:

  • name (str): name of property

  • property_type (OAAPropertyType): type for property


method to_dict

to_dict() → dict

Returns custom IdP property definitions.


method validate_property_name

validate_property_name(property_name: 'str', entity_type: 'str') → None

Validate that a property name has been defined for a given IdP entity.

Raises exception if property name has not been previously defined for entity

Args:

  • property_name (str): name of property to validate

  • entity_type (str): type of entity custom property is for (domain, users, groups)

Raises:

  • OAATemplateException: If property name is not defined


class Tag

Veza Tag data model.

Args:

  • key (str): key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str, optional): Value for tag, will appear in Veza as key:value. Must be letters, numbers, whitespace and the special characters @,._- only.

Attributes:

  • key (str): key for tag, aka name. Must be present and must be letters, numbers or _ (underscore) only.

  • value (str): Value for tag, will appear in Veza as key:value. Must be letters, numbers and the special characters @,._ only.

method __init__

__init__(key: 'str', value: 'str' = '') → None

class HRISProvider

Class for modeling Human Resource Information Systems (HRIS) Template

HRIS template consists of base information about the HRIS instance, Employees and Groups.

Employees and Groups are tracked in case insensitive dictionaries that can be used to reference entities after creation.

Args:

  • name (str): Name for HRIS Instance

  • hris_type (str): Type for HRIS. Typically the vendor or product name.

  • url (str): Instance URL for HRIS.

Attributes:

  • employees (dict[string]): Dictionary of HRISEmployee instances keyed by Employee ID

  • groups (dict[string]): Dictionary of HRISGroup instances keyed by Group ID

method __init__

__init__(name: 'str', hris_type: 'str', url: 'str')

method add_employee

add_employee(
    unique_id: 'str',
    name: 'str',
    employee_number: 'str',
    first_name: 'str',
    last_name: 'str',
    is_active: 'bool',
    employment_status: 'str'
) → HRISEmployee

Add a new Employee

Function creates a new HRISEmployee instance and adds it to the HRISProvider.employees keyed by the unique_id

Args:

  • unique_id (str): Unique Identifier for Employee

  • name (str): Display name for employee

  • employee_number (str): The employee's number that appears in the third-party integration.

  • first_name (str): Employee first name

  • last_name (str): Employee last name (family name)

  • is_active (bool): Boolean for employee active status

  • employment_status (str): String representation of employee status, e.g. "ACTIVE", "TERMINATE", "PENDING"

Raises:

  • OAATemplateException: Employee with ID already exists

Returns:

  • HRISEmployee: Entity for new employee


method add_group

add_group(unique_id: 'str', name: 'str', group_type: 'str') → HRISGroup

Add a new Group

Used to represent any subset of employees, such as PayGroup or Team. Employees can be in multiple Groups. Groups can also be members of other groups to create hierarchy.

Some properties of HRISEmployee such as department must reference an existing HRISGroup by its ID.

Args:

  • unique_id (str): Unique ID for group

  • name (str): Display name

  • group_type (str): Type for group such as "Team", "Department", "Cost Center"

Returns:

  • HRISGroup: Entity for new group


method get_payload

get_payload() → dict

Get the OAA payload.

Returns the complete OAA template payload for HRIS as serializable dictionary

Returns:

  • dict: OAA payload as dictionary


class HRISSystem

HRISSystem information

Representation for HRISSystem information. The system information is used to represent additional details for the HRIS Instance.

Args:

  • name (str): Name for system Instance

  • url (str, optional): URL for instance . Defaults to "". TODO: Is this right?

method __init__

__init__(name: 'str', url: 'str' = '')

method add_idp_type

add_idp_type(provider_type: 'IdPProviderType') → list[IdPProviderType]

Link HRIS to External IdP of given type

Sets the IdP types (Okta, AzureAD, ect) for Veza to link employee identities too.

Args:

  • provider_type (IdPProviderType): Type of IdP for source identities

Raises:

  • ValueError: provider_type must be IdPProviderType enum

Returns:

  • list[IdPProviderType]: List of configured IdP types


method to_dict

to_dict() → dict

class HRISEmployee

HRIS Employee Entity

Represents an employee record in the HRIS system. Each employee must have a unique ID to identify it in the payload. This ID is also used to reference one employee to the other for manager hierarchy.

Init variables are all required and must not be empty such as ""

Args:

  • unique_id (str): Unique Identifier for Employee

  • name (str): Name for employee record.

  • employee_number (str): The employee's number that appears in the third-party integration.

  • first_name (str): Employee first name

  • last_name (str): Employee last name (family name)

  • is_active (bool): Boolean for employee active status

  • employment_status (str): String representation of employee status, e.g. "ACTIVE", "TERMINATE", "PENDING"

Parameters:

  • company (str): The company (or subsidiary) the employee works for.

  • preferred_name (str): The employee's preferred first name.

  • display_full_name (str): The employee's full name, to use for display purposes.

  • canonical_name (str): The employee's canonical name.

  • username (str): The employee's username that appears in the integration UI.

  • email (str): The employee's work email.

  • idpid (str): The ID for this employee on the destination IDP provider used to automatically connect to it, if not supplied email is used.

  • personal_email (str): The employee's personal email.

  • home_location (str): The employee's home location.

  • work_location (str): The employee's work location.

  • cost_center (str): The cost center ID (Group ID) that the employee is in.

  • department (str): The department ID (Group ID) that the employee is in.

  • managers (str): The employee IDs of the employee's managers.

  • groups (str): The IDs of groups this user is in

  • start_date (str): The date that the employee started working. RFC3339 timestamp.

  • termination_date (str): The employee's termination date. RFC3339 timestamp.

  • job_title (str): The title of the employee.

  • employment_typ (str): The employee's type of employment. For example: FULL_TIME, PART_TIME, INTERN, CONTRACTOR, FREELANCE.

  • primary_time_zone (str): The time zone which the employee primarily lives.

Raises:

  • ValueError: Any of the required arguments are empty.

method __init__

__init__(
    unique_id: 'str',
    name: 'str',
    employee_number: 'str',
    first_name: 'str',
    last_name: 'str',
    is_active: 'bool',
    employment_status: 'str'
)

method add_group

add_group(group_id: 'str') → None

Add employee to group

Adds employee to a group by the group ID. Group must also be defined for HRISInstance with HRISProvider.add_group()

Args:

  • group_id (str): Unique ID of HRISGroup to add employee too


method add_manager

add_manager(manager_id: 'str') → None

Add manager to Employee

Adds a manager to the employee by the manager's HRISEmployee instance unique ID. Manger employee record must also exist.

Args:

  • manager_id (str): Unique ID for manager HRISEmployee instance


method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set Employee custom property value

Property name must be defined for employee before calling set_property

Args:

  • property_name (str): Name of property

  • property_value (any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.


method to_dict

to_dict() → dict

Output employee to dictionary for payload.


class HRISGroup

HRIS Group

Represents any group of employees in the HRIS system. HRISGroups can be used to represent teams, departments, cost centers or any organizational unit. Each group has a type to make searching and grouping easier.

Group's Unique ID must be unique across all group types.

Args:

  • unique_id (str): Unique ID for group

  • name (str): Display name

  • group_type (str): Type for group such as "Team", "Department", "Cost Center"

method __init__

__init__(unique_id: 'str', name: 'str', group_type: 'str')

method set_property

set_property(
    property_name: 'str',
    property_value: 'any',
    ignore_none: 'bool' = False
) → None

Set HRIS Group custom property value

Property name must be defined for group before calling set_property

Args:

  • property_name (str): Name of property

  • property_value (any): Value for property, type should match OAAPropertyType for property definition

  • ignore_none (bool, optional): Do not set property if value is None. Defaults to False.. Defaults to False.

Raises:

  • OAATemplateException: If property with property_name is not defined.


method to_dict

to_dict() → dict

Dictionary output for inclusion in payload


class HRISPropertyDefinitions

method __init__

__init__()

method define_employee_property

define_employee_property(name: 'str', property_type: 'OAAPropertyType') → None

method define_group_property

define_group_property(name: 'str', property_type: 'OAAPropertyType') → None

method define_system_property

define_system_property(name: 'str', property_type: 'OAAPropertyType') → None

method to_dict

to_dict() → dict

method validate_name

validate_name(name: 'str') → None

Check property name for valid characters

Raises an exception if the name string does not match required pattern. Name must start with a character and can only contain letters and _ character.

Args:

  • name (str): name of property to validate

Raises:

  • OAATemplateException: Name is not a string

  • OAATemplateException: Name contains invalid characters or does not start with a letter


Custom Application Template
Custom Identity Provider Template
custom property definition
Custom properties
Veza Tags
incremental update
Open Authorization API
custom property definition
custom application
Custom Properties
Veza tags
incremental update
incremental update
custom app metadata payload
Lifecycle Management
custom properties
custom application
identity_to_permissions
publishing
domain
users
groups
apps
identity_mapping_configuration
Source Identity Assignments
creating an OAA provider
more examples

name

string

Identifies the app in Veza Search. Used to bind permissions to the application

application_type

string

Applied to all entities within the application as a searchable property. Multiple instances of an application can share the same type

description

string

Any additional notes to show in the entity details, limit 256 characters

custom_properties

dictionary

tags

array

Specify tags with a key and optional value (optional)

local_users

array

local_groups

array

local_roles

array

resources

array

name

string

Resource name. Primary ID for mapping users to individual resource permissions.

id

string

Optional value to use as the unique ID, instead of the resource name*.

resource_type

string

Searchable label for the resource type. The application entity details in Veza will show the contained resource types as properties.

description

string

Shown in Veza entity details, max 255 characters.

custom_properties

dictionary

sub_resources

array

Used for additional resource layers, nested data sources, services, and so on.

connections

Optional list of resource connections to external entities discovered by Veza

tags

array

Specify tags with a key and optional value (optional)

name

string

Name of the local user, shown in the Veza UI.

unique_id

string

Optional identifier to use for mapping users to groups, roles, and permissions.

identities

identities array

Maps the user to a federated identity by login email or group name. Use when your IdP provisions local accounts, or if the local user can be assumed by an external group. Must match a discovered Okta, Google Workspace, or Azure AD entity Name, PrincipalName, or Identity.

groups

groups array

is_active

boolean

If activity state is available from the provider, use this field to make the value available as a searchable property (optional).

created_at

RFC3339 string

User creation date (optional), for example 1996-12-19T16:39:57-08:00

last_login_at

RFC3339 string

(optional)

password_last_changed_at

RFC3339 string

(optional)

deactivated_at

RFC3339 string

(optional)

custom_properties

dictionary

tags

Specify tags with a key and optional value (optional)

name

string

Name of the local group. Primary ID for mapping group to permissions.

unique_id

string

Optional identifier to use for permissions mapping

custom_properties

dictionary

identities

array

If IdP users are members of the local group, or if the local group directly maps to an IdP group, list them here.*

groups

array

List of local group this group is a member of (for applications that support adding groups to other groups)

tags

array

Specify tags with a key and optional value (optional)

name

string

Name to associate with the provider in Veza.

custom_property_definition

Defines the key and types for properties that can be applied to other objects in the push payload

idp_type

string

Type descriptor for IdP, can be unique or share across multiple IdP (for example ldap, IPA)

idp_description

string

Any notes to add as entity details (optional)

domains

Domain model

users

Dictionary of CustomIdPUser class instances

groups

Dictionary of CustomIdPGroup class instances

incremental_change

boolean

identity_mapping_configuration

Configuration for mapping identities between IdP User and other User types from external data sources

name

string

IdP Domain name

custom_properties

Each element of the push payload can have property_values, validated against the custom_property_definition.

dynamic_properties

Dynamic Properties

tags

Any tags to create and apply to the domain.

operation

enum

name

string

Primary ID for user

email

string

Optional email for user

identity

string

Optional unique identifier for user

groups

string list

Assign groups memberships by group identity (optional)

full_name

string

Full name to display in Veza

department

string list

Any departments to apply as a searchable property (optional).

is_active

boolean

If available, will be applied to the entity as a searchable property (optional).

is_guest

boolean

If available, will be applied to the entity as a searchable property (optional).

assumed_role_arns

array

AWS IAM roles that can be assumed by the IdP user, in the format {"identity": ["arn:aws:iam::123456789012:role/S3Access"]} (optional).

tags

Any tags to create and apply to the user.

dynamic_properties

Dynamic Properties

custom_properties

Each element of the push payload can have property_values, validated against the custom_property_definition.

manager_id

string

entities_owned

If another resource is specified by entity type and entity id, a Veza tag will be created on the resource to indicate the owner.

operation

enum

source_identity

Optionally link IdP user to user from another IdP for federation use cases.

name

string

IdP group name.

identity

string

Unique ID used for user-group assignments.

full_name

string

Optional display name for group

groups

string list

other custom IdP groups this group is a member of

is_security_group

boolean

Sets the is security group searchable property for the entity in Veza (optional).

tags

Veza Tags list

custom_properties

Each element of the push payload can have property_values, validated against the custom_property_definition.

dynamic_properties

Dynamic Properties

operation

enum

assumed_role_arns

array

AWS IAM roles the group can assume, in the format {"identity": ["arn:aws:iam::123456789012:role/S3Access"]} (optional).

id

string

App unique identifier.

name

string

IdP app name.

description

string

Description for the App (optional).

assumed_role_arns

array

AWS IAM roles the app can assume, in the format {"identity": ["arn:aws:iam::123456789012:role/S3Access"]} (optional).

custom_properties

Each element of the payload can have property_values, validated against the custom_property_definition.

tags

Veza Tags list

operation

enum

id

string

Assignment unique identifier.

name

string

Display name for the assignment.

app_id

string

Unique ID of the App to assign the identity to.

custom_properties

Each element of the payload can have property_values, validated against the custom_property_definition.

mappings

IdentityMappingSubmission

List of mappings to create between IDP Users and external data sources

operation

enum

OAA Push API

Methods for working with Custom Data Providers and Sources

Overview

    • The populated template can describe additional resources and sub-resources, such as individual databases, repositories, or views.

Authentication

curl -X GET "https://$VEZA_URL/api/v1/providers/custom" \
-H "authorization: Bearer $API_KEY"

Follow best practices for managing API keys: Do not save credentials in connector code. Consider using a secrets manager to securely store API keys and make them available at run time.

First Run

To add a custom application, you will need to:

  • Create a new custom provider and data source.

  • push the entity and authorization data in a JSON payload.

Create a provider using the "Custom Application" template

curl -X POST "https://$VEZA_URL/api/v1/providers/custom" \
-d '{"name":"DemoApp","custom_template":"application"}'

The response will return the Provider's ID, which you will need to create and manage the data sources:

{
  "value": {
    "id": "a6ef8d8d-d17b-4491-a67a-635ad70f1ba9",
    "name": "DemoApp",
    "custom_template": "application",
    "state": "ENABLED",
    "application_types": [],
    "resource_types": [],
    "idp_types": [],
    "schema_definition_json": "e30="
  }
}
  • Name the provider generically after the application or SaaS provider. Use the same Provider for all data sources for that application.

  • If you are creating providers dynamically, your OAA integration should check if the provider and data source exists before creating a new one.

Create a Data Source for the Provider

curl -X POST "https://${VEZA_URL}/api/v1/providers/custom/${PROVIDER_ID}/datasources" \
-H 'accept: application/json' \
-H 'authorization: Bearer '${API_KEY} \
-d '{"id": "<PROVIDER ID>", "name":"DemoApp - Documentation Datasource"}'

The response will include the data source ID:

{
  "value": {
    "id": "1bd31da0-64ee-4dfe-82c9-cb9f0f2fc369",
    "name": "DemoApp - Documentation Datasource"
  }
}
  • Datasources should be unique to the data collected by an OAA integration instance. For example, if an application has a "prod" and "dev" instance, creating a datasource for each will enable independent updates to each environment.

  • Name the data source uniquely based on the application instance to discover. Try to include the hostname or organization name in the data source. For example, don't use "GitHub" use "GitHub - Acme Inc" or "Portal - prod.corp.com"

  • Note that a provider id is required in both the request path and body.

Push data source metadata

json_data must contain the populated OAA template as a single JSON string (escaping any unsafe characters such as ").

body.json
{
  "id": "532f6fe3-189f-4576-afdf-8913088961e4",
  "compression_type": "none",
  "data_source_id": "b6a32af6-b854-47e1-8325-e5984f78bb4d",
  "json_data": "{\"name\":\"CustomApp\",\"application_type\"...}"
}
curl -X POST "https://$VEZA_URL/api/v1/providers/custom/$PROVIDER_ID/datasources/$DATASOURCE_ID:push" \
-H 'accept: application/json' \
-H 'authorization: Bearer '$API_KEY \
--compressed --data-binary @body.json

Get Custom Providers

curl -X GET "https://$VEZA_URL/api/v1/providers/custom" \
-H 'accept: application/json' \
-H 'authorization: Bearer '$API_KEY

Get Custom Data Sources

curl -X GET "https://$VEZA_URL/api/v1/providers/custom/$PROVIDER_ID" \
-H 'accept: application/json' \
-H 'authorization: Bearer '$API_KEY

Update Custom Data Source

curl -X POST "https://$VEZA_URL/api/v1/providers/custom/$PROVIDER_ID/datasources/$DATASOURCE_ID:push" \
-H 'accept: application/json' \
-H 'authorization: Bearer '$API_KEY \
--compressed --data-binary @payload.json

OAA .NET SDK

Building blocks for your custom OAA integration

The Veza SDK includes the following core components:

  • Veza.Sdk.Client: A base API client for making REST calls to a Veza tenant

  • Veza.OAA.Client: An OAA API client for interacting with integration providers, data sources, and pushing OAA metadata to a Veza tenant.

For example usage, see C# OAA Application Connector.

Sample Workflow

Create the Veza API connection and a new custom application:

using Veza.OAA;
using Veza.OAA.Application;
using Veza.OAA.Base;

// inside namespace/class
            OAAClient oaaClient = new(api_key: <your_api_key>, url: <veza_tenant_url>);
            CustomApplication customApp = new(name: "sample app",
                applicationType: "sample", description: "This is a sample application");

Once the CustomApplication class is instantiated, you can use its public methods to populate the new app with users, groups, resources, and permissions metadata:

            // add custom permissions
            customApp.AddCustomPermission(name: "Admin", permissions: new List<Permission>
                {
                    Permission.DataRead,
                    Permission.DataWrite,
                    Permission.MetadataRead,
                    Permission.MetadataWrite,
                    Permission.NonData
                },
                applyToSubResources: true
            );

            // define custom user properties
            customApp.DefinedProperties[typeof(User)].DefineProperty("is_guest", typeof(bool));

            // add user
            User user = customApp.AddUser(name: "bob");
            user.AddIdentity("bob@example.com");
            user.IsActive = true;
            user.CreatedAt = "2001-01-01T00:00:00.000Z".FromRFC3339();
            user.DeactivatedAt = "2003-03-01T00:00:00.000Z".FromRFC3339();
            user.LastLoginAt = "2002-02-01T00:00:00.000Z".FromRFC3339();
            user.PasswordLastChangedAt = "2004-04-01T00:00:00.000Z".FromRFC3339();
            user.SetProperty(name: "is_guest", value: false);

            // define group properties
            customApp.DefinedProperties[typeof(Group)].DefineProperty("group_id", typeof(int));

            // add group
            Group group1 = customApp.AddGroup("group1");
            group1.CreatedAt = "2001-01-01T00:00:00.000Z".FromRFC3339();
            group1.SetProperty(name: "group_id", 1);
            customApp.Users["bob"].AddGroup("group1");
            Group group2 = customApp.AddGroup("group2");
            group2.AddGroup("group1");

            // idp identities
            customApp.AddIdPIdentity("user01@example.com");

            // define role properties
            customApp.DefinedProperties[typeof(Role)].DefineProperty("custom", typeof(bool));

            // add roles
            Role role1 = customApp.AddRole(name: "role1", permissions: new List<string> { "all", "Admin", "Manage_Thing" });
            role1.SetProperty(name: "custom", value: false);

            // define resource properties
            customApp.DefineResourceProperty("private", typeof(bool), "thing");

            // add resources
            Resource thing1 = customApp.AddResource(name: "thing1", resourceType: "thing", description: "thing1");
            thing1.SetProperty(name: "private", false);
            thing1.AddTag(name: "tag1", value: "This is a value @,-_.");
            Resource cog1 = thing1.AddSubResource(name: "cog1", resourceType: "cog");
            cog1.AddConnection(id: "service_account@some-project.iam.gserviceaccount.com", nodeType: "GoogleCloudServiceAccount");

            // authorizations
            customApp.Users["bob"].AddRole(name: "role1", applyToApplication: true);
            customApp.Groups["group2"].AddRole(name: "role1", resources: new List<Resource> { thing1 });
            customApp.IdPIdentities["user01@example.com"].AddRole(name: "role1", applyToApplication: true);

            return customApp;

Once all identities, permissions, and resources are added to the CustomApplication object, use the client connection to push the data to Veza:

    await oaaClient.CreateProvider(provider_name: "sample app", custom_template: "application");
    await oaaClient.PushApplication(provider_name: "sample app", data_source_name: "sample app 1", customApp);

Handling Errors

The Veza.OAA namespace provides exception types for common errors that occur when interacting with Veza APIs.

  • An OAAClientException is raised if there are errors interacting with the Veza API.

  • A TemplateException is raised if a provided payload does not conform to the template requirements. The inner exception will contain details about the exact issues encountered.

Additional Documentation

Each OAA connector will be slightly different, depending on the methods each source application or service provides for retrieving entities, authorization, and other required metadata. You should consult the API documentation for your application when considering how you will source the information, and refer to existing Veza-supported OAA connectors for real-world examples.

  • OAA connector source code and Veza components are thoroughly annotated for reference when building your own integrations.

oaaclient modules

Modules

Classes

Functions

Application Outline

This document provides a high-level overview and examples for getting started with a new OAA connector to integrate Veza with SaaS applications, infrastructure systems, custom-built applications, and other systems. These examples use Python and the oaaclient SDK.

When developing a connector, the source systems and customer needs can require changes to code flow for different deployment scenarios. The overall goals, best practices, and flow will apply for most integrations:

Code goals

The sample code was written with the following goals in mind:

  • Connector should be easy to run from automation platforms and the command line.

    • Parameters are passed through environment variables as well as command line flags. This makes the code easier to package into containers or serverless stacks and control through outside configuration. Connectors by nature require secrets such as the Veza API key. Managing these through variables affords additional options for secrets management.

  • Connectors do not require state:

    • Connectors do not require any persistent data between runs.

    • There is no special invocation for the first run or subsequent runs.

    • The connector handles all of the logic for provider and data source creation internally, as needed, or by discovering existing ones.

      • Data Source name should be unique to the discovered environment. This can be achieved by including a hostname or instance ID in the data source name: discoverable by the code and consistent between runs. This ensures that two instances of the same connector do not interfere with each other if discovering separate instances of the application. When such a property cannot be determined, a command line parameter is an option.

  • Connector code is importable:

    • The flexibility to import connector code into another piece of Python code enables a setup wrapper to handle job management tasks such as:

      • Secrets management

      • Output logging

      • Other configurations required by the environment

    • A separate run function implements connector end-to-end logic. This can be imported and invoked by providing the necessary parameters. The main function that runs when invoked from the command line should only process command line inputs and environment variables for setup.

High-level code flow

The exact flow of the connector can change to meet specific requirements, but the general steps are as follows:

  1. Process and validate configuration parameters. Ensure you have supplied all necessary values such as host names, user names, and API keys.

  2. Call the main run function with all the required and optional parameters.

  3. Initialize the oaaclient connection to the Veza tenant. Initializing the client verifies that the Veza URL and API key are valid before starting any application discovery.

  4. Create an instance of the oaaclient.templates.CustomApplication to populate with the application information.

  5. Connect to the system and perform discovery of required entities:

    1. The discovery order for users, groups, roles, and so on can be changed based on relationships and interface.

    2. Populate the CustomApplication instance with the identity, roles and permissions, resources, and authorization information.

  6. Check if Provider and Data Source exist on Veza. Create them if they do not exist.

  7. Push the application to the Data Source. The SDK creates the JSON payload from the CustomApplication instance.

    1. Process any returned warnings or errors.

  8. Exit.

Implementing from the example

  1. Run the connector to validate the output in Veza.

  2. Automate the connector to run on a regular schedule.

Code walkthrough for custom application

The code below can serve as a template and the comments explain the reasoning beyond the patterns.

oaa-app.py
#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import logging
import os
import sys

import requests
from requests.exceptions import HTTPError, RequestException

from oaaclient.client import OAAClient, OAAClientError
from oaaclient.templates import CustomApplication, OAAPermission, OAAPropertyType, LocalUser
import oaaclient.utils as oaautils

"""
Logging in connectors is very important. Establishing a local logging function here
allows the connector log even if its imported into another block of code
"""
logging.basicConfig(
format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)
log = logging.getLogger(__name__)

"""
The main logic for connecting to the destination application.
Authorization data collection and OAA template population should be structured into a class.
The class can store the authentication tokens making connections through an API or SDK easier.
The class should also instantiate the OAA CustomApplication or CustomIdP class
to manage populating all the identity, resource and authorization data.
"""
class OAAConnector():
    APP_TYPE="SampleApp"
    def __init__(self, auth_token: str) -> None:
        self.auth_token = auth_token


        # Set the application name and type. The type will generally be the vendor or product.
        # The App Name can be the same, or contain additional context like the instance name.
        app_name = "My App - West"
        self.app = CustomApplication(app_name, application_type=self.APP_TYPE)

        # declaring custom properties as part of the `__init__` keeps them together
        self.app.property_definitions.define_local_user_property("email", OAAPropertyType.STRING)
        self.app.property_definitions.define_local_user_property("has_mfa", OAAPropertyType.BOOLEAN)

    """
    A `discover` method that starts the discovery cycle.
    The discovery cycle should be invoked separately from the init.
    More complex connectors may have additional setup steps between init and discovery
    """
    def discover(self) -> None:
        """Discovery method"""
        log.info(
        "Start App discovery")  # Start and stop log messages provide progress as discovery proceeds
        self._discover_users()
        self._discover_roles()
        log.info("Finished App discovery")
        return

    """
    Smaller functions to perform portions of the discovery like users, groups, roles
    should be private `_` functions to imply that they should not be run alone,
    unless care is taken to ensure no dependencies.
    For example, discovery of roles may assume that users are already discovered.
    """
    def _discover_users(self) -> None:
        log.info("Start user discovery")

        # perform user discovery, for example process each user returned from an API call
        for user in self._api_get("/Users"):
            local_user = self.app.add_local_user(id=user["id"], name=user["name"])
            local_user.is_active = user["active"]
            local_user.set_property("has_mfa", user["mfa_enabled"])

        log.info("Finished user discovery")
        return

    def _discover_roles(self) -> None:
        log.info("Start role discovery")
        # perform user discovery
        log.info("Finished role discovery")
        return

    """
    Any required methods to interface with the application should be defined
    as part of the class. Not all connectors need these methods, as they may use
    other SDKs to interface with the application.
    """
    def _api_get(self, path: str) -> dict:
        # implement logic to make API call, process results, handle errors, retries ect.
        # Could be done with a vendor SDK, SQL, or any method supported by the application
        return {}


"""
A run function that is separate from `main` makes it easy to import the connector
into another piece of Python code. This may be useful to call the connector from
code that retrieves secrets or manages the job in other ways.
All necessary parameters should be taken in through the `run` function
"""
def run(veza_url: str, veza_api_key: str, app_key: str, **config_args) -> None:

    # Process any configuration arguments
    if config_args.get("debug"):
        log.setLevel(logging.DEBUG)
        logging.getLogger("urllib3").setLevel(logging.INFO)
        log.info("Enabling debug logging")
    else:
        log.setLevel(logging.INFO)

    save_json = config_args.get("save_json", False)
    if not isinstance(save_json, bool):
        raise TypeError("save_json argument must be boolean")

    # Connect to the Veza instance before discovery to validate that the credentials are valid
    try:
        conn = OAAClient(url = veza_url, api_key = veza_api_key)
    except OAAClientError as error:
        log.error(f"Unable to connect to Veza {veza_url}")
        log.error(error.message)
        # run function should raise any exception so that they can be handled by the parent code, never exit
        raise error

    # Initialize the connector class and run discovery
    try:
        app = OAAConnector(auth_token=app_key)
        app.discover()
    except RequestException as e:
    # process possible exceptions from the app discovery
        log.error("Error during discovery")
        log.error(f"{e} - {e.response.status_code} {e.response.text}")
        raise e

    # After discovery is complete, set up the Provider and Data Source to push the data to

    # Provider name should be consistent with the vendor and application
    provider_name = "My App"
    provider = conn.get_provider(provider_name)

    if provider:
        log.info("found existing provider")
    else:
        log.info(f"creating provider {provider_name}")
        provider = conn.create_provider(provider_name, "application", base64_icon=APP_SVG_B64)
    log.info(f"provider: {provider['name']} ({provider['id']})")

    # Data Source name should be unique to the instance of the app that is discovered but consistent.
    # For example the hostname of the application or deployment name. Do not use something that will change.
    data_source_name = f"App - {app.unique_identifier}"

    try:
        log.info("uploading application data")
        response = conn.push_application(provider_name,
                                        data_source_name = data_source_name,
                                        application_object = app.app,
                                        save_json = save_json
                                        )
        # An OAA Push can succeed with warnings, you can log out the warnings
        if response.get("warnings", None):
            log.warning("Push succeeded with warnings:")
            for e in response["warnings"]:
                log.warning(e)
        log.info("success")
    except OAAClientError as error:
    # if there is an issue with the OAA payload the error details should contain useful information to help resolve the problem
        log.error(f"{error.error}: {error.message} ({error.status_code})")
        if hasattr(error, "details"):
            for detail in error.details:
                log.error(detail)
        raise error

    return

"""
Setting an application icon helps visually identify the app in the Veza UI.
A Base64 encoding of an SVG or PNG in the app code is an option.
You can also import an icon from a file with `oaaclient.utils.encode_icon_file`.
"""
APP_SVG_B64 = """
PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFRE
IFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgd2lkdGg9IjQwMCIgaGVpZ2h0
PSI0MDAiIHZpZXdCb3g9IjAgMCAyMDAgMjAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICA8cGF0aCBmaWxsPSJyZWQiIHN0cm9r
ZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIyLjUiIGQ9Ik0xNjggMTY4SDMyVjMyaDEzNnoiLz4NCjwvc3ZnPg0K
"""

"""
The main entry point should only deal with processing parameters and invoking
the run function. No OAA or application discovery should happen during the main
function. All required parameters should be configurable through the OS
environment. It should be possible to run the connector from the command line
with no arguments.
"""
def main():
    """
    process command line and OS environment variables, then call `run`
    """
    parser = argparse.ArgumentParser(description = "OAA Connector")
    # using the `default=os.getenv()` pattern makes it easier to get parameters from command line or OS environment
    parser.add_argument("--veza-url", default=os.getenv("VEZA_URL"), help="the URL of the Veza instance")
    parser.add_argument("--debug", action="store_true", help="Set the log level to debug")
    parser.add_argument("--save-json", action="store_true", help="Save OAA JSON payload to file")
    args = parser.parse_args()

    # Secrets should only be passed in through ENV
    veza_api_key = os.getenv("VEZA_API_KEY")
    veza_url = args.veza_url
    save_json = args.save_json

    if not veza_api_key:
        oaautils.log_arg_error(log, None, "VEZA_API_KEY")
    if not veza_url:
        oaautils.log_arg_error(log, "--veza-url", "VEZA_URL")

    # ensure required variables are provided
    if None in [veza_api_key, veza_url]:
        log.error(f"missing one or more required parameters")
        sys.exit(1)

    try:
        run( veza_url=veza_url, veza_api_key=veza_api_key, save_json=save_json, debug=args.debug)
    except (OAAClientError, RequestException):
        log.error("Exiting with error")
        sys.exit(1)


if __name__ == "__main__":
    # replace the log with the root logger if running as main
    log = logging.getLogger()
    logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)

    main()

OAA Python SDK

Building blocks for your custom OAA integration

The oaaclient SDK includes the following components:

  • oaaclient.client: Veza API communication (data provider management, payload push, etc.). Requires an API key for authentication.

  • oaaclient.templates: Classes for modeling and generating an OAA payload.

  • oaaclient.utils: Additional utility functions (icon encoding, etc.).

Sample Workflow

Create the Veza API connection and a new custom application:

from oaaclient.client import OAAClient
from oaaclient.templates import CustomApplication, OAAPermission

# creates a connection class to communicate with Veza
veza_con = OAAClient(url=veza_url, token=veza_api_key)

# creates a new Custom Application model
custom_app = CustomApplication(name="Sample App", application_type="sample")

Once the CustomApplication class is instantiated, you can use the public methods to populate the new app with local users, groups, resources, and permissions metadata:

# define a permission
custom_app.add_custom_permission("owner", [OAAPermission.DataRead, OAAPermission.DataWrite])
# create a local user
jsmith = custom_app.add_local_user(unique_id="jsmith", name="Jane Smith", identities=["jane@example.com"])
# create a resource
resource1 = custom_app.add_resource(name="Resource 1", resource_type="Thing")
# assign a user to a resource
jsmith.add_permission(permission="owner", resources=[resource1])

Once all identities, permissions and resources are added to the CustomApplication object, the client connection handles the final push to Veza:

veza_con.push_application(provider, data_source_name, application_object=custom_app)

Handling Errors

The OAAClient class handles API connections to Veza. If there are errors connecting or the API returns errors OAAClient will raise an OAAClientError exception. If the payload doesn't conform to the template requirements the OAAClientError.details will contain a list of any issues encountered.

    try:
        response = veza_con.push_application(provider_name=provider_name,
                                             data_source_name=data_source_name,
                                             application_object=custom_app,
                                            )
        if response.get("warnings"):
            print("Push succeeded with warnings:")
            for w in response["warnings"]:
                print(w)
    except OAAClientError as e:
        print(f"Error: {e.error}: {e.message} ({e.status_code})", file=sys.stderr)
        if hasattr(e, "details"):
            for d in e.details:
                print(d, file=sys.stderr)

Additional documentation

Since any given source application or service will have different methods for retrieving entities, authorization, and other required metadata, each OAA connector will be slightly different. You should consult the API documentation for your application when considering how you will source the information, and refer to existing Veza-supported OAA connectors for real-world examples.

C# OAA Application Connector

This document provides a high-level overview of and examples for getting started with a new OAA connector to integrate Veza with SaaS applications, infrastructure systems, custom-built applications, and other systems. These examples use C# and the Veza.OAA SDK.

When developing a connector, source system specifics and individual customer requirements will require alterations to code flow. However, the overall goals, best practices, and development flow are common to most integrations.

Code goals

The example code was written with the following goals in mind:

  • Connector should be easy to run from automation platforms and the Command Prompt.

  • Parameters are passed through environment variables as well as command line flags.

  • Connector does not require maintenance of state:

    • Connector does not require any persistent data between invocations.

    • There is no special invocation for the first execution.

    • The connector handles all provider and data source management logic.

    • Data source name is unique to the discovered environment.

High-level code flow

The exact flow of an OAA connector can change to meet specific requirements, but the general steps are as follows:

  1. Process and validate configuration parameters. Ensure that all required values are present and valid.

  2. Initialize the API client connection to the Veza tenant. Doing so early in the application flow validates the URL and API key before continuing discovery.

  3. Create an instance of the Veza.OAA.Application.CustomApplication class to populate with application metadata.

  4. Connect to the system and perform discovery of required entities.

    • In your custom integrations, discovery order for users, groups, roles, and other entities can adapt to suit application requirements.

    • Populate the CustomApplication instance with the identity, role, permission, resource, and authorization information collected.

  5. Check if the Provider and Data Source exist on Veza. Create them if they do not exist.

  6. Push the application to the Data Source on Veza. The SDK creates the required JSON payload from the CustomApplication instance.

    • Process any returned warnings or errors.

  7. Exit.

Customizing the example

To use this example as a starting point for your application integration, follow these steps:

  1. Update the name, applicationType, and description of the CustomApplication object based on the source system for integration with Veza.

  2. Implement the discovery steps in the Discover() function to collect user, group, role, resource, and permission data for the application. As entities are collected, add them to the CustomApplication object.

  3. Run the connector to validate the output in Veza.

Example: custom application

The following code provides a template and examples for creating a new application integration using the Veza.OAA SDK.

example_app.cs
using RestSharp;
using RestSharp.Authenticators;
using Veza.OAA;
using Veza.OAA.Application;
using Veza.OAA.Client;
using NLog;

namespace Example.Integrations
{
    /// <summary>
    /// Example application group object
    /// </summary>
    public class AppGroup {
        public string Name { get; set; }
        public string Type { get; set; }
        public string CreatedAt { get; set; }
        public List<string> Users { get; set; }
    }

    /// <summary>
    /// Example application resource object
    /// </summary>
    public class AppResource {
        public string Name { get; set; }
        public int SiteId { get; set; }
        public string ResourceType { get; set; }
    }

    /// <summary>
    /// Example application role object
    /// </summary>
    public class AppRole {
        public string Name { get; set; }
        public int SystemId { get; set; }
        public string CreatedAt { get; set; }
        public List<string> Users { get; set; }
        public List<string> Resources { get; set; }
    }

    public class ExampleApp
    {
        // Optional NLog logger; can be replaced with any standard logging interface
        private static Logger logger = LogManager.GetCurrentClassLogger();

        // The base64-encoded logo for the application (displayed on the Veza UI)
        public string LogoBase64;

        // The name of the provider for the application
        public string ProviderName;

        // The custom application object for the example application
        // This object is used to build the application payload for Veza
        public CustomApplication CustomApp { get; set; }

        // The example application client for the example application API (not shown in this example)
        private ExampleAppClient AppClient { get; set; }

        # region "Construction"
        public ExampleApp()
        {
            // Instantiate the example application
            CustomApp = new CustomApplication(
                name: "Example Application 1",
                applicationType: "Example App",
                description: "Example application for Veza integration"
            );

            // Define an "uncategorized" permission for the example application
            // This can be used to group permissions that do not fit into another category,
            // or if the application API does not provide permission information
            CustomApp.AddCustomPermission(
                name: "Uncategorized",
                permissions: new List<Permission> { Permission.Uncategorized }
            );

            // define custom properties for the example application
            DefineCustomProperties();

            // Set the application icon for the Veza UI
            // This should be a base64-encoded SVG or PNG image
            LogoBase64 = "abc123...def987654"
        }

        /// <summary>
        /// Define custom properties for the example application.
        /// This method is called by the constructor to define any custom properties
        /// that the example application entities may have.
        /// </summary>
        private void DefineCustomProperties()
        {
            CustomApp.DefinedProperties[typeof(User)].
                DefineProperty("locked_out", typeof(bool);
            CustomApp.DefinedProperties[typeof(Group)].
                DefineProperty("type", typeof(string));
            CustomApp.DefinedProperties[typeof(Role)].
                DefineProperty("system_id", typeof(int));
            CustomApp.DefineResourceProperty("site_id", typeof(int)), "widget");
        }

        # endregion

        # region "Discovery"
        // Individual methods for discovering users, groups, roles, and resources.
        // Should be scoped as private to ensure that they are called only by the Discover method
        // and not directly by the client application.

        /// <summary>
        /// Discover users for the example application.
        /// This method is called by the Discover method to discover users for the example application.
        /// </summary>
        private void DiscoverUsers()
        {
            Logger.Info("Discovering users for the example application");

            // Get users from the example application client.
            // In this example, the GetUsers method returns a list of dictionaries of user data.
            List<Dictionary<string, string>> users = AppClient.GetUsers();

            // Iterate over the users response and add them to the application payload
            foreach (Dictionary<string, string> u in users)
            {
                // Create a new user object and add it to the application payload
                User user = CustomApp.AddUser(name: u["username"]);
                user.AddIdentity(u["email"]);
                user.IsActive = u["active"];
                user.CreatedAt = u["created_at"];
            }

            Logger.Info("User discovery complete");
        }

        /// <summary>
        /// Discover groups for the example application.
        /// This method is called by the Discover method to discover groups for the example application.
        /// </summary>
        private void DiscoverGroups()
        {
            Logger.Info("Discovering groups for the example application");

            // Get groups from the example application client
            // in this example, the GetGroups method returns a list of AppGroup objects
            List<AppGroup> groups = AppClient.GetGroups();

            // Iterate over the groups response and add them to the application payload
            foreach (AppGroup g in groups)
            {
                // Create a new group object and add it to the application payload
                Group group = CustomApp.AddGroup(name: g.Name);
                group.CreatedAt = g.CreatedAt;
                group.SetProperty(name: "type", value: g.Type);

                // Iterate users in the group and add them to the group
                foreach (string user in g.Users)
                {
                    CustomApp.Users[user].AddGroup(g.Name);
                }
            }

            Logger.Info("Group discovery complete");
        }

        /// <summary>
        /// Discover resources for the example application.
        /// This method is called by the Discover method to discover resources for the example application.
        /// </summary>
        private void DiscoverResources()
        {
            Logger.Info("Discovering resources for the example application");

            // Get resources from the example application
            // In this example, the GetResources method returns a list of AppResource objects
            List<AppResource> resources = AppClient.GetResources();
            foreach (AppResource r in resources)
            {
                // Create a resource object and add it to the application payload
                Resource resource = CustomApp.AddResource(name: r.Name, resourceType: r.ResourceType);

                // Set the `site_id` property for the resource if the resource is a "widget"
                // Cstom resource properties are defined per-resource type, so non-"widget" resources will not have this property
                if (r.ResourceType == "widget")
                {
                    resource.SetProperty(name: "site_id", value: r.SiteId);
                }
            }

            Logger.Info("Resource discovery complete");
        }

        /// <summary>
        /// Discover roles for the example application.
        /// This method is called by the Discover method to discover roles for the example application.
        /// </summary>
        private void DiscoverRoles()
        {
            Logger.Info("Discovering roles for the example application");

            // get roles from the example application
            // in this example, the GetRoles method returns a list of AppRole objects
            List<AppRole> roles = AppClient.GetRoles();
            foreach (Role role in roles)
            {
                // create a new role object and add it to the application payload
                Role role = CustomApp.AddRole(name: role.Name);
                role.CreatedAt = role.CreatedAt;
                role.SetProperty(name: "system_id", value: role.SystemId);

                // iterate users in the role and add them to the role
                // set the applyToApplication flag to true to apply the role to the entire application
                foreach (string user in role.Users)
                {
                    CustomApp.Users[user].AddRole(name: role.Name, applyToApplication: true);
                }
                Application.AddRole(role);
            }

            Logger.Info("Role discovery complete");
        }

        # endregion

        # region "Execution"

        /// <summary>
        /// Discover the example application.
        /// This method is called by the Run method to discover the example application.
        /// It serves as a place to instantiate a client for the example application API
        /// and then call each of the discovery methods required to build the application payload.
        /// </summary>
        /// <param name="exampleApiKey">The API key for the example application API</param>
        /// <param name="exampleUrl">The URL for the example application API</param>
        /// <returns></returns>
        public void Discover(string exampleApiKey, string exampleUrl)
        {
            // instantiate an API client for the example application
            AppClient = new ExampleAppClient(exampleApiKey, exampleUrl);

            Logger.Info("Beginning example application discovery");

            // discover the example application components
            DiscoverUsers();
            DiscoverGroups();
            DiscoverResources();
            DiscoverRoles();

            Logger.Info("Example application discovery complete");
        }

        /// <summary>
        /// Handle integration execution.
        /// This is separated from the Main method to more easily adapt to changes
        /// to application execution (e.g. from Command Prompt, as part of another application, etc.)
        /// </summary>
        /// <param name="exampleApiKey">The API key for the Example application API</param>
        /// <param name="exampleUrl">The URL for the Example application API</param>
        /// <param name="vezaApiKey">The API key for the Veza tenant</param>
        /// <param name="vezaUrl">The URL for the Veza tenant</param>
        /// <returns></returns>
        public async Task Run(
            string exampleApiKey,
            string exampleUrl,
            string vezaApiKey,
            string vezaUrl
        )
        {
            Logger.Info("Starting example application discovery");

            // Instantiate a connection to the Veza API.
            // The client will attempt to reach the Veza API and throw an exception if it fails.
            // This is to ensure that the Veza API is reachable before attempting to discover and push data.
            try
            {
                OAAClient oaaClient = new(vezaApiKey, vezaUrl);
            }
            catch (ClientException e)
            {
                Logger.Error("Failed to connect to Veza API: {0}", e.Message);
                return;
            }

            // Discover the example application
            Discover(exampleApiKey, exampleUrl);

            // Get or create the Veza provider for the payload
            Logger.Debug("Checking Veza for an existing provider for the example application");
            Sdk.Client.ApiClient.VezaApiResponse providerResponse = await oaaClient.GetProvider(ProviderName);

            // Create the provider if none exists
            if (providerResponse is null)
            {
                Logger.Info("No Veza provider exists; creating provider");
                await oaaClient.CreateProvider(ProviderName, "application", base64_icon: LogoBase64);
            }

            // Push OAA payload to Veza
            Logger.Info("Pushing example application metadata to Veza");
            RestResponse<Sdk.Client.ApiClient.VezaApiResponse> pushResponse = await oaaClient.PushApplication(ProviderName, Environment.MachineName, CustomApp, save_json: true);
            if (pushResponse.IsSuccessful)
            {
                Logger.Info("Example application discovery complete");
            } else
            {
                Logger.Error($"Push response code: {pushResponse.StatusCode}");
                Logger.Error($"Push response content: {pushResponse.Content}");
            }
        }

        # endregion
    }
}

Sample Apps

Usage examples for the oaaclient Python SDK

To run the code, you will need to export environment variables for the Veza URL, user and API keys, for example:

Sample Application

The most common OAA use case is modeling local identities, data sources, and permissions within an application containing sensitive information such as a database, ticket desk, or SCM platform. This sample app uses the CustomApplication class to create an OAA payload for a typical application that includes users, groups, roles and resources.

Sample Identity Provider

Customers that implement a custom Identity Provider (or one that doesn't have a native Veza integration) can use the OAA Custom IdP template to describe federated users and groups. This sample app generates a custom payload containing users, groups, and identity metadata, using the CustomIdPProvider class.

The example also demonstrates OAA support for AWS role entitlements, for scenarios where users can assume AWS roles in ways that can't be discovered by Veza's native AWS integration.

Sample IdP from CSV input

Sample app for importing Custom Identity Provider users from a CSV file.

This example can be used as a simple starting point for an OAA data source importer. Demonstrates use of CustomIdPProvider to create IdP users and assign properties using an input file with with the column headings:

identity,name,full_name,is_active,is_guest,manager_id

IdPImportCSV.py

Utils

oaaclient utility functions.

Copyright 2022 Veza Technologies Inc.

Use of this source code is governed by the MIT license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.

helper functions commonly used by OAA integrations


function log_arg_error

Helper function for logging errors when loading parameters

Helper function used to create consistent messages in connectors when required parameters can be set at command line or as environment variables.

Message can include information on parameter and/or environment variable but must provide one.

Args:

  • log (object): logging facility object to log to

  • arg (str, optional): Command line option for parameter such as --veza-url. Defaults to None.

  • env (str, optional): OS Environment variable for parameter such as VEZA_URL. Defaults to None.

Raises:

  • Exception: if neither arg or env are supplied


function load_json_from_file

Load JSON from file

Args:

  • json_path (str): path to JSON file on disk

Raises:

  • Exception: Unable to process JSON

  • Exception: Error reading JSON file

Returns:

  • dict: JSON decoded to dictionary


function encode_icon_file

read an icon file to a base64 encoded string

Args:

  • icon_path (str): Path to icon file on disk

Returns:

  • str: base64 encoding of file


function exists_in_query_array


function build_report

Creates or updates a Veza report from a dictionary

Creates a report and containing queries from a dictionary definition. Function will create any queries it does not find based on name. If a query with the same name already exists the existing query will be added to the report.

If a report already exists with the same name any missing queries will be added to the report.

report_definition must be a dictionary with name for the report and queries list of Veza query definitions:

{"name": "My Report", "queries": [{..},{...}]}

Args:

  • veza_con (OAAClient): OAAClient connection to make Veza API calls

  • report_definition (dict): Report definition

Raises:

  • ValueError: Missing name or queries key

Returns:

  • dict: API response from Report creation or update


function truncate_string

Helper function to truncate strings

Helper function to truncate strings to conform to maximum length requirements for templates.

Returns a string that is the first N bytes of the source string

Args:

  • source_str (str): Source string to truncate

  • length (int, optional): Length to shorten to. Defaults to 256.

Returns:

  • str: truncated string


Example Connectors

Open Authorization API usage examples

The official Veza connectors are useful references for understanding the decisions and strategies that come into play when building a custom Open Authorization API (OAA) integration.

Veza provides working connectors and source code for:

  • GitHub

  • GitLab

  • Jira

  • Looker

  • PagerDuty

  • Zendesk

Client

Classes for calling Veza APIs and managing OAA providers and data sources.

Copyright 2022 Veza Technologies Inc.

Use of this source code is governed by the MIT license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.

Global Variables


  • OAACLIENT_VERSION

  • PROVIDER_ICON_MAX_SIZE


function report_builder_entrypoint

Entry point for oaaclient-report-builder command

Reads a JSON file and passes it to the oaaclient.utils.build_report method


function main


class OAAClientError

Error raised by OAAClient.

Raised for issues connecting to the OAA API and when the API returns an error.

Args:

  • error (str): short string for error message

  • message (str): detailed error message

  • status_code (int, optional): status code for HTTP related errors. Defaults to None.

  • details (list, optional): list of additional details for error. Defaults to None.

method __init__


class OAAResponseError

Error returned from API Call

method __init__


class OAAConnectionError

Error with API Connection

method __init__


class OAAClient

Class for OAA API Connection and Management.

Utilities for OAA-related operations with Veza API calls. Manages custom providers and data sources, and can push OAA payloads from JSON or template objects.

Connection url and API key can be automatically loaded from OS environment values if set. To utilize environment variables initialize OAAClient without providing a URL or API key value and set the VEZA_URL and VEZA_API_KEY OS environment variables.

Args:

  • url (str, optional): URL for Veza instance.

  • api_key (str, optional): Veza API key.

  • username (str, optional): Not used (legacy). Defaults to None.

  • token (str, optional): Legacy parameter name for API key. Defaults to None.

Attributes:

  • url (str): URL of the Veza instance to connect to

  • api_key (str): Veza API key

  • enable_compression (bool): Enable or disable compression of the OAA payload during push, defaults to enabled (True)

Raises:

  • OAAClientError: For errors connecting to API and if API returns errors

method __init__


method add_query_report

Add a Query to a Report

Adds a Query to an existing Report by ID

Args:

  • report_id (str): Report UUID to add Query to

  • query_id (str): Query UUID to add

Returns:

  • dict: API Response


method api_delete

Perform REST API DELETE operation.

Args:

  • api_path (str): API Path API path relative to Veza URL

Raises:

  • OAAResponseError: API returned an error

  • OAAConnectionError: Connection error during HTTP operation

Returns:

  • dict: API response from call


method api_get

Perform a Veza API GET operation.

Makes the GET API call to the given path and processes the API response. Returns the value or values result returned from the API.

  • For API endpoints that return a list like /api/v1/providers/custom function will return a list of entities or an empty list if the API returns no results.

  • For API endpoints that are a specific ID such as /api/v1/providers/custom/<uuid> function will return the dictionary result of the JSON returned by the API.

Args:

  • api_path (str): API path relative to Veza URL (example /api/v1/providers).

Raises:

  • OAAResponseError: API returned an error

  • OAAConnectionError: Connection error during HTTP operation

Returns:

  • list|dict: Returns list or dict based on API destination


method api_patch

Perform REST API PATCH operation.

Args:

  • api_path (str): API Path API path relative to Veza URL

Raises:

  • OAAResponseError: API returned an error

  • OAAConnectionError: Connection error during HTTP operation

Returns:

  • dict: API response from call


method api_post

Perform a Veza API POST operation.

Call POST on the supplied Veza instance API path, submitting a data payload.

Returns value or values response from API result. Paginated responses are automatically processed to collect all responses a single list.

Args:

  • api_path (str): API path relative to Veza URL example /api/v1/providers

  • data (dict): dictionary object included as JSON in body of POST operation

  • params (dict, optional): Optional HTTP query parameters. Defaults to empty dictionary.

Raises:

  • OAAResponseError: API returned an error

  • OAAConnectionError: Connection error during HTTP operation

Returns:

  • dict: API response as dictionary


method api_put

Perform Veza API PUT operation.

Call PUT on the supplied Veza instance API path, including the data payload.

Returns value or values response from API result. Paginated responses are automatically processed to collect all responses a single list.

Args:

  • api_path (str): API path relative to Veza URL example /api/v1/providers

  • data (dict): dictionary object included as JSON in body of PUT operation

  • params (dict, optional): Optional HTTP query parameters. Defaults to empty dictionary.

Raises:

  • OAAResponseError: API returned an error

  • OAAConnectionError: Connection error during HTTP operation

Returns:

  • dict: API response as dictionary


method create_data_source

Create a new Data Source for the given Provider ID.

Args:

  • name (str): Name for new Data Source

  • provider_id (str): Unique identifier for the Provider

  • options: (dict, optional): Additional arguments to be included with data source create call to Veza. Defaults to None.

Raises:

  • ValueError: Data source name contains invalid characters

Returns:

  • dict: dictionary of new Data Source


method create_datasource

Deprecated Legacy function for backward-compatibility.


method create_provider

Create a new Provider.

Creates a new Provider with the given name. An error will be raised for naming conflicts.

Args:

  • name (str): new Provider name

  • custom_template (str): the OAA template to use for the Provider ("application" or "identity_provider")

  • base64_icon (str, optional): Base64 encoded string of icon to set for Provider. Defaults to "".

  • options: (dict, optional): Additional arguments to be included with provider create call to Veza. Defaults to None.

Raises:

  • ValueError: Provider name contains invalid characters

Returns:

  • dict: dictionary representing the created Provider


method create_query

Create a new Assessment Query

For details on how to define an Assessment Query see the Veza docs.

Args:

  • query (dict): Query definition

Returns:

  • dict: API response including ID of created Query


method create_report

Create a new Report

For details on how to define a new Report see the Veza docs.

Args:

  • report (dict): Report definition

Returns:

  • dict: API response including ID of created Report


method delete_data_source

Delete an existing Data Source by ID.

Removes a Data Source and all entity data.

Args:

  • data_source_id (str): ID of Data Source to delete

  • provider_id (str): ID of Data Source Provider

Returns:

  • dict: API response


method delete_provider

Delete an existing provider by ID.

Deleting a provider removes all datasources and historical data. Fully deleting the provider is a background operation that will complete after API response is returned.

Args:

  • provider_id (str): ID of provider to delete

Returns:

  • dict: API response


method delete_query

Delete an Assessment Query by ID

Args:

  • id (str): UUID of Query to delete

  • force (bool): Force deletion of query that may be part of a report. Defaults to False

Returns:

  • dict: API response from delete


method delete_report

Delete Report by ID

Args:

  • id (str): UUID of Report to delete

Returns:

  • dict: API response


method get_data_source

Get Provider's Data Source by name.

Find a Data Source from a specific provider based on the name of the Data Source

Args:

  • name (str): Data Source name

  • provider_id (str): Provider unique ID

Returns:

  • dict: Data Source as dict or None


method get_data_sources

Get Data Sources for Provider by ID.

Get the list of existing Data Sources, filtered by Provider UUID.

Args:

  • provider_id (str): ID of Provider

Returns:

  • list[dict]: List of Data Sources as dictionaries


method get_provider

Get Provider by name.

Args:

  • name (str): name of Provider

Returns:

  • dict: dictionary representing Provider or None


method get_provider_by_id

Get Provider by UUID identifier.

Args:

  • provider_id (str): Unique global identifier for provider

Returns:

  • dict: dictionary representation of Provider or None


method get_provider_list

Return list of Providers.

Returns:

  • list[dict]: Returns a list of existing Providers as dictionaries


method get_queries

Get all saved Assessment Queries

Veza can filter out queries that include inactive entity types (e.g. Okta Users on a system without Okta configured). To only retrieve queries that include active entity types set include_inactive_queries to False.

Args:

  • include_inactive_queries (bool): Set False to exclude inactive queries from result. Defaults to True.

Returns:

  • list: List of assessment Queries as dictionaries


method get_query_by_id

Get Assessment Query by ID

Args:

  • id (str): UUID identifier for Query

Returns:

  • dict: Query definition


method get_report_by_id

Get Report by ID

Veza can filter out queries from reports that only contain entity types that are not configured (e.g. Okta Users on a system without Okta configured). To only return queries configured on the report that match entity types configured on the system set include_inactive_queries to False

Args:

  • id (str): UUID of Report to get

  • include_inactive_queries (bool): Set True to include inactive queries. Default True.

Returns:

  • dict: Report definition


method get_reports

Get all Reports

Gets Reports created on the system. To get all reports include_inactive_reports and include_inactive_queries must be set to True.

Args:

  • include_inactive_reports (bool, Optional): Set to True to include reports that contain no active providers, defaults to True.

  • include_inactive_queries (bool, Optional): Set to True to include reports that contain only inactive queries, defaults to True.

Returns:

  • list[dict]: List of Reports as dictionary objects


method push_application

Push an OAA Application Object (such as CustomApplication).

Extracts the OAA JSON payload from the supplied OAA class (e.g. CustomApplication, CustomIdPProvider, etc) and push to the supplied Data Source.

The Provider with provider_name must be a valid existing Provider or create_provider must be set to True. A new data source will be created automatically by default if it does not already exist.

For logging, and debugging, the optional save_json flag writes the payload to a local file (before push). Output file name is formatted with a timestamp: {data source name}-{%Y%m%d-%H%M%S}.json

Args:

  • provider_name (str): Name of an existing Provider.

  • data_source_name (str): Name for Data Source (will be created if it doesn't exist).

  • application_object (Class): OAA object to extract the payload from

  • save_json (bool, optional): Save the JSON payload to a local file before push. Defaults to False.

  • create_provider (bool, optional): Create a new Provider if Provider does not already exists. Defaults to False.

  • options (dict, optional): Additional dictionary of key/values to be included in push API call. Defaults to None.

Raises:

  • OAAClientError: If any API call returns an error (including errors processing the OAA payload).

Returns:

  • dict: API response from push, including any warnings that are returned.


method push_metadata

Push an OAA payload dictionary to Veza.

Publishes the supplied metadata dictionary representing an OAA payload to the specified provider and data source. The function will create a new data source if it does not already exist, but requires the Provider be created ahead of time.

Args:

  • provider_name (str): Name of existing Provider

  • data_source_name (str): Name for Data Source, will be created if doesn't exist.

  • metadata (dict): Dictionary of OAA payload to push.

  • save_json (bool, optional): Save the OAA JSON payload to a local file before push. Defaults to False.

  • options (dict, optional): Additional dictionary of key/values to be included in push API call. Defaults to None.

Raises:

  • OAAClientError: If any API call returns an error including errors processing the OAA payload.

Returns:

  • dict: API response to the push request (including any warnings).


method update_provider_icon

Update an existing custom provider icon from base64 encoded string.

To load an icon from file, use utils.encode_icon_file to get the base64 encoding of the file first

Args:

  • provider_id (str): unique ID of existing provider

  • base64_icon (str): base64 encoded string of new icon

Raises:

  • ValueError: If icon size exceeds maximum allowed size


method update_report

Update an existing report

Args:

  • report_id (str): UUID of Report to updated

  • report (dict): Updated Report definition

Returns:

  • dict: API response


method update_user_agent

Updates the User-Agent string passed with all API calls

Generates a User-Agent with the oaaclient version, Python version and platform information.

The optional extra string will be appended if provided.

Args:

  • extra (str, optional): Additional information to append to User-Agent string. Defaults to "".


class OAARetry

Super class for urllib3.util.retry

Super class to allow modifying the default max backoff time from 120 seconds to our own value

Args:

  • Retry (type): description

method __init__


contain property_values validated against the custom_property_definition

Contains zero or more local users (see ).

Contains zero or more (collections of users).

Defines permissions for any within the application.

Contains any and sub-resources.

See .

list of any memberships as strings. Must exist in local groups.

See .

array

See .

When true, enables operations (optional).

Up to 5 attributes to apply to the domain (deprecated, use instead)

list

For , the operation to use.

list

Up to 5 attributes to apply to the user (deprecated, use instead)

If the same as another user's identity, that user will be recommended for reviews. Entity details for the user will be updated on push to include the manager as a searchable property.

array

For , the operation to use (optional).

Any to create and apply to the group.

Up to 5 attributes to apply to the domain. (deprecated, use instead)

For , the operation to use (optional).

Any to create and apply to the group.

For , the operation to use (optional).

For , the operation to use.

This document provides a basic overview of the API requests for creating and updating an OAA data source. These steps and can be adapted for your client or programming language of choice. You can also use the oaaclient Python module to handle Veza authentication, register the data source, and push the populated template.

While registering sources and pushing authorization metadata with is relatively straightforward, it is important to understand how Veza organizes custom providers and data sources as endpoints:

You will first register a new custom application provider with a (specifying the app name and template).

The determines the application type of the provider's custom data sources (identity_provider or application).

Each custom provider can have one or more data sources (such as different instances or domains), generated using .

You can for each custom data source.

All custom data sources are shown on the Configuration > Apps & Data Sources menu, and can be retrieved using .

You should typically name the provider based on the generic application provider (such as GitHub) and the data source after the top-level instance (such as GitHub - Organization). See the for more information about parsing and identifying entities using metadata from the source application.

Your requests will need to include a Veza API Key. For OAA APIs, using a is recommended. Provide it as the bearer auth token in the header of each request, for example:

Use to register a new top-level custom provider:

Each provider needs at least one data source. Create one with

Once the data source and provider are active, publish the payload with . The request body must include the Provider ID and Data Source ID.

Specifying the Provider ID and Data Source ID, perform the same used for the initial push.

To update an existing data source, use the operations and operations to get the provider and data source IDs.

You can download the Veza C# SDK from .

The Veza package provides data models, methods, and helpers for using the . It provides helper methods to populate OAA templates for custom applications, filesystems, HRIS systems, and identity providers, and push the payloads to Veza. The SDK can also be used as a generic Veza API client.

See the directory for full examples.

For additional information about developing a custom OAA integration, please see section of the User Guide.

: Classes for calling Veza APIs and managing OAA providers and data sources.

: Classes for constructing an OAA JSON payload (Custom "Application" or "IdP").

: oaaclient utility functions.

: OAA API Connection and Management.

: Error raised by OAAClient.

: Base class for CustomApplication.

: Model for defining custom properties for application and its entities (users, groups, roles, resources).

: Class for modeling application authorization using the OAA Application template.

: Domain model for Custom IdP provider.

: Group model for CustomIdPProvider.

: CustomIdPProvider class for modeling Identity Providers (IdP) using OAA Custom Identity Provider Template.

: User model for CustomIdPProvider.

: CustomPermission class for defining CustomApplication permissions.

: Class for resources and sub-resources.

: IdP entity types.

: IdP identity derived from Identity base class.

: Model for defining custom properties for CustomIdPProvider and its entities (users, groups, domain).

: Veza supported IdP provider types.

: Base class for deriving all identity types (should not be used directly).

: LocalGroup identity.

: Represent a Custom Application Local Role.

: LocalUser identity, derived from Identity base class.

: Types of identities for permission mapping.

: Canonical permissions used by Veza Authorization Framework.

: Supported types for custom properties on OAA entities such as application, resource, and identity.

: General exception used for violations of the template schema.

: Base class for CustomProvider.

: Veza tag data model.

: Helper function to simplify appending.

: Returns a list of unique strings from input list case insensitive

: read an icon file to a base64 encoded string

: Load JSON from file

: Helper function for logging errors when loading parameters

Update the Provider Name, App Type, and Application Name based on the source system. These values will typically be set to the product name. The data source name must be unique - check that an appropriate distinguishing value such as hostname is included in the data source name. For more information on naming, see

Define any needed in the __init__ method. Properties must be defined on the CustomApplication entities before setting them.

Implement the discovery steps for the discover() function to collect Users, Groups, Roles, and any resources for the application. As the entities are discovered, add them to the CustomApplication object using the appropriate .

oaaclient can be downloaded from , or installed with pip3 install oaaclient.

The `oaaclient` package provides data models, methods and a command-line interface for using the . You can use it to populate OAA templates including as Application, IdP, and HRIS, pushing OAA data to Veza and even as a general Veza API client.

For example usage, please see and the directory.

See the directory for complete examples.

Connector source code and oaaclient are thoroughly annotated, for reference when building your own integrations.

For additional information about developing a custom OAA integration, please see section of the User Guide.

Define any needed. Properties must be defined on the CustomApplication object before their values are set on any entities.

The examples on this page can be used as a starting point for building new connectors for custom applications. You should also refer to the current list of for real-world examples, and to check if an integration already exists for your use case.

sample-app.py
sample-idp.py

Each connector is similar in basic function, yet adapts to the resource hierarchies and interfaces unique to the technology provider. Each uses the Python package to construct a payload, create a custom provider and data source, and publish the extracted metadata.

See the for setup instructions and the most recent releases. The repository also includes sample applications demonstrating basic oaaclient usage. You can also browse these examples in the .

Custom Properties
Custom Properties
Custom Properties
Custom Properties
Custom Property Definition
incremental update
Custom Properties
custom properties
Veza Tags
incremental updates
Veza Tags
custom properties
Custom Properties
governance
incremental updates
tags
Custom Properties
custom properties
incremental updates
Custom Properties
tags
incremental updates
Custom Properties
incremental updates
API calls
Open Authorization API
template
Core Concepts
GitHub
Open Authorization API
quickstarts
Open Authorization API
Providers, Data Sources, Names and Types
custom properties
SDK operations
GitHub
Open Authorization API
modules
samples
GitHub quickstarts
modules
Open Authorization API
custom_properties
local_identities
local groups
roles
resources
Resource Connections
group
tags
IdP Domain
IdP Users
IdP Group
Identity Mapping Configuration
Entities Owned
Source Identity
POST request to /api/providers/custom
Create Datasource
push authorization metadata
List Custom Provider Datasources
Create Custom Provider
Create Custom Provider Datasource
Push Custom Provider Datasource
post operation
List Provider
List Datasources
templates
templates.Application
templates.ApplicationPropertyDefinitions
templates.CustomApplication
templates.CustomIdPDomain
templates.CustomIdPGroup
templates.CustomIdPProvider
templates.CustomIdPUser
templates.CustomPermission
templates.CustomResource
templates.IdPEntityType
templates.IdPIdentity
templates.IdPPropertyDefinitions
templates.IdPProviderType
templates.Identity
templates.LocalGroup
templates.LocalRole
templates.LocalUser
templates.OAAIdentityType
templates.OAAPermission
templates.OAAPropertyType
templates.OAATemplateException
templates.Provider
templates.Tag
templates.append_helper
templates.unique_strs
export OAA_TOKEN="xxxxxxx"
export VEZA_URL="https://myveza.vezacloud.com"
./sample-app.py
#!env python3
"""
Copyright 2022 Veza Technologies Inc.

Use of this source code is governed by the MIT
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.

Example of using the `CustomApplication` class to model a typical application where users and groups are assigned
permissions to the application or resources.

If you want to run the code you will need to export environment variables for the Veza URL, user and API keys.

```
export OAA_TOKEN="xxxxxxx"
export VEZA_URL="https://myveza.vezacloud.com"
./sample-app.py
```

"""

from oaaclient.client import OAAClient, OAAClientError
from oaaclient.templates import CustomApplication, OAAPermission
import os
import sys


def main():

    # OAA requires an API token, which you can generate from your Veza user profile
    # Export the API token, and Veza URL as environment variables
    # Making them available to your connector in this way keeps credentials out of the source code
    veza_api_key = os.getenv('VEZA_API_KEY')
    veza_url = os.getenv('VEZA_URL')
    if None in (veza_url, veza_api_key):
        print("Unable to local all environment variables")
        sys.exit(1)

    # Instantiates a client connection. The client will confirm the credentials and Veza URL are valid
    # Checking this early helps prevents connection failures in the final stage
    veza_con = OAAClient(url=veza_url, api_key=veza_api_key)

    # Create an instance of the OAA CustomApplication class, modeling the application name and type
    # `name` will be displayed in the Veza UI
    # `application_type` should be a short key reflecting the source application authorization is being modeled for
    # You can use the same type for multiple applications
    custom_app = CustomApplication(name="Sample App", application_type="sample")

    # In the OAA payload, each permission native to the custom app is mapped to the Veza effective permission (data/nondata C/R/U/D).
    # Permissions must be defined before they can be referenced, as they are discovered or ahead of time.
    # For each custom application permission, bind them to the Veza permissions using the `OAAPermission` enum:
    custom_app.add_custom_permission("admin", [OAAPermission.DataRead, OAAPermission.DataWrite])
    custom_app.add_custom_permission("operator", [OAAPermission.DataRead])

    # Create resources and sub-resource to model the entities in the application
    # To Veza, an application can be a single entity or can contain resources and sub-resources
    # Utilizing resources enables tracking of authorizations to specific components of the system being modeled
    # Setting a `resource_type` can help group entities of the same type for reporting/queries
    entity1 = custom_app.add_resource(name="Entity1", resource_type="thing", description="Some entity in the application")
    entity2 = custom_app.add_resource(name="Entity2", resource_type="thing", description="Another entity in the application")
    other = custom_app.add_resource(name="Other", resource_type="other", description="Something totally different")

    # Sub-resources can be added to any resource (including other sub-resources)
    child1 = entity1.add_sub_resource(name="Child 1", resource_type="child", description="My information about resource")
    child1.add_sub_resource(name="Grandchild 1", resource_type="grandchild", description="My information about resource")

    # Any users and groups local to the application can be defined.
    # IdP users can be mapped directly without defining them in the OAA application (see below)
    custom_app.add_local_user("bob")
    # A local user can be associated with an IdP user by adding an identity to the user:
    custom_app.local_users["bob"].add_identity("bob@example.com")
    # Identities, groups and roles can be assigned to local users at creation or after (groups and roles must exist):
    jane = custom_app.add_local_user("jane", identities="jane@example.com")

    # when adding a user the new user is returned and can updated if needed, there are multiple built in properties that can be set for a user
    jane.is_active = False
    jane.created_at = "2022-01-26T20:48:12.460Z"

    # Define a local group and add a user to it
    custom_app.add_local_group("admins")
    custom_app.local_users["jane"].add_group("admins")

    # adding local users and groups requires that the name not already exist
    if "yan" not in custom_app.local_users:
        custom_app.add_local_user("yan")

    # For each Identity (user, group, IdP) assign permissions to the application or resource.
    # The identities (users, groups) permissions and resources must already be defined

    # To add a permission directly to the application use `apply_to_application=True`
    custom_app.local_users["bob"].add_permission(permission="operator", apply_to_application=True)
    custom_app.local_groups["admins"].add_permission(permission="admin",  apply_to_application=True)

    # You can describe specific permissions to individual resources or sub-resources:
    custom_app.local_users["yan"].add_permission(permission="operator", resources=[entity1, child1])

    # Authorization can also be created directly for an IdP identity
    custom_app.add_idp_identity("user_identity@example.com")
    # resources can also be referenced by name from the application model
    custom_app.idp_identities["user_identity@example.com"].add_permission(permission="admin", resources=[custom_app.resources['Entity1']])

    # Once all authorizations have been mapped, the final step is to publish the app to Veza
    # Connect to the API to Push to Veza, define the provider and create if necessary:

    provider_name = "Sample"
    provider = veza_con.get_provider(provider_name)
    if provider:
        print("-- Found existing provider")
    else:
        print(f"++ Creating Provider {provider_name}")
        provider = veza_con.create_provider(provider_name, "application")
    print(f"-- Provider: {provider['name']} ({provider['id']})")

    # Push the metadata payload:

    try:
        response = veza_con.push_application(provider_name,
                                               data_source_name=f"{custom_app.name} ({custom_app.application_type})",
                                               application_object=custom_app,
                                               save_json=False
                                               )
        if response.get("warnings", None):
            # Veza may return warnings on a successful uploads. These are informational warnings that did not stop the processing
            # of the OAA data but may be important. Specifically identities that cannot be resolved will be returned here.
            print("-- Push succeeded with warnings:")
            for e in response["warnings"]:
                print(f"  - {e}")
    except OAAClientError as e:
        print(f"-- Error: {e.error}: {e.message} ({e.status_code})", file=sys.stderr)
        if hasattr(e, "details"):
            for d in e.details:
                print(f"  -- {d}", file=sys.stderr)
    return


if __name__ == '__main__':
    main()
#!env python3
"""
Copyright 2022 Veza Technologies Inc.

Use of this source code is governed by the MIT
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.

Example of using the `CustomIdPProvider` class to model an identity provider as a source of users.

If you want to run the code you will need to export environment variables for the Veza URL, user and API keys.

```
export VEZA_API_KEY="xxxxxxx"
export VEZA_URL="https://myveza.vezacloud.com"
./sample-idp.py
```

Since the example includes fake AWS ARNs that Veza will not have discovered the expected output will
contain warning like "Cannot find IAM role by names ..."
"""

from oaaclient.client import OAAClient, OAAClientError
from oaaclient.templates import CustomIdPProvider, OAAPropertyType
import os
import sys


def main():

    # OAA requires a Veza API key, which you can generate from Administration > API Keys
    # Export the API key, and Veza URL as environment variables
    # Making them available to your connector in this way keeps credentials out of the source code
    veza_api_key = os.getenv("VEZA_API_KEY")
    veza_url = os.getenv("VEZA_URL")
    if not veza_api_key or not veza_url:
        print("Unable to load VEZA_API_KEY and VEZA_URL from OS")
        sys.exit(1)

    # Instantiates a client connection. The client will confirm the credentials and Veza URL are valid
    # Checking this early helps prevents connection failures in the final stage
    veza_con = OAAClient(url=veza_url, api_key=veza_api_key)

    # create a CustomIdPProvider to represent your IdP. This can be named generically or specific to the environment if you have
    # multiple namespaces to model. idp_type will typically be the technology/vendor for the provider.
    idp = CustomIdPProvider("My IdP", domain="example.com", idp_type="custom_idp")

    # add users to the idp, properties for users can be set during creation or updated after
    idp.add_user("mrichardson", full_name="Michelle Richardson", email="mrichardson@example.com")

    evargas_user = idp.add_user("evargas")
    evargas_user.full_name = "Elizabeth Vargas"
    evargas_user.email = "evargas@example.com"

    # users and groups can have optional identity property. The identity serves as the unique reference identifier across
    # Veza. If omitted CustomIdPProvider will automatically populate the identity with the name
    idp.add_user("willis", email="willis@example.com", identity="cwilliams")

    # OAA can support custom properties for users to track additional metadata unique to the environment
    # to use custom properties the property must first be defined and given a type, then can be set for the individual entity
    idp.property_definitions.define_user_property("region", OAAPropertyType.STRING)
    idp.property_definitions.define_user_property("is_contractor", OAAPropertyType.BOOLEAN)

    idp.users['willis'].set_property("region", "NorthAmerica")
    idp.users['willis'].set_property("is_contractor", True)

    # Create Groups
    idp.add_group("developers")
    idp.add_group("sec-ops")
    idp.add_group("everyone", full_name="All Company Employees")

    # users can be added to groups using the add_group function, users can be added to multiple groups in a single call
    for username in idp.users:
        idp.users[username].add_groups(["everyone"])

    evargas_user.add_groups(["developers", "sec-ops"])
    idp.users["mrichardson"].add_groups(["developers"])

    # Veza CustomIdP supports tracking the AWS Roles a user can assume. For users who can assume roles Veza can calculate
    # their effective permissions to AWS resources based on the role(s)
    # roles are added by ARN
    idp.users["mrichardson"].add_assumed_role_arns(["arn:aws:iam::123456789012:role/role001", "arn:aws:iam::123456789012:role/role002"])

    # After adding users and groups, the IdP information is pushed to Veza using the OAA API
    provider_name = "Sample-IdP"
    provider = veza_con.get_provider(provider_name)
    if provider:
        print("-- Found existing provider")
    else:
        print(f"++ Creating Provider {provider_name}")
        provider = veza_con.create_provider(provider_name, "identity_provider")
    print(f"-- Provider: {provider['name']} ({provider['id']})")

    # Push the metadata payload:
    try:
        response = veza_con.push_application(provider_name,
                                               data_source_name=f"{idp.name} ({idp.idp_type})",
                                               application_object=idp,
                                               save_json=True
                                               )
        if response.get("warnings", None):
            # Veza may return warnings on a successful uploads. These are informational warnings that did not stop the processing
            # of the OAA data but may be important, for example: AWS role ARNs assigned to users that Veza has not discovered
            print("-- Push succeeded with warnings:")
            for e in response["warnings"]:
                print(f"  - {e}")
    except OAAClientError as e:
        print(f"-- Error: {e.error}: {e.message} ({e.status_code})", file=sys.stderr)
        if hasattr(e, "details"):
            for d in e.details:
                print(f"  -- {d}", file=sys.stderr)


if __name__ == '__main__':
    main()
#!env python3
"""Example of using `oaaclient` to import users from a CSV file.

Reads user properties from the input file, populates an OAA payload,
and creates a new OAA identity provider containing the imported users.

Expected CSV headers are `identity,name,full_name,is_active,is_guest,manager_id`
Can be updated to match custom column headings or apply custom properties.

Example:
    ```
    export VEZA_URL=<Veza URL>
    export VEZA_API_KEY=<Veza API key>
    ./idp-importer-csv.py --provider MyIdpProvider --datasource MyDatasource  ./my-users.csv

    ```

Copyright 2022 Veza Technologies Inc.

Use of this source code is governed by the MIT
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.

"""

from oaaclient.client import OAAClient, OAAClientError
from oaaclient.templates import CustomIdPProvider
import click
import csv
import logging
import os
import sys


logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)
log = logging.getLogger()


def load_users(idp: CustomIdPProvider, source: str) -> None:
    """Populate the idp with user from the source csv file"""

    log.info(f"Loading users from {source}")
    with open(source) as f:
        for r in csv.DictReader(f):
            # get the identity, name, full_name and email
            try:
                identity = r["identity"]
                name = r["name"]
                full_name = r["full_name"]
                email = r["email"]
            except KeyError as e:
                log.error(f"Incorrect CSV column headers, missing column {e}")
                sys.exit(1)

            # create a new IDP user
            new_user = idp.add_user(name=name, full_name=full_name, email=email, identity=identity)

            # set the user to active and guest or not, look for strings like true/false or yes/no
            if r.get("active"):
                active_string = r["active"].lower()
                if active_string in ["true", "yes"]:
                    new_user.is_active = True
                elif active_string in ["false", "no"]:
                    new_user.is_active = False

            if r.get("is_guest"):
                guest_string = r["is_guest"].lower()
                if guest_string in ["true", "yes"]:
                    new_user.is_guest = True
                elif guest_string in ["false", "no"]:
                    new_user.is_guest = False

            # if the manager id column is filled in, set the new users manager
            if r.get("manager_id"):
                new_user.manager_id = r.get("manager_id")

    return

@click.command()
@click.option("--provider", required=True)
@click.option("--datasource", required=True)
@click.option("--save-json", is_flag=True)
@click.argument("file", required=True)
def main(provider, datasource, save_json, file):

    # load the Veza URL and API key from the environment
    veza_url = os.getenv("VEZA_URL")
    veza_api_key = os.getenv("VEZA_API_KEY")

    if not (veza_url or veza_api_key):
        log.error("Must set VEZA_URL and VEZA_API_KEY")
        sys.exit(1)

    try:
        log.info("Testing Veza credentials")
        veza_con = OAAClient(url=veza_url, api_key=veza_api_key)
    except OAAClientError as e:
        log.error("Unable to connect to Veza API")
        log.error(e)
        sys.exit(1)

    # create a new provider if the provider doesn't already exist
    if not veza_con.get_provider(provider):
        log.info(f"Creating new provider {provider}")
        veza_con.create_provider(provider, "identity_provider")

    # Configure the Custom IdP
    idp = CustomIdPProvider("Custom IdP", idp_type="custom_idp", domain="example.com", description=None)

    # load the user from
    load_users(idp, file)

    try:
        # push the IdP to Veza, log and errors or warnings
        log.info("Sending to Veza")
        response = veza_con.push_application(provider, datasource, idp, save_json=save_json)
        if response.get("warnings", None):
            log.warning("Push succeeded with warnings")
            for w in response['warnings']:
                log.warning(w)
        log.info("Success")
    except OAAClientError as e:
        log.error(f"Error during push {e.message} {e.status_code}")
        if e.details:
            log.error(e.details)
        sys.exit(1)

    return

if __name__ == "__main__":
    main()
community connectors
log_arg_error(log: object, arg: str = None, env: str = None) → None
load_json_from_file(json_path: str) → dict
encode_icon_file(icon_path: str) → str
exists_in_query_array(value_to_find, input_array) → bool
build_report(veza_con, report_definition: dict) → dict
truncate_string(source_str: str, length: int = 256) → str
utils
utils.encode_icon_file
utils.load_json_from_file
utils.log_arg_error
report_builder_entrypoint() → None
main()
__init__(
    error: 'str',
    message: 'str',
    status_code: 'int' = None,
    details: 'list' = None
) → None
__init__(*args, **kwargs)
__init__(
    error: 'str',
    message: 'str',
    status_code: 'int' = None,
    details: 'list' = None
) → None
__init__(
    url: 'str' = None,
    api_key: 'str' = None,
    username: 'str' = None,
    token: 'str' = None
)
add_query_report(report_id: 'str', query_id: 'str') → dict
api_delete(api_path: 'str', params: 'dict' = None) → dict
api_get(api_path: 'str', params: 'dict' = None) → list | dict
api_patch(api_path: 'str', data: 'dict', params: 'dict' = None) → dict
api_post(api_path: 'str', data: 'dict', params: 'dict' = None) → list | dict
api_put(api_path: 'str', data: 'dict', params: 'dict' = None) → list | dict
create_data_source(
    name: 'str',
    provider_id: 'str',
    options: 'dict | None' = None
) → dict
create_datasource(name, provider_id)
create_provider(
    name: 'str',
    custom_template: 'str',
    base64_icon: 'str' = '',
    options: 'dict | None' = None
) → dict
create_query(query: 'dict') → dict
create_report(report: 'dict') → dict
delete_data_source(data_source_id: 'str', provider_id: 'str') → dict
delete_provider(provider_id: 'str') → dict
delete_query(id: 'str', force: 'bool' = False) → dict
delete_report(id: 'str') → dict
get_data_source(name: 'str', provider_id: 'str') → dict
get_data_sources(provider_id: 'str') → list[dict]
get_provider(name: 'str') → dict
get_provider_by_id(provider_id: 'str') → dict
get_provider_list() → list[dict]
get_queries(include_inactive_queries: 'bool' = True) → list[dict]
get_query_by_id(id: 'str') → dict
get_report_by_id(id: 'str', include_inactive_queries: 'bool' = True) → dict
get_reports(
    include_inactive_reports: 'bool' = True,
    include_inactive_queries: 'bool' = True
) → list[dict]
push_application(
    provider_name: 'str',
    data_source_name: 'str',
    application_object: 'CustomApplication | CustomIdPProvider',
    save_json: 'bool' = False,
    create_provider: 'bool' = False,
    options: 'dict | None' = None
) → dict
push_metadata(
    provider_name: 'str',
    data_source_name: 'str',
    metadata: 'dict',
    save_json: 'bool' = False,
    options: 'dict | None' = None
) → dict
update_provider_icon(provider_id: 'str', base64_icon: 'str') → None
update_report(report_id: 'str', report: 'dict') → dict
update_user_agent(extra: 'str' = '') → None
__init__(backoff_max=30, **kwargs) → None
client
client.OAAClient
client.OAAClientError
client.main
Veza-supported connectors
oaaclient
GitHub repository
User Guide
Sample Application
Sample Identity Provider
Sample IdP from CSV file
Team API key
App Type Search
Application Example
Users example
Users example
PagerDuty App
GitLab App
get
Authorizations
Query parameters
filterstringOptional
order_bystringOptional
page_sizeinteger · int32Optional

The maximum number of results to be returned. Fewer results may be returned even when more pages exist.

page_tokenstringOptional

The token specifying the specific page of results to retrieve.

Responses
200
OK
application/json
default
Default error response
application/json
get
GET /api/v1/providers/custom HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{
  "values": [
    {
      "id": "text",
      "external_id": "text",
      "name": "text",
      "custom_template": "text",
      "custom_templates": [
        "text"
      ],
      "state": 1,
      "application_types": [
        "text"
      ],
      "idp_types": [
        "text"
      ],
      "file_system_types": [
        "text"
      ],
      "hris_types": [
        "text"
      ],
      "principal_types": [
        "text"
      ],
      "schema_definition_json": "text",
      "provisioning": true,
      "push_type": 1,
      "internal_app_name": "text",
      "configuration_json": "text",
      "data_plane_id": "text",
      "lifecycle_management_state": 1,
      "team_id": "text",
      "csv_mapping_configuration": {
        "template_type": "text",
        "column_mappings": [
          {
            "column_name": "text",
            "destination_type": "text",
            "destination_property": "text",
            "custom_property": {
              "name": "text",
              "type": 1
            },
            "as_list": true
          }
        ],
        "application": {
          "application_name": "text",
          "application_type": "text",
          "identity": [
            "text"
          ],
          "resource_type": "text"
        },
        "advanced": {
          "list_delimiter": "text"
        },
        "idp": {
          "idp_type": "text",
          "domain": "text"
        },
        "hris": {
          "hris_name": "text",
          "hris_type": "text",
          "hris_url": "text"
        }
      }
    }
  ],
  "next_page_token": "text",
  "has_more": true
}
get
Authorizations
Path parameters
idstringRequired
Responses
200
OK
application/json
default
Default error response
application/json
get
GET /api/v1/providers/custom/{id} HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{
  "value": {
    "id": "text",
    "external_id": "text",
    "name": "text",
    "custom_template": "text",
    "custom_templates": [
      "text"
    ],
    "state": 1,
    "application_types": [
      "text"
    ],
    "idp_types": [
      "text"
    ],
    "file_system_types": [
      "text"
    ],
    "hris_types": [
      "text"
    ],
    "principal_types": [
      "text"
    ],
    "schema_definition_json": "text",
    "provisioning": true,
    "push_type": 1,
    "internal_app_name": "text",
    "configuration_json": "text",
    "data_plane_id": "text",
    "lifecycle_management_state": 1,
    "team_id": "text",
    "csv_mapping_configuration": {
      "template_type": "text",
      "column_mappings": [
        {
          "column_name": "text",
          "destination_type": "text",
          "destination_property": "text",
          "custom_property": {
            "name": "text",
            "type": 1
          },
          "as_list": true
        }
      ],
      "application": {
        "application_name": "text",
        "application_type": "text",
        "identity": [
          "text"
        ],
        "resource_type": "text"
      },
      "advanced": {
        "list_delimiter": "text"
      },
      "idp": {
        "idp_type": "text",
        "domain": "text"
      },
      "hris": {
        "hris_name": "text",
        "hris_type": "text",
        "hris_url": "text"
      }
    }
  }
}
delete
Authorizations
Path parameters
idstringRequired
Responses
200
OK
application/json
Responseobject
default
Default error response
application/json
delete
DELETE /api/v1/providers/custom/{id} HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{}
get
Authorizations
Path parameters
idstringRequired
Query parameters
filterstringOptional
order_bystringOptional
page_sizeinteger · int32Optional

The maximum number of results to be returned. Fewer results may be returned even when more pages exist.

page_tokenstringOptional

The token specifying the specific page of results to retrieve.

Responses
200
OK
application/json
default
Default error response
application/json
get
GET /api/v1/providers/custom/{id}/datasources HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{
  "values": [
    {}
  ],
  "next_page_token": "text",
  "has_more": true
}
get
Authorizations
Path parameters
idstringRequired
data_source_idstringRequired
Responses
200
OK
application/json
default
Default error response
application/json
get
GET /api/v1/providers/custom/{id}/datasources/{data_source_id} HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{
  "value": {}
}
delete
Authorizations
Path parameters
idstringRequired
data_source_idstringRequired
Responses
200
OK
application/json
Responseobject
default
Default error response
application/json
delete
DELETE /api/v1/providers/custom/{id}/datasources/{data_source_id} HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{}
get
Authorizations
Path parameters
idstringRequired
Responses
200
OK
application/json
default
Default error response
application/json
get
GET /api/v1/providers/custom/{id}:icon HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{
  "mime_type": "text",
  "icon_base64": "text"
}
get
Authorizations
Query parameters
app_or_idp_typestringOptionalDeprecated
custom_schema_typestringOptional
node_typestringOptional
Responses
200
OK
application/json
default
Default error response
application/json
get
GET /api/v1/providers/custom:icon HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{
  "mime_type": "text",
  "icon_base64": "text",
  "provider_id": "text"
}
delete
Authorizations
Path parameters
idstringRequired
Responses
200
OK
application/json
Responseobject
default
Default error response
application/json
delete
DELETE /api/v1/providers/custom/{id}:icon HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Accept: */*
{}
post
Authorizations
Body
namestringOptional
custom_templatestringOptional
provisioningbooleanOptional
push_typeinteger · enumOptional
internal_app_namestringOptional
configuration_jsonstringOptional
data_plane_idstringOptional
custom_templatesstring[]Optional
Responses
200
OK
application/json
default
Default error response
application/json
post
POST /api/v1/providers/custom HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 645

{
  "name": "text",
  "custom_template": "text",
  "provisioning": true,
  "push_type": 1,
  "internal_app_name": "text",
  "configuration_json": "text",
  "data_plane_id": "text",
  "custom_templates": [
    "text"
  ],
  "csv_mapping_configuration": {
    "template_type": "text",
    "column_mappings": [
      {
        "column_name": "text",
        "destination_type": "text",
        "destination_property": "text",
        "custom_property": {
          "name": "text",
          "type": 1
        },
        "as_list": true
      }
    ],
    "application": {
      "application_name": "text",
      "application_type": "text",
      "identity": [
        "text"
      ],
      "resource_type": "text"
    },
    "advanced": {
      "list_delimiter": "text"
    },
    "idp": {
      "idp_type": "text",
      "domain": "text"
    },
    "hris": {
      "hris_name": "text",
      "hris_type": "text",
      "hris_url": "text"
    }
  }
}
{
  "value": {
    "id": "text",
    "external_id": "text",
    "name": "text",
    "custom_template": "text",
    "custom_templates": [
      "text"
    ],
    "state": 1,
    "application_types": [
      "text"
    ],
    "idp_types": [
      "text"
    ],
    "file_system_types": [
      "text"
    ],
    "hris_types": [
      "text"
    ],
    "principal_types": [
      "text"
    ],
    "schema_definition_json": "text",
    "provisioning": true,
    "push_type": 1,
    "internal_app_name": "text",
    "configuration_json": "text",
    "data_plane_id": "text",
    "lifecycle_management_state": 1,
    "team_id": "text",
    "csv_mapping_configuration": {
      "template_type": "text",
      "column_mappings": [
        {
          "column_name": "text",
          "destination_type": "text",
          "destination_property": "text",
          "custom_property": {
            "name": "text",
            "type": 1
          },
          "as_list": true
        }
      ],
      "application": {
        "application_name": "text",
        "application_type": "text",
        "identity": [
          "text"
        ],
        "resource_type": "text"
      },
      "advanced": {
        "list_delimiter": "text"
      },
      "idp": {
        "idp_type": "text",
        "domain": "text"
      },
      "hris": {
        "hris_name": "text",
        "hris_type": "text",
        "hris_url": "text"
      }
    }
  }
}
post
Authorizations
Path parameters
idstringRequired
Body
idstringOptional
namestringOptional
custom_templatestringOptional
Responses
200
OK
application/json
default
Default error response
application/json
post
POST /api/v1/providers/custom/{id}/datasources HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 52

{
  "id": "text",
  "name": "text",
  "custom_template": "text"
}
{
  "value": {
    "id": "text",
    "name": "text"
  }
}
post
Authorizations
Path parameters
idstringRequired
data_source_idstringRequired
Body
idstringOptional
data_source_idstringOptional
json_datastringOptional
compression_typeinteger · enumOptional
priority_pushbooleanOptional
Responses
200
OK
application/json
default
Default error response
application/json
post
POST /api/v1/providers/custom/{id}/datasources/{data_source_id}:push HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 98

{
  "id": "text",
  "data_source_id": "text",
  "json_data": "text",
  "compression_type": 1,
  "priority_push": true
}
{
  "warnings": [
    {
      "message": "text"
    }
  ]
}
post
Authorizations
Path parameters
idstringRequired
data_source_idstringRequired
Body
idstringOptional
data_source_idstringOptional
csv_datastringOptional
namestringOptional
typestringOptional
compression_typeinteger · enumOptional
priority_pushbooleanOptional
Responses
200
OK
application/json
default
Default error response
application/json
post
POST /api/v1/providers/custom/{id}/datasources/{data_source_id}:push_csv HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 125

{
  "id": "text",
  "data_source_id": "text",
  "csv_data": "text",
  "name": "text",
  "type": "text",
  "compression_type": 1,
  "priority_push": true
}
{
  "warnings": [
    {
      "message": "text"
    }
  ]
}
post
Authorizations
Path parameters
idstringRequired
data_source_idstringRequired
Body
idstringOptional
data_source_idstringOptional
json_datastringOptional
compression_typeinteger · enumOptional
priority_pushbooleanOptional
Responses
200
OK
application/json
default
Default error response
application/json
post
POST /api/v1/providers/custom/{id}/datasources/{data_source_id}:push HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 98

{
  "id": "text",
  "data_source_id": "text",
  "json_data": "text",
  "compression_type": 1,
  "priority_push": true
}
{
  "warnings": [
    {
      "message": "text"
    }
  ]
}
post
Authorizations
Path parameters
idstringRequired
data_source_idstringRequired
Body
idstringOptional
data_source_idstringOptional
csv_datastringOptional
namestringOptional
typestringOptional
compression_typeinteger · enumOptional
priority_pushbooleanOptional
Responses
200
OK
application/json
default
Default error response
application/json
post
POST /api/v1/providers/custom/{id}/datasources/{data_source_id}:push_csv HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 125

{
  "id": "text",
  "data_source_id": "text",
  "csv_data": "text",
  "name": "text",
  "type": "text",
  "compression_type": 1,
  "priority_push": true
}
{
  "warnings": [
    {
      "message": "text"
    }
  ]
}
post
Authorizations
Path parameters
idstringRequired
Body
idstringOptional
icon_base64stringOptional
Responses
200
OK
application/json
Responseobject
default
Default error response
application/json
post
POST /api/v1/providers/custom/{id}:icon HTTP/1.1
Host: 
Authorization: Bearer Bearer <API key>
Content-Type: application/json
Accept: */*
Content-Length: 34

{
  "id": "text",
  "icon_base64": "text"
}
{}