Configure a CSV Resource with Multiple CSV Files

Last modified 25 May 2026 15:03 +02:00

This guide explains how to configure a resource using the CSV connector that consists of two or more CSV files. Each file represents a group of objects with a distinct object type. The guide also shows how to define relationships between these object types.

This guide is designed to be followed from top to bottom. Each chapter builds on the previous one.
In addition to step-by-step instructions, this guide also includes an example of a complete configuration at the end, which you can refer to throughout the process.

Resource configuration

Prerequisites

Prepare a folder accessible from midPoint that contains the CSV files used by the resource. Each file represents one object type (e.g., one for users, another one for organizations).

A multi-file CSV resource should have one primary (main) file.

This file represents the primary object class (typically accounts) and is configured using the filePath property in the connector configuration.

Additional files defined in the object class definition file are treated as secondary object classes.

Create a definition file

To configure a CSV resource composed of multiple files, you need to define an additional object class (or multiple classes if you have more than two files). This is done using a simple text file (commonly with the .prop extension).

The primary object class is provided by the CSV connector by default. It represents the main CSV file and does not need to be explicitly defined in the additional object class definition file.

In the file, specify:

  • Paths to the additional resource files.

  • Key-value property pairs describing how each of the additional CSVs should be interpreted, prefixed by an arbitrary prefix that identifies the additional object class and the properties listed in the table below.
    Each entry in the file follows this format:

    <prefix>.<property>=<value>
    Property Type Description

    filePath

    string

    Path to the CSV file.

    fieldDelimiter

    string

    Delimiter used in the CSV file.

    uniqueAttribute

    string

    Column used as the unique identifier.

    nameAttribute

    string

    Column used as the object name.

    headerExists

    boolean

    Defines whether the CSV file contains a header row.

    trim

    boolean

    Defines whether whitespaces should be trimmed.

    container

    boolean

    Defines whether the object class should be treated as a standalone container object.

    auxiliary

    boolean

    Defines whether the object class should be treated as auxiliary. Auxiliary object classes are defined in addition to the primary object class and can be used to represent additional files in a multi-file CSV resource.

For a setup with multiple CSV files, configure the last two properties as follows:

  • container=true — So that it is treated as a standalone resource object.

  • auxiliary=true — Because it is defined in addition to the primary account object class.

The file is referenced from the CSV connector configuration using the objectClassDefinition property which will be set in a following section of the guide. This tells the CSV connector to load an additional object class definition from the specified file.

Additional object class names always start with Custom, then include the prefix used in the text file where the object class is defined, and end with ObjectClass.

For example, if your prefix is Org, the resulting name will be:

CustomOrgObjectClass

Create a CSV resource in midPoint

Create a new resource using the CSV connector. For a detailed guide, see the Create a New Resource tutorial. Use your primary CSV as the source file during setup.

In your resource, click Edit raw, and in the connector configuration, i.e., in the connectorConfiguration of the resource XML, set the cfg:objectClassDefinition property. This makes sure midPoint loads the additional object class definition from the file you created in the previous step.

<cfg:objectClassDefinition>[/path/to/definition/file]</cfg:objectClassDefinition>

Refresh and inspect the resource schema

If you are configuring the resource using the GUI, refresh the resource schema by going to the resource and clicking Refresh schema. Check that you can see your new object class in the schema now by going to Schema > Select object class in your resource.

If you do not see it, check that midPoint does not generate schema constraints that limit the resource to a single object class (typically AccountObjectClass). You can do this clicking Edit raw in your resource and looking up the following section in the resource definition:

<generationConstraints>
    <generateObjectClass>ri:AccountObjectClass</generateObjectClass>
</generationConstraints>

If this section is present, remove it and refresh the schema again to make the additional object class defined in the properties file available.

Configure object types

Once the resource schema is available, create an object type for each object class represented by the CSV files.

Each object type should correspond to the kind of objects represented by the particular CSV file.

The object type based on the primary CSV file should be configured as the default one.

Each object type must reference the corresponding resource object class.

If you want to continue configuring the association types using the GUI, make sure that the entitlement object type has intent set. Otherwise, the GUI may not offer it as a selectable option when configuring association types.

You have now successfully imported a resource into midPoint and defined its object types. The next step is to define the relationships between the different object types (users and organizations).

Configure object processing

After defining the object types, configure inbound mappings, correlation, and synchronization for all relevant object types.

Inbound mappings specify how attributes from resource objects are mapped to midPoint objects during data processing. These mappings provide the data needed to populate midPoint objects and are essential for further processing.

Correlation defines how midPoint determines whether a resource object corresponds to an existing midPoint object. Without correlation, midPoint cannot reliably match resource objects to their counterparts in midPoint.

Synchronization defines how midPoint handles resource objects when they are processed. It specifies whether objects should be created, linked, updated, or removed based on their current state.

Without proper inbound mappings, correlation, and synchronization, objects may be imported without the attributes needed for matching, may not be linked correctly, or may not be created in midPoint at all.

Configure resource capabilities

The CSV connector does not support associations (such as group membership) out of the box.

To work with them, you first need to define relationships between objects, e.g., between organizational units and users.

These relationships are defined as references in the resource capabilities. They are later used in the association type configuration to create and manage relationships between objects in midPoint. To configure the relationships you need to specify:

  • name - The name of the reference.

  • direction - The direction of the reference (either from subject to object or the opposite).

  • primary binding attribute - the attribute that binds the subject and object. This links the subject and object by carrying the reference value on one side and matching it to an identifying attribute on the other side.

  • delineation - the object classes for the subject and object.

You can edit these:

Configure capabilities in GUI

  1. While editing the resource, click Details.

  2. Select References.

  3. Set Enabled to True.

  4. Configure the references according to the relationships in your data by adding a new section to Type.

Configure capabilities in raw XML

You can also edit the raw resource configuration directly in the resource by clicking Edit raw:

  1. Locate the <capabilities> section.

  2. Add a <configured> block inside it.

  3. In the <configured> block, define the references capability describing the relationship between users and organizations.

The following example shows a generic configuration of a reference using the subjectToObject direction.

<c:configured xmlns="http://midpoint.evolveum.com/xml/ns/public/resource/capabilities-3">
    <references>
        <type>
            <name>ri:yourAssociation</name> (1)
            <subject>
                <delineation>
                    <objectClass>ri:YourSubjectClass</objectClass> (2)
                </delineation>
                <primaryBindingAttributeRef>ri:yourAttribute</primaryBindingAttributeRef> (3)
                <localItemName>yourAssociation</localItemName> (4)
            </subject>
            <object>
                <delineation>
                    <objectClass>ri:YourObjectClass</objectClass> (5)
                </delineation>
                <primaryBindingAttributeRef>ri:yourIdentifier</primaryBindingAttributeRef> (6)
            </object>
            <direction>subjectToObject</direction>
        </type>
    </references>
</c:configured>
1 An arbitrary logical name for this reference type.
2 The object class for your primary (accounts) CSV file. For the CSV connector, this is typically ri:AccountObjectClass.
3 The attribute on the account side that carries the reference value.
4 The name midPoint uses internally to refer to this association on the subject side. This must match to what you use in the association type configuration.
5 The object class for your secondary CSV file. This is derived from the prefix you defined in your definition file.
6 The attribute on the object side used to match the reference value.

Configure association types

Using capabilities, we have defined that relationships can exist between objects on the resource. The next step is to define association types, which describe how these relationships are interpreted and processed in midPoint.

An association type has two aspects:

  1. It defines the structure of the relationship: its name, the subject side, the object side, and the reference linking it to the capability definition.

  2. It defines how the relationship is processed and translated into midPoint data.

The processing logic is evaluated on the subject side of the association.

To ensure that the relationship is correctly established, it must be mapped to the appropriate midPoint object. It needs to be projected from the shadow to its owner.

This is typically achieved by resolving the shadow owner and using it as the target of the association:

<mapping>
    <expression>
        <shadowOwnerReferenceSearch/>
    </expression>
    <target>
        <path>targetRef</path>
    </target>
</mapping>

In addition to mapping, synchronization behavior must be defined to ensure that the relationship is actually applied in midPoint. While mapping determines which relationship should be created, synchronization rules define how it is handled when resource data is processed — for example, whether it should be created if it does not exist, or updated if it already exists. This applies not only during import, but also during reconciliation and live synchronization.

Without synchronization rules, the relationship would be detected but not persisted in midPoint.

Import objects

After configuring the resource, the last step is to import the objects into midPoint.

Create a separate import task for accounts and for entitlements.

In the task configuration, specify the object classes, and for each CSV, select a corresponding object class.

Run each task separately.

With the import tasks completed, the CSV resource is fully configured and operational.

Example of a complete configuration

This part presents a complete example of configuring a CSV resource composed of multiple files and defining relationships between the data they contain.

In our scenario:

  • Users are stored in one CSV file.

  • Organizations are stored in another CSV file.

  • We need to define membership relationship between users and organizations.

Input files

Our HR database consists of the following CSV files:

  • users.csv

    userid;name;organization
    001;user1;org1#org2
    002;user2;org1
    003;user3;org2
    004;user4;
    005;user5;org3
    • userid — User identification number.

    • name — Name of the user.

    • organization — Name of the organization the user belongs to. There can be multiple values separated by the hash sign (#) because users can be members of multiple organizational units.

  • organizations.csv

    orgid;name
    001;org1
    002;org2
    003;org3
    • orgid — Organization identification number.

    • name — Name of the organization.

Object class definition file

Users are represented by the primary object class provided by the CSV connector. This object class is automatically derived from the main CSV file, while additional object classes for other files must be defined explicitly. We do this via the following definition file named source.prop:

org.filePath=/opt/midpoint/var/organizations.csv
org.fieldDelimiter=;
org.uniqueAttribute=orgid
org.nameAttribute=name
org.headerExists=true
org.container=true
org.auxiliary=true

Connector configuration

The following configuration shows how to set up the CSV connector.

<connectorConfiguration xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">
<icfc:configurationProperties
xmlns:cfg="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-csv/com.evolveum.polygon.connector.csv.CsvConnector">
<cfg:multivalueAttributes>organization</cfg:multivalueAttributes> (1)
<cfg:multivalueDelimiter>#</cfg:multivalueDelimiter> (2)
<cfg:fieldDelimiter>;</cfg:fieldDelimiter>
<cfg:headerExists>true</cfg:headerExists>
<cfg:filePath>/path/to/users.csv</cfg:filePath>
<cfg:nameAttribute>name</cfg:nameAttribute>
<cfg:uniqueAttribute>userid</cfg:uniqueAttribute>
<cfg:objectClassDefinition>/path/to/source.prop</cfg:objectClassDefinition> (3)
</icfc:configurationProperties>
</connectorConfiguration>
1 Declaration of a multi-value attribute.
2 Specification of a multivariate delimiter.
3 The path to the class definition file.

Capability configuration

After defining object types for each object class and configuring basic processing (such as mappings, correlation, and synchronization), you can proceed to configure resource capabilities. Object types are configured using standard midPoint mechanisms.

The following configuration defines a reference that links user accounts to organizations by matching values between the two CSV files. It represents the membership of a user in an organization.

<c:configured xmlns="http://midpoint.evolveum.com/xml/ns/public/resource/capabilities-3">
    <references>
        <type>
            <name>ri:orgMember</name> (1)
            <subject>
                <delineation>
                    <objectClass>ri:AccountObjectClass</objectClass> (2)
                </delineation>
                <primaryBindingAttributeRef>ri:organization</primaryBindingAttributeRef> (3)
                <localItemName>orgMember</localItemName> (4)
            </subject>
            <object>
                <delineation>
                    <objectClass>ri:CustomOrgObjectClass</objectClass> (5)
                </delineation>
                <primaryBindingAttributeRef>ri:name</primaryBindingAttributeRef> (6)
            </object>
            <direction>subjectToObject</direction> (7)
        </type>
    </references>
</c:configured>
1 Logical name of the reference.
2 Object class of the primary CSV file (users).
3 Attribute in the users CSV file that contains the organization reference.
4 Local name of the association on the subject side. This name is used later in the association type configuration.
5 Object class of the secondary CSV file (organizations).
6 Attribute in the organizations CSV file used for matching.
7 Direction of the reference. In this example, the value is read from the subject side (account) and matched to the object side (organization).

Association type configuration

After defining the reference in resource capabilities, the next step is to define how this relationship is interpreted and processed in midPoint.

In this example, the association represents a membership in which a user (account) is a member of an organization.

<associationType>
    <name>orgMember</name> (1)
    <displayName>Organization Member</displayName> (2)
    <subject> (3)
        <objectType>
            <kind>account</kind>
            <intent>default</intent>
        </objectType>
        <association> (4)
            <ref>ri:orgMember</ref> (5)
            <inbound>
                <name>Org-Member</name>
                <strength>strong</strength>
                <expression>
                    <associationSynchronization>
                        <objectRef>
                            <ref>ri:orgMember</ref> (5)
                            <correlator/>
                            <mapping> (6)
                                <name>OrgMember</name>
                                <expression>
                                    <shadowOwnerReferenceSearch/>
                                </expression>
                                <target>
                                    <path>targetRef</path>
                                </target>
                            </mapping>
                        </objectRef>
                        <synchronization> (7)
                            <reaction>
                                <situation>unmatched</situation>
                                <actions>
                                    <addFocusValue/>
                                </actions>
                            </reaction>
                            <reaction>
                                <situation>matched</situation>
                                <actions>
                                    <synchronize/>
                                </actions>
                            </reaction>
                        </synchronization>
                    </associationSynchronization>
                </expression>
            </inbound>
            <sourceAttributeRef>ri:orgMember</sourceAttributeRef>
        </association>
    </subject>
    <object> (8)
        <objectType>
            <kind>entitlement</kind>
            <intent>default</intent>
        </objectType>
    </object>
</associationType>
1 Name of the association type.
2 Display name shown in the GUI.
3 Subject of the association. In this example, it is the account. All processing logic (association, mappings) is evaluated on the subject side.
4 Definition of the association. This is where the reference from the resource is interpreted and transformed into a relationship in midPoint.
5 Reference defined in the capabilities configuration. All occurrences must match the localItemName and reference name defined earlier.
6 Mapping that resolves the target object. It finds the owner of the account shadow (User) and sets the association target (targetRef).
7 Synchronization rules that determine how the association is created or updated in midPoint.
8 Object side of the association — in this example, organizations are represented as entitlements.

Next step: use organization membership to assign roles

Now that the resource is configured and objects are imported, midPoint is aware of the organizational structure and the membership of users within it. This opens up a range of possibilities for automating access management.

One example is using organization membership to automatically grant roles. By adding an inducement to an organization, any user assigned to that org automatically receives an induced role. No extra rules or triggers are needed.

Add an inducement to your organization object referencing the role you want to grant:

<org>
    <name>MyOrganization</name>

    <inducement>
        <targetRef oid="<role-oid>" type="c:RoleType"/>
    </inducement>
</org>

Once a user is assigned to the organization, midPoint evaluates the inducement and grants the role. You can verify this in the user’s raw XML — the roleMembershipRef for the role will include provenance metadata showing the assignment path through the organization. To see this, in your resource, go to Accounts, click a user, and then click Edit raw.

For a detailed explanation of inducements and role construction, see the Roles Configuration reference page.

Was this page helpful?
YES NO
Thanks for your feedback