4GL Programming For OpenEdge Multi-Tenant Databases
4GL Programming For OpenEdge Multi-Tenant Databases
Agenda
Introduction Regular Tenant Programming Model Super-tenant Programming Model AppServer and Client-Principal Questions
Multi-Tenant Database
Each multi-tenant database user belongs to some domain and hence some type of tenant
User logging in as a member of a domain that is not blank and not associated with a Super-tenant
Has access as a regular type of tenant
Super-tenant users
Cannot access regular tenant data unless the Super-tenant user uses new ABL language elements
New SET-EFFECTIVE-TENANT and TENANT-WHERE constructs allow temporary access to regular tenant data Access is still subject to the Super-tenant users normal access rights
Data Access for 2 tenants, HomeDepot and Lowes Simple Multi-Tenant and Shared Data
HomeDepot Customers Orders Items Lowes Customers Orders Items Default
Tenancy Layer
Shared
_file State
_field
_tenant
_tenant
Default Lowes
| 0 | 2
HomeDepot | 1
Domains
name
HomeDepot
Data
HomeDepot
Customers Orders
tenant
HomeDepot
Tenancy Layer
Items
name
Rich Lowes John Lowes Claudio Lowes Louie Lowes Lowes
tenant
Lowes
Lowes
Customers Orders Items
name
blank
tenant
Default
Default
deallocated or migrated data
edward james
Shared
_file state _field _tenant
The CLIENT-PRINCIPAL is an ABL built-in object with methods similar to SETUSERID Getting a domain using SETUSERID (obsolete): IF NOT SETUSERID(rich@homedepot,encoded_password) THEN error Getting the same domain using CLIENT-PRINCIPAL: CREATE CLIENT-PRINCIPAL hCP. hCP:INITIALIZE(rich@homedepot,?,?,encoded_password). IF NOT SET-DB-CLIENT(hCP,dbname) THEN error SEAL the CLIENT-PRINCIPAL or NOT??
9
2012 Progress Software Corporation. All rights reserved.
11.x uses CLIENT-PRINCIPALs to Manage Users and their access to Tenant data
BEST security
Use SET-DB-CLIENT() or SECURITY-POLICY:SET-CLIENT() 11.1+ : configurable server-side ABL plug-in which results in a sealed CLIENT-PRINCIPAL with no domain access code outside database 11.0+:configurable _USER and _OSlocal plug-in
BETTER security
Use SET-DB-CLIENT() or SECURITY-POLICY:SET-CLIENT() Client ABL creates/seals CLIENT-PRINCIPAL and SSO to database Requires secure r-code with domain access code outside database
OK security
10
Use SETUSERID() Not extensible no more enhancements Continue to use in data servers (for now ) Do replace for OpenEdge 11.x RDBMS
Agenda
Introduction Regular Tenant Programming Model Super-Tenant Programming Model AppServer and Client-Principal Questions
11
The same pcode and rcode can serve for all Regular tenants
No special ABL coding is required for a regular tenant user to access a multi-tenant table
Legacy code only needs recompile in version 11+ to be run as multi-tenant code by a regular tenant user
For two tenants, HomeDepot and Lowes, you will get a different report from the same rcode
FOR EACH Customer: DISPLAY CustNum Name. END.
13
CREATE Customer. /*automatically goes to the right tenant*/ Name = New Cust DISPLAY CustNum Name.
Sequences - Multi-tenant
If the sequence is multi-tenant, it will increment independently in each tenant For the two tenants in our hardware application, the custNums from a MT sequence:
Start with 1 for each tenant Are non-unique across tenants Ideal for use where any join tables have the same tenancy type
15
For the same database, the custNum from a shared or non-multi-tenant sequence will number consecutively across tenants
Customer
The custNum therefore is unique across all tenants (only 1 Cust 4) Why would you ever want this?
FOR EACH Customer, EACH Order of Customer. If the Order table is shared, then the Order.CustNum would be non-unique and useless (e.g. 2 Cust 4s) unless the CustNum sequence is shared.
16
2012 Progress Software Corporation. All rights reserved.
Home Depot
Regular tenant code may not use these two functions in a WHERE clause:
/* NOT OKAY TO DO THIS!!! */ FOR EACH Customer WHERE TENANT-NAME() = Lowes: The ABL already knows what tenant a regular tenant belongs to
And there is no hidden column in any table or index that can be used to select on in a regular tenant WHERE clause.
Because tenants are like mini-databases, it is equivalent to saying: /* NOT OKAY TO DO THIS!!! */ FOR EACH Customer WHERE DBNAME = Sports:
18
A DB has 3 tenants, HomeDepot, LowesNY and LowesBos LowesNY and LowesBos are in the same group for Items
FOR EACH Item: DISPLAY ItemNum Item-Desc. END.
19
Data Access for 3 tenants, HomeDepot and LowesBos, LowesNy and 1 Item table group
HomeDepot Customers Orders LowesBos Customers Orders LowesNy Customers Orders LowesItm Group Items for both LowesBos and Ny Default deallocated, or recently migrated data
_file _field State _tenant
Items
Tenancy Layer
Shared
20
BUFFER-GROUP-ID and BUFFER-GROUP-NAME functions and buffer methods provide group information for a buffer You must use shared sequences for unique indexes with groups
Item
LowesBOS And LowesNY, as GROUP LowesItm 1 Shovel bos 3 Extension cable bos 4 Hammer ny 7 Green Paint bos 8 Faucet ny 9 Lamp bos
21
Agenda
Introduction Regular Tenant Programming Model Super-tenant Programming Model AppServer and Client-Principal Questions
22
Super-tenants have no data of their own Super-tenants have special ABL to allow them to:
Get access to regular tenant data Execute legacy code
23
SET-EFFECTIVE-TENANT function
Available only to a Super-tenant user Allows a Super-tenant user to act on behalf of a regular tenant
So you dont have to SETUSERID or SET-DB-CLIENT to actually become a real user of that tenant SET-EFFECTIVE-TENANT(HomeDepot). FIND FIRST Customer. DISPLAY CustNum Name. RUN myCustApp.p etc.
Home Depot
FOR EACH Customer TENANT-WHERE TENANT-NAME() < M: SET-EFFECTIVE-TENANT(BUFFER-TENANT-ID(Cust)). DISPLAY BUFFER-TENANT-ID(Cust) CustNum Name. RUN myCustApplication.p(CustNum). END.
Home Depot
Sorting will be slow, across all _tenants. It would be better to use the nested form which can take advantage of indexing.
FOR EACH _tenant WHERE _tenant._tenantId > 0 BY _tenant._tenant-name: SET-EFFECTIVE-TENANT(_tenant._tenantId). FOR EACH Customer BY Customer.Name: Etc. END. END.
28
2012 Progress Software Corporation. All rights reserved.
Only 1 level of join can have the TENANT-WHERE phrase The AVM automatically propagates the current tenancy to lower levels of join, where appropriate
So the join will contain records from the same tenant throughout the current tenant iteration FOR EACH Customer TENANT-WHERE TENANT-ID() > 0, EACH Order of Customer, EACH Order-line of Order.
29
To copy Customers from the default data segment into the correct tenant:
DEFINE BUFFER bCust FOR Cust. FOR EACH Cust: SET-EFFECTIVE-TENANT(Cust.Ten-name). CREATE bCust. BUFFER-COPY Cust TO bCust. END.
Tenancy Layer
Shared
_tenant State
DEFINE BUFFER bCust FOR Cust. FOR EACH Cust: CREATE bCust FOR TENANT(Cust.Ten-name). /*CREATE triggers?*/ BUFFER-COPY Cust TO bCust. DELETE Cust. /*DELETE TRIGGERS may not work*/ END.
2 Lawn Mower 5 Screw Driver 6 Table 1 Shovel bos 3 Extension cable bos 4 Hammer ny 7 Green Paint bos 8 Faucet ny 9 Lamp bos 1 Shovel bos 3 Extension cable bos 4 Hammer ny 7 Green Paint bos 8 Faucet ny 9 Lamp bos
LowesItm group appears twice once for LowesBos tenant and once for LowesNY To skip the 2nd LowesItm group use SKIP-GROUPDUPLICATES
FOR EACH Item TENANT-WHERE TENANT-ID() > 0 SKIP-GROUP-DUPLICATES:
32
2012 Progress Software Corporation. All rights reserved.
Agenda
Introduction Regular Tenant Programming Model Super-tenant Programming Model AppServer and Client-Principal Questions
33
All types of AppServers will need to manage user logins with CLIENT-PRINCIPALS to get correct user auditing, permissions, and tenancy Stateless, State-free and WebSpeed AppServers in a Multitenant environment will need some form of context management of CLIENT-PRINCIPALS because
multiple appserver instances serve the same client session across multiple requests
State-reset, State-aware can optionally use context management to resume user logins that span connections Everything else works normally for a regular tenant user
34
2012 Progress Software Corporation. All rights reserved.
35
mycp table
sessionId | cp raw data.. raw data.. ajfrbo9kk | lqjdkor71 |
3. User logout: disconnect.p or equivalent : 4. Start remote procedure: activate.p (no equivalent ):
Find/receive the CLIENT-PRINCIPAL identity context Switch user identity contexts from previous to current one May include saving the context from the previous user
NOTE: State-reset and state-aware servers do usually not need 4 and 5. Webspeed,/WebServices/AIA do 2 and 3 without clientContextId
38
2012 Progress Software Corporation. All rights reserved.
The CONNECT method of the clients SERVER object allows you to optionally pass the userid, password, and a character string to the AppServer. They become the 3 parameters to the connect.p on the AppServer. This is one of many ways to get your userid@domain and user password to the connect.p.
DEFINE INPUT PARAMETER user_domain AS CHAR. DEFINE INPUT PARAMETER encryptd_pswd AS CHAR. DEFINE INPUT PARAMETER mychar AS CHAR. CREATE CLIENT-PRINCIPAL hCP. hCP:INITIALIZE(user_domain,?,?,encrypted_pswd).
39
2012 Progress Software Corporation. All rights reserved.
AppServer context switching automatically clears buffers and invalidates query index cursors
When AppServer (or any AVM) switches tenant context because its user is changed to be a user of a different tenant , the AVM
clears out all Multi-tenant buffers (temp-tables are not Multi-tenant) marks all Multi-tenant index cursor scans as invalid
Stateless/State-free Appservers switch tenant context per request Dangerous to use a Super-Tenant and SET-EFFECTIVETENANT on an AppServer since no automatic context clearing happens
40
Questions
41
42