Skip to content

Merge feature branch to master#7149

Open
liulinC wants to merge 60 commits into
masterfrom
feature/ldaps
Open

Merge feature branch to master#7149
liulinC wants to merge 60 commits into
masterfrom
feature/ldaps

Conversation

@liulinC

@liulinC liulinC commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Lin Liu and others added 30 commits March 9, 2026 07:16
Signed-off-by: Lin Liu <lin.liu01@citrix.com>
- Update all extauth configuration into domain_info
- config_winbind_daemon take domain_info as argument
- persist_extauth_config take domain_info as argument

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
This API can switch between ldap and ldaps so existing users
can switch without rejoin domain
This API would
- Perform proper checks
- Call this API to all hosts
- Restore to previous states if any host set failed
- Set winbind configuration with new ldaps and restart daemon

Besides, this commit also do following refines
- Move kdcs_of_domain etc to head of file to share with others
- Setup DomainInfo module for encapsulation
- Drop exec_with_new_task with current context

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
- add host-external-auth-set-ldaps for debug purpose
- use find_opt to reduce backtrace
- use Listext.List.try_map_collect to reduce indent and improve perf
- some wording refine

Co-authored-by: Pau Ruiz Safont <psafont@users.noreply.github.com>
Signed-off-by: Lin Liu <lin.liu01@citrix.com>
This API can switch between ldap and ldaps so existing users can switch
without rejoin domain
This API would
- Perform proper checks
- Call this API to all hosts
- Restore to previous states if any host set failed
- Set winbind configuration with new ldaps and restart daemon

Besides, this commit also do following refines
- Move kdcs_of_domain etc to head of file to share with others
- Setup DomainInfo module for encapsulation
- Drop exec_with_new_task with current context
`try_map_any f l` apply f on l and return
- Ok if any `f e` succeed
- Error list if all failed

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
- Define new errors for invalid certificate, pool and host level
- Remove AD joined check as it was already done in extauth.ml
- Move certificate to extauth_plugin_ADwinbind.ml so it can shared
between set-ldaps and enable-ad
- ping_domain use try_map_any to propagate the error details

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
External auth configure/write ops(enable, disable, set-ldaps)
should be synced with read ops(auth-username-and-password, etc).
Xapi/ocaml does not prefer read/write locks, so we just use
classic mutex, presuming no much concurrent ops.
At the same time, serialize_auth_service is introduced to skip
the lock if performance is preferred

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
External auth configure/write ops(enable, disable, set-ldaps) should be
synced with read ops(auth-username-and-password, etc). Xapi/ocaml does
not prefer read/write locks, so we just use classic mutex, presuming no
much concurrent ops.
At the same time, serialize_auth_service is introduced to skip the lock
if performance is preferred
Select CA bundles to setup TLS connection to DC in following
preference
- /etc/trusted-certs/ca-bundle-ldaps.pem
- /etc/trusted-certs/ca-bundle-general.pem
- /etc/stunnel/certs (Legacy, will be removed with trusted certs)

Raise proper error code when no certs exists

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
Select CA bundles to setup TLS connection to DC in following preference
- /etc/trusted-certs/ca-bundle-ldaps.pem
- /etc/trusted-certs/ca-bundle-general.pem
- /etc/stunnel/certs (Legacy, will be removed with trusted certs)

Raise proper error code when no certs exists
Signed-off-by: Lin Liu <lin.liu01@citrix.com>
During pool join, if both joining host and the pool joined the same
domain, pre-check is passed and the joining host is permitted to
join the pool.
However, the ldaps status needs to be synced during pool join to
keep pool consistent.
Note: certificates will be synced during the pool join, so no need
to worry about the ldaps certificates.

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
Signed-off-by: Lin Liu <lin.liu01@citrix.com>
During pool join, if both joining host and the pool joined the same
domain, pre-check is passed and the joining host is permitted to join
the pool.
However, the ldaps status needs to be synced during pool join to keep
pool consistent.
Note: certificates will be synced during the pool join, so no need to
worry about the ldaps certificates.
Keep winbind configuration on failure by default is good for debug
- Get configuration details that cause the fail
- Can perform a manual retry

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
Keep winbind configuration on failure by default is good for debug
- Get configuration details that cause the fail
- Can perform a manual retry
- Add `ldaps` as one of the trusted certs purpose
- Bump up `external_auth_set_ldaps` API version according to master
- Get trusted certs dir by consts instead of hardcode

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
- Add `ldaps` as one of the trusted certs purpose
- Bump up `external_auth_set_ldaps` API version according to master
- Get trusted certs dir by consts instead of hardcode
minglumlu and others added 26 commits May 12, 2026 15:37
Signed-off-by: Ming Lu <ming.lu@cloud.com>
Signed-off-by: Ming Lu <ming.lu@cloud.com>
Add a new API pool.sync_trusted_certificates_from to facilitate the
secure LDAP feature in pool.join case. It is also a general API to
download trusted certificates.
- Provide different error message for various reasons
- Provide error details for setup TLS

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
- Provides different error message for various reasons
- Provide error details for setup TLS
XenServer9 has winbind_kerberos_encryption_type set to strong,
This means only AES based encryption types are supported.

Capture this error details from output and report to user, so
the encryption failures can be easily identified

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
XenServer9 has winbind_kerberos_encryption_type set to strong, This
means only AES based encryption types are supported.

Capture this error details from output and report to user, so the
encryption failures can be easily identified
ldaps sync failed is ignored by ignore_error by intention,
however, `@@` is right-associative low-precedence application and
the fun () -> body greedily absorbs every following statement until
the enclosing delimiter, the second ignore_error is part of the first
lambda's body, thus, the exception in first ignore_error(sync ldaps)
skiped the second ignore_error function body, e.g: update_non_vm_metadata
and later got no change to execute.

The issue is fixed by removing `@@` and providing function body enclosed

Signed-off-by: Lin Liu <lin.liu01@citrix.com>
ldaps sync failed is ignored by ignore_error by intention, however, `@@`
is right-associative low-precedence application and the fun () -> body
greedily absorbs every following statement until the enclosing
delimiter, the second ignore_error is part of the first lambda's body,
thus, the exception in first ignore_error(sync ldaps) skiped the second
ignore_error function body, e.g: update_non_vm_metadata and later got no
change to execute.

The issue is fixed by removing `@@` and providing function body enclosed
Rename the user-facing "certs"/"certificates" wording to "trusted
certs" in the ldaps external-auth error paths, and add a hint pointing at
both possible causes for invalid trusted certificates.

- extauth_plugin_ADwinbind.ml: "No certs..." -> "No trusted certs..."
- AUTH_NO_TRUSTED_CERTS: "No certificates found..." ->
  "No trusted CA certificates found..."
- external-auth-ldaps.md: align error-code descriptions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Lin Liu <lin.liu01@citrix.com>
Rename the user-facing "certs"/"certificates" wording to "trusted certs"
in the ldaps external-auth error paths, and add a hint pointing at both
possible causes for invalid trusted certificates.

- extauth_plugin_ADwinbind.ml: "No certs..." -> "No trusted certs..."
- AUTH_NO_TRUSTED_CERTS: "No certificates found..." ->
  "No trusted CA certificates found..."
- AUTH_INVALID_TRUSTED_CERTS and
AUTH_ENABLE_FAILED_INVALID_TRUSTED_CERTS: reword to "trusted
certificates" and append "This can be caused by trusted certificates on
XenServer or certificates on Active Directory."
- external-auth-ldaps.md: align error-code descriptions.
When LDAPS is enabled, pool.enable_external_auth could intermittently
fail with POOL_AUTH_ENABLE_FAILED_SETUP_TLS_CONNECTION: "net ads join"
auto-selects a domain controller via DsGetDcName without considering its
TLS certificate, so if the chosen DC presents a certificate that does not
chain to a trusted CA the LDAPS bind fails (GnuTLS signer_not_found).

When ldaps is enabled, probe the candidate DCs in on_enable and join via
the first one whose LDAPS certificate validates against the trusted CAs:
enumerate the KDCs (kdcs_of_domain) and run Ldap.query_sid over LDAPS for
each, then pin the join with "net ads join -S <dc>". The probe uses the
supplied join credentials rather than the machine account, which does not
exist yet during the join.

For this, query_sid takes optional ?duser/?dpass arguments: when both are
given it authenticates via the USER/PASSWD environment variables instead
of --machine-pass.

When ldaps is disabled the behaviour is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Lin Liu <lin.liu01@citrix.com>
When LDAPS is enabled, pool.enable_external_auth could intermittently
fail with POOL_AUTH_ENABLE_FAILED_SETUP_TLS_CONNECTION: "net ads join"
auto-selects a domain controller via DsGetDcName without considering its
TLS certificate, so if the chosen DC presents a certificate that does
not chain to a trusted CA the LDAPS bind fails (GnuTLS
signer_not_found).

When ldaps is enabled, probe the candidate DCs in on_enable and join via
the first one whose LDAPS certificate validates against the trusted CAs:
enumerate the KDCs (kdcs_of_domain) and run Ldap.query_sid over LDAPS
for each, then pin the join with "net ads join -S <dc>". The probe uses
the supplied join credentials rather than the machine account, which
does not exist yet during the join.

For this, query_sid takes optional ?duser/?dpass arguments: when both
are given it authenticates via the USER/PASSWD environment variables
instead of --machine-pass.

When ldaps is disabled the behaviour is unchanged.
Fold Wbinfo.kdc_of_domain (wbinfo --getdcname) into the same match as
Ldap.query_user in query_subject_information_user, so a DC-location or
LDAP query failure falls back to default_account instead of aborting
subject creation via let*. Fixes subject-add for one-way trusted-domain
users when getdcname cannot locate the trusted DC; attributes are
refreshed later by update_all_subjects.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Lin Liu <Lin.Liu01@cloud.com>
Fold Wbinfo.kdc_of_domain (wbinfo --getdcname) into the same match as
Ldap.query_user in query_subject_information_user, so a DC-location or
LDAP query failure falls back to default_account instead of aborting
subject creation via let*. Fixes subject-add for one-way trusted-domain
users when getdcname cannot locate the trusted DC; attributes are
refreshed later by update_all_subjects.
Signed-off-by: Sola.Zhang <Sola.Zhang@cloud.com>
Comment thread ocaml/idl/datamodel_host.ml Outdated
~lifecycle:
[
( Published
, "26.12.0-next"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you set to version 26.15.0-next. I think this can't be recognized by auto generating tool. So we need to change it manually. A correct version help us to do the work.

liulinC and others added 3 commits June 29, 2026 08:22
external_auth_set_ldaps (host and pool) declared its ~lifecycle and
param_release versions as 26.12.0-next. The lifecycle auto-generation
tool does not recognise -next versions, so the release must be set
manually to the current development version. Update all 8 occurrences
(ocaml/idl/datamodel_host.ml: 4, ocaml/idl/datamodel_pool.ml: 4) from
26.12.0-next to 26.15.0-next.

Addresses review feedback on PR #7149.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Lin Liu <Lin.Liu01@cloud.com>
…cates_from

pool.sync_trusted_certificates_from is a new message declared with an empty
~lifecycle:[], so (like its sibling trusted-certificate messages) its
prototyped version must be recorded in the generated
ocaml/idl/datamodel_lifecycle.ml. That entry was missing, leaving the
generated file out of date: `make` / dune build @ocaml/idl/update-dm-lifecycle
would otherwise produce an uncommitted diff. Add the auto-generated entry,
stamping it at the current development version (26.15.0-next).

Generated with: dune build @ocaml/idl/update-dm-lifecycle --auto-promote

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Lin Liu <Lin.Liu01@cloud.com>
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.

4 participants