Multi Tenancy Architecture
We need to support multiple customers in our system. Main requirement: data from one tenant shouldn’t be exposed to another (e.g. tenant 1 can’t see calls and get media for call from tenant 2).
/wiki/spaces/RedboxHome/pages/2562775073
Basic flow
TenantID (tenantGlobalID) will be returned as a claim from the ADFS (required claim that will be set per integration). This tenant id will be put into JWT token that will be used by client to make requests to the API Gateway. API Gateway will validate the token, extract tenantID from the token and put it to the proxy request header (see Auditing - Flowing the User Identity through the Architecture). Core API will use this value to filter entities.
From collector we have two different options (see more details below):
- Collector per tenant. In this case collector will include tenant ID into call metadata so it can be processed by core services without any modifications.
- Collector per multiple tenants. In this case tenantID will be obtained from the device (collector includes deviceID into metadata).
Entities that need to be changes (add tenantGlobalID field):
- CallMetadata
- InProgress Call Metadata
- MediaMetadata
- Device
- Agent
- User
- Annotation filed
- Roles
- ClaimsMapping
Infrustructure level
We would need ability to separate tenants on the infrastructure level. There are multiple options for separations (multiple types could be used in parallel):
Infrastructure per multiple tenants
Everything is shared across multiple tenants, collector sends a deviceID that is used to obtain tenant ID from the configuration database
Infrastructure per tenant
The simplest way of separation - each tenant has its own infrastructure
Collector Per Tenant
In this case collector will know what tenantID to put into the metadata
Core Service Per Tenant
In this case we can spin up a separate micro service per each tenant. Each event will be put into event store with the tenant identification in the metadata. Event Store Projection will be created per each tenant and each micro service would subscribe to the tenant’s projection. It could be supported with minimal changes in code (just put tenantID into event’s metadata), however would require a lot of work for DevOps – automatically create projections in the EventStore and script service deployment and configuration per tenant.
All Core Services Per Tenant
We would need to put a mapping to the consumer services that will put event into appropriate EventStore based on the tenantID
Core API Per Tenant
Not sure if we would need such implementation since under the hood it would use singe instance of unified storage (ElasticSearch and MinIO). In this case we would put mapping into API Gateway that will pick proxy URL based on the tenantID
Unified Storage Per Tenant
This is the most complex implementation where we have a single stack of services, but different unified storage per tenant. It would require to put mapping into each service that works with unified storage, also would require implementation Core API Per tenant.
Would require further investigation of impact if needed to be supported
Simon Jolly (Unlicensed) , what types are we going to support in first place (Infurstructure per tenant and per multiple tenants and collector per tenant will be supported by default)?
In my vew, except default types we should add support only for core service per tenant for now.
Plan
- Add tenant to the authorization pipeline.
- Configure ADFS to send tenant ID claim
- Add claim mapping to the Identity Server
- Read token on the API Gateway side and add it to the X-RBR-USER-IDENTITY header
- Add tenant support to Identity Service:
- Add tenantID field to Role, User, ClaimsMapping entities
- Add filtering for the entities on the IdentityServiceReadAPI
- Add tenant support to Metadata/Media
- Apply tenantID on the consumer side to the metadata (read device configuration and apply tenantID based on the deviceID)
- Add tenantID field to the metadata index
- Filter metadata by tenantID on the metadata API side
- Add tenant support to Configuration Services
- Add tenantID to Device, Agent entities
- Add filtering by tenantID
- Add tenant information to all event store events and create PoC for Core Service Per Tenant, so it can be reviewed and scripted later by DevOps
- Add mapping for the event store per tenant to the consumer services (if needed, see All Core Services Per Tenant)
- Add mapping for the proxy urls to the api gateway (if needed, see Core API Per Tenant)
- DevOps: Script Core Service Per tenant
- Automatic projection creation per tenant
- Automatically start service per tenant (configure correct event store stream and group name)