运维_基础设施_OpenLDAP


目录:

介绍

轻型目录访问协议(英文: 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协议包括:

  1. DAP (Directory Access Protocol)
  2. DSP (Directory System Protocol)
  3. DISP (Directory Information Shadowing Protocol)
  4. DOP (Directory Operational Bindings Management Protocol)
  5. 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

集成

需要小心一点的是,一旦完成集成,应用原来的账号可能就无法再登录(所以推荐新起应用来测试),如果有可能的话对原有配置做一个备份。可能一看集成配置需要很多,但抽丝剥茧后会发现这些配置都是必要的,例如:

  1. 登录OpenLDAP的URL、账号、密码;
  2. 用户基础DN和搜索过滤;
  3. 组基础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"
}

服务器

参考资料: