介绍
轻型目录访问协议(英文: LightweightDirectoryAccessProtocol,缩写: LDAP)是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。OpenLDAP是轻型目录访问协议( LightweightDirectoryAccessProtocol, LDAP)的自由和开源的实现,在其 OpenLDAP许可证下发行,并已经被包含在众多流行的 Linux发行版中。可以这样讲:市面上只要你能够想像得到的所有工具软件,全部都支持 LDAP协议。
它本身是一个小型文件数据库。Ldap是树形结构的,能够通过server + client(服务端+客户端)的方式。进行统一的用户(账号)管理。
例如:
如果有100台机器,一个用户需要登录这100台机器。传统的做法就是每台机器中,都需要创建登录账号,操作100次。如果使用ldap来管理,就只需要在ldap服务中创建一次就可以了。账号清理也是类似的道理。我们通过控制一台机器登录账号,即可控制所有机器登录账号。
概念
当在部署及使用过程中遇到问题请查看概念
协议基础
目录服务
目录服务(Directory service)是一个储存、组织和提供信息访问服务的软件系统,在软件工程中,一个目录是指一组名字和值的映射。(简单点说是提供文件存储与检索的软件系统,一个目录指其中所有数据与其对应名称的映射)
目录服务遵循LDAP和X.500协议。
应用层协议
应用层(英语:Application layer)位于OSI模型的第七层。应用层直接和应用程序接口结合,并提供常见的网络应用服务。应用层也向第六层表示层发出请求。
注:以下为常见应用层协议
LDAP&X.500协议
X.500是计算机目录服务的标准系列。最早是ITU-T X.500开发,前身为CCITT(ITU的前身)的目录服务系统,并于1988年首次批准,此一目录可以成为全球目录服务标准的一部分。
X.500协议包括:
- DAP (Directory Access Protocol)
- DSP (Directory System Protocol)
- DISP (Directory Information Shadowing Protocol)
- DOP (Directory Operational Bindings Management Protocol)
- LDAP (Lightweight Directory Access Protocol)
目录服务在开发内部网和与互联网程序共享用户、系统、网络、服务和应用的过程中占据了重要地位。例如,目录服务可能提供了组织有序的记录集合,通常有层级结构,例如公司电子邮件目录。同理,也可以提供包含了地址和电话号码的电话簿。
LDAP的一个常用用途是单点登录,用户可以在多个服务中使用同一个密码,通常用于公司内部网站的登录中(这样他们可以在公司电脑上登录一次,便可以自动在公司内部网上登录)。
LDAP基于X.500标准的子集。因为这个关系,LDAP有时被称为X.500-lite。
OpenLDAP
OpenLDAP是轻型目录访问协议(Lightweight Directory Access Protocol,LDAP)的自由和开源的实现,在其OpenLDAP许可证下发行,并已经被包含在众多流行的Linux发行版中。
注:基于LDAP协议实现的开源服务软件
它主要包括下述4个部分:
- slapd - 独立LDAP守护服务
- slurpd - 独立的LDAP更新复制守护服务
- 实现LDAP协议的库
- 工具软件和示例客户端
通过以上理论可得知,目录服务是基于应用协议X.500实现的,而LDAP是X.500协议中的子协议之一,OpenLDAP则是基于LDAP协议的开源服务软件。
架构
服务端
指 OpenLDAP 的服务器本身,这个东西其实只相当于是一个 mysql数据库。它是没有酷炫的图形界面的,每次使用都需要手敲一大堆代码,实现起来较复杂,所以引入了 web 控制台(phpLDAPadmin)的概念。
Web控制台
安装名为 phpLDAPadmin 的工具,这是一个图形界面,至少可以解放手撸代码。通过 web 页面实现对 OpenLDAP 的增删改查。
PWM
提供给用户一个修改自己账号密码的地方。本文不涉及该工具。
客户端
基础
旨在快速了解OpenLDAP所使用到的各个名词及使用方式
信息模型
LDAP的信息模型是建立在"条目"(entries)的基础上。一个条目是一些属性的集合,并且具有一个全局唯一的"可区分名称"DN,一个条目可以通过DN来引用。每一个条目的属性具有一个类型和一个或者多个值。
objectClass
LDAP通过属性objectClass来控制哪一个属性必须出现或允许出现在一个条目中,它的值决定了该条目必须遵守的模式规则。可以理解为关系数据库的表结构。例如当我对一个条目添加'organization'这个objectClass时,该条目就会有organization所需的字段。
objectClass | 含义 |
---|---|
olcGlobal | 全局配置文件类型, 主要是cn=config.ldif 的配置项 |
top | 顶层的对象 |
organization | 组织,比如公司名称,顶层的对象 |
organizationalUnit | 重要, 一个目录节点,通常是group,或者部门这样的含义 |
inetOrgPerson | 重要, 我们真正的用户节点类型,person类型, 叶子节点 |
groupOfNames | 重要, 分组的group类型,标记一个group节点 |
olcModuleList | 配置模块的对象 |
常用关键字
LDAP的entry由各种字段构成,可以理解为关系数据库的字段。
关键字 | 英文全称 | 含义 |
---|---|---|
dc | Domain Component | 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com |
uid | User Id | 用户ID,如“tom” |
ou | Organization Unit | 组织单位,类似于Linux文件系统中的子目录,它是一个容器对象,组织单位可以包含其他各种对象(包括其他组织单元),如“market” |
cn | Common Name | 公共名称,如“Thomas Johansson” |
sn | Surname | 姓,如“Johansson” |
dn | Distinguished Name | 惟一辨别名,类似于Linux文件系统中的绝对路径,每个对象都有一个惟一的名称,如“uid= tom,ou=market,dc=example,dc=com”,在一个目录树中DN总是惟一的 |
rdn | Relative dn | 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson” |
c | Country | 国家,如“CN”或“US”等。 |
o | Organization | 组织名,如“Example, Inc.” |
这里,我们把dn当做用户唯一主键, cn是common name,应该等同于用户名,因为用户名必须唯一,通常为邮箱前缀 ,比如ryan.miao. sn作为姓氏, uid作为用户id。通常用户id也是唯一的。所以在使用ldap做认证的时候, 大概逻辑如下:
- 配置ldap host, admin, admin pass
- 用户登录时传递username
- 读取配置的ldap信息,查询cn或者uid等于username的数据
- 取出第一个记录, 获得dn, 根据dn和password再次去ldap服务器认证。即我们必须保证cn或uid是全局唯一的, 认证通常需要进行两次。原因就在于dn没办法根据用户名计算出来。
一个ldap用户组织可能是这样的:
使用
部署
安装
使用docker-conpose的形式安装
$ cat /usr/local/wlhiot/docker-compose-file/openldap.yaml
version: '3'
services:
openldap: # OpenLDAP服务器
image: osixia/openldap # 镜像名称
container_name: openldap
restart: always # 重启策略
ports:
- "389:389"
- "636:636"
environment:
- LDAP_ORGANISATION=wlhiot openldap # LDAP组织
- LDAP_DOMAIN=wlhiot.com # LDAP域
- LDAP_ADMIN_PASSWORD=wlhldap # LDAP密码
- LDAP_CONFIG_PASSWORD=wlhldap
volumes:
- /usr/local/wlhiot/mount/ldap/var:/var/lib/ldap # 挂载文件
- /usr/local/wlhiot/mount/ldap/etc:/etc/ldap/slapd.d
ldap-admin: # Web 控制台
image: osixia/phpldapadmin # 镜像名称
container_name: phpldapadmin
restart: always
ports:
- "8000:80"
- "6443:443"
environment:
# 默认启用HTTPS地址,通过https://IP:6443访问。若无需HTTPS加密添加'- PHPLDAPADMIN_HTTPS=false',且通过http://IP:8000访问。
- PHPLDAPADMIN_LDAP_HOSTS=192.168.254.29 # LDAP地址
$ docker-compose -f /usr/local/wlhiot/docker-compose-file/openldap.yaml up -d # 后台运行
# docker-compose的使用安装见github文档,印象中只要下载安装包添加个软链接即可使用
访问
Login DN:cn=admin,dc=wlhiot,dc=com
Password:wlhldap
组织架构
例如公司里的部门,推荐Organisational Unit(能实现基本的登录功能)或者Posix Group(有额外的用户信息,可用作员工信息管理)。对于具体的人,推荐使用Courier Mail: Acccount(附带邮件)或者User Account(可归属于指定组)来创建。还可根据需要对组或用户添加额外的属性以标识,毕竟功能强大能对用户的各种信息进行记录(地址簿、邮箱、工作信息等)
有一个小细节目前还不知道有什么用。用户创建出来后它会有一个唯一标识的DN,是可以通过该DN登录到OpenLDAP中的,应该是可以实现对指定用户设置只读,然后该用户登陆后只能对组织架构进行只读。
用户条目
配置
配置文件正常情况不需要修改,且即使要修改也需要通过专门的工具例如phpLDAPadmin或者ldapmodify
配置文件目录结构
$ tree /etc/ldap/slapd.d
slapd.d/
├── cn=config # 配置文件目录
│ ├── cn=module{0}.ldif
│ ├── cn=schema
│ │ ├── cn={0}core.ldif
│ │ ├── cn={1}cosine.ldif
│ │ ├── cn={2}nis.ldif
│ │ ├── cn={3}inetorgperson.ldif
│ │ ├── cn={4}ppolicy.ldif
│ │ ├── cn={5}kopano.ldif
│ │ ├── cn={6}openssh-lpk.ldif
│ │ ├── cn={7}postfix-book.ldif
│ │ └── cn={8}samba.ldif
│ ├── cn=schema.ldif
│ ├── olcDatabase={0}config.ldif
│ ├── olcDatabase={-1}frontend.ldif
│ ├── olcDatabase={1}mdb
│ │ ├── olcOverlay={0}memberof.ldif
│ │ └── olcOverlay={1}refint.ldif
│ └── olcDatabase={1}mdb.ldif # db的存储格式,有hdb和mdb两种
├── cn=config.ldif # 核心配置文件,ldif为ldap目录特定的格式。内容自动生成,修改使用phpLDAPadmin或者ldapmodify
├── docker-openldap-was-admin-password-set
└── docker-openldap-was-started-with-tls
集成
需要小心一点的是,一旦完成集成,应用原来的账号可能就无法再登录(所以推荐新起应用来测试),如果有可能的话对原有配置做一个备份。可能一看集成配置需要很多,但抽丝剥茧后会发现这些配置都是必要的,例如:
- 登录OpenLDAP的URL、账号、密码;
- 用户基础DN和搜索过滤;
- 组基础DN和搜索过滤;
完成集成后,通过LDAP中的uid作为用户账号,userPassword作为用户密码进行登录
harbor
minIO
点击链接跳转
mc config host add minio http://192.168.254.23:30009 master wlh@2021 # 连接到minio
mc admin policy set minio consoleAdmin user=cn=root,ou=product,ou=wlhiot,dc=wlhiot,dc=com # 添加管理用户
mc admin policy set minio consoleAdmin group=ou=wlhiot,dc=wlhiot,dc=com # 添加管理组
gerrit
点击链接跳转
$ cat /usr/local/wlhiot/mount/gerrit/etc/gerrit.config # 配置文件
[ldap]
server = ldap://192.168.254.29
username = cn=admin,dc=wlhiot,dc=com
accountBase = ou=product,ou=wlhiot,dc=wlhiot,dc=com
accountPattern = (&(objectClass=person)(uid=${username}))
accountFullName = displayName
accountEmailAddress = mail
groupBase = ou=product,ou=wlhiot,dc=wlhiot,dc=com
sonarqube
点击链接跳转
$ cat /usr/local/wlhiot/mount/nfsdata/dynamic/basic-sonarqube-data-pvc-948b2777-16e4-41bb-83e6-b7ab83d2500d/conf/sonar.properties # 配置文件
# LDAP configuration
# General Configuration
sonar.security.realm=LDAP
ldap.url=ldap://192.168.254.29
ldap.bindDn=cn=admin,dc=wlhiot,dc=com
ldap.bindPassword=wlhldap
# User Configuration
ldap.user.baseDn=ou=product,ou=wlhiot,dc=wlhiot,dc=com
ldap.user.request=(&(objectClass=inetOrgPerson)(uid={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail
# Group Configuration
ldap.group.baseDn=ou=product,ou=wlhiot,dc=wlhiot,dc=com
ldap.group.request=(&(objectClass=posixGroup)(memberUid={uid}))
Jenkins
点击链接跳转
gitlab
点击链接跳转
$ cat /usr/local/wlhiot/mount/gitlab/config/gitlab.rb
gitlab_rails['ldap_enabled'] = true
gitlab_rails['prevent_ldap_sign_in'] = false
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
main:
label: 'LDAP'
host: '192.168.254.29'
port: 389
uid: 'uid'
bind_dn: 'cn=admin,dc=wlhiot,dc=com'
password: 'wlhldap'
encryption: 'plain'
active_directory: false
allow_username_or_email_login: false
block_auto_created_users: false
base: 'ou=product,ou=wlhiot,dc=wlhiot,dc=com'
user_filter: ''
attributes: # 登录成功后gitlab中的用户信息
username: ['cn']
email: ['mail']
name: 'sn'
first_name: 'givenName'
last_name: 'cn'
EOS
$ docker exec -it gitlab /bin/bash
root@81dde61ce6db:/# gitlab-ctl reconfigure # 更新配置
grafana
mm-wiki
LDAP登录配置查看'登录认证文档',用户名前缀为登录成功的用户的前缀,名称和用户名前缀均可自定义,核心在于'认证URL'及'附加参数',附加参数的配置如下:
{
"basedn": "dc=wlhiot,dc=com",
"bind_username": "cn=admin,dc=wlhiot,dc=com", # ldap登录用户
"bind_password": "wlhldap",
"account_pattern": "(&(objectClass=inetOrgPerson)(uid=%s))", # 根据实际情况修改,因为我的用户是以inetOrgPerson为节点
"given_name_key": "sn",
"email_key": "mail"
}
服务器
参考资料: