目录
Unable to connect to the server at "xxxx" on port 4444
exception is javax.net.ssl.SSLHandshakeException:
backend-userRoot.lock was not granted
基本介绍
LDAP基于X.500标准的子集是一个目录服务,设计主要考虑了快速查找(提供索引)和高可用性,而OpenDJ用Java编写 基于轻量级目录访问协议 Lightweight Directory Access Protocol(LDAP)支持:
DAPv3协议。
目录服务标记语言:Directory Services Markup Language (DSML)(已XML 格式描述目录数据和基本目录操作)
超文本协议:Hypertext Transfer Protocol (HTTP),REST
OpenDJ 还提供:
- 提供客户端管理工具。
- 支持导入、导出、备份和恢复目录数据。
- 支持配置管理权限和细粒度的访问控制。
- 支持复制同步
基本结构
可以在ldap-demo中了解大致的结构
LDAP 目录数据被组织成条目,条目包含许多属性,有些是必须的,有些是自定义的,例如DN 就是必须的且唯一。
LDAP 条目在目录中是金字塔结构,最顶层是DC,正是这样的结构,为了方便管理添加了更多的组织结构,例如:UO、CN等
LDAP常常用来与AD域控等企业系统平台结合一起做统一账号管理,一般用来做单点登录。
服务专有名词
baseDN在配置时 一般都是使用CD标签,但也不是必须的。也可以指定为 o=PW,c=CN
缩写 | 全称 | 解释 |
DN | distinguished name | dn: uid=bjensen,ou=People,ou=company,dc=example,dc=com 唯一标识符,显示在条目顶部,通常由不区分大小写的属性组成 |
DC | domain component | dc=example,dc=com 倒叙打方式将域名拆成多个, |
baseDN | 基于DN,最小单位为DC,最大为DN。在命令行或者客户端中使用 | |
bindDN | root(超级管理员)用户一般默认为cn=Directory Manager | |
OU | Organization Unit | 组织单位,可以是多个,也OU深度 |
CN | Common Name | 公共名称,一般不出现DN中,root(超级管理员)用户一般默认为cn=Directory Manager |
DSE | "空"的条目,保存DN的组织信息,在信息导出export-ldif 后的文件位于最上层 | |
Backend ID | 存储空间,也叫 backends name , 用户默认为userRoot,系统默认adminRoot |
安装
需要java环境支持:Java Environment.
官方提供了GUI方式和命令行方式(Command-Line):详细步骤请查看:Home · OpenIdentityPlatform/OpenDJ Wiki · GitHub
可选:
系统环境 /etc/security/limits.conf opendj soft nofile 65536 opendj hard nofile 131072 ./setup --cli ./uninstall --cli #卸载
命令行工具
详细的工具使用方法在:./bin/xxx options --help (Windows 是 ./bat/xxx.bat)
使用过程中用到过的:
- 进程启停: start-ds、status、stop-ds、create-rc-script(生成启动脚本)
- 导出导入:export-ldif、import-ldif、ldif-diff(LDIF 文件比较)
- 备份恢复:backup、restore
- 用户管理:ldapmodify、ldapdelete、ldapsearch(查询)、ldapcompare(比较)
- 配置管理:dsconfig
- 集群同步:dsreplication
- index管理:verify-index(验证索引正确,需要关闭服务)、rebuild-index
常见的通用参数
- --trustAll选项信任所有 SSL 证书,例如用于测试的默认自签名证书。
- --no-prompt 非交互模式,会导致非信任证书客户端执行失败。
在交互式命令行中,为了简单可以省略非必须的默认参数,比如./bin/dsconfig list-connection-handlers
密码管理
密码策略不仅管理密码,还管理账户锁定
用户的密码策略可以复制同步,服务器的密码策略配置不能复制同步,多节点需要每个节点配置
后端存储使用SSHA 哈希
可以配置强制定期更改密码、新用户在首次登录后更改密码、帐户锁定、禁用帐户
[root@tserver121 opendj]# ./bin/ldapsearch --baseDN dc=example,dc=com --bindDN "cn=Directory Manager" "(uid=bjensen)" pwdPolicySubentry dn: uid=bjensen,ou=People,dc=example,dc=com pwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config #默认的密码策略 需要配置objectClass: pwdValidatorPolicy 对应的验证器
重置管理员密码
#生成密码 encode-password --storageScheme SSHA512 --clearPassword password 修改配置文件 ./config/config.ldif userpassword: #替换新的密码 重启服务 cn: Directory Manager
管理服务器进程
./bin/start-ds 后端启动 ./bin/start-ds -N 前端启动 ./bin/start-ds -L 使用上次成功启动的配置启动 ./config/config.ldif.startok ./bin/start-ds -s 显示系统信息 ./bin/stop-ds ./bin/stop-ds -R 重启 ./bin/stop-ds -r, --stopReason #关闭原因,用来排查问题 开机启动 ./bin/create-rc-script --outputFile /etc/init.d/opendj --userName root #生产启动脚本 chkconfig opendj on service opendj start
管理索引
索引是为了能够快速响应搜索,越具体的DN 搜索越快,系统默认会提供cn、uid、mail、objectClass 等默认索引
查看未被索引的日志grep -B 1 unindexed ./logs/access
#打开索引分析功能 ./bin/dsconfig set-backend-prop --set index-filter-analyzer-enabled:true --trustAll #选择Backend 默认为userRoot 在使用客户端搜索或者使用ldapsearch搜索时,将结果保存在内存中,可以通过界面读取cn=monitor #执行搜索 [root@tserver121 opendj]# ./bin/ldapsearch --bindDN "cn=Directory Manager" --baseDN "cn=userRoot Storage,cn=monitor" "(objectclass=*)" filter-use filter-use: (uid=jdoe) hits:2 maxmatches:1 message: #hits(使用过滤器的次数)、maxmatches(匹配数) #debugsearchindex 不会执行搜索,而是返回调试信息 [root@tserver121 opendj]# ./bin/ldapsearch --baseDN dc=example,dc=com --bindDN "cn=Directory Manager" "(uid=user.1000)" * debugsearchindex dn: cn=debugsearch debugsearchindex: filter=(uid=user.1000)[INDEX:uid.equality][COUNT:1] final=[COUNT:1] #未被索引 [root@tserver121 opendj]# ./bin/ldapsearch --baseDN dc=example,dc=com --bindDN "cn=Directory Manager" "(uid=*)" debugsearchindex dn: cn=debugsearch debugsearchindex: filter=(uid=*)[INDEX:uid.presence][NOT-INDEXED] scope=sub[NOT-INDEXED] final=[NOT-INDEXED] #NOT-INDEXED [INDEX:index-id]标识可用于查找此过滤器的匹配项的索引。 [COUNT:entry-count]指定与过滤器匹配的条目数。 [LIMIT-EXCEEDED]表示服务器维护一个匹配的索引,但是索引条目限制已超出指定的值。 [NOT-INDEXED]表示没有找到匹配的索引值或索引键。
如何搜索
./bin/backendstat 执行有点问题 需要关闭进程 见'backend-userRoot.lock was not granted'
./bin/backendstat list-indexes
./bin/backendstat dump-index --indexName state 详细信息
# - 是否存在搜索的属性-uid 比较快,更少占用空间 ./bin/ldapsearch --baseDN dc=example,dc=com --bindDN "cn=Directory Manager" "(uid=*)" - #只列出mail字段 数据多的情况下非常有用 ./bin/ldapsearch --baseDN dc=example,dc=com --bindDN "cn=Directory Manager" "(uid=*)" mail (uid=bjensen) (uid~=bjensen) #相似 看起来不准 (uid=bj*) #*匹配 (uid>=bjensen) #相似排序 看起来也不准
管理索引
条目限制 --set index-entry-limit:10000 #不常用,默认限制基本够用 backendstat show-index-status 查看 ./bin/verify-index --baseDN dc=example,dc=com --index cn --clean --countErrors #检查 以下的不常用 ./bin/dsconfig create-backend-index --bindDN "cn=Directory Manager" --backend-name myData --index-name cn --set index-type:equality #创建索引 ./bin/dsconfig set-backend-index-prop --bindDN "cn=Directory Manager" --backend-name myData --index-name cn --set index-type:approximate #创近似索引 rebuild-index --baseDN dc=example,dc=com --index cn #重建索引 rebuild-index --baseDN dc=example,dc=com --rebuildDegraded #重建降级的索引 rebuild-index --baseDN dc=example,dc=com --clearDegradedState #清理和降级
管理目录数据
条目的属性定义- 在config/schema目录中存放的所有的条目属性配置,OpenDJ 按排序顺序读取模式文件,99-user.ldif 属于用户自定义的配置 在随后加载
比如在schema/00-core.ldif 文件中对于mail定义:
attributeTypes: ( 0.9.2342.19200300.100.1.3 NAME ( 'mail' 'rfc822Mailbox' )
EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} X-ORIGIN 'RFC 4524' )
# OID 开头
objectClass::所有条目均有一个用于标识其对象类的属性
测试数据
#测试数据:config/MakeLDIF 下面有剩测试数据的模版example.template 以及其它基本测试数据,使用make-ldif生成测试数据文件 ./bin/make-ldif --randomSeed 0 --templateFile ./config/MakeLDIF/example.template --ldifFile /tmp/generated.ldif
导出数据
导出数据,离线导出更快,可以指定backendID, #--start 20111221230000 #定时导出 停止服务器会在启动后尝试执行该任务 #--trustAll选项信任所有 SSL 证书,例如用于测试的默认自签名证书。 ./bin/export-ldif --bindDN "cn=Directory Manager" --includeBranch dc=example,dc=org --backendID userRoot --ldifFile /root/backup.ldif --trustAll
导入数据
导入需要验证字段, config/schema/99-user.ldif
存放的是用户定义的属性
导入数据 import-ldif命令参数与export-ldif一致的 #--start 20111221230000 #定时导出 停止服务器会在启动后尝试执行该任务 #--trustAll选项信任所有 SSL 证书,例如用于测试的默认自签名证书。 ./bin/import-ldif --bindDN "cn=Directory Manager" --includeBranch dc=example,dc=org --backendID userRoot --ldifFile /root/backup.ldif --trustAll
LDIF文件数据查看和比较
LDIF文件可以使用less/view等系统工具去查看数据,openDJ提供了 ldifsearch
、ldifmodify
、ldif-diff
,ldifmodify
常常用来合并文件。
数据存储-Backends
提供 JE 和 PDB 类型的选择。常用PDB类型,可以通过命令切换使用类型
默认存放位置:db/userRoot/
./bin/dsconfig 命令修改参数后 会修改./config/config.ldif
并且会将修改前的配置文件存在./config/archived-configs
目录下
./bin/dsconfig --help-all #查看功能 #创建 dsconfig create-backend --bindDN "cn=Directory Manager" --type pdb --backend-name myData --set base-dn:dc=example,dc=com --set enabled:true --set db-cache-percent:25 --trustAll --no-prompt [root@tserver121 opendj]# ./bin/dsconfig list-backends Backend : Type : enabled : base-dn ----------:------:---------:-------------------- adminRoot : ldif : true : cn=admin data myData : pdb : true : "dc=example,dc=com" userRoot : pdb : true : "o=example,c=com" #查看 dsconfig get-backend-prop ···· dsconfig list-backend-indexes ··· 修改 dsconfig set-backend-prop ···· 删除 dsconfig delete-backend
关于加密
默认db存储文件可以通过strings
命令查看部分数据,可以选择牺牲掉部分性能加密文件存储 --set confidentiality-enabled:true
传输加密:可以使用StartTLS 、SSL等配置
配置连接
openDJ 默认端口和协议:
[root@tserver121 opendj]# ./bin/status --- Connection Handlers --- Address:Port : Protocol : State -------------:-------------:--------- -- : LDIF : Disabled 8989 : Replication : Enabled 0.0.0.0:161 : SNMP : Disabled 0.0.0.0:389 : LDAP : Enabled 0.0.0.0:636 : LDAPS : Enabled 0.0.0.0:1689 : JMX : Disabled 0.0.0.0:8080 : HTTP : Disabled 加上 Administration Connector: Port 4444 (LDAPS) [root@tserver121 opendj]# ./bin/dsconfig list-connection-handlers 获得handler-name Connection Handler : Type : enabled : listen-port : use-ssl -------------------------:------:---------:-------------:-------- HTTP Connection Handler : http : false : 8080 : false JMX Connection Handler : jmx : false : 1689 : false LDAP Connection Handler : ldap : false : 389 : false LDAPS Connection Handler : ldap : true : 636 : true LDIF Connection Handler : ldif : false : - : - SNMP Connection Handler : snmp : false : 161 : - #开启和关闭 389 ./bin/dsconfig set-connection-handler-prop --handler-name "LDAP Connection Handler" --set enabled:false --trustAll ./bin/dsconfig set-connection-handler-prop --handler-name "LDAP Connection Handler" --set enabled:true --trustAll #use-ssl ./bin/dsconfig set-connection-handler-prop --handler-name "LDAPS Connection Handler" --set use-ssl:true --trustAll
开启 HTTP/HTTPS连接
REST访问数据映射、 REST访问权限、 REST认证等 To Set Up REST Access to User Data、
#开启 http 8080 ./bin/dsconfig set-connection-handler-prop --handler-name "HTTP Connection Handler" --set enabled:true --trustAll #启用 HTTP 访问日志 --/logs/http-access 还可以配置Debugr日志与审计日志 也可以在config.ldif 中修改 当起不来的时候 非常有用 [root@tserver121 opendj]# ./bin/dsconfig list-log-publishers 获得 log publisher-name Log Publisher : Type : enabled ------------------------------:------------------------:-------- File-Based Access Logger : file-based-access : true File-Based Audit Logger : file-based-audit : false File-Based Debug Logger : file-based-debug : false File-Based Error Logger : file-based-error : true File-Based HTTP Access Logger : file-based-http-access : false Replication Repair Logger : file-based-error : true [root@tserver121 opendj]# ./bin/dsconfig set-log-publisher-prop --publisher-name "File-Based HTTP Access Logger" --set enabled:true --trustAll #开启HTTPS(指定JKS) ./bin/dsconfig set-trust-manager-provider-prop --provider-name "Blind Trust" --set enabled:true --trustAll ./bin/dsconfig set-connection-handler-prop --handler-name "HTTP Connection Handler" \ --set use-ssl:true --set key-manager-provider:JKS --set trust-manager-provider:"Blind Trust" --trustAll [root@tserver121 opendj]# ./bin/stop-ds --restart
使用 REST访问 -openDJ3.0
修改config/http-config.json 配置信息--修改之前记得备份
#config/http-config.json 修改修改实际的dc 修改完成后需要重启 "searchBaseDN" : "ou=people,dc=example,dc=com", "baseDN" : "ou=people,dc=example,dc=com", [root@tserver121 opendj]# ./bin/stop-ds --restart #查询 [root@tserver121 opendj]# curl http://host:8080/users/jdoe --user jdoe:password {"_id":"jdoe","_rev":"000000003f07e62f","schemas":["urn:scim:schemas:core:1.0"],"displayName":"John Doe","name":{"familyName":"Doe"},"contactInformation":{},"meta":{"created":"2024-06-20T10:30:36Z"}}
使用证书
keytool
命令将客户端应用程序的二进制格式自签名证书添加到 OpenDJ 信任库的命令
服务端需要打开LDAPS 在安装的时候可以选择
Address:Port : Protocol : State
-------------:-------------:---------
0.0.0.0:636 : LDAPS : Enabled
#查看opendj已安装服务器证书 server-cert.crt 默认证书 keytool -list -alias server-cert -keystore ./config/keystore -storepass `cat ./config/keystore.pin` #如果有自己的证书 列如myapp-cert.crt 建议使用`import` 导入到truststore 文件中 keytool -import -alias myapp-cert -file myapp-cert.crt -keystore ./config/truststore -storepass `cat ./config/keystore.pin` #导出 keytool -export -alias server-cert -file server-cert.crt -keystore ./config/keystore -storepass `cat ./config/keystore.pin` #删除 keytool -delete -alias server-cert
是否能将opendj的 默认证书添加到系统默认 --测试中
#将server-cert.crt 默认证书导出使用 keytool -export -alias server-cert -file server-cert.crt -keystore ./config/keystore -storepass `cat ./config/keystore.pin` #拷贝到系统证书目录下 mv server-cert.crt /etc/pki/ca-trust/source/anchors/ #更新 update-ca-trust extract
安全设置
- 限制匿名访问
攻击者可以直接通过LDAP客户端工具使用匿名连接既可访问LDAP中的隐秘数据。
./bin/dsconfig set-global-configuration-prop --set reject-unauthenticated-requests:true
- 拒绝空密码访问
默认值: true
./bin/dsconfig set-global-configuration-prop --set bind-with-dn-requires-password:true
- 返回有关绑定失败debug信息
默认值: false
./bin/dsconfig set-global-configuration-prop --set return-bind-error-messages:false
配置权限和访问控制
访问控制指令 (ACI)
为了安全 默认是不允许访问的
匹配规则
- 匹配顺序:目录结构 从下往上;匹配过程中,匹配到拒绝策略后,立即拒绝
- 若无拒绝策略,则匹配允许策略
- 若拒绝和允许都没匹配中,则默认拒绝
语法主要由四部分组成
targets(version 3.0;acl "name";permissions subjects;)
变量 | 解释 |
targets | 指明 条目(target = "ldap:///*=*,*,dc=example,dc=com")、属性(targetattr != "attr-list")、 控制和扩展操作(extop != "OID")。用 ()括起来,多个targets之前使用AND连接 |
name | 描述作用 |
permissions | allow(action[, action …]) 权限: |
subjects | 客户端访问限制条件,指定连接的人员、连接时间、连接地点和连接方式 |
#允许对除密码之外的所有属性进行匿名读取访问 dn: dc=example,dc=com objectClass: domain objectClass: top dc: example aci: (target ="ldap:///dc=example,dc=com")(targetattr != "userPassword")(version 3.0;acl "Anonymous read-search access"; allow (read, search, compare)(userdn = "ldap:///anyone");) aci: (target="ldap:///dc=example,dc=com") (targetattr = "*")(version 3.0; acl "allow all Admin group"; allow(all) groupdn = "ldap:///cn=Directory Administrators,ou=Groups,dc=example,dc=com";)
权限管理
独立于acl
#部分权限 * #所有权限,默认为root权限 backend-backup* backend-restore* bypass-acl* #忽略ACL配置 bypass-lockdown* #忽略操作锁 cancel-request* #取消任何客户请求 changelog-read* #查看changelog(在cn=changelog) config-read* config-write* data-sync #同步数据 ldif-export* ldif-import* modify-acl* password-reset* #重置其他用户的密码 privilege-change* #更改分配给用户的权限 subentry-write* 执行 LDAP 子条目写入操作
如何配置
#权限使用ds-privilege-name 属性指定 cat privilege.ldif dn: uid=kvaughan,ou=People,dc=example,dc=com changetype: modify add: ds-privilege-name ds-privilege-name: config-read ds-privilege-name: password-reset #生效 ./bin/ldapmodify --bindDN "cn=Directory Manager" --filename privilege.ldif ---------------------------------------------------------------------------- #使用组属性 cat collective.ldif dn: cn=Administrator Privileges,dc=example,dc=com objectClass: collectiveAttributeSubentry objectClass: extensibleObject objectClass: subentry objectClass: top cn: Administrator Privileges ds-privilege-name;collective: config-read ds-privilege-name;collective: config-write ds-privilege-name;collective: ldif-export ds-privilege-name;collective: modify-acl ds-privilege-name;collective: password-reset ds-privilege-name;collective: proxied-auth subtreeSpecification: {base "ou=people", specificationFilter "(isMemberOf=cn=Directory Administrators,ou=Groups,dc=example,dc=com)" } #生效 ./bin/ldapmodify --bindDN "cn=Directory Manager" --filename collective.ldif
Replication -同步
是基于时间来定义最新数据,更新频率较高的话可以定期清理历史信息,清理频率不要过高
同步复制是基于DN指定,不同的DN可以同步不同的节点,另外系统管理的cn=schema和cn=admin data 也会被复制
同步的优先级:越"近"的越优先,权重越高的越优先
onlyReplicationServer 仅用来复制的服务器得大集群了吧···
#新服务器作为host2 来配置 ./bin/dsreplication \ enable \ --baseDN dc=example,dc=com \ --host1 opendj.example.com \ --port1 4444 \ --bindDN1 "cn=Directory Manager" \ --replicationPort1 8989 \ --host2 opendj2.example.com \ --port2 4444 \ --bindDN2 "cn=Directory Manager" \ --replicationPort2 8989 \ --trustAll #新的服务器最好先执行dsreplication initialize-all 然后在创建同步 #禁止同步 dsconfig set-synchronization-provider-prop --port 4444 --hostname opendj2.example.com --bindDN "cn=Directory Manager" --bindPassword password --provider-name "Multimaster Synchronization" --set enabled:false --trustAll 停止同步 sreplication disable --disableAll --hostname opendj2.example.com
备份与恢复
如果是单节点的话 很有需要做异机备份
关于配置的的配置在config/archived-configs/ 每次修改配置程序会自动备份
可以加密备份数据
在线备份 ./bin/backup --port 4444 --bindDN "cn=Directory Manager" --backendID userRoot --backupDirectory /usr/local/src/userRoot/ --start 0 ./bin/backup --port 4444 --bindDN "cn=Directory Manager" --backUpAll --backupDirectory /usr/local/src/userRoot/ --start 0 #备份所有数据 #定时备份 ./bin/backup --port 4444 --bindDN "cn=Directory Manager" --backUpAll --backupDirectory /usr/local/src/userRoot/ --recurringTask "00 02 * * *" #增量备份 ./bin/backup --port 4444 --bindDN "cn=Directory Manager" --backendID userRoot --backupDirectory /usr/local/src/userRoot/ --incremental --recurringTask "00 02 * * *" 离线备份 ./bin/backup --backendID userRoot --backupDirectory /usr/local/src/userRoot/ 离线恢复 ./bin/restore --backupDirectory /export/rpm/OpenDJ-3.0.0/userRoot/ --listBackups #查看--backupID ./bin/restore --backupDirectory /export/rpm/OpenDJ-3.0.0/userRoot/ --backupID 20240620075220Z
监控、日志记录和警报
公开监控信息存在在cn=monitor
中
使用 Elasticsearch 审计日志处理程序
问题处理:
Unable to connect to the server at "xxxx" on port 4444
[root@tserver121 opendj]# ./bin/dsconfig list-backend-indexes --trustAll --no-prompt Unable to connect to the server at "xxxx" on port 4444 ------------------------------------------------------------------- Administration Connector: Port 4444 (LDAPS) 为LDAPS需要配置ssl证书 而且--no-prompt使用的是非交互模式 所以会执行失败
exception is javax.net.ssl.SSLHandshakeException:
[root@tserver121 opendj]# ./bin/status >>>> Specify OpenDJ LDAP connection parameters Administrator user bind DN [cn=Directory Manager]: Password for user 'cn=Directory Manager': Error reading configuration. Details: javax.naming.CommunicationException: simple bind failed: 0.0.0.0:4444 [Root exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present] ------------------------------------------------------------------- Administration Connector: Port 4444 (LDAPS) 为LDAPS需要配置ssl证书 简单的办法是:在交互命令中 接--trustAll参数, 或者在交互命令中选择 3) Yes, also add it to a truststore
backend-userRoot.lock was not granted
[root@tserver121 opendj]# ./bin/backendstat llist-backends --backendID userRoot userRoot: The exclusive lock requested for file /export/app/opendj/locks/backend-userRoot.lock was not granted, which indicates that another process already holds a shared or exclusive lock on that file. This generally means that some other process has exclusive access ------------------------------------------------------------------- # 文件被程序占用,关闭程序可以执行 [root@tserver121 opendj]# fuser -uv locks/* USER PID ACCESS COMMAND /export/app/opendj/locks/backend-adminRoot.lock: root 53283 f.... (root)java 可能是因为不能查看userRoot 的backend 的状态,但是在导入导出、备份等可以使用 可以使用 ./bin/dsconfig list-backends --trustAll 查看
参阅:
OpenDJ:Home · OpenIdentityPlatform/OpenDJ Wiki · GitHub
web管理端phpLDAPadmin:PLA - 🥇 The BEST ldap admin tool!
web管理端web2ldap:web2ldap - How to improve usability
ldap 工具https://ldap.com/ldap-tools/