Skip to main content
Astro Private Cloud can authenticate users directly against an LDAP directory server, so people who already have accounts in your Active Directory (AD) or OpenLDAP directory can sign in without an intermediate identity provider. When you enable LDAP, Houston binds to the directory on each sign-in, verifies the user’s credentials, provisions the account on first sign-in, and optionally maps LDAP groups to Astro Private Cloud Teams and system roles. Choose LDAP when your organization runs an on-premises AD or OpenLDAP directory that can’t or shouldn’t be exposed through an OIDC bridge, and when you want the simplest possible path from a directory account to a working Astro Private Cloud user.
Astro Private Cloud 2.1This feature was introduced in Astro Private Cloud 2.1. To access this feature, upgrade your Astro Private Cloud installation to 2.1 or later.

Overview

LDAP authentication in Astro Private Cloud gives you:
  • Username and password sign-in that goes directly to your directory. Houston never stores or caches the password.
  • Group-to-team reconciliation. Users’ directory groups can be turned into Astro Private Cloud Teams so team membership tracks the directory.
  • Group-to-system-role assignment. Directory groups can grant SYSTEM_ADMIN, SYSTEM_EDITOR, or SYSTEM_VIEWER roles on Astro Private Cloud.
  • Multiple group-resolution strategies to match how your directory represents membership. Houston supports four modes — direct memberOf, AD nested groups, sub-scoped search, and client-side recursive walk.
Supported directories: Active Directory Domain Services (AD DS), Microsoft Entra Domain Services, and OpenLDAP. Any RFC 4511 LDAP server works for basic authentication; nested-group behavior depends on which resolution mode the server supports.
The Astro CLI doesn’t accept LDAP credentials through its username and password prompt. LDAP users obtain an OAuth token by signing in to the Astro Private Cloud UI and paste it into astro login. See Sign in to the Astro CLI for the exact CLI flow.

Prerequisites

Before you enable LDAP, confirm:
  • The LDAP or LDAPS host is reachable from the Astro Private Cloud control plane. Houston makes outbound TCP connections to the host and port defined by auth.ldap.host and auth.ldap.port.
  • You have a service account in the directory with permission to search under the configured searchBase. Houston uses this account for the initial bind (the “service bind”). It doesn’t need to modify entries — search-only permission is enough.
  • You know the base distinguished name (DN) of your directory and the DN structure for users and groups. You use these when you set bindDn, searchBase, and the groups.* fields.
  • You have write access to the Astro Private Cloud values.yaml file and can apply Helm-values changes. See Apply a config change.

Configure the APC API through Helm values

Add an auth.ldap block to your astronomer.houston.config section in values.yaml. The following example shows every field you can set, with production-safe defaults. Field-by-field details for TLS, attribute mapping, group resolution, team reconciliation, and system-role assignment follow in later sections.
After you save values.yaml, apply the change to your platform through the standard Helm upgrade flow. See Apply a config change.

Secure bindCredentials with a Kubernetes Secret

The bindCredentials field accepts an inline value, but that inline value ends up on disk in values.yaml and in Helm release history. For production installs, source it from a Kubernetes Secret instead. Astro Private Cloud uses the same astronomer.houston.secret[] mechanism that the OIDC guide uses for clientSecret and that the install guide uses for EMAIL__SMTP_URL. Each entry in the list becomes a valueFrom.secretKeyRef environment variable on the Houston pod, and Houston reads the LDAP bind password from that environment variable rather than from the config file.
1

Create a Kubernetes secret

Replace <the-bind-password> with the password for the service account named in bindDn.
2

Reference the secret from values.yaml

Add the secret: block under astronomer.houston and remove the inline bindCredentials line:
The environment variable takes precedence when both an inline value and a secretKeyRef are present. secretKey is optional and defaults to value. Apply the change with helm upgrade and Houston restarts with the new environment variable bound.
The same astronomer.houston.secret[] block already carries OIDC client secrets and the SMTP connection string. If you already use one of those, add the LDAP entry as another list item rather than creating a second block.

Configure TLS

LDAP transports credentials over the network. Any deployment outside a fully isolated test environment must use TLS. Houston supports three transport modes through auth.ldap.tls.mode. Set auth.ldap.tls.verifyServerCert: true (the default) to have Houston validate the LDAP server’s certificate chain against its trusted CAs. This applies to both starttls and ldaps modes. Set it to false only for dev environments where the server presents a self-signed certificate that isn’t in Houston’s trust store. If your LDAP server presents a certificate signed by a private certificate authority, add the CA certificate to Houston’s trust store through the platform configuration and keep verifyServerCert: true. See Configure private CAs. auth.ldap.port is optional. When unset, Houston derives it from tls.mode: 636 for ldaps, 389 for none and starttls. Set the field explicitly only when your directory listens on a non-standard port.

Attribute mapping

Houston reads two attributes from each user’s LDAP entry to build the corresponding Astro Private Cloud user account:
  • attributes.email (default mail) — the value used as the user’s email address in Astro Private Cloud. Houston converts the value to lowercase before it stores the user. If the attribute is multi-valued in your directory, Houston takes the first value.
  • attributes.name (default cn) — the value used as the user’s full name in Astro Private Cloud.
For AD deployments, displayName produces a friendlier full name than cn:

Group name attribute

By default, when Houston resolves groups through the direct memberOf mode, it takes the group’s name from the leftmost relative distinguished name (RDN) of the group’s DN. For example, a memberOf: cn=engineering,ou=groups,dc=example,dc=com value produces a group name of engineering. To use a different attribute for the group name — such as description — set groups.nameAttribute:
When nameAttribute is anything other than cn, Houston fetches each group’s entry individually to read the configured attribute. This is one additional LDAP query per group, so the direct-memberOf mode is slower with a custom nameAttribute. The default nameAttribute: cn skips the per-group fetch and stays on the fast path.

Configure group resolution

If you enable groups.enabled: true, Houston resolves the user’s directory groups on each sign-in. Houston supports four resolution strategies through groups.nestedGroups. Choose the mode that matches how your directory represents nested membership. Every mode returns the same shape of result — a flat list of group names — so downstream reconciliation and role assignment don’t depend on which mode you pick.

Direct memberOf mode

The default. Use for Active Directory (where memberOf is native) or for OpenLDAP with the memberof overlay populated.
Verify that memberOf is populated on your user entry:
The response must include one memberOf: line per group the user belongs to. If it’s missing, either enable the memberof overlay on your directory or switch to nestedGroups: "search".

Nested groups mode

Use for Active Directory when you need transitive group membership — for example, when your users are direct members of a role group that is nested inside a broader access group and you want Houston to see both.
This mode requires groups.searchBase. Houston constructs the transitive query internally; you don’t need to configure the matching rule OID. Verify with ldapsearch:
The response includes every group the user reaches through direct or nested membership.

Search mode

Use when your directory doesn’t populate memberOf but does index group member entries.
groups.searchBase and groups.searchFilter are both required. Houston substitutes {{dn}} with the signed-in user’s DN before it runs the search. Multiple {{dn}} placeholders are supported — for example, to match either member or uniqueMember:
Houston escapes the user’s DN according to RFC 4515 before substitution. DN values that contain filter special characters (*, (, ), \, NUL) are handled safely.

Recursive mode

Use for non-AD directories where memberOf is populated on user entries and on group entries, and where you need transitive group traversal.
groups.maxDepth caps the walk. Houston stops walking once it reaches the configured depth, even if more parent groups exist above that point. The default of 10 is enough for most nesting patterns. Recursive mode starts from the user’s memberOf attribute and walks up the group hierarchy. If your OpenLDAP directory doesn’t populate memberOf, enable the memberof overlay on the directory server, or switch to nestedGroups: "search", which reads group membership from group entries instead.

Reconcile groups into Astro Private Cloud Teams

When groups.reconcileTeams: true, every resolved group becomes an Astro Private Cloud Team, and the signed-in user is added to the corresponding team.
Teams that Houston creates through LDAP reconciliation are tagged with provider='ldap' in the Houston database. They don’t collide with Teams from OIDC providers or Teams created manually — the two provider spaces are independent. For the extended cross-provider details, see Import identity provider (IdP) groups.

Filter which groups become Teams

groups.teamFilterRegex restricts which directory groups become Teams. Only groups whose name matches the regular expression are reconciled; the rest are ignored.
The regex is JavaScript syntax and is applied case-sensitively. It runs after group resolution completes, so it filters the exact names Houston sees — for direct-memberOf mode, those are the CN components of each memberOf DN. Only LDAP groups are affected; OIDC has its own separate filter.

Assign system roles from directory groups

Houston can grant SYSTEM_ADMIN, SYSTEM_EDITOR, or SYSTEM_VIEWER platform roles to Teams that come from specific directory groups.
Each list holds group names that map to that system role. Houston normalizes DN values in these lists to their CN components before matching, so you can list either short names (astro-platform-admins) or full DN values (cn=astro-platform-admins,ou=groups,dc=corp,dc=example,dc=com). Priority is SYSTEM_ADMIN > SYSTEM_EDITOR > SYSTEM_VIEWER. If the same group appears in more than one list, the highest role wins. Roles apply to the Team that Houston creates from the LDAP group — individual users inherit the role through their team membership rather than getting a direct role binding. Houston reconciles system roles on every sign-in. When a user is removed from a role-mapping group in the directory, they lose the corresponding system role the next time they sign in.
Setting manageSystemPermissions.enabled: false stops future synchronization from directory groups but doesn’t revoke roles that were previously auto-assigned. Existing system role assignments remain in place until you remove them manually in the Astro Private Cloud UI, in Settings > Teams. The OIDC equivalent (auth.openidConnect.manageSystemPermissionsViaIdpGroups.enabled) behaves the same way.

Security guards

Houston enforces the following guards on every LDAP sign-in.

Service and user bind are separate

Houston uses bindDn and bindCredentials only for the search that resolves the user’s DN. The actual authentication is a second bind that Houston performs with the user’s own DN and the password they submitted. The service account never authenticates users, and user passwords never travel outside the sign-in request. If a user with the same email already exists on the platform through local auth or an OIDC provider, LDAP sign-in for that email is rejected. Linking an existing account to LDAP requires an explicit OAuthCredential(provider='ldap', ...) row. See Sign-in migration paths.

Deactivated users can’t sign in

Only Astro Private Cloud users in the ACTIVE or PENDING status can complete an LDAP sign-in. Deactivating a user through Houston blocks their LDAP sign-in even if their directory account remains active.

Last-admin protection

Houston prevents removing the last user with the SYSTEM_ADMIN role. This applies to system-role reconciliation as well as manual role changes.

Error messages don’t distinguish failure modes

A failed bind produces a generic “Invalid username or password” message regardless of whether the user doesn’t exist, the password is wrong, or the account is deactivated. This prevents an attacker from probing the directory for valid usernames.

Passwords are never stored or cached

Houston uses the user’s password only during the sign-in bind. It doesn’t persist the password to the database, log it, or hold it in memory beyond the request.

Group-resolution failure isn’t sign-in failure

If group resolution returns an error or no groups, Houston still signs the user in. Their teams and system roles aren’t updated, but they can use the platform with whatever team and role state they already have. See Diagnose configuration issues for the log lines that surface this case.

LDAP filters escape user DN values

When Houston builds a filter that includes the user’s DN — for example, (member={{dn}}) in search mode — it escapes filter special characters (*, (, ), \, NUL) to their \XX hex-pair form according to RFC 4515. A crafted DN can’t alter the semantics of the query.

Diagnose configuration issues

Houston emits warn-level log lines that surface two silent-failure classes operators otherwise miss.

Invalid nestedGroups value

If groups.nestedGroups holds anything other than false, "ad", "recursive", or "search" — for example the boolean true, an integer, or a typo like "recursvie" — Houston logs a warn identifying the invalid value and falls back to direct-memberOf mode. Example:
Sign-in continues to work under the fallback, but the mode you configured is silently overridden. Search the Houston pod logs for Invalid auth.ldap.groups.nestedGroups after a config change to confirm your value was accepted.

Empty group resolution when reconciliation is expected

If you set groups.reconcileTeams: true or groups.manageSystemPermissions.enabled: true but group resolution returned zero groups for the signed-in user, Houston logs a warn that includes the user’s DN and a mode-specific mitigation hint. Example in direct-memberOf mode:
The hint text is mode-aware. In search mode, the hint suggests checking searchBase and searchFilter. In recursive mode, the hint points at the memberof overlay. Filter the Houston pod logs for LDAP group resolution returned no groups when a user reports that their teams or system roles aren’t being applied.

Sign-in migration paths

When both local auth and LDAP are enabled on the same platform, Astro Private Cloud user accounts aren’t automatically linked across providers. This is intentional — the account-takeover guard requires an explicit OAuthCredential(provider='ldap', ...) row before an LDAP sign-in can attach to an existing user. Choose one of three operator-driven paths to migrate.

Backfill

Recommended for platforms with a working user base you want to preserve. For each existing user who is moving to LDAP, insert an OAuthCredential(provider='ldap', oauthUserId=<identity>) row where <identity> is the value that matches auth.ldap.searchFilter for that user (typically their mail or uid). Backfill preserves User.id, existing team memberships, role bindings, and the audit trail across the migration. Users notice no change other than the sign-in flow itself.

Re-create

Clean-slate path. The Astro Private Cloud administrator deletes existing User rows for the affected users; the deletion cascades through Email, OAuthCredential, RoleBinding, and _TeamToUser in the Houston database. Users then sign in through LDAP as new accounts. Re-creation is simpler operationally but every affected user receives a new User.id, and existing audit entries in your security information and event management (SIEM) system continue to reference the old ID. Choose this path only if audit continuity across the migration isn’t a requirement.

Coexistence

Keep both providers active with no migration. Each user keeps whichever credential they were created with — local users continue to sign in with their email and password, LDAP users sign in through the directory. Astro Private Cloud doesn’t attempt to unify accounts even when the emails match.
A self-serve, in-platform “link my LDAP account to this Astro Private Cloud user” flow isn’t part of Astro Private Cloud 2.1.0. The three paths in the preceding section are the supported options.

Verify the setup

After you apply the LDAP configuration and Houston restarts, verify end-to-end sign-in.
1

Sign in through the UI

Open the Astro Private Cloud UI and sign in with a directory user’s credentials. Successful sign-in indicates that Houston can reach the directory, the service bind succeeded, the user search filter matched, and the user’s bind succeeded.
2

Confirm the database state

For a successful first sign-in, Houston writes:
  • One row in User with status = 'active'
  • One row in Email for the user’s directory email
  • One row in OAuthCredential with provider = 'ldap'
  • One row per resolved LDAP group in Team with provider = 'ldap' (when you enable reconcileTeams)
  • One RoleBinding per Team-to-system-role mapping (when you enable manageSystemPermissions)
You can confirm from a Houston pod with psql:
3

Verify the TLS mode on the wire

The LDAP server logs show which TLS transport Houston used:
  • mode: none — plain BIND lines with ssf=0.
  • mode: starttls — an EXT oid=1.3.6.1.4.1.1466.20037 line and TLS established tls_ssf=N before the bind.
  • mode: ldapsTLS established tls_ssf=N immediately after the ACCEPT on port 636.
If the server-side log shows ssf=0 when you expected TLS, review the tls.mode value and confirm the client and server ports agree.

Audit logging

Every LDAP sign-in attempt produces an audit record with action: auth.login, identical in shape to sign-ins through local auth and OIDC. Existing SIEM rules that filter on auth.login catch LDAP sign-ins uniformly. The record’s entity.identity field holds the LDAP username submitted at sign-in, and the password field is redacted by the platform’s existing redaction rules. Failed binds produce records with outcome: failure and the generic sign-in error message. Underlying cert or network errors go to the Houston pod log, not the audit record.

Limitations

  • The Astro CLI doesn’t accept LDAP credentials through its username and password prompt. LDAP users authenticate to the CLI by signing in to the Astro Private Cloud UI, retrieving an OAuth token, and pasting it into astro login. See Sign in to the Astro CLI for the token flow.
  • OIDC and LDAP can coexist, but accounts aren’t automatically linked between providers even when the emails match. See Sign-in migration paths.
  • Airflow UI authentication is unchanged. LDAP configuration on Astro Private Cloud doesn’t affect the Airflow security model. Airflow continues to use its Flask AppBuilder (FAB) authentication.
  • A self-serve account-linking UI isn’t available. Linking an existing Astro Private Cloud user to their LDAP identity requires the Backfill path described earlier.

Reference: auth.ldap fields