Skip to content

Add support for Active Directory LDAP Domain Scope control - #1197

Open
OmerRaifler wants to merge 2 commits into
trinodb:mainfrom
OmerRaifler:active-directory-domain-scope
Open

Add support for Active Directory LDAP Domain Scope control#1197
OmerRaifler wants to merge 2 commits into
trinodb:mainfrom
OmerRaifler:active-directory-domain-scope

Conversation

@OmerRaifler

Copy link
Copy Markdown

Description

Adds optional support for the Microsoft Active Directory Domain Scope LDAP control.

When ldapUserBaseDn is configured to the Active Directory domain root (for example, DC=example,DC=com), subtree searches can discover users from all organizational units. However, Active Directory may also return subordinate referrals for naming contexts such as DomainDnsZones and ForestDnsZones, which can cause authentication to fail when using the Apache Directory LDAP client.

This change introduces an optional configuration that enables the Microsoft Active Directory Domain Scope control (OID 1.2.840.113556.1.4.1339) for LDAP user searches. When enabled, the search is restricted to the current domain naming context, allowing users across all OUs within the domain to be found without returning subordinate referrals.

The feature is specific to Microsoft Active Directory and is disabled by default.

Additional context and related issues

This PR supersedes the previous referral-handling approach #1174 .

During the investigation, it became clear that the underlying requirement was not to follow LDAP referrals, but to prevent Active Directory from generating subordinate referrals when searching from the domain root. The Microsoft Active Directory Domain Scope control provides the desired behavior without requiring generic LDAP referral handling.

Closes #1173

Release notes

( ) This is not user-visible or is docs only, and no release notes are required.

(x) Release notes are required, with the following suggested text:

* Add optional support for the Microsoft Active Directory Domain Scope LDAP control, allowing LDAP user searches from the Active Directory domain root without returning subordinate referrals.

@cla-bot cla-bot Bot added the cla-signed label Jul 22, 2026
@ebyhr

ebyhr commented Jul 22, 2026

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an ldapAdDomainScopeControl LDAP configuration property and documents it. Refactors LDAP authentication and membership searches to use Apache Directory SearchRequest objects, optionally attaching an Active Directory domain-scope opaque control. LDAP codec services are registered and wired into connection creation. Tests cover request construction, authentication outcomes, membership lookup, control presence, and control encoding.

Assessment against linked issues

Objective Addressed Explanation
Support LDAP user searches from the Active Directory domain root with configurable referral handling [#1173] The PR adds ldapAdDomainScopeControl, but does not add ldapReferralPolicy or implement THROW, FOLLOW, and IGNORE referral behavior.

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes identified.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gateway-ha/src/main/java/io/trino/gateway/ha/security/LbLdapClient.java`:
- Around line 95-104: Escape the raw user value according to LDAP filter rules
before substituting it into the configured search filter. Apply this in both
LbLdapClient.authenticate() and getMemberOf(), preferably through a shared
helper, while preserving the existing ${USER} replacement and
authentication/member lookup behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 32e42b26-3034-4fa7-80b0-51182bedffc3

📥 Commits

Reviewing files that changed from the base of the PR and between c7c3eda and 8ecc3cd.

📒 Files selected for processing (5)
  • docs/security.md
  • gateway-ha/src/main/java/io/trino/gateway/ha/config/LdapConfiguration.java
  • gateway-ha/src/main/java/io/trino/gateway/ha/security/LbLdapClient.java
  • gateway-ha/src/test/java/io/trino/gateway/ha/security/TestLbLdapClient.java
  • gateway-ha/src/test/resources/auth/ldapTestConfig.yml

@ebyhr ebyhr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just skimmed.


public boolean isLdapAdDomainScopeControl()
{
return this.ldapAdDomainScopeControl;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Remove redundant this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done.

LbLdapClient(LdapConfiguration ldapConfig, LdapConnectionTemplate ldapConnectionTemplate)
{
config = ldapConfig;
this.ldapConnectionTemplate = ldapConnectionTemplate;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

requireNonNull is missing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added requireNonNull checks for ldapConfig and ldapConnectionTemplate.

public UserEntryMapper(String memberOfAttribute)
{
memberOf = memberOfAttr;
this.memberOfAttribute = memberOfAttribute;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

requireNonNull is missing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added requireNonNull for memberOfAttribute in UserEntryMapper.

new OpaqueControlFactory(ldapApiService, AD_DOMAIN_SCOPE_CONTROL_OID));
return ldapApiService;
}
catch (Exception exception) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Exception looks too broad.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Narrowed the initialization failure boundary around StandaloneLdapApiService() and wrapped it in IllegalStateException.

@OmerRaifler
OmerRaifler force-pushed the active-directory-domain-scope branch from 8ecc3cd to 86b9260 Compare July 25, 2026 12:41
@OmerRaifler
OmerRaifler requested a review from Chaho12 August 3, 2026 09:51

@vishalya vishalya left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For the tests, we need to get rid of the mocks and start using the actual containers. (may be in a separate PR!)

}

static LdapApiService createLdapApiService()
throws Exception

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Exception is too generic, can we narrow it down?

final class TestLbLdapClient
{
private static final Logger log = Logger.get(TestLbLdapClient.class);
private static final String AD_DOMAIN_SCOPE_CONTROL_OID = "1.2.840.113556.1.4.1339";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we use the same definition for AD_DOMAIN_SCOPE_CONTROL_OID from the LbLdapClient?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Support LDAP user searches from the Active Directory domain root

3 participants