Steps to setup Consortia env

Tenants topology


 Cross tenants Kafka communication

Deployment steps

Create central and institutional tenants

To perform multi tenancy consortia setup lets create 3 tenants with ids: consortium, university, college

Tenant creation

For tenants creation the standard okapi tenant creating endpoint should be used: POST /_/proxy/tenants

We need to create new host with UI only for the central tenant.

Only single host need to be deployed

Consortium users will use only the central tenant DNS host for all operations, if users need to apply operations from the context of another institutional tenant - they can switch active affiliation in the header.

Enable modules on tenants

We should follow the standard procedure of enabling tenants from install.json and enable all desired modules except one UI module folio_consortia-settings that should be enabled only in the consortium central tenant

Differences between central and institutional tenants

Module folio_consortia-settings should be enabled only in consortium central tenant

Configure tenants

  • Reference data & sample data should NOT be created on both central and institutional tenants.

Existing settings in a tenant cannot be shared via Consortium Manager. Settings have to be created via Consortium Manager to be shareable.

  • Reset password link, SMTP for sending emails should be configured on all tenants. Separate admin users in each tenant can be created to apply all this configuration.


Create admin user in the central tenant

For Consortia setup it is required to create admin user in the central consortium tenant. For other tenants shadow admin users with required set of permissions will be created automatically during Configure consortium tenants step.

This admin user should contain all existing permissions that admin users currently have for our common envs plus 2 additional:

  • consortia.consortium.item.post
  • consortia.tenants.item.post

Endpoint to create admin user

For user creation the standard endpoint should be used from mod-users: POST /users

Configure consortium tenants

Tenant context

All operation to configure consortium tenants should be executed in context of the central tenant, meaning with x-okapi-tenant = 'consortium'

Create consortium record

Validation requirements:

  • Only 1 consortium record should exist across cluster. adding more is prohibited

Request to create consortium record:

POST /consortia HTTP/1.1
X-Okapi-Tenant: consortium
X-Okapi-Token: <JWT>
Content-Type: application/json

{
    "id": "a617d446-4c00-4f8f-bcd4-5beacbccef67",
    "name": "Mobius"
}

Create consortium tenants

Actions performed under the hood of invoiking POST /consortia/{consortiumId}/tenants:

  • Store central tenant id in the consortia_settings table of the desired tenant
  • Perform primary affiliation creating for all existing users asynchronously
  • Invoke /user-tenant to store dummy user

Validation rules:

  • Consortium record should be created before adding tenant
  • Name and code fields should be unique
  • Name min length - 2, max length - 150
  • Code min length - 3, max length - 3, regex pattern - '^[a-zA-Z0-9]*$'
  • Tenant should not be existed already
  • Central tenant should be added firstly
  • Adding tenant when some another tenant has setupStatus = "IN_PROGRESS" is forbidden


Add central tenant to the consortium

Request to create central consortium tenant:

POST /consortia/a617d446-4c00-4f8f-bcd4-5beacbccef67/tenants HTTP/1.1
X-Okapi-Tenant: consortium
X-Okapi-Token: <JWT>
Content-Type: application/json

{
    "id": "consortium",
    "name": "Central office",
    "code": "MCO",
    "isCentral": true
}
 Steps executed when adding central tenant to the consortium

 PlantUML source code
PlantUML
@startuml
!pragma teoz true

!theme cerulean

autonumber

actor "user" as user

participant "mod-consortia" as mc
database "mod-consortia DB" as mc_db
participant "mod-users" as mu
participant "mod-login" as ml

user -> mc: Add central tenant to consortium
activate mc
group  #F3F0E1 Central tenant schema
mc -> mc: Check consortium exists ot throw an error
mc -> mc: Check tenant not yet added or throw an error
mc -> mc: Check if don't have have a central tenant or throw an error
mc -> mc_db: Save central tenant in tenant table
mc -> ml: Login by system user and use his token for all subsequent requests
group System user makes all subsequent calls
note left
System user permissions:
consortia.consortia-configuration.item.post
users.collection.get
users.item.get
users.item.post
users.item.put
perms.users.item.put
perms.users.item.post
perms.users.item.delete
perms.users.assign.immutable
perms.users.assign.mutable
perms.users.get
user-tenants.item.post
end note
mc -> mc_db: Save central tenant id in consortia-configuration table

group  #eeeee4 Create primary affiliation for existed users(async)
  mc -> mu: Retrieve all existed users from central tenant
  loop users size count
    mc -> mc_db: Check if primary user affiliation already exists in user_tenant table
    alt #E8F3E1 User was not affiliatied yet
      mc -> mc_db: Save primary user affiliation in user_tenant table
      mc -> mu: Send CONSORTIUM_PRIMARY_AFFILIATION_CREATED event
    else #F3E1E2 User was already affiliatied previously
      mc -> mc: Skipping creating primary affiliation for this user
  end
end

end
mc --> user: Status: Created
@enduml


Add institutional tenants to the consortium

New request param adminUserId added

Pay attenation that new request parameter adminUserId has beed added. It used to create shadow admin user in the desired teanant with predefined set of permissions.
It should be adminUserId for admin user from the central Tenant

Request to create University tenant:

POST /consortia/a617d446-4c00-4f8f-bcd4-5beacbccef67/tenants?adminUserId=b20c4397-ad56-479f-891a-30a5a471f24b HTTP/1.1
X-Okapi-Tenant: consortium
X-Okapi-Token: <JWT>
Content-Type: application/json

{
    "id": "university",
    "name": "University",
    "code": "UNI",
    "isCentral": false
}

Request to create College tenant:

POST /consortia/a617d446-4c00-4f8f-bcd4-5beacbccef67/tenants?adminUserId=b20c4397-ad56-479f-891a-30a5a471f24b HTTP/1.1
X-Okapi-Tenant: consortium
X-Okapi-Token: <JWT>
Content-Type: application/json

{
    "id": "college",
    "name": "College",
    "code": "COL",
    "isCentral": false
}
 Steps executed when adding member tenant to the consortium

 PlantUML source code
PlantUML
@startuml

!pragma teoz true

!theme cerulean

autonumber


actor "user" as user

participant "mod-consortia" as mc
database "mod-consortia DB" as mc_db
participant "mod-users" as mu
participant "mod-login" as ml
participant "mod-permissions" as mp

user -> mc: Add member tenant to consortium
activate mc
group  #F3F0E1 Central tenant schema
mc -> mc: Check consortium exists ot throw an error
mc -> mc: Check tenant not yet added or throw an error
mc -> mc_db: Save member tenant in tenant table
group #E7BFF5 Create shadow admin user_tenant association in central tenant
  mc -> mc_db: Get central tenant id
  mc -> mu: Fetch admin user to prepare shadow user
  mc -> mc_db: Save shadow admin associatation in user_tenant table      
end
end

group  #DBE1F1 Member tenant schema
  mc -> ml: Login by system user in member tenant and use his token for all subsequent requests
  group System user makes all subsequent calls
    note left
      System user permissions:
      consortia.consortia-configuration.item.post
      users.collection.get
      users.item.get
      users.item.post
      users.item.put
      perms.users.item.put
      perms.users.item.post
      perms.users.item.delete
      perms.users.assign.immutable
      perms.users.assign.mutable
      perms.users.get
      user-tenants.item.post
    end note

    mc -> mc_db: Save central tenant id in consortia-configuration table
    mc -> mu: Create dummy user_tenant record    

    group #E7BFF5 Create shadow admin user with permissions in member tenant
      mc -> mu: Create shadow admin user
      mc -> mp: Add predefined set of permissions to shadow admin user
      note left
        Shadow admin user permissions:
        ui-users.editperms
      end note
    end

    group  #eeeee4 Create primary affiliation for existed users(async)
    mc -> mu: Retrieve all existed users from this member tenant
    loop users size count
      mc -> mc_db: Check if primary user affiliation already exists in user_tenant table
      alt #E8F3E1 User was not affiliatied yet
        mc -> mc_db: Save primary user affiliation in user_tenant table
        mc -> mu: Send CONSORTIUM_PRIMARY_AFFILIATION_CREATED event
      else #F3E1E2 User was already affiliatied previously
        mc -> mc: Skipping creating primary affiliation for this user
    end
  end
end
mc --> user: Status: Created
end




@enduml

Order to add tenants to the consortium

Sequential order to add tenants to the consortium should be used, because under the hood we are making operations to create users in other tenants and simultaneously have an async operation to migrate existing users in current tenant.

Firstly, an automation job should create a central tenant and after this - all member tenants.

To control the tenant setup state we have a field 'setupStatus' in tenant response body with allowed values: "IN_PROGRESS", "COMPLETED", "COMPLETED_WITH_ERRORS", "FAILED".

Automation deployment job should make polling of GET /consortia/{{consortiumId}}/tenants/{{tenantId}} endpoint until COMPLETED or COMPLETED_WITH_ERRORS  status.

Poll interval can be chosen as 10 sec for example.

mod-consortia prevents adding new tenant when some tenant in DB has setupStatus with "IN_PROGRESS" value.

Here is description of all possible statuses:

StatusDescription
IN_PROGRESS

Adding tenant to the consortium is in progress, new POST requests to add another tenants is prohibited

COMPLETED

Adding tenant is completed, can start adding next tenant

COMPLETED_WITH_ERRORS

Tenant has been added, but not all existing users have been affiliated though the mod-consortia pipeline, pipeline can continue adding another tenants.

To repeat the process of syncing primary affiliations for existing users /sync-primary-affiliations can be invoked.

FAILED

Some unexpected error occurred, the tenant has not been added to the consortium or not all existing users have been affiliated though the mod-consortia pipeline.

The preferred way here is to stop executing automation pipeline and investigate reasons for these errors via logs

User type is required in ECS mode

On some of the customers it is possible to have more than 1.3 million of patron users, ECS does not need to process all of them through a consortium pipeline, because patron users can not and should not login to consortia.

 So 'type' field for user is required now in ECS mode, for non ECS it is optional.

This change brings 2 benefits:

  • General performance of ECS increases because ECS logic will work with thousands of staff/system users instead of millions of patron users
  • A clear way to distinguish user types in Folio appears

Possible user types:

User typeDescriptionProcessed by consortia pipeline?
1staffRegular staff userYes
2patronRegular parton userNo
3systemUser created by internal modules usage Yes
4shadow

Shadow user created when adding

affiliation to the desired tenant

No  (kafka messages will be send only

for real users, but not for shadow) 

How to deal with existing users

What is going on during this process of migrating existing users?

When adding a tenant to the consortium, the process of migrating existing users through the consortia pipeline begins within the scope of each:

  • Primary affiliation, and Affiliation in the central tenant (if the user is from a member tenant), with shadow users created.
  • The 'user-tenants' table in 'mod-users' is populated in the central tenant, which enables existing users to log in to ECS.

In conclusion, users processed by the consortia pipeline can log in, and affiliations will be manageable in ECS mode.

When to migrate existing users, before or after enabling ECS mode?

Before enabling ECS mode

The process of migrating existing users has been added to handle certain system or admin users through the ECS pipeline. This process is also triggered when ECS mode is enabled on a tenant that already has users with a populated 'type' field.

The query used to fetch existing users, as used by 'mod-consortia,' is as follows: (cql.allRecords=1 NOT type="patron" NOT type="dcb" NOT type="shadow"). With this query, all users without a populated 'type' field or with a 'type' that does not equal 'patron' or 'dcb' will be migrated.

One important point to consider is that if, for example, 1.5 million patron users were created without populating the 'type' field as 'patron' when ECS was not enabled, all 1.5 million users will be migrated. This behavior is not desired because the validation of the 'type' as a required field is only enabled when ECS mode is enabled, and ECS should skip processing these users in the pipeline.

After enabling ECS mode

If we have a choice, it's preferable to enable ECS mode for the tenant and then begin creating/migrating users. These users will be processed by 'mod-consortia' via Kafka domain events sent by 'mod-users.'

In this scenario, users cannot be created without populating the 'type' field because validation is enabled in ECS mode. For some customers, we may have more than 1.5 million patron users and only a couple of thousand staff users. In this case, we can ensure that 'mod-consortia' will process only these thousands of staff users and exclude the millions of patrons.

In conclusion, it's better to migrate existing users after enabling ECS mode for the tenant.

Do we need to adjust our existing admin users to populate type='staff'

Let's begin with system users. All repositories have been updated to create new system users with the type 'system,' and a migration script has been written in 'mod-users' to add 'type='system'' for all existing system users.

So, for system users, no further actions are required.

For admin users, it's advisable but not mandatory. We recommend adding 'type='staff'' to avoid confusion regarding users that existed without a populated 'type' field in ECS mode, where this type field is required.

Additionally, some new features, such as filtering by user type in the Users App, will not consider users without a 'type' value.

However, even if 'type' is not populated for admin users, 'mod-consortia' will still select such users and process them through the ECS pipeline during the 'migrate existing users' process when adding the tenant to the consortium. This process includes users without a 'type' populated.

In conclusion, no action is needed for 'system' users, but for common admin users, it's advisable to add 'type='staff''.

Changes for config values

In consortium mode we have only 1 UI available for a central tenant, so properties that are stored in mod-configuration like FOLIO_HOST  should be pointed to this single host for every tenant.

BE Modules modified for supporting consortia functionality

Thunderjet team

ModuleChanges madeHosting changes
1mod-consortia
  • Tenant management
  • User affiliations/shadow users managements
  • Share instances
  • Share/Edit/Delete any setting
  • Implement Publish Coordinator mechanism to perform any multitenant operation

Make sure that password for consortia system user populated

via this env variable: SYSTEM_USER_PASSWORD, OKAPI_URL also should be populated.

The full list of env variables is presented in the Readme:

https://github.com/folio-org/mod-consortia#environment-variables

2mod-users
  • Implement sending USER_CRETED, USER_UPDATED, USER_DELETED events when consortia mode is enabled
  • Check username uniqueness across tenants
  • Add mechanism with /user_tenant to identify is consortia mode enabled and to get central tenant id
  • Store info about all users from all consortium tenants in central place with using /user-tenant endpoint
-
3mod-users-bl
  • Populate all required user's info from correct tenant after login occurred
  • Forgot password/ Forgot username for ECS mode
  • Support resetting password for ECS mode
-
4mod-login
  • Allow to login by any consortium user into the correct tenant from the central tenant UI
-
5mod-authtoken
  • Allow cross tenant requests in ECS mode
  • Add suport of RTR in ECS mode

System param(declared in JAVA_OPTS) should be added: 

-Dallow.cross.tenant.requests=true

RANCHER-903 - Getting issue details... STATUS

Firebird team

ModuleChanges madeHosting changes
1mod-oai-pmh
  • Harvesting of shared instances
-
2edge-oai-pmh
  • Cross tenants harvesting
permissions + users, To be defined
3mod-data-export
  • Export of the shared instances
-

Folijet team

ModuleChanges madeHosting changes
1mod-inventory
  • Sharing instance functionality accross tenants
-
2mod-inventory-storage
  • Storage for sharing instance functionality accross tenants
-
3mod-source-record-manager
  • Allow importing a record with a known identifier
-
4mod-source-record-storage
  • Perform MARC To MARC matching in Local Tenant & Central Tenant
-

Spitfire team

ModuleChanges madeHosting changes
1mod-search
  • Adjust search, browse and stream ids functionalities for lookup across tenants

Tenant paramenter centralTenantId should be added(during tenant enabling)

RANCHER-898 - Getting issue details... STATUS

2mod-entities-links
  • Shadow authorities population, adjustments for shared authorities linking
-

Volaris team

ModuleChanges madeHosting changes
1edge-patronProvide a consortia-level access point/mechanism for retrieving patron data-
2edge-commonSupport Consortium Authentication & Routing-

Issues found during consortia env setup 

Issue descriptionRelated tickets
1Simaultainious adding tenants to consortia can cause concurrent issues

MODCON-73 - Getting issue details... STATUS

RANCHER-893 - Getting issue details... STATUS