Install Directory Proxy

Directory proxy servers forward LDAP requests for user data to remote directory servers. Proxy servers make it possible to provide a single point of access to a directory service, and to hide implementation details from client applications.

Check Compatibility

DS proxy servers connect to remote LDAP directory servers using proxied authorization. The proxied authorization control (OID: 2.16.840.1.113730.3.4.18) is defined by RFC 4370 Lightweight Directory Access Protocol (LDAP) Proxied Authorization Control. If the LDAP directory server does not support proxied authorization, it cannot be used with DS directory proxy server.

The following list of LDAP servers do not support proxied authorization, and so, do not work with DS directory proxy server:

  • Microsoft Active Directory

  • Oracle Internet Directory

The following list of LDAP servers support proxied authorization according to their documentation. ForgeRock does not test all servers listed:

  • ForgeRock Directory Services

  • ApacheDS

  • NetIQ eDirectory

  • OpenDJ

  • OpenLDAP

  • Oracle Directory Server Enterprise Edition

  • PingDirectory

  • Red Hat Directory Server

If your LDAP server does not appear in the lists above, check its documentation regarding support for proxied authorization. Alternatively, check the list of supportedControl values on the server’s root DSE.

Try DS Directory Proxy

Before installing DS directory proxy server in production, or with a non-DS directory server, try it on your computer.

Configuration with proxy and directory servers
Figure 1. Proxy Configuration

The following examples demonstrate DS directory proxy server forwarding LDAP requests to two DS replicas on your computer. This demonstration includes the following high-level tasks:

  • Install two DS directory server replicas as proxied servers.

  • Set up the DS directory proxy server to forward requests to the DS directory servers.

  • Send LDAP requests to the DS directory proxy server, and observe the results.

The deployment key for installing the server is stored in the environment variable DEPLOYMENT_KEY. Install all servers in the same deployment with the same deployment key and deployment key password. For details, read Key Management.

Install two DS directory server replicas with the evaluation and proxied server profiles:

# Unpack server files:
unzip -q ~/Downloads/DS-7.1.1.zip -d /tmp

# Copy server files before setting up each replica:
mkdir /path/to/opendj && cp -r /tmp/opendj/* /path/to/opendj
mkdir /path/to/replica && cp -r /tmp/opendj/* /path/to/replica

# Set up the servers as replicas of each other
# with StartTLS support for the proxy connections:
/path/to/opendj/setup \
  --deploymentKey $DEPLOYMENT_KEY \
  --deploymentKeyPassword password \
  --hostname localhost \
  --ldapPort 11389 \
  --enableStartTls \
  --ldapsPort 11636 \
  --adminConnectorPort 14444 \
  --rootUserDN uid=admin \
  --rootUserPassword password \
  --profile ds-evaluation \
  --profile ds-proxied-server \
  --set ds-proxied-server/baseDn:dc=example,dc=com \
  --replicationPort 18989 \
  --bootstrapReplicationServer localhost:28989 \
  --acceptLicense \
  --start \
  --quiet

/path/to/replica/setup \
  --deploymentKey $DEPLOYMENT_KEY \
  --deploymentKeyPassword password \
  --hostname localhost \
  --ldapPort 21389 \
  --enableStartTls \
  --ldapsPort 21636 \
  --adminConnectorPort 24444 \
  --rootUserDN uid=admin \
  --rootUserPassword password \
  --profile ds-evaluation \
  --profile ds-proxied-server \
  --set ds-proxied-server/baseDn:dc=example,dc=com \
  --replicationPort 28989 \
  --bootstrapReplicationServer localhost:18989 \
  --acceptLicense \
  --start \
  --quiet

# Update PATH to include DS tools:
export PATH=/path/to/opendj/bin:${PATH}

Notice that the examples apply two setup profiles to each replica:

  • The DS evaluation setup profile adds sample Example.com data.

    For details, see Install DS for Evaluation.

  • The DS proxied server setup profile adds a service account for the proxy server, and sets ACIs to grant the account permission to use proxied authorization. The proxy authenticates to the directory servers with its certificate, whose subject DN is CN=DS, O=ForgeRock.com.

Set up a directory proxy server to forward requests to the replicas:

# Copy server files before setting up the proxy:
mkdir /path/to/proxy && cp -r /tmp/opendj/* /path/to/proxy

# Set up the proxy server to access the replicas:
/path/to/proxy/setup \
 --serverId proxy \
 --deploymentKey $DEPLOYMENT_KEY \
 --deploymentKeyPassword password \
 --rootUserDN uid=admin \
 --rootUserPassword password \
 --hostname localhost \
 --ldapPort 1389 \
 --enableStartTls \
 --ldapsPort 1636 \
 --adminConnectorPort 4444 \
 --profile ds-proxy-server \
 --set ds-proxy-server/bootstrapReplicationServer:"localhost:14444" \
 --set ds-proxy-server/bootstrapReplicationServer:"localhost:24444" \
 --set ds-proxy-server/rsConnectionSecurity:start-tls \
 --set ds-proxy-server/certNickname:ssl-key-pair \
 --set ds-proxy-server/keyManagerProvider:PKCS12 \
 --set ds-proxy-server/trustManagerProvider:PKCS12 \
 --start \
 --acceptLicense

# Grant access to data through the proxy server:
dsconfig \
 create-global-access-control-policy \
 --hostname localhost \
 --port 4444 \
 --bindDN uid=admin \
 --bindPassword password \
 --policy-name "Authenticated access to example.com data" \
 --set authentication-required:true \
 --set request-target-dn-equal-to:"dc=example,dc=com" \
 --set request-target-dn-equal-to:"**,dc=example,dc=com" \
 --set permission:read \
 --set permission:write \
 --set allowed-attribute:"*" \
 --set allowed-attribute:isMemberOf \
 --set allowed-attribute-exception:authPassword \
 --set allowed-attribute-exception:userPassword \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --no-prompt

As you set up only DS servers which all use the same default schema, there is no need to manually align the proxy LDAP schema with the directory server schema.

Send LDAP requests to the DS directory proxy server, and observe the results.

The following example searches the directory through the proxy:

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery \
 --baseDN "ou=people,dc=example,dc=com" \
 "(|(cn=Babs Jensen)(cn=Sam Carter))" \
 cn

dn: uid=bjensen,ou=People,dc=example,dc=com
cn: Barbara Jensen
cn: Babs Jensen

dn: uid=scarter,ou=People,dc=example,dc=com
cn: Sam Carter

The following example modifies directory data through the proxy:

$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=bjensen,ou=people,dc=example,dc=com \
 --bindPassword hifalutin << EOF
dn: uid=bjensen,ou=People,dc=example,dc=com
changetype: modify
replace: description
description: Modified by Babs Jensen
EOF

# MODIFY operation successful for DN uid=bjensen,ou=People,dc=example,dc=com

Notice that the bind DNs and passwords are those of the users in the remote directory service.

For more background on each high-level task, read the rest of this page.

Create a Service Account

When preparing to use DS directory proxy servers with directory servers that are not DS servers, create a service account for the proxy to connect to the non-DS remote directory service.

The directory proxy server binds with this service account, and then forwards LDAP requests on behalf of other users.

For DS directory servers, use the proxied server setup profile if possible. For details, see Install DS For Use With DS Proxy.

The service account must have the following on all remote directory servers:

  • The same bind credentials.

    If possible, use mutual TLS to authenticate the proxy user with the backend servers.

  • The right to perform proxied authorization.

    Make sure the LDAP servers support proxied authorization (control OID: 2.16.840.1.113730.3.4.18).

    For details, see RFC 4370, Lightweight Directory Access Protocol (LDAP) Proxied Authorization Control.

  • When using a replication discovery mechanism with remote DS directory servers, the service account requires the config-read and monitor-read privileges for the service discovery mechanism. It requires the proxied-auth privilege and an ACI to perform proxied authorization.

The following listing shows an example service account that you could use with DS replicas. Adapt the account as necessary for your directory service:

dn: uid=proxy
objectClass: top
objectClass: account
objectClass: ds-certificate-user
uid: proxy
ds-certificate-subject-dn: CN=DS, O=ForgeRock.com
ds-privilege-name: config-read
ds-privilege-name: monitor-read
ds-privilege-name: proxied-auth
aci: (targetcontrol="ProxiedAuth")
  (version 3.0; acl "Allow proxied authorization";
  allow(read) userdn="ldap:///uid=proxy";)

Set Up a Directory Proxy

The deployment key for installing the server is stored in the environment variable DEPLOYMENT_KEY. Install all servers in the same deployment with the same deployment key and deployment key password. For details, read Key Management.

Proxy to DS Servers

  1. Before proceeding, install the server files.
    For details, see Unpack Files.

  2. Run the setup --profile ds-proxy-server command.

    The command is located where you installed the files, /path/to/opendj/setup:

    The following example sets up a directory proxy server that discovers remote servers based on the DS replication topology. It works with replicas set up using the ds-proxied-server setup profile.

    This feature works only with DS servers. If the remote LDAP servers in your deployment are not DS servers, see Proxy to Non-DS Servers.

    This proxy forwards all requests to public naming contexts of remote servers. Generally, this means requests targeting user data, as opposed to the proxy’s configuration, schema, or monitoring statistics:

    $ /path/to/opendj/setup \
     --deploymentKey $DEPLOYMENT_KEY \
     --deploymentKeyPassword password \
     --rootUserDN uid=admin \
     --rootUserPassword str0ngAdm1nPa55word \
     --hostname ds.example.com \
     --ldapPort 1389 \
     --enableStartTls \
     --ldapsPort 1636 \
     --adminConnectorPort 4444 \
     --profile ds-proxy-server \
     --set ds-proxy-server/bootstrapReplicationServer:"rs.example.com:4444" \
     --set ds-proxy-server/rsConnectionSecurity:start-tls \
     --set ds-proxy-server/certNickname:ssl-key-pair \
     --set ds-proxy-server/keyManagerProvider:PKCS12 \
     --set ds-proxy-server/trustManagerProvider:PKCS12 \
     --start \
     --acceptLicense

    This example uses mutual TLS with a certificate generated with a deployment key and password. Adjust the security settings as required for your deployment.

Proxy to Non-DS Servers

  1. Before proceeding, install the server files.
    For details, see Unpack Files.

  2. Run the setup --profile ds-proxy-server command.

    The command is located where you installed the files, /path/to/opendj/setup:

    The following example sets up a directory proxy server that has a static list of remote servers to connect to. It forwards only requests targeting dc=example,dc=com:

    # Initially configure the server with a fake replication service discovery mechanism:
    $ /path/to/opendj/setup \
     --deploymentKey $DEPLOYMENT_KEY \
     --deploymentKeyPassword password \
     --rootUserDN uid=admin \
     --rootUserPassword str0ngAdm1nPa55word \
     --hostname ds.example.com \
     --ldapPort 1389 \
     --enableStartTls \
     --ldapsPort 1636 \
     --adminConnectorPort 4444 \
     --profile ds-proxy-server \
     --set ds-proxy-server/bootstrapReplicationServer:"fake-rs.example.com:4444" \
     --set ds-proxy-server/rsConnectionSecurity:start-tls \
     --start \
     --acceptLicense
    # Create a static service discovery mechanism:
    $ dsconfig \
     create-service-discovery-mechanism \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword str0ngAdm1nPa55word \
     --mechanism-name "Static Service Discovery Mechanism" \
     --type static \
     --set primary-server:local1.example.com:636 \
     --set primary-server:local2.example.com:636 \
     --set secondary-server:remote1.example.com:636 \
     --set secondary-server:remote2.example.com:636 \
     --set ssl-cert-nickname:ssl-key-pair \
     --set key-manager-provider:PKCS12 \
     --set trust-manager-provider:"JVM Trust Manager" \
     --set use-ssl:true \
     --set use-sasl-external:true \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt
    # Replace the fake replication service discovery mechanism with the static one:
    $ dsconfig \
     set-backend-prop \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword str0ngAdm1nPa55word \
     --backend-name proxyRoot \
     --set shard:"Static Service Discovery Mechanism" \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

    This example uses mutual TLS with a certificate generated with a deployment key and password. Adjust the security settings as required for your deployment.

Configure Access Control

  1. Explicitly grant appropriate access to remote data.

    The following example grants authenticated users access to data under dc=example,dc=com:

    $ dsconfig \
     create-global-access-control-policy \
     --hostname localhost \
     --port 4444 \
     --bindDN uid=admin \
     --bindPassword str0ngAdm1nPa55word \
     --policy-name "Authenticated access to example.com data" \
     --set authentication-required:true \
     --set request-target-dn-equal-to:"dc=example,dc=com" \
     --set request-target-dn-equal-to:"**,dc=example,dc=com" \
     --set permission:read \
     --set permission:write \
     --set allowed-attribute:"*" \
     --set allowed-attribute:isMemberOf \
     --set allowed-attribute-exception:authPassword \
     --set allowed-attribute-exception:userPassword \
     --usePkcs12TrustStore /path/to/opendj/config/keystore \
     --trustStorePassword:file /path/to/opendj/config/keystore.pin \
     --no-prompt

    DS proxy servers do not use ACIs for access control. Instead, they use global access control policies. By default, the access rights are configured the same as the default settings for a directory server. You no doubt need to adapt these policies for your deployment. For additional examples, see Access Control.

  2. Make sure the backend directory servers are properly prepared, as described Create a Service Account.

For more background on LDAP proxy features, see LDAP Proxy.

Default Global Policies

Access control rules are defined using individual access control policy entries. A user’s access is defined as the union of all access control rules that apply to that user. In other words, an individual access control rule can only grant additional access and can not remove rights granted by another rule. This approach results in an access control policy which is easier to understand and audit, since all rules can be understood in isolation.

Policy Settings

Anonymous extended operation and control access

authentication-required
  • false

allowed-extended-operation
  • Cancel

  • GetSymmetricKey

  • PasswordModify

  • StartTLS

  • WhoAmI

allowed-control
  • Assertion

  • MatchedValues

  • NoOp

  • PasswordQualityAdvice

  • PermissiveModify

  • PostRead

  • PreRead

  • RealAttrsOnly

  • SimplePagedResults

  • VirtualAttrsOnly

  • AuthorizationIdentity

  • PasswordPolicy

  • TransactionId

  • Vlv

Authenticated extended operation and control access

authentication-required
  • true

allowed-extended-operation
  • PasswordPolicyState

allowed-control
  • ManageDsaIt

  • SubEntries

  • RelaxRules

  • SubtreeDelete

  • ServerSideSort

Schema access

authentication-required
  • true

request-target-dn-equal-to
  • cn=schema

permission
  • read

allowed-attribute
  • objectClass

  • @subschema

  • etag

  • ldapSyntaxes

  • modifiersName

  • modifyTimestamp

Root DSE access

authentication-required
  • false

request-target-dn-equal-to
  • ""

permission
  • read

allowed-attribute
  • objectClass

  • namingContexts

  • subSchemaSubEntry

  • supportedAuthPasswordSchemes

  • supportedControl

  • supportedExtension

  • supportedFeatures

  • supportedLDAPVersion

  • supportedSASLMechanisms

  • supportedTLSCiphers

  • supportedTLSProtocols

  • vendorName

  • vendorVersion

  • fullVendorVersion

  • alive

  • healthy

Monitor access

authentication-required
  • true

request-target-dn-equal-to
  • cn=monitor

permission
  • read

allowed-attribute
  • *

  • +

Align LDAP Schema

Directory servers can reject LDAP change requests that do not comply with LDAP schema. LDAP client applications read LDAP schema definitions from directory servers to determine in advance whether a change request complies with LDAP schema.

When an LDAP client requests LDAP schema from the proxy, the proxy returns its LDAP schema. Ideally, the LDAP schema definitions on the proxy match the LDAP schema definitions on the remote directory servers. Otherwise, client applications might check their requests against the proxy’s LDAP schema, and yet still see their requests fail with schema violations when the proxy forwards a request to a directory server.

If, after installation, the LDAP schema definitions on the directory servers and the proxy server differ, align the LDAP schema of the proxy server with the LDAP schema of the remote directory servers.

For more information, see LDAP Schema. Schema definitions on a non-DS remote directory server might require translation from another format before you add them on DS directory proxy servers.

Troubleshooting

Common errors with DS directory proxy server installations include the following:

49 (Invalid Credentials)

When LDAP bind requests through the proxy invariably result in an invalid credentials error, but bind requests to the directory server with the same credentials do not, the problem lies with the proxy service account.

The proxy service account must allow bind requests to the directory server. The following example demonstrates a request sent directly to a directory server. The command makes a bind request and then a search request. The directory server is set up according to the instructions in Try DS Directory Proxy:

$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --usePkcs12TrustStore /path/to/opendj/config/keystore \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=kvaughan,ou=people,dc=example,dc=com \
 --bindPassword bribery \
 --baseDN "ou=people,dc=example,dc=com" \
 "(|(cn=Babs Jensen)(cn=Sam Carter))" \
 cn

dn: uid=bjensen,ou=People,dc=example,dc=com
cn: Barbara Jensen
cn: Babs Jensen

dn: uid=scarter,ou=People,dc=example,dc=com
cn: Sam Carter

Start with the filtered directory server access log, logs/filtered-ldap-access.audit.json, to debug bind failures.

123 (Authorization Denied)

Make sure that access control on the remote LDAP servers allows the proxy service account to use the proxied authorization control.

Furthermore, proxied authorization does not allow operations on remote LDAP servers as the following users. Do not connect as these users when trying to access a directory server through the proxy:

  • Directory superuser (uid=admin)

  • An anonymous user (no bind DN, no bind password)

For administrative requests on remote LDAP servers, access the servers directly. This includes monitoring requests. Many applications perform some operations anonymously, such as reading the root DSE or LDAP schema. These operations are in fact requests to the proxy, not forwarded to remote LDAP servers. For applications to receive an appropriate response for LDAP schema requests, align LDAP schema on the proxy with LDAP schema on the remote LDAP servers as described above.