Skip to content

Configuration changes using overrides

This guide provides detailed steps for updating the server.xml properties and for configuring the Digital Experience (DX) Compose server using configuration.webEngine.configOverrideFiles.

The snippets are merged into the Open Liberty server.xml file. After making changes to the respective values.yaml file, apply them by using the helm upgrade command. Open Liberty picks up and applies changes at runtime; this does not require a restart.

Configuring users or user groups

The following sample snippet shows how to configure a DX WebEngine server to configure or override a user or a user group.

configOverrideFiles:
  user-overrides.xml: |
    <server description="DX Web Engine server"> 
      <basicRegistry id="basic" realm="defaultWIMFileBasedRealm"> 
        <user name="wpsadmin" password="newPass" />
        <user name="newuser1" password="password" />
        <group name="wpsadmins" id="cn=wpsadmins,o=defaultWIMFileBasedRealm">
          <member name="wpsadmin" />
        </group>
        <group name="nonadmins" id="cn=nonadmins,o=defaultWIMFileBasedRealm">
          <member name="newuser1" />
        </group>
      </basicRegistry> 
    </server>

The name of the customization in the example (user-overrides.xml) can be any string. However, it is recommended that you use a name that describes the change it applies.

To update the default administrator username and password, refer to the steps in Updating the default admin password.

Configuring DX Compose to use a mail server

The following is an example snippet of configuring DX WebEngine server to use a mail server. The smtphost will need to be replaced with the proper hostname of the mail server. If authentication is required to communicate with the mail server then replace smtpUser and smtpPassword with the correct values, otherwise remove those lines from the snippet.

configOverrideFiles:
  smtpOverride.xml: | 
    <server description="DX Web Engine server">
      <mailSession
        id="dxWebEngineMail"
        host="smtphost.com"
        from="no-reply@smtphost.com"
        jndiName="mail/BuilderMailSession"
        description="DX WebEngine MailSession"
        mailSessionID="dxWebEngineMail"
        user="smtpUser"
        password="smtpPassword">
          <property name="mail.smtp.auth" value="false" />
          <property name="mail.smtp.port" value="25" />
      </mailSession>
    </server>

The name of the customization in the example (smtpOverride) can be any string. However, it is recommended that you use a name that describes the change it applies.

Configuring SSL

The Open Liberty may not trust default certificates. By providing the following configuration setting, Open Liberty trusts the default certificates, enabling communication with third-party services.

configOverrideFiles:
   sslOverride.xml: |
      <server description="DX Web Engine server">  
        <ssl id="defaultSSLConfig" trustDefaultCerts="true" />
      </server>

The name of the customization in the example (sslOverride) can be any string. However, it is recommended that you use a name that describes the change it applies.

Configuring LDAP

The following sample snippet shows how to configure the DX Compose server to use a Lightweight Directory Access Protocol (LDAP) server, such as OpenLDAP.

configOverrideFiles:
  ldapOverride.xml: | 
    <server description="DX Web Engine server"> 
      <ldapRegistry id="ldap" realm="SampleLdapCustomRealm"
        host="127.0.0.1" port="1389" ignoreCase="true"
        baseDN="dc=dx,dc=com"
        ldapType="Custom"
        sslEnabled="false"
        recursiveSearch="false"
        bindDN="cn=dx_user,dc=dx,dc=com"
        bindPassword="p0rtal4u">
          <customFilters
            userFilter="(&amp;(uid=%v)(objectclass=inetOrgPerson))"
            groupFilter="(&amp;(cn=%v)(objectclass=groupOfUniqueNames))"
            userIdMap="*:uid"
            groupIdMap="*:cn"
            groupMemberIdMap="groupOfUniqueNames:uniqueMember">
          </customFilters>
          <attributeConfiguration>
            <attribute name="mail" propertyName="ibm-primaryEmail" entityType="PersonAccount"/>
            <attribute name="title" propertyName="ibm-jobTitle" entityType="PersonAccount"/>
          </attributeConfiguration>
      </ldapRegistry>
      <federatedRepository>
        <primaryRealm name="FederatedRealm" allowOpIfRepoDown="true">
          <participatingBaseEntry name="o=defaultWIMFileBasedRealm"/>
          <participatingBaseEntry name="dc=dx,dc=com"/>
        </primaryRealm>
      </federatedRepository>
    </server>
  • host: Specifies the domain name or IP address of the target LDAP server.
  • port: Specifies the connection port number for the LDAP server.
  • baseDN: Specifies the starting point in the LDAP directory tree for search queries.
  • ldapType: Specifies the LDAP server vendor type.

    • For predefined LDAP types supported by OpenLiberty, use the corresponding filters tags (for example, idsFilters, activedFilters, domino50Filters, edirectoryFilters, iplanetFilters, netscapeFilters, and securewayFilters).
    • For custom LDAP types, use customFilters to define search filters for users and groups.
  • sslEnabled: Controls whether the connection to the LDAP server uses SSL/TLS. Set to true when your LDAP server requires a secure connection, and ensure that the LDAP server certificate is trusted by the Liberty keystore, or configure trustDefaultCerts as described in Configuring SSL.

  • recursiveSearch: Specifies whether to perform recursive searches for nested groups (default: false).

    • Set to false to resolve nested group membership internally in DX Compose for authentication and access control while preserving group hierarchy in the UI. Use this default setting for most deployments.
    • Set to true to resolve nested group membership through the LDAP server and display a flat list of users in the UI without group hierarchy. Use only if user access fails under the default setting.
  • bindDN: Specifies the distinguished name (DN) of the LDAP service account used to authenticate with the LDAP server.

  • bindPassword: Specifies the password associated with the bindDN user account.

For more information, refer to Configuring nested LDAP groups and LDAP User Registry (ldapRegistry).

Mapping user IDs when group membership uses DNs

When group membership attributes store members as DNs, set userIdMap to match the attribute used in the relative distinguished name (RDN) of the user DN stored in the group membership attribute. For example, if uniqueMember contains a DN such as cn=Gene Hayes,ou=internal,ou=users,ou=dxdemo,dc=dx,dc=com, use userIdMap="*:cn". If the DN starts with uid=..., use userIdMap="*:uid". Choose the value that matches your LDAP directory.

Mapping LDAP attributes

The attributeConfiguration element in the LDAP registry configuration allows you to map LDAP attributes to user registry attributes. This is useful when the attribute names in your LDAP directory do not match the expected attribute names. Each attribute element specifies a mapping:

  • name: The name of the attribute in the LDAP directory
  • propertyName: The name of the attribute to be mapped to. In the following example, the LDAP mail attribute is mapped to ibm-primaryEmail, which is the attribute used to display the email address of a user. The LDAP title attribute is mapped to ibm-jobTitle, which is the attribute used to display job title of a user.

To set up a custom LDAP server in Liberty, refer to Configuring LDAP.

Configuring LDAP settings for virtual portal realm support

The following is a sample snippet that shows how to configure the DX Compose server to use multiple OpenLDAP servers with their own realms. These realms define user access when you create a virtual portal. The realm value selected in the Virtual Portal administration portlet restricts the available groups for initial administration. Replace baseDN, bindDN, bindPassword, host, and port with your environment values.

configOverrideFiles:
  ldap-overrides.xml: | 
    <server description="DX Web Engine server"> 
      <ldapRegistry id="toyldap" realm="ldapToyRealm"
        host="127.0.0.1" port="1389" ignoreCase="true"
        baseDN="ou=ToyCompany,dc=dx,dc=com"
        ldapType="Custom"
        sslEnabled="false"
        recursiveSearch="false"
        bindDN="cn=dx_user,dc=dx,dc=com"
        bindPassword="passw0rd">
          <customFilters
            userFilter="(&amp;(uid=%v)(objectclass=inetOrgPerson))"
            groupFilter="(&amp;(cn=%v)(objectclass=groupOfUniqueNames))"
            userIdMap="*:uid"
            groupIdMap="*:cn"
            groupMemberIdMap="groupOfUniqueNames:uniqueMember">
          </customFilters>
          <attributeConfiguration>
            <attribute name="mail" propertyName="ibm-primaryEmail" entityType="PersonAccount"/>
            <attribute name="title" propertyName="ibm-jobTitle" entityType="PersonAccount"/>
          </attributeConfiguration>
      </ldapRegistry>
      <ldapRegistry id="boatldap" realm="ldapBoatRealm"
        host="127.0.0.1" port="1389" ignoreCase="true"
        baseDN="ou=BoatCompany,dc=dx,dc=com"
        ldapType="Custom"
        sslEnabled="false"
        recursiveSearch="false"
        bindDN="cn=dx_user,dc=dx,dc=com"
        bindPassword="passw0rd">
          <customFilters
            userFilter="(&amp;(uid=%v)(objectclass=inetOrgPerson))"
            groupFilter="(&amp;(cn=%v)(objectclass=groupOfUniqueNames))"
            userIdMap="*:uid"
            groupIdMap="*:cn"
            groupMemberIdMap="groupOfUniqueNames:uniqueMember">
          </customFilters>
          <attributeConfiguration>
            <attribute name="mail" propertyName="ibm-primaryEmail" entityType="PersonAccount"/>
            <attribute name="title" propertyName="ibm-jobTitle" entityType="PersonAccount"/>
          </attributeConfiguration>
      </ldapRegistry>
      <federatedRepository>
        <primaryRealm name="FederatedRealm" allowOpIfRepoDown="true">
          <participatingBaseEntry name="o=defaultWIMFileBasedRealm"/>
          <participatingBaseEntry name="ou=ToyCompany,dc=dx,dc=com"/>
          <participatingBaseEntry name="ou=BoatCompany,dc=dx,dc=com"/>
        </primaryRealm>
      </federatedRepository>
    </server>

This configuration enables creating virtual portals for separate organizations, such as a toy company and a boat company shown in the sample configuration. The baseDN values specify the users that belong to the respective organizational units: ou=ToyCompany,dc=dx,dc=com and ou=BoatCompany,dc=dx,dc=com. Matching realm values appear as options in the Virtual Portal administration portlet during creation. Selecting ldapToyRealm for the toy company virtual portal restricts log in access to users in that organization.

Combining realms for virtual portals

You can combine multiple realms under a parent realm by using the federatedRealms extension. Selecting this parent realm during virtual portal creation combines all child realm entries to define user access. Selecting a parent realm grants access to users resolved from all listed child realms. For example:

      ...
      </ldapRegistry>
      <federatedRepository>
        <primaryRealm name="FederatedRealm" allowOpIfRepoDown="true">
          <participatingBaseEntry name="o=defaultWIMFileBasedRealm"/>
          <participatingBaseEntry name="ou=ToyCompany,dc=dx,dc=com"/>
          <participatingBaseEntry name="ou=BoatCompany,dc=dx,dc=com"/>
        </primaryRealm>
      </federatedRepository>
      <federatedRealms>
        <parentRealm name="ToyRealm">
          <realmEntry name="ldapToyRealm"/>
          <realmEntry name="defaultWIMFileBasedRealm"/>
        </parentRealm>
        <parentRealm name="BoatRealm">
          <realmEntry name="ldapBoatRealm"/>
          <realmEntry name="defaultWIMFileBasedRealm"/>
        </parentRealm>
      </federatedRealms>      
    </server>

This configuration enables creating a virtual portal with multiple combined realms. Selecting BoatRealm during virtual portal creation grants access to all users in ldapBoatRealm and the default file-based users defined in basicRegistry.

Additional LDAP configuration samples

Use the following LDAP configuration samples based on your server type:

IBM Directory Server

    configOverrideFiles:
      myCustomOverride.xml: |
        <?xml version="1.0" encoding="UTF-8"?> 
        <server description="DX Web Engine server">
          <ldapRegistry id="ldap" realm="SampleLdapIDSRealm"
            host='your_LDAP_Server_HostName'
            port='1389' ignoreCase="true"
            baseDN='dc=dx,dc=com'
            ldapType='IBM Tivoli Directory Server'
            sslEnabled='false'
            recursiveSearch='false'
            bindDN='${LDAP_BIND_USER}'
            bindPassword='${LDAP_BIND_PASSWORD}'>
            <idsFilters
              userFilter="(&amp;(uid=%v)(objectclass=inetOrgPerson))"
              groupFilter="(&amp;(cn=%v)(objectclass=groupOfUniqueNames))"
              userIdMap="*:uid"
              groupIdMap="*:cn"
              groupMemberIdMap="groupOfUniqueNames:uniqueMember">
            </idsFilters>
            <ldapCache>
              <attributesCache size="4000" sizeLimit="4000" timeout="2400s" />
              <searchResultsCache resultsSizeLimit="4000" size="4000" timeout="2400s" />
            </ldapCache>
            <contextPool preferredSize="20"/>
            <attributeConfiguration>
              <attribute name="mail" propertyName="ibm-primaryEmail" entityType="PersonAccount"/>
              <attribute name="title" propertyName="ibm-jobTitle" entityType="PersonAccount"/>
            </attributeConfiguration>
          </ldapRegistry>
          <federatedRepository>
            <primaryRealm name="FederatedRealm" allowOpIfRepoDown="true">
              <participatingBaseEntry name="o=defaultWIMFileBasedRealm"/>
              <participatingBaseEntry name='dc=dx,dc=com' />
              <uniqueUserIdMapping inputProperty="uniqueName" outputProperty="uniqueName"/>  
              <userSecurityNameMapping inputProperty="principalName" outputProperty="principalName"/>  
              <userDisplayNameMapping inputProperty="principalName" outputProperty="principalName"/>  
              <uniqueGroupIdMapping inputProperty="uniqueName" outputProperty="uniqueName"/>      
              <groupSecurityNameMapping inputProperty="cn" outputProperty="cn"/>  
              <groupDisplayNameMapping inputProperty="cn" outputProperty="cn"/>                
            </primaryRealm>
          </federatedRepository>   
          <basicRegistry id="basic" realm="defaultWIMFileBasedRealm">
              <user name="${DX_ADMIN}" password="${DX_PASSWORD}" id="uid=wpsadmin,o=defaultWIMFileBasedRealm"/>
              <user name="nonadmin" password="nonadminpwd" id="uid=nonadmin,o=defaultWIMFileBasedRealm"/>
              <user name="admin1" password="admin1pwd" id="uid=admin1,o=defaultWIMFileBasedRealm"/>
              <group name="wpsadmins" id="cn=wpsadmins,o=defaultWIMFileBasedRealm">
                  <member name="${DX_ADMIN}" />
                  <member name="admin1" />
                  <member  name="tuser1"/>
              </group>
              <group name="nonadmins" id="cn=nonadmins,o=defaultWIMFileBasedRealm">
                  <member name="nonadmin" />
              </group>
          </basicRegistry>          
        </server>

Microsoft Active Directory Server

    configOverrideFiles:
      myCustomOverride.xml: |
        <?xml version="1.0" encoding="UTF-8"?>  
        <server description="DX Web Engine server">  
                <ldapRegistry  
                  id="ldap"  
                  realm="SampleLdapADRealm"  
                  host="your_LDAP_Server_HostName"  
                  port="389"  
                  ignoreCase="true"  
                  baseDN="DC=ad,DC=test,DC=com"  
                  bindDN="CN=Administrator,CN=Users,DC=ad,DC=test,DC=com"  
                  bindPassword="your_password"  
                  ldapType="Microsoft Active Directory"  
                  sslEnabled="false"  
                  referral="ignore"  
                  recursiveSearch="false"  
                  bindAuthMechanism="simple"  
                  returnToPrimaryServer="true">  
                    <activedFilters 
                    userFilter="(&amp;(sAMAccountName=%v)(objectcategory=user)" 
                    groupFilter="(&amp;(cn=%v)(objectcategory=group))" 
                    userIdMap="user:sAMAccountName" 
                    groupIdMap="*:cn" 
                    groupMemberIdMap="memberOf:member">  
                    </activedFilters>  
                    <ldapEntityType name="PersonAccount">  
                      <objectClass>user</objectClass>  
                    </ldapEntityType>  
                    <ldapEntityType name="Group">  
                      <objectClass>group</objectClass>  
                  </ldapEntityType>  
                  <groupProperties>  
                      <memberAttribute name="member" scope="direct" objectClass="group"/>  
                      <membershipAttribute name="memberOf" scope="direct"/>  
                  </groupProperties>  
                  <loginProperty name="uid">uid</loginProperty>  
                  <ldapCache>
                    <attributesCache size="4000" timeout="1200s" enabled="true" sizeLimit="2000"/>
                    <searchResultsCache size="2000" timeout="1200s" enabled="true" resultsSizeLimit="1000"/>
                  </ldapCache>
                </ldapRegistry>  
                  <federatedRepository>  
                    <primaryRealm name="FederatedRealm" allowOpIfRepoDown="true" delimiter="/">  
                      <participatingBaseEntry name="o=defaultWIMFileBasedRealm" id="FileBasedEntry"/>  
                      <participatingBaseEntry name="DC=ad,DC=test,DC=com" id="LDAPEntry"/>  
                      <uniqueUserIdMapping inputProperty="uniqueName" outputProperty="uniqueName"/>  
                      <userSecurityNameMapping inputProperty="principalName" outputProperty="principalName"/>  
                      <userDisplayNameMapping inputProperty="principalName" outputProperty="principalName"/>  
                      <uniqueGroupIdMapping inputProperty="uniqueName" outputProperty="uniqueName"/>      
                      <groupSecurityNameMapping inputProperty="cn" outputProperty="cn"/>  
                      <groupDisplayNameMapping inputProperty="cn" outputProperty="cn"/>         
                    </primaryRealm>  
                  </federatedRepository>  
        </server>  

Microsoft Active Directory Server using SSL

    configOverrideFiles:
      myCustomOverride.xml: |
        <?xml version="1.0" encoding="UTF-8"?>  
        <server description="DX Web Engine server">  
                <ldapRegistry  
                  id="ldap"  
                  realm="SampleLdapADRealm"  
                  host="your_LDAP_Server_HostName"  
                  port="636"  
                  ignoreCase="true"  
                  baseDN="DC=ad,DC=test,DC=com"  
                  bindDN="CN=Administrator,CN=Users,DC=ad,DC=test,DC=com"  
                  bindPassword="your_password"  
                  ldapType="Microsoft Active Directory"  
                  sslEnabled="true"
                  sslRef="customSSLConfig"
                  referral="ignore"  
                  recursiveSearch="false"  
                  bindAuthMechanism="simple"  
                  returnToPrimaryServer="true">  
                    <activedFilters 
                    userFilter="(&amp;(sAMAccountName=%v)(objectcategory=user)" 
                    groupFilter="(&amp;(cn=%v)(objectcategory=group))" 
                    userIdMap="user:sAMAccountName" 
                    groupIdMap="*:cn" 
                    groupMemberIdMap="memberOf:member">  
                    </activedFilters>  
                    <ldapEntityType name="PersonAccount">  
                      <objectClass>user</objectClass>  
                    </ldapEntityType>  
                    <ldapEntityType name="Group">  
                      <objectClass>group</objectClass>  
                  </ldapEntityType>  
                  <groupProperties>  
                      <memberAttribute name="member" scope="direct" objectClass="group"/>  
                      <membershipAttribute name="memberOf" scope="direct"/>  
                  </groupProperties>
                  <attributeConfiguration>
                    <attribute name="sAMAccountName" propertyName="uid" entityType="PersonAccount"/>
                    <attribute name="mail" propertyName="ibm-primaryEmail" entityType="PersonAccount"/>
                    <attribute name="title" propertyName="ibm-jobTitle" entityType="PersonAccount"/>                    
                  </attributeConfiguration>
                  <loginProperty name="uid">uid</loginProperty>  
                </ldapRegistry>  
                  <federatedRepository>  
                    <primaryRealm name="FederatedRealm" allowOpIfRepoDown="true" delimiter="/">  
                      <participatingBaseEntry name="o=defaultWIMFileBasedRealm" id="FileBasedEntry"/>  
                      <participatingBaseEntry name="DC=ad,DC=test,DC=com" id="LDAPEntry"/>  
                      <uniqueUserIdMapping inputProperty="uniqueName" outputProperty="uniqueName"/>  
                      <userSecurityNameMapping inputProperty="principalName" outputProperty="principalName"/>  
                      <userDisplayNameMapping inputProperty="principalName" outputProperty="principalName"/>  
                      <uniqueGroupIdMapping inputProperty="uniqueName" outputProperty="uniqueName"/>      
                      <groupSecurityNameMapping inputProperty="cn" outputProperty="cn"/>  
                      <groupDisplayNameMapping inputProperty="cn" outputProperty="cn"/>         
                    </primaryRealm>  
                  </federatedRepository>  
        </server>  

Security hardening

Out-of-the-box configuration

Several out of the box security hardenings have been applied based on Security hardening for production(https://openliberty.io/docs/latest/reference/config/ldapRegistry.html){target="_blank"}:

configOverrideFiles:
  securityOverride1.xml: | 
    <server description="DX Web Engine server"> 
      <webAppSecurity httpOnlyCookies="true" trackLoggedOutSSOCookies="false"/>
      <httpDispatcher enableWelcomePage="false" />
      <httpOptions removeServerHeader="true" />
      <httpSession invalidateOnUnauthorizedSessionRequestException="true" cookieHttpOnly="true"/>
    </server>  

The trackLoggedOutSSOCookies setting, when enabled, ensures that if a user logs out from one browser, the same user will be required to log in again if they try to access the resource from another browser. This setting helps prevent session replay attacks by marking the LTPA cookie as invalid upon logout.

However, enabling trackLoggedOutSSOCookies can impact your SSO scenarios. For example, if a user logs in from multiple browsers to the same server and logs out from one browser, they must log in again if they try to access the resource from another browser. As a result, trackLoggedOutSSOCookies is set to false by default but can be enabled for production environments.

To allow HTTP access for developer setups with the Docker image, SSL only has not been enforced.

For a production setup, you can apply the following as a server.xml override:

  configOverrideFiles:
    securityOverride2.xml: | 
      <server description="DX Web Engine server"> 
        <webAppSecurity httpOnlyCookies="true" removeServerHeader="true" disableXPoweredBy="true" trackLoggedOutSSOCookies="true" ssoRequiresSSL="true" sameSiteCookie="none"/>
        <httpSession invalidateOnUnauthorizedSessionRequestException="true" cookieHttpOnly="true" cookieSameSite="None"/>
      </server>

By default, the system is configured to trust any default certificates, which are typically included in all mainstream browsers. To change this default behavior and disable communication with third-party services, provide the following configuration setting:

  configOverrideFiles:
    securityOverride3.xml: | 
    <server description="DX Web Engine server"> 
      <ssl id="defaultSSLConfig" trustDefaultCerts="false" />
    </server>

See Security hardening for production for more information.

Additional configuration

You can use virtual hosts to limit the domains the server responds to. In the following example, the virtual host is configured to not respond to other hosts than localhost and sample.hcl.com:

<virtualHost id="default_host" allowFromEndpointRef="localHostOnly">
    <hostAlias>*:9080</hostAlias>
    <hostAlias>*:9443</hostAlias>
    <hostAlias>sample.hcl.com:80</hostAlias>
    <hostAlias>sample.hcl.com:443</hostAlias>
</virtualHost>

HCLSoftware U learning materials

Note

Access HCLSoftware U resources for free. Log in or Sign up to get started. If you have further questions, Contact us or check the FAQ.

For an introduction and a demo on how to upgrade your HCL Digital Experience deployment to the latest Cumulative Fix, go to Upgrade the HCL Digital Experience software.

To learn how to do a traditional installation, go to Deployment for Intermediate Users. In this course, you will also learn about additional installation tasks that apply to both container-based and traditional deployments using the Configuration Wizard, DXClient, ConfigEngine, and more. You can try it out using the Deployment Lab and corresponding Deployment Lab Resources.