LDAP policy

What

Use the LDAP Policy when access to protected resources should be limited to users in your LDAP provider—such as your admin users, organization users, and developers—especially when OAuth token access is either unnecessary or too heavyweight. The policy is also designed for retrieving domain name metadata for use in API proxy flows.

For example you can have an API call execute only when a user is successfully authenticated against LDAP; and then optionally retrieve DN attributes for the user after authentication succeeds.

For additional information, see:

Samples

Username/password authentication

<Ldap name="4GLdapPolicy">
   <LdapResource>ldap1</LdapResource>
   <Authentication>
       <UserName ref="request.header.username"/>
       <Password ref="request.header.password"/>
       <Scope>subtree</Scope>
       <BaseDN></BaseDN> <!-- default is dc=apigee,dc=com -->
    </Authentication>
 </Ldap>

This sample provides authentication against an LDAP provider. The policy passes username and password from the request to LDAP for authentication.

DN attribute authentication

<Ldap name="LdapPolicy">
   <LdapResource>ldap1</LdapResource>
   <Authentication>
       <Password ref="request.header.password"/>
       <SearchQuery>mail={request.header.mail}</SearchQuery>
       <Scope>subtree</Scope>
       <BaseDN></BaseDN> <!-- default is dc=apigee,dc=com -->
    </Authentication>
 </Ldap>

This policy gets the user’s DN with the email in the request header, then authenticates the user against LDAP with the password provided in the request header.

Searching LDAP

<Ldap name="LdapPolicy">
    <!-- using a custom LDAP provider -->
    <LdapConnectorClass>com.custom.ldap.MyProvider</LdapConnectorClass>
    <LdapResource>MyLdap</LdapResource>
    <Search>
        <BaseDN></BaseDN> <!-- default is dc=apigee,dc=com -->
        <SearchQuery>mail={request.header.mail}</SearchQuery>
        <Attributes>
            <Attribute>address</Attribute>
            <Attribute>phone</Attribute>
            <Attribute>title</Attribute>
        </Attributes>
        <Scope></Scope> <!-- default is ‘subtree’ -->
    </Search>
</Ldap>

This policy references a custom LDAP provider. It uses the email address in the request header to identify the user, then retrieves the user’s address, phone, and title from LDAP. The retrieved DN attributes are stored in a variable. See "Policy-specific variables".

To search LDAP and retrieve DN attributes, the request must include administrator credentials.

Element reference

Following are descriptions of the LDAP Policy elements and attributes.

Element

Description

Ldap

Parent element with a name attribute for you to enter the policy name.

LdapConnectorClass

When using the LDAP Policy with a custom LDAP provider (not provided by Apigee), specify the fully qualified LDAP connector class. That's the class in which you implemented Apigee's ExternalLdapConProvider interface.

LdapResource

Enter the environment name of the LDAP resource. See Create an LDAP resource for more information.

BaseDN

The base level of LDAP under which all of your data exists. For example, in Apigee's LDAP provider, all data are under dc=apigee,dc=com.

Scope

  • object: Authentication or search occurs only at the base level of LDAP.
  • onelevel: Authentication or search occurs one level below the base level.
  • subtree (default): Authentication or search occurs at the base level and fully recursively below base.

Authentication

Authentication

Parent element for the authentication behavior you implement.

UserName

Empty element that takes one of the following attributes:

  • ref: A reference to the username in the request, such as request.header.username
  • value: The username itself

If you aren't authenticating with username, or if username isn't included in the request, you don't need to include this element.

If username is in the request, but you want to authenticate a user with a DN attribute other than username, such as email, include a SearchQuery to get the user email associated with the password. The LDAP policy uses username to query the LDAP provider for the corresponding email address, which is then used for authentication.

Password

Empty element that takes one of the following attributes:

  • ref: A reference to the password in the request, such as request.header.password
  • value: The encrypted password itself

SearchQuery

If you want to authenticate using a DN attribute other than username, such as email, configure the LDAP policy to get a DN attribute from the request (such as username), which is used to identify the user in LDAP, retrieve the email, and authenticate the user.

For example, assuming LDAP defines a "mail" attribute for storing email address:

<SearchQuery>mail={request.header.mail}</SearchQuery>

Search

Search

Parent element for the search behavior you implement.

SearchQuery

By identifying the user with metadata in the request or response, you can use this element to retrieve additional DN attributes for the user from LDAP. For example, if the request contains the user email, and your LDAP defines a mail attribute for storing user email addresses, you&'d use the following setting:

<SearchQuery>mail={request.header.mail}</SearchQuery>

This query searches LDAP for an email matching the email in the request, and the policy can now retrieve additional DN attributes for that user with the Attributes element.

Attributes

Use one or more <Attribute> elements to identify the DN metadata you want to retrieve for the user. At least one attribute is required.

For example, after the SearchQuery identifies the user, the policy can now retrieve DN attributes for the user such as address, phone number, and the user's title, as shown in the following example.

Attribute values are the DN attribute names defined in your LDAP.

<Attributes>
  <Attribute>address</Attribute>
  <Attribute>phone</Attribute>
  <Attribute>title</Attribute>
</Attributes>

Usage notes

Apigee Edge for Private Cloud lets you leverage an LDAP provider in API calls. With the LDAP Policy, applications can authenticate credentials against users stored in LDAP, and you can retrieve distinguished names (DNs) from LDAP—the metadata, or attributes, associated with each user, such as email, address, and phone number. The returned DN is stored in a variable for further use by the API proxy.

The LDAP Policy provides:

  • Authentication: User credentials supplied in the request are validated against credentials in the LDAP provider. The LDAP policy gives you a lot of flexibility with authentication, letting you use any DN value along with the password, even if that DN value you want isn't in the request. For example, say you need to use email / password for authentication. The following options are possible:
    • If the email is in the request, you can simply use that with the password for LDAP authentication.
    • If the email isn't in the request, but another DN attribute is (such as phone number), you can use the phone number to get the corresponding email from LDAP, then use email / password to authenticate.
  • Distinguished name (DN) search: In addition to authentication, you can also use the LDAP Policy to identify a user attribute in the request, such as email, and perform a query that retrieves other DN attributes from LDAP for that user. The retrieved DN is stored in a variable.

Create an LDAP resource

The LDAP policy leverages an LDAP resource that you create in Apigee Edge. An LDAP resource provides the connection information to your LDAP repository.

To create and manage LDAP resources, use the following API and payload:

API

Create (POST) an LDAP resource or list (GET) all LDAP resources:

/v1/organizations/org_name/environments/environment/ldapresources

Get details for (GET), Update (POST), and Delete (DELETE) an LDAP resource:

/v1/organizations/org_name/environments/environment/ldapresources/ldap_resource_name

Payload

Following is a sample XML payload with usage comments.

<LdapResource name="ldap1">
  <Connection>
    <Hosts>
      <!-- port is optional: defaults to 389 for ldap:// and 636 for ldaps:// -->
      <Host port="636">foo.com</Host>
    </Hosts>
    <SSLEnabled>false</SSLEnabled> <!-- optional, defaults to false -->
    <Version>3</Version> <!-- optional, defaults to 3-->
    <Authentication>simple</Authentication> <!-- optional, only simple supported -->
    <ConnectionProvider>jndi|unboundid</ConnectionProvider> <!-- required -->
    <ServerSetType>single|round robin|failover</ServerSetType> <!-- not applicable for jndi -->
    <!-- If using a custom LDAP provider, the fully qualified class: -->
    <LdapConnectorClass>com.custom.ldap.MyProvider</LdapConnectorClass>
  </Connection>
  <ConnectPool enabled="true"> <!-- enabled is optional, defaults to true -->
    <Timeout>30000</Timeout> <!-- optional, in milliseconds; if not set, no timeout -->
    <Maxsize>50</Maxsize> <!-- optional; if not set, no max connections -->
    <Prefsize>30</Prefsize> <!-- optional; if not set, no pref size -->
    <Initsize></Initsize> <!-- optional; if not set, defaults to 1 -->
    <Protocol></Protocol> <!-- optional; if not set, defaults to 'ssl plain' -->
  </ConnectPool>
  <Admin>
    <DN>cn=manager,dc=apigee,dc=com</DN>
    <Password>secret</Password>
  </Admin>
</LdapResource>

curl example: Create an LDAP resource

The following example creates an LDAP resource named ldap1.

curl -X POST -H "Content-Type: application/xml" \
  https://api.enterprise.apigee.com/v1/organizations/myorg/environments/test/ldapresources \
  -u apigee_email:password -d \
  '<LdapResource name="ldap1">
    <Connection>
      <Hosts>
      <Host>foo.com</Host>
      </Hosts>
      <SSLEnabled>false</SSLEnabled>
      <Version>3</Version>
      <Authentication>simple</Authentication>
      <ConnectionProvider>unboundid</ConnectionProvider>
      <ServerSetType>round robin</ServerSetType>
    </Connection>
    <ConnectPool enabled="true">
      <Timeout>30000</Timeout>
      <Maxsize>50</Maxsize>
      <Prefsize>30</Prefsize>
      <Initsize></Initsize>
      <Protocol></Protocol>
    </ConnectPool>
    <Admin>
      <DN>cn=manager,dc=apigee,dc=com</DN>
      <Password>secret</Password>
    </Admin>
  </LdapResource>'

Response codes

Following are the HTML response codes the policy returns for success or failure:

  • Success: 200
  • Failure: 401

Using a custom LDAP provider in Edge for Private Cloud

Using a custom LDAP provider

Apigee Edge for Private Cloud comes with an LDAP provider that is already configured to interact with the LDAP Policy. However, if you are using a custom LDAP provider, you must enable the provider to support the LDAP Policy. To do this:

  1. In your LDAP provider class, implement the ExternalLdapConProvider interface.
    public interface ExternalLdapConProvider {
      void doAuthentication(LdapBean LlapBean, String userDN, String password, String baseDN);
    
      void doSearchAndAuthentication(LdapBean LlapBean, String password, String baseDN, String query, int scope);
    
      Collection<Map<String, String[]>> doSearch(LdapBean LlapBean, String query,
        String baseDN, Collection<String> requiredAttributes, int scope);
    
      void closeConnections();
    }
  2. In the <LdapConnectorClass> of the policy configuration (next sections), add the fully qualified class name of your custom LDAP provider.
  3. Download this file: custom-ldap.jar_.zip. (You might have to right-click and select Save As.)
  4. Unzip it.
  5. Add the custom-ldap.jar file to your environment and ensure that it's in your classpath.
  6. Create an environment resource for your LDAP provider. You'll use the environment resource name in the <LdapResource> element of the LDAP policy.

Using the UnboundID LDAP SDK for Java

You can use the UnboundID LDAP SDK with the LDAP policy, but you must first download version 2.3.1 and add it to each of your Message Processor's classpaths.

To use the UnboundID LDAP SDK with the LDAP policy:

  1. Open a browser and navigate to the Sourceforge file repository for the UnboundID LDAP SDK:
    https://sourceforge.net/projects/ldap-sdk/files/
  2. Find version 2.3.1 (SE or Standard Edition) of the SDK and download the ZIP file for that version. For example, download "unboundid-ldapsdk-2.3.1-se.zip".
  3. Extract the JAR file from the SDK ZIP file, as the following example shows:
    unzip -j -d ~/tmp ~/Downloads/unboundid-ldapsdk-2.3.1-se.zip unboundid-ldapsdk-2.3.1-se/unboundid-ldapsdk-se.jar

    This command extracts just the JAR file to the ~/tmp directory. It drops the directory structure with -j, although this is optional.

  4. On each Message Processor node:
    1. Copy the JAR file to the Message Processor's /opt/apigee/edge-gateway/lib/thirdparty directory.

      Edge adds all thirdparty libraries in the /opt/apigee/edge-gateway/lib/thirdparty directory to the classpath.

    2. Restart the Message Processor:
      /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart

Flow variables

Following are the LDAP Policy variables populated by a SearchQuery.

Variable

Description

ldap.policyName.execution.success

After the policy is executed, this flow variable contains a value of "true" or "false", depending on the result.

ldap.policyName.search.result[index].
  attribute.attrName[index]=value

The flexible format of this variable, the index in particular: accounts for multiple attributes, as well as attributes with multiple values. Index is a number that starts at 1. If no index number is provided, the default index number is 1.

If the policy returns address, phone, and email, you can retrieve the first attribute and value using these variables:

ldap.policyName.search.result.attribute.address
ldap.policyName.search.result.attribute.phone
ldap.policyName.search.result.attribute.email

If you wanted to retrieve the third address attribute in the search results, you'd use this:

ldap.policyName.search.result[3].attribute.address

If an attribute had multiple values (for example, if a user has multiple email addresses), you'd retrieve the second email address from the results like this:

ldap.policyName.search.result.attribute.mail[2]

Error codes

Errors returned from Edge policies follow a consistent format as described in the Error code reference.

This policy uses the following error codes:

Error Code Message
InvalidAttributeName Invalid attribute name {0}.
InvalidSearchBase Search base can not be empty.
InvalidValueForPassword Invalid value for password field. It can not be empty.
InvalidSearchScope Invalid scope {0}. Allowed scopes are {1}.
InvalidUserCredentials Invalid user credentials.
InvalidExternalLdapReference Invalid external ldap reference {0}.
LdapResourceNotFound Ldap resource {0} not found.
BaseDNRequired Base DN required.
OnlyReferenceOrValueIsAllowed Only value or reference is allowed for {0}.
AttributesRequired At least one attribute required for search action.
UserNameIsNull User name is null.
SearchQueryAndUserNameCannotBePresent Both search query and username can not be present in the authentication action. Please specify either one of them.