Skip to content

KNOX-3277 : LDAP Proxy improvements for working with AD backend#1177

Merged
smolnar82 merged 2 commits intoapache:masterfrom
handavid:KNOX-3277-ldapproxy-ad
Mar 20, 2026
Merged

KNOX-3277 : LDAP Proxy improvements for working with AD backend#1177
smolnar82 merged 2 commits intoapache:masterfrom
handavid:KNOX-3277-ldapproxy-ad

Conversation

@handavid
Copy link
Contributor

@handavid handavid commented Mar 13, 2026

KNOX-3277 LDAP Proxy improvements for working with AD backend

What changes were proposed in this pull request?

The LdapProxyBackend and GroupLookupInterceptors are updated to work with sAMAccountName in addition to uid and cn for user and group lookup. This involved adding the memberOf and sAMAccountName attribute types to the schema used by the proxy.

Group retrieval during user search is fixed to respect the useMemberOf flag.

Tests for the LdapProxyBackend were added.

How was this patch tested?

Changes were manually tested by running ant start-test-gateway configured against both AD and the test LDAP server.
Unit tests were added to cover the LdapProxyBackend behavior.

The LdapProxyBackend and GroupLookupInterceptors are updated to work
with sAMAccountName in addition to uid and cn for user and group lookup.
This involved adding the memberOf and sAMAccountName attribute types
to the schema used by the proxy.

Group retrieval during user search is fixed to respect the useMemberOf flag.

Tests for the LdapProxyBackend were added.
@handavid
Copy link
Contributor Author

@lmccay

@lmccay lmccay requested review from lmccay and smolnar82 March 13, 2026 18:46
@github-actions
Copy link

github-actions bot commented Mar 13, 2026

Test Results

7 tests   7 ✅  1s ⏱️
1 suites  0 💤
1 files    0 ❌

Results for commit 6d253d4.

♻️ This comment has been updated with latest results.

@lmccay lmccay changed the title KNOX-3277. LDAP Proxy improvements for working with AD backend KNOX-3277 : LDAP Proxy improvements for working with AD backend Mar 13, 2026
@smolnar82 smolnar82 requested review from hanicz and moresandeep March 18, 2026 09:22
Copy link
Contributor

@moresandeep moresandeep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @handavid for the PR! looks great, I have few questions, if you can answer them that'd be great!

private LdapBackend backend;
private static final Pattern UID_PATTERN = Pattern.compile(".*\\(uid=([^)]+)\\).*");
private static final Pattern CN_PATTERN = Pattern.compile(".*\\(cn=([^)]+)\\).*");
private static final Pattern SAMAACCOUNTNAME_PATTERN = Pattern.compile(".*\\(sAMAccountName=([^)]+)\\).*");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this SAMAACCOUNTNAME_PATTERN should be case-insensitive. This is what the MS docs say about cases for attribute names https://learn.microsoft.com/en-us/windows/win32/ad/characteristics-of-attributes.

Perhaps we need something like (?i) (not tested, used Gemini :) )
private static final Pattern SAMAACCOUNTNAME_PATTERN = Pattern.compile("(?i).*\\(sAMAccountName=([^)]+)\\).*");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a name normalizing filter somewhere in the interceptor chain prior to this point. The filter will have the normalized sAMAccountName string.

renamed "Entity" to "Entry" in LdapProxyBackend.
rethrow exception caught when copying attributes.
@handavid
Copy link
Contributor Author

@moresandeep I've updated the PR based on your comments. Thanks!

Copy link
Contributor

@moresandeep moresandeep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @handavid the PR looks good. Thank you for your contribution to Knox!

@smolnar82
Copy link
Contributor

Thanks, @handavid, for your contribution.
May I ask you to provide some information about the manual testing you did which includes the topology and the relevant settings? This would help us in the future to see the setup if we needed configure this feature for our own tests.
Thanks!

@handavid
Copy link
Contributor Author

Thanks, @handavid, for your contribution. May I ask you to provide some information about the manual testing you did which includes the topology and the relevant settings? This would help us in the future to see the setup if we needed configure this feature for our own tests. Thanks!

@smolnar82
Here's a snipped of the gateway-site.xml that configures the LDAP Proxy and Backend. I've included configs for either the knox test ldap server or some AD server.

    <!-- LDAP Proxy Service Configuration -->
    <property>
        <name>gateway.ldap.enabled</name>
        <value>true</value>
        <description>Enable the embedded LDAP service for user and group lookups. Set to true to enable.</description>
    </property>
    <property>
        <name>gateway.ldap.port</name>
        <value>3890</value>
        <description>Port for the LDAP service to listen on. Default is 3890.</description>
    </property>
    <property>
        <name>gateway.ldap.base.dn</name>
        <value>dc=proxy,dc=com</value>
        <description>Base DN for LDAP entries in the proxy server. Default is dc=proxy,dc=com.</description>
    </property>
    <property>
        <name>gateway.ldap.backend.type</name>
        <value>ldap</value>
        <description>Backend type for LDAP service. Currently supported: file, ldap. Future: jdbc, knox.</description>
    </property>

    <!-- LDAP backend proxy configuration using knox test LDAP server -->
    <!--
    <property>
        <name>gateway.ldap.backend.ldap.url</name>
        <value>ldap://localhost:33389</value>
        <description>LDAP server URL for proxy backend</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.remoteBaseDn</name>
        <value>dc=hadoop,dc=apache,dc=org</value>
        <description>Base DN of the remote LDAP server</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.systemUsername</name>
        <value>uid=guest,ou=people,dc=hadoop,dc=apache,dc=org</value>
        <description>LDAP bind DN for proxy backend authentication</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.systemPassword</name>
        <value>guest-password</value>
        <description>LDAP bind password for proxy backend authentication</description>
    </property>

    <property>
        <name>gateway.ldap.backend.data.file</name>
        <value>${GATEWAY_DATA_HOME}/ldap-users.json</value>
        <description>Path to JSON data file for file-based backend. Supports ${GATEWAY_DATA_HOME} variable.</description>
    </property>
    -->
    <!-- LDAP backend proxy configuration using AD -->
    <property>
        <name>gateway.ldap.backend.ldap.url</name>
        <value>ldap://<AD host>:389</value>
        <description>LDAP server URL for proxy backend</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.remoteBaseDn</name>
        <value><REMOTE BASE DN></value>
        <description>Base DN of the remote LDAP server</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.systemUsername</name>
        <value>cn=<REMOTE USERNAME>,cn=Users,<REMOTE BASE DN></value>
        <description>LDAP bind DN for proxy backend authentication</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.systemPassword</name>
        <value><REMOTE PASSWORD></value>
        <description>LDAP bind password for proxy backend authentication</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.userIdentifierAttribute</name>
        <!-- configure attribute to be used for user search against backend. Usually uid, cn, or sAMAccountName -->
        <!-- <value>cn</value> -->
        <value>sAMAccountName</value>
        <description>Attribute used for identifying users</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.userSearchBase</name>
        <value>cn=users,<REMOTE BASE DN></value>
        <description>Search base for users</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.groupSearchBase</name>
        <value>ou=groups,<REMOTE BASE DN></value>
        <description>Search base for groups</description>
    </property>
    <property>
        <name>gateway.ldap.backend.ldap.useMemberOf</name>
        <value>true</value>
        <description>Whether to use the memberOf attribute for efficiency when retrieving group memberships</description>
    </property>

After building knox, I ran the following commands to install and start the test gateway

ant install-test-home
# update the gateway-site.xml with the above configs
ant start-test-gateway

I then tested using ldapsearch against the LDAP proxy and verified that the returned information matched the queries against AD

# single user search
ldapsearch -v -x -H ldap://localhost:3890 -b '<REMOTE BASE DN>' '(sAMAccountName=username)'
ldapsearch -v -x -H ldap://localhost:3890 -b '<REMOTE BASE DN>' '(cn=username)'

# user substring search
ldapsearch -v -x -H ldap://localhost:3890 -b '<REMOTE BASE DN>' '(sAMAccountName=substring*)'
ldapsearch -v -x -H ldap://localhost:3890 -b '<REMOTE BASE DN>' '(cn=substring*)'
ldapsearch -v -x -H ldap://localhost:3890 -b '<REMOTE BASE DN>' '(sAMAccountName=*)'

@smolnar82
Copy link
Contributor

Thanks, @handavid, this is very useful!

@smolnar82 smolnar82 merged commit 18ab6c5 into apache:master Mar 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants