LDAP Viewer and LDAP 登录 - #6489
Conversation
t8y2
left a comment
There was a problem hiding this comment.
request changes:这个 head 目前不能合并。请先 rebase/split 到当前 main;GitHub 显示 3,032 个变更文件且状态为 CONFLICTING,merge-base 仍停留在 2026-04-30。
另外有三个 blocker:
apps/desktop/src/lib/backend/tauri.ts的ldapSearch()始终抛错,而桌面运行时会选择 Tauri backend,导致 LDAP 树、详情和搜索在桌面端全部不可用。crates/dbx-web/src/auth.rs在DBX_DISABLE_PASSWORD=1时无条件放行 API;启用 LDAP 后登录页虽要求认证,未登录请求仍能直接访问受保护接口。agents/drivers/ldap/src/main/java/com/dbx/agent/ldap/LdapAgent.java读取use_ssl,Core 实际发送的是ssl,所以 GSSAPI 的 LDAPS 配置不会生效;LDAP 连接表单也没有 TLS 开关。
修复后请补 Tauri Viewer、LDAP-only middleware 和 Core→Agent TLS 映射测试,并让 exact head 的 CI 完整通过。
|
OK, 我处理一下 |
Add LDAP as a first-class connection type in dbx-core: - ldap3-based native driver (simple bind / anonymous) plus GSSAPI routing to the Java agent - ldap_login (app-level LDAP login for the web backend) and ldap_ops (search dispatch) - DatabaseType::Ldap + 5 ldap_* ConnectionConfig fields, pool/keepalive/health branches - dbx-web: /ldap/search + /ldap/list-child routes, LDAP login backend, app-settings LDAP config - storage: LDAP login settings round-trip (preserves password hash) - agent tools: dedicated dbx_execute_ldap_search tool; LDAP excluded from SQL query paths
- LDAP browser + search components and sidebar entry tree (loadLdapRoot/loadLdapEntryChildren) - ConnectionDialog LDAP form (simple bind / GSSAPI / anonymous, keytab + krb5.conf) - LdapLoginSettings panel in editor settings; AppToolbar/AppTabBar LDAP-aware behavior - QuickConnectionOpenTarget, tabPresentation and i18n (en/zh-CN) for ldap modes - databaseNamespaceCreation / databasePropertyEditing mark LDAP as read-only browse - api/http/tauri backend wiring for ldap search endpoints
- agents/drivers/ldap: JDBC-style Java agent for GSSAPI/Kerberos LDAP via JNDI+JAAS - dbx-mcp: expose dbx_execute_ldap_search tool and LDAP connection options - agents/settings.gradle: register the ldap driver module - deploy/database/ldap: compose + ldif fixtures for local LDAP testing
|
先处理冲突问题, 之后的问题, 我会持续跟进 |
- ldap_login: drop redundant map_err identity; use assert! for bool checks - storage: use assert! for bool check in LDAP settings round-trip test - dbx-mcp: allow clippy::too_many_arguments on new_connection_config_with_ldap
# Conflicts: # agents/settings.gradle # crates/dbx-core/Cargo.toml
# Conflicts: # agents/versions.json # apps/desktop/src/App.vue # apps/desktop/src/components/connection/ConnectionDialog.vue # apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue # apps/desktop/src/types/database.ts # crates/dbx-core/Cargo.toml # crates/dbx-core/assets/database-drivers.manifest.json # crates/dbx-core/src/agent_catalog.rs # crates/dbx-core/src/database_capabilities.rs # crates/dbx-core/src/models/connection.rs # crates/dbx-mcp/src/server.rs
… regenerate duckdb agent lockfile
…tdb, zookeeper, rocketmq, rabbitmq)
|
apps/desktop/src/lib/backend/tauri.ts 的 ldapSearch() 始终抛错,而桌面运行时会选择 Tauri backend,导致 LDAP 树、详情和搜索在桌面端全部不可用。 以上截图已补 agents/drivers/ldap/src/main/java/com/dbx/agent/ldap/LdapAgent.java 读取 use_ssl,Core 实际发送的是 ssl,所以 GSSAPI 的 LDAPS 配置不会生效;LDAP 连接表单也没有 TLS 开关。 simple bind 的ssl测试 表单未加 最近比较忙, phase2 做 |




背景
为 DBX 增加原生 LDAP 目录浏览与登录能力,并保持与现有数据库驱动、Web 认证体系和 MCP 工具一致的可扩展边界。交互研究参考了Apache Directory Studio, 以及本人常用的交互方式
有rust原生支持方式(simple bind), 也有JNDI/JAAS的接入方式(GSSAPI), rust 下的ldap库对GSSAPI支持比较麻烦, 为了保证跨平台和兼容性, GSSAPI认证方式, 使用了java agent方式接入
登录流程、前端组件与实现代码均按 DBX 现有设计体系独立完成。
主要变更
原生 LDAP 驱动与数据层
ldap_driver.rs(基于ldap3crate),支持 simple bind 与搜索,暴露与既有 Java agent 一致的 JSON 输出形态(entries/dn/attributes/count/truncated)。ldap_ops.rs统一封装搜索与子节点列举(ldap_search_core/ldap_list_children_core),支持 base/one/sub scope、RFC 4515 过滤、属性白名单与 size_limit,并对 RFC 4514/4515 转义(DN 与 filter 注入防护)。DatabaseType、连接模型、连接池、schema 能力、production-safety 等扩展点登记 LDAP,接入通用连接生命周期(测试/连接/断开/关闭)。DBX_LDAP_INTEGRATION与DBX_LDAP_HOST/PORT/USER/PASSWORD/BASE_DN指向本地 OpenLDAP 容器(deploy/database/ldap/compose.yml+ldif/1/1.ldif,含 alice/bob/charlie 与 developers/managers 组),默认即连接 compose 环境。LDAP 登录(Web 认证)
ldap_login.rs登录模块,支持两种模式:NOSV(无服务账号):直接以用户输入绑定。Active Directory, 支持这种方式, 一般来说支持 domain\sAMAccountName, sAMAccountName, dn, mail + password, 具体支持情况需要咨询公司的AD team的开放情况SV(服务账号):先用服务账号查询用户 DN,再以用户 DN + password 绑定。openldap, 389 Directory等客户端, search 规则, 可以自己配置LdapLoginSettings),服务账号密码以脱敏方式存储、redacted()后回传,空白时保留已存密码。/auth/ldap-login登录接口与/auth/check的ldap_enabled联动;登录页支持 LDAP / 密码两种模式切换。/app-settings/ldap-login(含/test用于连接测试),统一由 auth 中间件保护。test_connection在服务账号密码留空时复用已存密码,避免“密码未配置”误报。MCP / AI 工具
dbx_execute_ldap_search工具:connection_id/name + base_dn + filter + scope + attributes[] + size_limit,仅对 LDAP 连接可用,走核心ldap_ops::ldap_search_core,只读。dbx_add_connection支持 LDAP 专属字段(ldap_security_protocol、ldap_principal、ldap_keytab_path、ldap_krb5_conf、ldap_base_dn),并补齐默认端口ldap→389、ldaps→636。dbx_execute_ldap_search工具与 MCP 工具共用同一执行路径。Java Agent
LdapAgent(JNDI) 作为可选实现;LdapAgentTest集成测试默认指向本地 OpenLDAP 容器(simple bind),GSSAPI 测试移除(无 Kerberos 环境)。dbx-agent-ldap.jar可直接替换~/.dbx/agents/drivers/ldap/agent.jar。安全设计
dbx_execute_ldap_search与 Agent 工具均不提供写路径,也不执行任意命令。auth_middleware/ 连接 allowlist / 只读策略约束,无绕过前端的直通路径。自审修复
/auth/*迁移到/app-settings/ldap-login,避免配置接口与登录接口混在同一权限域。/auth/check移除冗余的ldap_connections,仅保留ldap_enabled,减少未登录环境的信息暴露。(uid={user}),真正覆盖 AD(sAMAccountName)与 OpenLDAP(uid)。test_connection复用已存服务账号密码,修复“配置保存后测试报密码未配置”。LdapAgentTest集成配置改为 env 可覆盖并默认指向 compose,移除依赖真实 AD 的 GSSAPI 用例。bin.test修复 Windows 下EBUSY临时目录清理竞态(等待子进程退出后重试删除)。变更类型
涉及前端
客户端
DBX_DISABLE_PASSWORD=1, 开启 LDAP登录

验证
make dev-fast/cargo check --no-default-features:全 workspace 通过。cargo test --no-default-features -p dbx-core:3475 项通过、0 失败(含 LDAP 驱动集成测试、登录过滤转义、存储往返)。DBX_LDAP_INTEGRATION=1):simple bind 连接/搜索/size limit/属性返回 4 项全过。:ldap:test:20 项通过(simple bind 指向本地 OpenLDAP 容器)。pnpm test:packages:CLI + MCP-server 全部通过;dbx_execute_ldap_search对真实目录返回 DN/属性/组信息。cargo test -p dbx-web:66 项通过。pnpm typecheck、pnpm lint通过;pnpm test5708 项通过(2 项为并行 mock 竞态,单独运行该文件 32/32 通过)。cargo fmt --all -- --check:通过。关联 Issue
Related #1647
测试环境
deploy/database/ldap/compose.yml提供mlan/openldap:latest本地容器(默认端口 389/636,ldif/1/1.ldif自动导入),用于驱动、Java Agent 与登录流程的真实验证;rootless podman 环境需net.ipv4.ip_unprivileged_port_start=389。