Try OpenEdge Now
skip to main content
OpenEdge 11.6.2 New Information : Progress Application Server for OpenEdge : Enhanced multi-domain support
 

Enhanced multi-domain support

The first generation of multiple OpenEdge domain support in PAS for OpenEdge was limited to the use case where the user-id entered by the client was a fully qualified OpenEdge ID, including both the user-id and the domain (or tenant) name. This type of user authentication works well when the back-end user account storage is implemented with multiple user domain capabilities.
An OpenEdge domain is a group of user accounts that all share the same access control rights. A tenancy is a security feature that attributes access control to data for all user accounts of all the domains associated with a single tenant. A tenant is required to have one domain in which all user account members are members of the tenant. Any tenant may be associated with multiple domains.
Another use case exists where the back-end system’s user account storage is not implemented with multiple user domain capabilities. An example of this is the Spring Security’s LDAP Authentication Provider, which can be found in PAS for OpenEdge web applications. The user account storage in the LDAP server is a flat space holding all user accounts for all domains, and each account has a unique ID. In this case, the domain name is not something the client supplies during authentication, but rather something that must be related to the user account itself.
This topic describes how PAS for OpenEdge now supplies multi-domain support for non-domain aware user account implementations.

Changes in PAS for OpenEdge

The changes that update multi-domain support all occur in the Spring Security OEClientPrincipalFilter bean found in all of the oeablSecurity-*.xml configuration files. The OEClientPrincipalFilter bean has additional capabilities that allow it to derive a domain name from a user account’s granted roles.
This method of using Spring Security roles as OpenEdge domains follows the logical pathway where a user account becomes a member of an OpenEdge domain by virtue of being granted membership in the domain. This is the same reasoning used in LDAP directories when an administrator associates individual user accounts with an LDAP group for the purpose of controlling access.

Resolving user-id and domain names

The logic paths in the OEClientPrincipalFilter have been altered with respect to how an input OpenEdge ID is processed to yield the user-id and domain name. The user-id and domain are used in creating a client-principal object that is subsequently passed to the ABL application code.
The OEClientPrincipalFilter logic roughly follows the steps below when it is given control after Spring Security’s authentication provider has successfully authenticated the user:
1. If the input OpenEdge ID is fully qualified (user-id plus domain name), proceed to Step 3.
2. Try to resolve the domain name using the following steps:
a. First, look for a user role in the domainRoleFilter property, which is recognized as holding a domain name. If the domain name is found, proceed to Step 3.
b. Next, try using the OEClientPrincipalFilter domain property value. If the domain name is found, proceed to Step 3.
c. If the domain name remains unresolved after Steps 2a and 2b, raise an error condition.
3. Create a client-principal object and populate its data fields.
4. If the OEClientPrincipalFilter key property is configured, use its value as the Domain Access Code (DAC) for all domain names.
Note: The OEClientPrincipalFilter key and registryFile properties are mutually exclusive. Both cannot be configured at the same time.
5. If the OEClientPrincipalFilter registryFile property is configured, use the domain name (either input or resolved by one of the methods in Step 2) to look up the domain's DAC.
6. If the DAC cannot be resolved, raise an error condition.
7. Seal the client-principal with the DAC and store it in the user's HTTP login session context for use in subsequent client requests.

Obtaining a domain name from a role

The domainRoleFilter is a new property added to the Spring Security OEClientPrincipalFilter bean to support obtaining an OpenEdge domain name from a user-granted role. The domainRoleFilter property is a JavaRegEx pattern that is used to identify any role name produced by Spring Security and to extract the domain name from it. The basic concept is to use a role-naming convention to distinguish a role name that represents a domain from other role names.
The RegEx expression can be any valid pattern with a single extraction group (a RegEx pattern enclosed in parentheses). The full pattern is used to match a role name. Everything that matches the pattern enclosed in parentheses is extracted and becomes the domain name.
The following are examples of user role-naming conventions:
OED:(.*)
The domain name is everything after OED:
Domain-(.*)-name
The domain name is all characters between Domain- and -name
Spring Security authentication providers (the beans that authenticate user accounts) prefix ROLE_ to all role names provided for authenticated users. Since the role names presented to the OEClientPrincipalFilter bean are in the form ROLE_user-role-name, this is what would be matched by the domainRoleFilter property:
*ROLE_OED:(.*)
*ROLE_Domain-(.*)-name
When the domainRoleFilter property is not defined or is a blank string, looking for a domain name in the user’s list of granted roles is disabled.

Library installation

If you are working with a PAS for OpenEdge installed prior to the 11.6.2 release, you must install the 11.6.2o4glrt.jar and oesecurity-11.6.2.jar libraries.
To install:
1. Create your PAS for OpenEdge instance, deploy your ABL web applications and compiled r-code, configure, and test.
2. Change you working directory to the instance's ROOT directory.
3. Expand the .zip archive distribution, which places 11.6.2o4glrt.jar and oesecurity-11.6.2.jar in .../common/lib.
Note: By default, PAS for OpenEdge looks for Java classes first in an instance’s /common/lib directory, and then in oe-install-dir/servers/PAS for OpenEdge/common/lib.
After retesting to ensure that your application is operating normally, go to the next section on configuration.

Configuring multi-domain support

Configuring for multi-domain support begins with the follow steps:
1. Design the OpenEdge domain name space to be used by the ABL application, and assign a Domain Access Code (DAC) to each domain name.
2. Build a CSV text file with domain names and clear-text DAC pairs, one pair per line. Domain names and DACs are separated by a comma. For example:
domain-name,clear-text-DAC
3. Use the gendomreg utility to create an encrypted Java keystore file from the CSV file. For example:
oe-install-dir/bin/gendomreg domreg.csv domreg.keystore
4. Copy the encrypted Java keystore file to each PAS for OpenEdge instance's .../conf directory.
5. Configure the OEClientPrincipalFilter bean in the oeablSecurity-*.xml file as follows:
a. Remove the key property.
b. Add the registryFile property and set its value to the file name of the Java keystore that you created in Step 3. For example:
<b:property name="registryFile" value="domreg.keystore" />
c. Configure the domain property by setting it to a default domain that has minimal access rights to in your ABL application.
d. Optionally configure authz, accntinfo, roles, and other properties.
The next step is to design the role name pattern that will be used in the external user account systems to designate an OpenEdge domain. Ideally the name pattern will have a unique prefix that distinguishes it from all other names. The name pattern may also employ a postfix to help establish uniqueness.
Note: Since the OEClientPrincipalFilter bean uses Java RegEx functionality, create a role name pattern that is easy for Java RegEx to parse.
When you have established a domain name pattern, construct the Java RegEx pattern that will distinguish the domain name from any other normal user account granted roles. For example, with OED:domain-name as the domain name:
Table 3. Spring users.properties accounts
Role Name
Spring Security Role Name
Java RegEx Match Pattern
ROLE_OED:acme
ROLE_OED:acme
ROLE_OED:(.*)
Table 4. Spring LDAO groupOfUniqueNames object
Role Name
Spring Security Role Name
Java RegEx Match Pattern
cn=OED:acme
ROLE_OED:ACME
ROLE_OED:(.*)
The Spring LDAP Authentication Provider prefixes ROLE_ to any LDAP group name it uses as a user account role, and it converts the LDAP group name to upper case.
Finally, set the OEClientPrincipalFilter bean's domainRoleFilter property to the value of the Java RegEx match pattern.
Note: If your Java RegEx match pattern contains a back slash ( \ ), you may be required to escape it with another backslash ( \\ ).

Testing

Testing, along with debugging and fine-tuning, may be required to get your implementation running optimally.
You can begin by testing your oeablSecurity-*.xml configuration using the local Spring user account text file. This gives you the ability to experiment offline with role names and configurations before moving on to a more complex user account source such as LDAP.
After making oeablSecurity-xx-local*.xml your Spring Security configuration in .../WEB-INF/web/xml, add trial users to .../WEB-INF/users.properties. For example:
acmeuser1=password,ROLE_PSCUser,ROLE_OED:Acme,enabled
pscuser1=password,ROLE_PSCUser,ROLE_OED:PSC,enabled
adcuser1=password,ROLE_PSCUser,ROLE_OED:adc,enabled
adcuser2=password,ROLE_PSCUser,ROLE_OED:ADC,enabled
You can use a favorite HTTP client to test logins.
The built-in ping functionality is easy to use on each PAS for OpenEdgeweb application. The syntax is:
GET http://host:port/rest/_oepingService/_oeping
If you do not get an HTTP 200 response from a ping, you may have a configuration problem and need to check log files to determine what it is.
To enable logging, add the following setting in .../WEB-INF/logging.xml:
<logger
name="com.progress.appserv.services.security.OEClientPrincipalFilter"
level="DEBUG"/>
<loggername="com.progress.auth" level="DEBUG"/>
Additional logging for selected parts of the Spring Security framework can be added if necessary:
<loggername=”org.springframework.security” level=”DEBUG” />

LDAP Configuration

Once you know your OEClientPrincipalFilter bean configuration is fundamentally working, you can move on to the more complex systems such as LDAP. LDAP is a very widely used directory service that is commonly employed at the enterprise level for secure common storage and administration of information with regard to servers, applications, user accounts, user groups (a.k.a., roles), and many other things.
Spring Security LDAP configuration details will almost always be unique to each individual enterprise; however, the following will give you information about configuring OpenEdge domains in the directory service so that the OEClientPrincipalFilter bean can find and use them.
Each LDAP directory service has a schema that defines its objects and object attributes. Different implementations of a directory service may vary in the objects and object attributes it supports. Examples of different directory services are:
*Apache Directory Service
*Windows Active Directory
*OpenLDAP
An OpenEdge domain will be just another LDAP group object that contains a list of the user accounts (Distinguished Names) who are members of that group, and who are entitled to the access associated with the group. The difference is that the LDAP group’s name will be based on the name pattern you defined in the previous sections.
For example, directory service administrators use the LDAP groupofUniqueNames objects as user account roles, where each group member’s user account is in a uniqueMember attribute. The directory service’s hierarchical object space might look like the following:
dc=acme
ou=users
cn=acmeuser1,ou=users,dc=acme,dc=com
ou=groups
cn=OED:acme,ou=groups,dc=acme,dc=com
uniqueMember=cn=acmeuser1,ou=users,dc=acme,dc=com
In this simple example, the user account acmeuser1 is in the domain acme. This occurs because a group is defined with the name OED:acme, and the user account for acmeuser1 is a member of that group. Therefore, when Spring Security authenticates acmeuser1, it will see that acmeuser1 is a member in the ROLE_OED:acme. The role supplies the domain name acme for creating a client-principal’s domain-name field.