Allowing limited users to log in by using only LDAP

You might have scenarios where you want to provide a strict subset of accounts the ability to authenticate by using an LDAP server that is configured in your Identity Management (IM) instance.

For example, when you configure a SAML connection to use an existing LDAP connection as its identity provider (IdP), you cannot use that LDAP for IM authentication. This behavior is the default and is implemented to enforce multi-factor authentication across all account logins. You might still need to allow a subset of nonpersonal accounts or functional IDs to authenticate directly with the LDAP server despite this broader implementation. Or, perhaps you need to block some or all use of LDAP for authentication with IM, but do not want to change the user and group filters that are already set on the configurations in your LDAP connections.

In such situations, you can use the ID source update API to set an allowlist of users on one or more LDAP configurations in your cluster. You can do so by adding an ldap_allowlist in the idp_config of the LDAP configuration. The field is optional.

ldap_allowlist field settings

The following table describes the parameter values that are in the ldap_allowlist field.

Table 1. ldap_allowlist field settings
Value type Syntax Description
An array with one or more string values "ldap_allowlist": [ "user1", "user2", "user3" ] Allows only these listed accounts to use LDAP authentication through the identity management (IM) service
Empty array "ldap_allowlist": [] Deny all - blocks all attempts to use LDAP authentication through IM
No field present NA Default behavior - allows all attempts to use LDAP authentication through IM

Behavior on the IBM Cloud Pak console

If the PREFERRED_LOGIN field in the platform-auth-idp configmap has a nonempty value, the field must contain "LDAP", or else users cannot log in with LDAP. This requirement applies even in cases where an allowlist is defined for an LDAP connection.

When PREFERRED_LOGIN is set to a value that allows LDAP authentication, the enterprise LDAP login option is available to you on your IBM Cloud Pak console. Setting a nonempty allowlist on an LDAP connection that is being used as an IdP for a SAML connection adds the enterprise LDAP login option to the console if it was not already present. Then, the console no longer automatically redirects to the login page of your SAML provider: users from the allowlist can authenticate by using LDAP instead.

Behavior of ldap_allowlist with multiple LDAPs

If multiple LDAP servers are configured with IM, you can define an ldap_allowlist field on one or more of those configurations. When a user tries to log in to IM by using their LDAP credentials, IM checks whether allowlists are set on any of the configured LDAP servers. IM assumes that user or account names between the configured LDAP servers are unique. So, if any allowlists are set, IM checks whether the provided username is present in any of those allowlists. If present, IM allows the authentication to continue.

You must be careful when you add allowlists, especially when you use multiple LDAPs in IM. For example, if you add an allowlist on one LDAP and no allowlist on a second LDAP, then only the usernames from the allowlist of the first LDAP can authenticate with IM by using LDAP. Users from the second LDAP cannot use the LDAP authentication option because the second LDAP doesn't have an allowlist.

Also, if a username from the allowlist of the first LDAP exists in other LDAPs, even if the username is of a different user or account identity (for example, another person), IM allows the username to log in by using the other LDAP.

Adding ldap_allowlist field to the LDAP configuration

Use the /idprovider/v3/auth/idsource APIs to update the LDAP server with the ldap_allowlist field. Before you begin, make sure you have the following ready:

Define an ldap_allowlist by following these steps. The steps work from a terminal that uses a POSIX-compliant shell. For example, bash.

  1. Get the LDAP server information
  2. Add the ldap_allowlist field
  3. Update the LDAP configuration

Get the LDAP server information

Get the ID of the LDAP server.

  1. Obtain an access token from IM. See Preparing to run component or management API commands.

  2. Define the following environment variables:

    • access token

        export access_token=<access_token_value>
      
    • LDAP server name of the users that you want to add in the ldap_allowlist field

        export LDAP_NAME=<ldap_name>
      
    • cp-console domain name

        export CP_CONSOLE_DOMAIN=<domain_name>
      
  3. Get the LDAP server details. If you are using jq, see Using jq with the commands.

     curl \
       --location \
       --request GET \
       --insecure \
       --silent \
       --header 'Content-Type: application/json' \
       --header 'Accept: application/json' \
       --header "Authorization: Bearer ${access_token}" \
       --get \
       -d "name=${LDAP_NAME}" \
       -d 'protocol=ldap' \
       "https://${CP_CONSOLE_DOMAIN}/idprovider/v3/auth/idsource"
    

    The response looks something like the following response. Note the uid value from the response. The uid value is used in the API call to update the LDAP connection configuration.

     {
       "idp": [
         {
           "name": "example_ldap",
           "description": "An example LDAP",
           "protocol": "ldap",
           "type": "IBM Tivoli Directory Server",
           "idp_config": {
             "ldap_id": "example_ldap",
             "ldap_realm": "REALM",
             "ldap_url": "ldap://ldap.example.com:389",
             "ldap_host": "ldap.example.com",
             "ldap_port": "389",
             "ldap_protocol": "ldap",
             "ldap_basedn": "o=example.com",
             "ldap_binddn": "",
             "ldap_bindpassword": "",
             "ldap_type": "IBM Tivoli Directory Server",
             "ldap_ignorecase": "false",
             "ldap_userfilter": "(&(uid=%v)(objectclass=ePerson))",
             "ldap_useridmap": "*:uid",
             "ldap_groupfilter": "(&(cn=%v)(objectclass=groupOfUniqueNames))",
             "ldap_groupidmap": "*:cn",
             "ldap_groupmemberidmap": "groupOfUniqueNames:uniqueMember",
             "ldap_nestedsearch": "false",
             "ldap_pagingsearch": "false"
           },
           "uid": "917a0ac9-9cf0-49aa-9313-53aa5b9e87ec"
         }
       ]
     }
    
  4. Define environment variables for the UID and JSON response.

    • UID

        export uid=<ldap_uid_from_previous_command>
      
    • JSON response

        export json_response=<response_from_previous_command>
      
  5. Write the JSON response to a file so that you can edit the response and submit an update request.

     echo "${json_response}" > ldap.json
    

Add the ldap_allowlist field

Add the ldap_allowlist field in the ldap.json file that you created in the earlier section.

You must add the ldap_allowlist field to the idp_config field and set it to an array value.

Important: Remove the uid field from the ldap.json file. PUT requests do not accept payloads if the uid is present. If you used jq filter in the previous section, the command automatically removes the uid field.

After you add the ldap_allowlist field and remove the uid, the ldap.json file content must resemble the following payload. The "ldap_allowlist" array must have your list of account names:

{
  "name": "example_ldap",
  "description": "An example LDAP",
  "protocol": "ldap",
  "type": "IBM Tivoli Directory Server",
  "idp_config": {
    "ldap_id": "example_ldap",
    "ldap_realm": "REALM",
    "ldap_url": "ldap://ldap.example.com:389",
    "ldap_host": "ldap.example.com",
    "ldap_port": "389",
    "ldap_protocol": "ldap",
    "ldap_basedn": "o=example.com",
    "ldap_binddn": "",
    "ldap_bindpassword": "",
    "ldap_type": "IBM Tivoli Directory Server",
    "ldap_ignorecase": "false",
    "ldap_userfilter": "(&(uid=%v)(objectclass=ePerson))",
    "ldap_useridmap": "*:uid",
    "ldap_groupfilter": "(&(cn=%v)(objectclass=groupOfUniqueNames))",
    "ldap_groupidmap": "*:cn",
    "ldap_groupmemberidmap": "groupOfUniqueNames:uniqueMember",
    "ldap_nestedsearch": "false",
    "ldap_pagingsearch": "false",
    "ldap_allowlist": [ "ldap_user1", "ldap_user2", "ldap_user_etc"]
  }
}

Update the LDAP configuration

Update the LDAP connection configuration by using the PUT method on the idsource API.

curl \
  --location \
  --request PUT \
  --insecure \
  --silent \
  --header "Authorization: Bearer ${access_token}" \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  -d @ldap.json \
  "https://${CP_CONSOLE_DOMAIN}/idprovider/v3/auth/idsource/${uid}"

Using jq with the commands

If you are using jq, you can pipe the JSON response into it when you run the curl commands.

  1. Get the LDAP server details. The following command is the same as the curl command run in step 4, but stored as an array.

     curl_command=(
       curl
       --location
       --request GET
       --insecure
       --silent
       --header 'Content-Type: application/json'
       --header 'Accept: application/json'
       --header "Authorization: Bearer ${access_token}"
       --get
       -d "name=${LDAP_NAME}"
       -d 'protocol=ldap'
       "https://${CP_CONSOLE_DOMAIN}/idprovider/v3/auth/idsource"
     )
    
  2. Read uid and LDAP idsource JSON into variables in your shell.

    Note: The following example command assumes that the query parameters are specific enough to narrow the results down to a single LDAP entry.

     IFS='|' read -r uid json_response <<< "$("${curl_command[@]}" | jq -r -c -M '.idp[] | [.uid, (. | del(.uid))] | "\(.[0])|\(.[1])"')"
    
  3. Confirm that the variables were set properly.

     echo "UID: ${uid}"
     echo "JSON response: ${json_response}"
    
  4. Write the JSON response to a file to edit and submit for update request.

     echo "${json_response}" > ldap.json
    

Next, create the ldap_allowlist field and update the LDAP configuration.