Skip to content

[WIP] certificates: Allow LDAP enrollment#1401

Draft
denisonbarbosa wants to merge 11 commits into
mainfrom
ldap-cert-enrollment
Draft

[WIP] certificates: Allow LDAP enrollment#1401
denisonbarbosa wants to merge 11 commits into
mainfrom
ldap-cert-enrollment

Conversation

@denisonbarbosa

Copy link
Copy Markdown
Member

Allow certificate enrollment through LDAP protocol.

denisonbarbosa and others added 11 commits June 1, 2026 07:22
Add the following Go module dependencies required for the native
LDAP-based certificate enrollment implementation:

- github.com/go-ldap/ldap/v3: LDAP client for CA/template discovery
- github.com/oiweiwei/go-msrpc: DCE/RPC client for MS-ICPR CSR submission
- github.com/oiweiwei/gokrb5.fork/v9: Kerberos library for GSSAPI auth

Along with their transitive dependencies (ASN.1/BER, NTLMSSP, etc.).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement a gssapiClient adapter that bridges the gokrb5 Kerberos
library to the go-ldap GSSAPIClient interface. This handles the
three-phase GSSAPI/SASL handshake:

1. AP-REQ token generation with mutual authentication
2. AP-REP verification and subkey extraction (RFC 4121)
3. SASL negotiation with integrity-only wrap/unwrap (RFC 4752)

This client is used by the LDAP connector to authenticate to Active
Directory domain controllers using the machine's Kerberos credentials.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add two new modules for the LDAP enrollment path:

- state.go: JSON-based enrollment state persistence that replaces the
  Samba TDB cache. Tracks enrolled CAs, templates, certificate/key file
  paths, and certmonger tracking IDs per machine.

- trust.go: System CA trust store management. Installs root CA
  certificates from AD to the local trust directory, creates symlinks
  in the global trust directory, and triggers update-ca-certificates.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement LDAP queries for discovering Certificate Authorities and
certificate templates from Active Directory:

- Query pKIEnrollmentService objects under the configuration naming
  context to discover enrollment services (MS-CAESO 4.4.5.3.1.2)
- Query pKICertificateTemplate objects for template attributes
  (minimum key size, etc.)
- Kerberos-authenticated LDAP connections using the machine's ccache
- DNS-based DC hostname resolution for SPN matching

The LDAPClient and LDAPConnector interfaces allow dependency injection
for testing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement certificate signing request submission to AD CS using the
MS-ICPR protocol (ICertPassage::CertServerRequest) over DCE/RPC:

- CSR generation with configurable key sizes per template
- Kerberos-authenticated RPC connections using the machine's ccache
- UTF-16 attribute encoding for certificate template selection
- Support for both direct submission and pending (manual approval) flows

The CSRSubmitter interface allows dependency injection for testing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a new binary that acts as a certmonger submission helper for
AD CS certificate enrollment via the MS-ICPR protocol.

Supported operations:
- SUBMIT: Submit a CSR to AD CS and return the issued certificate
- IDENTIFY: Return the helper identity string
- GET-SUPPORTED-TEMPLATES: Query available templates from the CA

The helper authenticates using Kerberos credentials from KRB5CCNAME
and replaces the cepces-submit helper for the LDAP enrollment method.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add constants for the certificate enrollment method selection:

- CertEnrollmentLDAP: selects native Go LDAP/RPC enrollment
- CertEnrollmentCEPCES: selects legacy Python/CEPCES enrollment
- DefaultCertificateEnrollment: defaults to CEPCES for backward
  compatibility with existing installations

Update the example configuration file with the new
certificate_enrollment option.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refactor the certificate Manager to support two selectable enrollment
methods via the certificate_enrollment config key:

- "ldap": Native Go implementation using LDAP for CA discovery and
  MS-ICPR/RPC for CSR submission. This is the new default for fresh
  installations.

- "cepces": Legacy implementation delegating to the embedded Python
  script with Samba/CEPCES. This remains the default for existing
  installations.

Changes across the stack:
- certificate.go: Add enrollment method dispatch in ApplyPolicy,
  new enroll/unenroll flows for LDAP path, new Option functions
  (WithEnrollmentMethod, WithLDAPConnector, WithCSRSubmitter)
- daemon.go: Add --certificate-enrollment CLI flag and config binding
- adsysservice.go: Wire WithCertificateEnrollment option through
- manager.go: Replace WithCertAutoenrollCmd with WithCertificateManager
  and WithCertificateEnrollment options
- policy.go: Remove cert-autoenroll-script debug command (script is
  no longer the primary enrollment mechanism)
- Update all tests (certificate_test, manager_test, integration tests)
  to use LDAP mocks instead of shell script mocks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update the Debian packaging to reflect the shift from CEPCES to
native LDAP enrollment:

- postinst: Create /etc/adsys.yaml with certificate_enrollment: ldap
  for new installations (existing installs keep CEPCES default)
- control: Move python3, python3-samba, python3-cepces from Depends
  to Recommends (no longer required for LDAP enrollment)
- control: Remove samba from Build-Depends
- install: Remove usr/share/adsys/python (vendored Samba code)
- rules: Remove vendored Python copy step, disable dh_auto_test
- apport: Remove python3-samba from related packages
- copyright: Remove vendored Samba copyright entry
- changelog: Add 0.16.5~test12 entry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update all certificate-related documentation to reflect the new
LDAP enrollment method:

- explanation/certificates.md: Document both enrollment methods,
  configuration options, and new policy application sequence
- how-to/certificates/setup.md: Separate package requirements by
  enrollment method (LDAP vs CEPCES)
- how-to/certificates/configure.md: Add enrollment method config
  section, update certmonger helper example
- how-to/certificates/troubleshoot.md: Remove CEPCES-specific
  debugging section, update state file paths
- reference/external-links.md: Remove CEP/CES section
- how-to/certificates/index.md: Remove cepces dependency mention

Also update e2e provisioning to remove python3-cepces installation
since the LDAP enrollment method doesn't require it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The adsysd integration tests run the daemon against a guest-only smbd
with no real KDC, relying on libsmbclient falling back from kerberos to
anonymous authentication. Samba >= 4.23 dropped that implicit fallback,
causing the SMB fetch to fail with EINVAL. Gate a test-only
ADSYS_TESTS_WITHOUT_KERBEROS environment variable in ad.New() so the
daemon skips kerberos entirely when running under the test harness; it
must never be set in production.

Additionally, the mock D-Bus/polkit/systemd containers resolve the
connecting user through the bind-mounted /etc/passwd and /etc/group.
When the suite runs as a user only known through NSS (e.g. an LDAP/SSSD
user not present in the local files), the container can't resolve the
UID and resets the connection. Generate augmented passwd/group databases
that also contain the current user and group before mounting them.
@denisonbarbosa denisonbarbosa force-pushed the ldap-cert-enrollment branch from de6f2bd to e7ef5e8 Compare June 8, 2026 13:57
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.

1 participant