openldap介紹和使用


openldap介紹和使用

為什么會有本文?

早期,公司是沒有統一認證這個東西的,所以各自玩各自的。於是, confluence一個用戶體系,gitlab一個用戶體系,Jenkins一個用戶體系等等, 開發中要用到的開源軟件數不勝數,每個軟件都要認證, 必須想辦法統一賬號。
第三系統的認證通常都是配置化的, 比如oauth, openid, ldap。兼容最廣泛就是ldap了,雖然是很老的系統(LDAPv3 was developed in the late 1990's to replace LDAPv2.),最后還是要使用它。

在開始使用之前再明確一下我們的目標。為了統一公司內部的賬號登錄體系。公司的人員組織架構假設是這樣子的:

.
└── company
    ├── ceo-Ryan
    ├── HR
    │   └── hr-a
    ├── 市場
    │   └── a
    ├── 研發
    │   ├── cto-Ryan
    │   ├── dev1
    │   │   ├── dev-Ryan
    │   │   ├── dev-Ryan2
    │   │   └── manager-Ryan
    │   ├── dev2
    │   └── dev3
    └── 行政

實際上會復雜的多,簡化的來看分為部門和成員。ldap就是存儲這樣的數據結構tree.

咬牙看了很多博客,依舊雲里霧里的感覺,最終決定上手嘗試,並完整記錄整個過程來加深理解。接下來將以一個什么都不懂的角色開始探索和使用ldap。

先了解一些概念

以下概念主要面向理解,去除了不關注的官方完整介紹,旨在能夠快速了解我們要用的東西是什么樣,如果需要更完整的概念介紹,參考后面的參考文獻即可。

什么是ldap

LDAP是輕量目錄訪問協議,英文全稱是Lightweight Directory Access Protocol,一般都簡稱為LDAP。按照我們對文件目錄的理解,ldap可以看成一個文件系統,類似目錄和文件樹。

ldap的軟件

ldap並不是一款軟件,而是一個協議。

現在市場上有關LDAP的產品已有很多,各大軟件公司都在他們的產品中集成了LDAP服務,如Microsoft的ActiveDirectory、Lotus的Domino Directory、IBM的WebSphere中也集成了LDAP服務。LDAP的開源實現是OpenLDAP,它比商業產品一點也不差,而且源碼開放。

OpenLDAP 是最常用的目錄服務之一,它是一個由開源社區及志願者開發和管理的一個開源項目,提供了目錄服務的所有功能,包括目錄搜索、身份認證、安全通道、過濾器等等。大多數的 Linux 發行版里面都帶有 OpenLDAP 的安裝包。OpenLDAP 服務默認使用非加密的 TCP/IP 協議來接收服務的請求,並將查詢結果傳回到客戶端。由於大多數目錄服務都是用於系統的安全認證部分比如:用戶登錄和身份驗證,所以它也支持使用基於 SSL/TLS 的加密協議來保證數據傳送的保密性和完整性。OpenLDAP 是使用 OpenSSL 來實現 SSL/TLS 加密通信的。

ldap的信息模型

【重要部分】

LDAP的信息模型是建立在"條目"(entries)的基礎上。一個條目是一些屬性的集合,並且具有一個全局唯一的"可區分名稱"DN,一個條目可以通過DN來引用。每一個條目的屬性具有一個類型和一個或者多個值。類型通常是容易記憶的名稱,比如"cn"是通用名稱(common name) ,或者"mail"是電子郵件地址。條目的值的語法取決於屬性類型。比如,cn屬性可能具有一個值"Babs Jensen" 。一個mail屬性可能包含"bbs@kevin.com" 。一個jpegphoto屬性可能包含一幅JPEG(二進制)格式的圖片。

LDAP的objectClass

LDAP通過屬性objectClass來控制哪一個屬性必須出現或允許出現在一個條目中,它的值決定了該條目必須遵守的模式
規則。可以理解為關系數據庫的表結構。接下來會用到的objectClass有

objectClass 含義
olcGlobal 全局配置文件類型, 主要是cn=config.ldif 的配置項
top 頂層的對象
organization 組織,比如公司名稱,頂層的對象
organizationalUnit 重要, 一個目錄節點,通常是group,或者部門這樣的含義
inetOrgPerson 重要, 我們真正的用戶節點類型,person類型, 葉子節點
groupOfNames 重要, 分組的group類型,標記一個group節點
olcModuleList 配置模塊的對象

LDAP常用關鍵字列表

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用戶組織可能是這樣的:



一個倒樁樹組成結構。

centos7上的安裝

不同軟件不同版本在不同環境的安裝和結構是不太一樣的。以下所有行為都是基於cento7openLDAP-2.4.44-21.el7_6

為了方便測試,我們采用docker-centos7作為容器環境: https://github.com/Ryan-Miao/docker-china-source/tree/master/docker-centos7

以特權模式啟動

docker run -d -it --rm --name=ldap  --privileged -p 8070:80  ryan/centos:7 /usr/sbin/init
docker exec -it ldap /bin/bash

安裝openldap

yum install -y openldap openldap-clients openldap-servers   
  • openldap-servers – This is the main LDAP server
  • openldap-clients – This contains all required LDAP client utilities
  • openldap – This packages contains the LDAP support libraries

啟動

systemctl start slapd

開機啟動

systemctl enable slapd

添加防火牆允許

firewall-cmd --add-service=ldap --permanent
firewall-cmd --reload 

ldap的配置文件

安裝后的配置目錄是: /etc/openldap, 內容包括下列這些文件

.
|-- certs
|   |-- cert8.db
|   |-- key3.db
|   |-- password
|   `-- secmod.db
|-- check_password.conf
|-- ldap.conf
|-- schema
|   |-- collective.ldif
|   |-- collective.schema
|   |-- corba.ldif
|   |-- corba.schema
|   |-- core.ldif
|   |-- core.schema
|   |-- cosine.ldif
|   |-- cosine.schema
|   |-- duaconf.ldif
|   |-- duaconf.schema
|   |-- dyngroup.ldif
|   |-- dyngroup.schema
|   |-- inetorgperson.ldif
|   |-- inetorgperson.schema
|   |-- java.ldif
|   |-- java.schema
|   |-- misc.ldif
|   |-- misc.schema
|   |-- nis.ldif
|   |-- nis.schema
|   |-- openldap.ldif
|   |-- openldap.schema
|   |-- pmi.ldif
|   |-- pmi.schema
|   |-- ppolicy.ldif
|   `-- ppolicy.schema
`-- slapd.d
    |-- cn=config
    |   |-- cn=schema
    |   |   `-- cn={0}core.ldif
    |   |-- cn=schema.ldif
    |   |-- olcDatabase={-1}frontend.ldif
    |   |-- olcDatabase={0}config.ldif
    |   |-- olcDatabase={1}monitor.ldif
    |   `-- olcDatabase={2}hdb.ldif
    `-- cn=config.ldif

cn=config.ldif

默認配置文件,位於/etc/openldap/slapd.d, 文件格式為LDAP Input Format (LDIF), ldap目錄特定的格式。

cat cn\=config.ldif 
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 094432b2
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/openldap/slapd.args
olcPidFile: /var/run/openldap/slapd.pid
olcTLSCACertificatePath: /etc/openldap/certs
olcTLSCertificateFile: "OpenLDAP Server"
olcTLSCertificateKeyFile: /etc/openldap/certs/password
structuralObjectClass: olcGlobal
entryUUID: 6cd8a04c-527e-1039-96b7-9fc5056bce1b
creatorsName: cn=config
createTimestamp: 20190814012729Z
entryCSN: 20190814012729.299304Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20190814012729Z

olcDatabase={2}hdb.ldif

db存儲格式,有bdb和hdb兩種,這里是hdb. 可以直接查看文件,也可以查詢:

ldapsearch  -Y EXTERNAL -H ldapi:/// -b cn=config dn | grep olcDatabase

核心配置文件,位於/etc/openldap/slapd.d/cn=config, 可以配置域名(olcSuffix), 管理員賬號(olcRootDN)等。

cat olcDatabase\=\{2\}hdb.ldif 
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 e3322b1b
dn: olcDatabase={2}hdb
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=my-domain,dc=com
olcRootDN: cn=Manager,dc=my-domain,dc=com
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
structuralObjectClass: olcHdbConfig
entryUUID: 6cd940ba-527e-1039-96bd-9fc5056bce1b
creatorsName: cn=config
createTimestamp: 20190814012729Z
entryCSN: 20190814012729.304147Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20190814012729Z

可以看到很多文件名和字段名都有前綴"olc" (OpenLDAP Configuration), 理解就好。

創建olcRootDN作為管理員賬號

看到前面兩個配置文件,官方不推薦我們直接修改配置文件,而是通過ldapmodify來更新配置。

類似於update by pk, 這里的pk就是dn了。

創建rootdn.ldif

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=admin,dc=demo,dc=com
-
replace: olcSuffix
olcSuffix: dc=demo,dc=com
-
replace: olcRootPW
olcRootPW: <pass>
  • 修改olcRootDN, 設置為我們的admin: cn=admin,dc=demo,dc=com
  • 修改olcSuffix, 設置為我們的域名dc=demo,dc=com
  • 修改olcRootPW, 設置我們的admin密碼, 這個需要加密,所以暫時放一個占位符,等下替換
  • changetype變更類型, replace表示替換, add表示增加。

cn=config是全局配置,必須包含objectClass: olcGlobal.

然后創建changeroot.sh

admin_pass=`slappasswd -s admin`
echo "admin pass is:  ${admin_pass}"
sed "s!<pass>!${admin_pass}!g"   rootdn.ldif > tmp.ldif

echo "備份默認配置"

cp /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif.bak

echo "將要修改的內容:"
cat tmp.ldif

ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f tmp.ldif

echo "修改后的變化"
diff /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif.bak

使用腳本進行變更,而不是直接命令行交互式變更,這樣可以更容易梳理變更邏輯, 而且可以重復使用。

驗證

通過diff,可以看到配置文件已經發生了變更

修改后的變化
2c2
< # CRC32 b643556d
---
> # CRC32 9b5dd3fc
7a8,9
> olcSuffix: dc=my-domain,dc=com
> olcRootDN: cn=Manager,dc=my-domain,dc=com
14,19c16,18
< olcRootDN: cn=admin,dc=demo,dc=com
< olcSuffix: dc=demo,dc=com
< olcRootPW:: e1NTSEF9Q3puZEw4QzN4aWJNQTlHeEpYV2doNEN3NHJXSm5Fb0s=
< entryCSN: 20190814074323.492640Z#000000#000#000000
< modifiersName: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
< modifyTimestamp: 20190814074323Z
---
> entryCSN: 20190814074118.406339Z#000000#000#000000
> modifiersName: cn=config
> modifyTimestamp: 20190814074118Z

我們可以通過search語法來確定賬號密碼是否正確:

# ldapsearch -H ldapi:///  -D "cn=admin,dc=demo,dc=com" -w admia 
ldap_bind: Invalid credentials (49)


# ldapsearch -H ldapi:///  -D "cn=admin,dc=demo,dc=com" -w admin 
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1
  • ldapsearch 查詢語法, -H指定host, -D指定admin的賬號,即rootdn, -w指定密碼, -x啟用認證

添加我們的base組織結構

有了管理員,還需要配置組織結構base.ldif。在這之前,我們需要導入一些模板。schema類似數據庫表定義,
定義了字段名稱和類型。

schema地址:

/etc/openldap/schema

默認安裝加載了core.ldif , 我們現在加載幾個想要的schema:

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif 
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif 
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif 

然后

創建文件base.ldif

# cat base.ldif
dn: dc=demo,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: ldap測試組織
dc: demo

dn: cn=Manager,dc=demo,dc=com
objectClass: organizationalRole
cn: Manager
description: 組織管理人

dn: ou=People,dc=demo,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=demo,dc=com
objectClass: organizationalUnit
ou: Group

使用ldapadd添加base:

ldapadd -x -D cn=admin,dc=demo,dc=com -w admin -f base.ldif 

使用ldapsearch來檢查內容

[root@a1791f1044ba data]# ldapsearch -x -D cn=admin,dc=demo,dc=com -w admin -b "dc=demo,dc=com"
# extended LDIF
#
# LDAPv3
# base <dc=demo,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# demo.com
dn: dc=demo,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o:: bGRhcOa1i+ivlee7hOe7hw==
dc: demo

# Manager, demo.com
dn: cn=Manager,dc=demo,dc=com
objectClass: organizationalRole
cn: Manager
description:: 57uE57uH566h55CG5Lq6

# People, demo.com
dn: ou=People,dc=demo,dc=com
objectClass: organizationalUnit
ou: People

# Group, demo.com
dn: ou=Group,dc=demo,dc=com
objectClass: organizationalUnit
ou: Group

# search result
search: 2
result: 0 Success

# numResponses: 5
# numEntries: 4
  • -x 啟用認證
  • -D bind admin的dn
  • -w admin的密碼
  • -b basedn, 查詢的基礎dn
  • 可以看到中文被替換成hash, 后面可以通過其他方式看到

添加人員

ou並不能當做分組,而僅僅是組織架構的一個單元。ldap的分組都是通過單獨的group來實現的。

添加人員

添加人員對應的是樹的葉子節點,使用的oebjectClass: inetOrgPerson

添加組織部門對應的是目錄,使用的objectClass: organizationalUnit.

我們要把人員添加到ou=People,dc=demo,dc=com下。

創建adduser.ldif

dn: ou=研發部門,ou=People,dc=demo,dc=com
changetype: add
objectClass: organizationalUnit
ou: 研發部門

dn: ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
changetype: add
objectClass: organizationalUnit
ou: 后台組



dn: cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
changetype: add
objectClass: inetOrgPerson
cn: ryan.miao
departmentNumber: 1
sn: Miao
title: 大牛
mail: ryan.miao@demo.com
uid: 10000
displayName: 中文名



dn: cn=someone,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
changetype: add
objectClass: inetOrgPerson
cn: someone
departmentNumber: 1
sn: someone
title: Java工程師
mail: someone@demo.com
uid: 10001
displayName: 某人


dn: ou=測試組,ou=研發部門,ou=People,dc=demo,dc=com
changetype: add
objectClass: organizationalUnit
ou: 測試組


dn: cn=tester.miao,ou=測試組,ou=研發部門,ou=People,dc=demo,dc=com
changetype: add
objectClass: inetOrgPerson
cn: tester.miao
departmentNumber: 2
sn: Miao
title: 測試工程師
mail: tester@demo.com
uid: 10002
displayName: 測試某人


dn: ou=HR,ou=People,dc=demo,dc=com
changetype: add
objectClass: organizationalUnit
ou: HR


dn: cn=fang.huang,ou=HR,ou=People,dc=demo,dc=com
changetype: add
objectClass: inetOrgPerson
cn: fang.huang
departmentNumber: 3
sn: Huang
title: HRBP
mail: fang.huang@demo.com
uid: 10003
displayName: 黃芳

使用ldapadd來添加我們的用戶

[root@e6043aeb680e data]# ldapadd -x -D cn=admin,dc=demo,dc=com -w admin -f adduser.sh 
adding new entry "ou=研發部門,ou=People,dc=demo,dc=com"

adding new entry "ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com"

adding new entry "cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com"

adding new entry "cn=someone,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com"

adding new entry "ou=測試組,ou=研發部門,ou=People,dc=demo,dc=com"

adding new entry "cn=tester.miao,ou=測試組,ou=研發部門,ou=People,dc=demo,dc=com"

adding new entry "ou=HR,ou=People,dc=demo,dc=com"

adding new entry "cn=fang.huang,ou=HR,ou=People,dc=demo,dc=com"

使用ldapsearch來查詢用戶

指定唯一id來查詢某個用戶,比如cn唯一,則

[root@e6043aeb680e data]# ldapsearch -x -D cn=admin,dc=demo,dc=com -w admin -b "dc=demo,dc=com" "cn=ryan.miao"  
# extended LDIF
#
# LDAPv3
# base <dc=demo,dc=com> with scope subtree
# filter: cn=ryan.miao
# requesting: ALL
#

# ryan.miao, \E5\90\8E\E5\8F\B0\E7\BB\84, \E7\A0\94\E5\8F\91\E9\83\A8\E9\97\A8,
  People, demo.com
dn:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlLGRjP
 WRlbW8sZGM9Y29t
objectClass: inetOrgPerson
cn: ryan.miao
departmentNumber: 1
sn: Miao
title:: 5aSn54mb
mail: ryan.miao@demo.com
uid: 10000
displayName:: 5Lit5paH5ZCN

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

和前面的示例相比,多了一個參數filter

ldapsearch -x -D "admin的dn" -w "admin的密碼" -b "basedn, 最外層的分組" "search filter:"

還可以指定返回的字段

[root@e6043aeb680e data]# ldapsearch -x -D cn=admin,dc=demo,dc=com -w admin -b "ou=HR,ou=People,dc=demo,dc=com"  cn uid  displayName
# extended LDIF
#
# LDAPv3
# base <ou=HR,ou=People,dc=demo,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: cn uid displayName 
#

# HR, People, demo.com
dn: ou=HR,ou=People,dc=demo,dc=com

# fang.huang, HR, People, demo.com
dn: cn=fang.huang,ou=HR,ou=People,dc=demo,dc=com
cn: fang.huang
uid: 10003
displayName:: 6buE6Iqz

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

在配置第三方認證的時候,比如airflow, 就是通過這樣userfilter來search用戶的。

添加用戶密碼

剛才添加用戶太快,忘記添加用戶密碼了。這就涉及到添加用戶的同時指定密碼和admin修改密碼以及用戶
自己修改密碼三個情況了。

添加用戶的時候指定密碼

一個hr肯定太累了,添加一個新的hr hr-ryan

創建文件addone.ldif

dn: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com
changetype: add
objectClass: inetOrgPerson
cn: hr-ryan
userPassword: 123456
departmentNumber: 3
sn: hr-ryan
title: HRBP
mail: hr-ryan@demo.com
uid: 10004
displayName: 我是獵頭

執行添加

ldapadd -x -D cn=admin,dc=demo,dc=com -w admin -f addone.ldif

查詢驗證

root@e6043aeb680e data]# ldapsearch -x -D cn=admin,dc=demo,dc=com -w admin -b dc=demo,dc=com "cn=hr-*"
# extended LDIF
#
# LDAPv3
# base <dc=demo,dc=com> with scope subtree
# filter: cn=hr-*
# requesting: ALL
#

# hr-ryan, HR, People, demo.com
dn: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com
objectClass: inetOrgPerson
cn: hr-ryan
userPassword:: MTIzNDU2
departmentNumber: 3
sn: hr-ryan
title: HRBP
mail: hr-ryan@demo.com
uid: 10004
displayName:: 5oiR5piv54yO5aS0

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

可以看到,filter里可以使用通配符。並且,用戶密碼被加密了。

我們前文說,第三方系統第一步通過search拿到dn,也就是上面這一步。然后第二個是驗證密碼,驗證密碼是怎么做的呢?直接通過search語法連接ldap,通過則證明密碼正確。

[root@a1791f1044ba data]# ldapsearch -x -D cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com -w 123456
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1

修改用戶密碼

管理員權限最大,可以修改任意密碼。使用ldapmodify

創建文件updatepass.ldif

dn: cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
changetype: modify
replace: userPassword
userPassword: ryanmiao

執行修改

ldapmodify -a -H ldap://172.17.0.2:389 -D "cn=admin,dc=demo,dc=com" -w admin -f updatepass.ldif 

查詢確認

ldapsearch -x -D cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com -w ryanmiao -b dc=demo,dc=com "cn=ryan.miao"

可以確認密碼修改成功了,同時也暴露了一個問題,任意一個人都可以bind登錄,然后查詢所有用戶的信息。后面我
們將關注acl權限問題,讓每個人只能查詢自己的信息,讓指定的group可以查詢所有人的信息。

注意到,我們使用的明文作為密碼存儲, 這樣的傳輸方式是不推薦的, 可以使用sha1來存儲。

slappasswd -s ryanmiao
{SSHA}r5yzPeESGLsvX7oxQetVEpel9LhygFef


dn: cn=ryan.miao,ou=后台組,ou=研發部門,dc=demo,dc=com
changetype: modify
replace: userPassword
userPassword: {SSHA}r5yzPeESGLsvX7oxQetVEpel9LhygFef


[root@a1791f1044ba schema]# slappasswd -h {sha} -s ryanmiao
{SHA}vMV4cx3BhPVf0dRvEur3NOWIDEw=
[root@a1791f1044ba schema]# slappasswd -h {md5} -s ryanmiao
{MD5}J3sqNCJFas5wgycX4lJPsg==

或者sha1
userPassword: {SHA}vMV4cx3BhPVf0dRvEur3NOWIDEw=

值得注意的是sha1的結果並不是通常我們用的hex結果,而是通過utf8轉換的:

public static String sha1(String str)
    throws NoSuchAlgorithmException, UnsupportedEncodingException {
    if (null == str || str.length() == 0) {
        return null;
    }
    MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
    mdTemp.update(str.getBytes("UTF-8"));
    byte[] md = mdTemp.digest();

    return "{SHA}" + Utf8.decode(java.util.Base64.getEncoder().encode(md));
}

Springboot提供了LdapShaPasswordEncoder, 但標記為deprecated, 理由是明文的加密算法不夠安全。
我們的ldap由於屬於同步服務,即ldap不負責用戶信息的維護,只負責查詢。需要由用戶中心來同步給ldap信息。
這就涉及到密碼的問題,用戶中心沒有存儲用戶明文的,也就是不能直接同步到ldap。好在可以獲得用戶密碼的sha,
通過sha來同步ldap的密碼,即ldap中的密碼是一個sha的方式存儲的。雖然不夠安全,容易被撞,但用着也還行。
如果不信任這種算法,那就不用ldap。可以使用oauth的方式認證第三方系統,大部分系統已支持這種認證方案。

@deprecated Digest based password encoding is not considered secure. Instead use an
adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
password upgrades. There are no plans to remove this support. It is deprecated to indicate
that this is a legacy implementation and using it is considered insecure.

前面提到用戶已知個人密碼的情況下,如何自己修改密碼。

ldappasswd -x -h 172.17.0.2 -p 389 -D "cn=Barbara Jensen,dc=example,dc=org" -w VSzhfbwA -s 123456

我們先不關注這種行為吧,默認所有第三方系統只有登錄權限。關於組織架構的維護,即ldap組織的更新,我們采用
其他的方案去管理,ldap只是用來輔助第三方登錄的。即,其他系統想要修改密碼之類的,統一到我們的用戶中心服務
去修改變更,用戶中心負責把信息同步給ldap。

添加組Group

有人會問,我之前添加人員的時候添加了很多部門的ou,不就是group嗎。

是的,理論上應該是group。但是由於我們丟了一步,沒有設置ou的objectClass為group。所以,這里單獨講group的故事。

ldap的group是一種單獨的類型objectClass: groupOfNames, 有個字段叫做member, value就是entry的dn。如此,
實現了group-user的映射關系。

我們可以通過group來查詢member,然而,並不能通過user直接獲取到group。這在配置第三方系統的時候,沒辦法做group認證,
比如airflow要求輸入group filter, 默認通過memberof的屬性值來獲取group。所以,理論上user應該有個字段叫做memberof,
value是group。

大家可能會覺得dn已經很明顯的分組了好吧,為啥還要這么復雜。事實上,ldap也提供了Reverse Group Membership Maintenance.
由系統來維護二者的映射關系。即

  • group添加member的時候會自動給對應的entry添加memberof字段
  • 當刪除entry的時候,也會從group里刪除member字段

這個需要單獨配置,默認是不支持的。

添加memberof模塊

創建add_module_group.sh

dn: cn=module,cn=config
cn: module
objectClass: olcModuleList
olcModulePath: /usr/lib64/openldap

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: memberof.la

執行添加

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f  add_module_group.sh 

創建add_group_objectClass.sh

dn: olcOverlay=memberof,olcDatabase={2}hdb,cn=config
objectClass: olcConfig
objectClass: olcMemberOf
objectClass: olcOverlayConfig
objectClass: top
olcOverlay: memberof
olcMemberOfDangling: ignore
olcMemberOfRefInt: TRUE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member     
olcMemberOfMemberOfAD: memberOf

執行添加

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f  add_group_objectClass.sh

添加一個group

創建addgroup.ldif

dn: cn=g-admin,ou=Group,dc=demo,dc=com
objectClass: groupOfNames
cn: g-admin
member: cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com

執行

ldapmodify -a -H ldap://172.17.0.2:389 -D "cn=admin,dc=demo,dc=com" -w admin -f addgroup.ldif

查看組

[root@e6043aeb680e data]# ldapsearch -H ldapi:/// -x -D "cn=admin,dc=demo,dc=com" -w admin -b "ou=Group,dc=demo,dc=com" 
# extended LDIF
#
# LDAPv3
# base <ou=Group,dc=demo,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# Group, demo.com
dn: ou=Group,dc=demo,dc=com
objectClass: organizationalUnit
ou: Group

# g-admin, Group, demo.com
dn: cn=g-admin,ou=Group,dc=demo,dc=com
objectClass: groupOfNames
cn: g-admin
member:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlL
 GRjPWRlbW8sZGM9Y29t
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

再來查看entry是否添加了memberof, ldapsearch當不指定字段的時候,默認返回全部強制字段,memberof不屬於強制,需要單獨指明

[root@e6043aeb680e data]# ldapsearch -H ldapi:/// -x -D "cn=admin,dc=demo,dc=com" -w admin -b "ou=People,dc=demo,dc=com" "(|(cn=ryan.miao)(cn=hr-*))" memberof
# extended LDIF
#
# LDAPv3
# base <ou=People,dc=demo,dc=com> with scope subtree
# filter: (|(cn=ryan.miao)(cn=hr-*))
# requesting: memberof 
#

# ryan.miao, \E5\90\8E\E5\8F\B0\E7\BB\84, \E7\A0\94\E5\8F\91\E9\83\A8\E9\97\A8,
  People, demo.com
dn:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlLGRjP
 WRlbW8sZGM9Y29t
memberOf: cn=g-admin,ou=Group,dc=demo,dc=com

# hr-ryan, HR, People, demo.com
dn: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com
memberOf: cn=g-admin,ou=Group,dc=demo,dc=com

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

可以看到,這兩個人都link到了admin組。如此實現了我們的組添加和管理。

同時,再次引入了新的查詢語法,filter的正則匹配。

  • (|(cn=ryan.miao)(cn=hr-*)) 表示或者滿足某個條件,這里就是為了查詢這兩個人,另外*表示通配符
  • (&(objectClass=inetOrgPerson)(cn=ryan.miao)) 第三方系統,比如Python集成ldap的配置,通常會有一個basedn, 就是我們的域名了,然后userfilter,
    這個filter就是這個。我們通常填寫objectClass=inetOrgPerson。然后讓我們配置user_name_attr, 這就是唯一屬性,我們說我們的cn唯一。

所以,一個Python的ldap配置,通常是這個樣子的。

[ldap]
# set this to ldaps://<your.ldap.server>:<port>
uri = ldap://172.17.0.2:389
user_filter = objectClass=inetOrgPerson
user_name_attr = cn
group_member_attr = memberof
superuser_filter =
data_profiler_filter =
bind_user = cn=admin,dc=demo,dc=com
bind_password = admin
basedn = dc=demo,dc=com
cacert = 
search_scope = SUBTREE

源碼 https://github.com/apache/airflow/blob/master/airflow/contrib/auth/backends/ldap_auth.py#L101

search_filter = "(&({0})({1}={2}))".format(user_filter, user_name_att, username)

添加用戶到group

我們來創建一個common group, 表示所有人都應該在的一個group。

# commongroup.sh
dn: cn=g-users,ou=Group,dc=demo,dc=com
objectClass: groupOfNames
cn: g-users
member: cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com

ldapmodify -a -H ldap://172.17.0.2:389 -D "cn=admin,dc=demo,dc=com" -w admin -f commongroup.sh

到目前為止,我們添加了2個group:

[root@40e6bf0b50dc data]# ldapsearch -H ldap:/// -D cn=admin,dc=demo,dc=com -w admin -b dc=demo,dc=com -s sub "objectClass=groupOfNames"  dn member
# extended LDIF
#
# LDAPv3
# base <dc=demo,dc=com> with scope subtree
# filter: objectClass=groupOfNames
# requesting: dn member 
#

# g-admin, Group, demo.com
dn: cn=g-admin,ou=Group,dc=demo,dc=com
member:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlL
 GRjPWRlbW8sZGM9Y29t
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com

# g-users, Group, demo.com
dn: cn=g-users,ou=Group,dc=demo,dc=com
member:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlL
 GRjPWRlbW8sZGM9Y29t
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com

接下來,我們把剩下的用戶加入到g-users這個group, 以后所有人加入的默認group。

創建addUserToGroup.sh

dn: cn=g-users,ou=Group,dc=demo,dc=com
changetype: modify
add: member
member: cn=fang.huang,ou=HR,ou=People,dc=demo,dc=com
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com
member: cn=someone,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com
member: cn=tester.miao,ou=測試組,ou=研發部門,ou=People,dc=demo,dc=com

執行

ldapmodify -H ldap:/// -x -D cn=admin,dc=demo,dc=com -w admin -f addUserToGroup.sh

查看

[root@40e6bf0b50dc data]# ldapsearch -H ldap:/// -D cn=admin,dc=demo,dc=com -w admin -b dc=demo,dc=com -s sub "objectClass=groupOfNames"  
# g-admin, Group, demo.com
dn: cn=g-admin,ou=Group,dc=demo,dc=com
objectClass: groupOfNames
cn: g-admin
member:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlL
 GRjPWRlbW8sZGM9Y29t
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com

# g-users, Group, demo.com
dn: cn=g-users,ou=Group,dc=demo,dc=com
objectClass: groupOfNames
cn: g-users
member:: Y249cnlhbi5taWFvLG91PeWQjuWPsOe7hCxvdT3noJTlj5Hpg6jpl6gsb3U9UGVvcGxlL
 GRjPWRlbW8sZGM9Y29t
member: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com
member: cn=fang.huang,ou=HR,ou=People,dc=demo,dc=com
member: cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com
member:: Y249c29tZW9uZSxvdT3lkI7lj7Dnu4Qsb3U956CU5Y+R6YOo6ZeoLG91PVBlb3BsZSxkY
 z1kZW1vLGRjPWNvbQ==
member:: Y249dGVzdGVyLm1pYW8sb3U95rWL6K+V57uELG91PeeglOWPkemDqOmXqCxvdT1QZW9wb
 GUsZGM9ZGVtbyxkYz1jb20=

從Group中移除user

g-admin是一個管理員分組,我們去掉普通用戶cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com

創建removeUserFromGroup.sh

dn: cn=g-admin,ou=Group,dc=demo,dc=com
changetype: modify
delete: member
member: cn=ryan.miao,ou=后台組,ou=研發部門,ou=People,dc=demo,dc=com

執行

ldapmodify -H ldap:/// -x -D cn=admin,dc=demo,dc=com -w admin -f removeUserFromGroup.sh

最終Group和user的關系

group可以有多個user, user可以歸屬於多個group,是多對多的關系。

group有多個member字段, user有多個memberof字段。

ACL權限控制

Access Control List (ACL) 表示權限控制。從前面的測試可以看到,默認是沒開啟權限的。任何人都可以連接查詢和操作。

acl的設置方式很多,鑒於我們並沒有將ldap作為主要的數據存儲方案,即不做過多的權限設置了,只要關掉匿名訪問,只允許read,
允許個人修改個人信息就好了。更多設置方案可以參照官網。

acl的配置文件

配置文件還是開始提到的,我們可以查看現有的配置:

[root@e6043aeb680e data]# ldapsearch  -Y EXTERNAL -H ldapi:/// -b cn=config dn
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=config> with scope subtree
# filter: (objectclass=*)
# requesting: dn 
#

# config
dn: cn=config

# module{0}, config
dn: cn=module{0},cn=config

# schema, config
dn: cn=schema,cn=config

# {0}core, schema, config
dn: cn={0}core,cn=schema,cn=config

# {1}cosine, schema, config
dn: cn={1}cosine,cn=schema,cn=config

# {2}nis, schema, config
dn: cn={2}nis,cn=schema,cn=config

# {3}inetorgperson, schema, config
dn: cn={3}inetorgperson,cn=schema,cn=config

# {-1}frontend, config
dn: olcDatabase={-1}frontend,cn=config

# {0}config, config
dn: olcDatabase={0}config,cn=config

# {1}monitor, config
dn: olcDatabase={1}monitor,cn=config

# {2}hdb, config
dn: olcDatabase={2}hdb,cn=config

# {0}memberof, {2}hdb, config
dn: olcOverlay={0}memberof,olcDatabase={2}hdb,cn=config

# search result
search: 2
result: 0 Success

# numResponses: 13
# numEntries: 12

acl就在dn: olcDatabase={2}hdb,cn=config, 我們可以查看具體的配置:

[root@e6043aeb680e data]#  ldapsearch  -Y EXTERNAL -H ldapi:/// -b cn=config 'olcDatabase={2}hdb'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=config> with scope subtree
# filter: olcDatabase={2}hdb
# requesting: ALL
#

# {2}hdb, config
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
olcRootDN: cn=admin,dc=demo,dc=com
olcSuffix: dc=demo,dc=com
olcRootPW: {SSHA}kSEbfJCLQXtHKe+O/HoIXD0k50e7SubL

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

接下來,使用modify添加acl即可。

創建addacl.sh

dn: olcDatabase={2}hdb,cn=config
changetype: modify
# 只有自己可以修改密碼, 不允許匿名訪問, 允許g-admin組修改
add: olcAccess
olcAccess: {0}to attrs=userPassword by self write by anonymous auth by group.exact="cn=g-admin,ou=Group,dc=demo,dc=com"  write by * none
-
# 自己可以修改自己的信息,g-admin可以修改任何信息
add: olcAccess
olcAccess: {1}to * by self write by group.exact="cn=g-admin,ou=Group,dc=demo,dc=com"  write   by * none

執行

ldapmodify -H ldapi://  -Y EXTERNAL -f addacl.sh

驗證權限

添加一個普通用戶;

# addtwo.sh
dn: cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com
changetype: add
objectClass: inetOrgPerson
cn: hr-miao
userPassword: 123456
departmentNumber: 3
sn: hr-miao
title: HRBP
mail: hr-miao@demo.com
uid: 10006
displayName: 我是HR

ldapmodify -a -H ldapi:// -D "cn=admin,dc=demo,dc=com" -w admin -f addtwo.sh

現在我們有兩個用戶來比較

  • cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com 是普通用戶
  • cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com 是g-admin用戶

分別來查詢:

[root@e6043aeb680e data]# ldapsearch -H ldap:/// -x -D cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com -w 123456 -b dc=demo,dc=com "cn=hr-ryan"  dn memberof
# extended LDIF
#
# LDAPv3
# base <dc=demo,dc=com> with scope subtree
# filter: cn=hr-ryan
# requesting: dn memberof 
#

# hr-ryan, HR, People, demo.com
dn: cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com
memberOf: cn=g-admin,ou=Group,dc=demo,dc=com

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

[root@e6043aeb680e data]# ldapsearch -H ldap:/// -x -D cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com -w 123456 -b dc=demo,dc=com "cn=hr-miao"  dn memberof
# extended LDIF
#
# LDAPv3
# base <dc=demo,dc=com> with scope subtree
# filter: cn=hr-miao
# requesting: dn memberof 
#

# search result
search: 2
result: 32 No such object

# numResponses: 1

可以看到,g-admin成員可以查詢其他所有, 普通用戶只能連接。

比較更新密碼能力:

# updateselfpass.sh
dn: cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com
changetype: modify
replace: userPassword
userPassword: ryanmiao

# 修改自己的密碼ok
[root@e6043aeb680e data]# ldapmodify -H ldap:/// -x -D cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com -w 123456 -f updateselfpass.sh 
modifying entry "cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com"

# 確認密碼被修改
[root@e6043aeb680e data]# ldapmodify -H ldap:/// -x -D cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com -w 123456 -f updateselfpass.sh 
ldap_bind: Invalid credentials (49)

# 修改dn為別人后不能修改密碼
[root@e6043aeb680e data]# ldapmodify -H ldap:/// -x -D cn=hr-miao,ou=HR,ou=People,dc=demo,dc=com -w ryanmiao -f updateselfpass.sh 
modifying entry "cn=hr-ryan,ou=HR,ou=People,dc=demo,dc=com"
ldap_modify: Insufficient access (50)

總結ldap命令

ldap主要命令有ldapadd, ldapmodify, ldapsearch. 我們用到的操作項有

option 含義
-H ldap server地址, 可以是ldap://192.168.12.18:389 表示tcp, 可以是ldap:/// 表示本地的tcp, 可以是ldapi:/// 本地unix socket連接
-x 啟用簡單認證,通過-D dn -w 密碼的方式認證
-f 指定要修改的文件
-a 使用ldapmodify增加一個entry的時候等同於ldapadd
-b basedn 根目錄, 將在此目錄下查詢
-Y EXTERNAL 本地執行,修改配置文件,比如basedn, rootdn,rootpw,acl, module等信息

ldapadd

添加一個entry. 可以

添加schema配置

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif 

添加額外的module

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f  add_module_group.sh 

添加普通entry

ldapadd -x -D cn=admin,dc=demo,dc=com -w admin -f base.ldif 

ldapmodify

修改entry, 可以

更新配置信息

ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f tmp.ldif

對應的更新文件語法

dn: 要更新的entry的dn, 配置為olcDatabase={2}hdb,cn=config, 用戶為用戶dn
changetype: modify
replace: olcRootDN   replace替換的字段
olcRootDN: cn=admin,dc=demo,dc=com
-
replace: olcSuffix
olcSuffix: dc=demo,dc=com
-
add: olcRootPW   add添加新的字段
olcRootPW: <pass>

ldapsearch

search查詢,主要集中在filter的使用上。

ldapsearch -H ldapi:/// -D cn=admin,cn=demo,cn=com -w admin -s sub "filter"  attr

-s scope 指定查詢范圍, 有base|one|sub|children 主要用sub表示base之下的所有子目錄。對應Python里的SUBTREE

filter語法,正則語法。因為使用的時候傳遞過來的通常是username, 需要比較username在ldap中的字段, 比如

(|(cn=Steve*)(sn=Steve*)(mail=Steve*)(givenName=Steve*)(uid=Steve*))

attr要返回的字段, 必須返回的字段可以在配置文件里查看。memberof非必須。

安裝phpldapadmin

ldap提供了一個可視化的php web phpldapadmin.

yum install httpd phpldapadmin -y

備份配置文件

 cp /etc/httpd/conf.d/phpldapadmin.conf  /etc/httpd/conf.d/phpldapadmin.conf.bak
 cp /etc/phpldapadmin/config.php /etc/phpldapadmin/config.php.bak

修改配置文件/etc/httpd/conf.d/phpldapadmin.conf,允許其他人訪問

Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs

<Directory /usr/share/phpldapadmin/htdocs>
     <RequireAny>
       #Require ip 127.0.0.1
       #Require ip ::1
       Require all granted
     </RequireAny>
</Directory>

修改配置文件/etc/phpldapadmin/config.php,使用dn登錄

//$servers->setValue('login','attr','uid');      #注釋掉這一行
$servers->setValue('login','attr','dn');         #添加這一行

啟動httpd

systemctl start httpd

默認80端口訪問,由於本測試已經映射端口為本地的8070,直接訪問
http://localhost:8071/phpldapadmin 或http://localhost:8071/ldapadmin即可。

登錄dn: cn=admin,dc=demo,dc=com

登錄密碼: admin

docker ldap

將我們上述的docker提交即可獲取一個ldap的docker鏡像。

docker commit -a "Ryan Miao" -m "這是一個ldap demo學習鏡像"  ldap ldap-demo

然而,docker鏡像推薦使用dockerfile來構建,
也就是說,需要把我們上述的操作都變成腳本去執行,把需要修改的內容變成環境變量。考驗腳本編寫能力。

我們先來看看網絡現有的docker鏡像: https://github.com/osixia/docker-openldap

ACL 附錄

關於acl語法

olcAccess: <access directive>
    <access directive> ::= to <what>
        [by <who> [<access>] [<control>] ]+
    <what> ::= * |
        [dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
        [filter=<ldapfilter>] [attrs=<attrlist>]
    <basic-style> ::= regex | exact
    <scope-style> ::= base | one | subtree | children
    <attrlist> ::= <attr> [val[.<basic-style>]=<regex>] | <attr> , <attrlist>
    <attr> ::= <attrname> | entry | children
    <who> ::= * | [anonymous | users | self
            | dn[.<basic-style>]=<regex> | dn.<scope-style>=<DN>]
        [dnattr=<attrname>]
        [group[/<objectclass>[/<attrname>][.<basic-style>]]=<regex>]
        [peername[.<basic-style>]=<regex>]
        [sockname[.<basic-style>]=<regex>]
        [domain[.<basic-style>]=<regex>]
        [sockurl[.<basic-style>]=<regex>]
        [set=<setspec>]
        [aci=<attrname>]
    <access> ::= [self]{<level>|<priv>}
    <level> ::= none | disclose | auth | compare | search | read | write | manage
    <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
    <control> ::= [stop | continue | break]

關於acl中的who

Table 6.3: Access Entity Specifiers

Specifier Entities
* All, including anonymous and authenticated users
anonymous Anonymous (non-authenticated) users
users Authenticated users
self User associated with target entry
dn[. ]= Users matching a regular expression
dn. = Users within scope of a DN

關於dn的授權

For example, if the directory contained entries named:

    0: o=suffix
    1: cn=Manager,o=suffix
    2: ou=people,o=suffix
    3: uid=kdz,ou=people,o=suffix
    4: cn=addresses,uid=kdz,ou=people,o=suffix
    5: uid=hyc,ou=people,o=suffix
Then:

dn.base="ou=people,o=suffix" match 2; 
dn.one="ou=people,o=suffix" match 3, and 5; 
dn.subtree="ou=people,o=suffix" match 2, 3, 4, and 5; and 
dn.children="ou=people,o=suffix" match 3, 4, and 5.

一個acl示例


# ACL1
access to attrs=userpassword
       by self       write
       by anonymous  auth
       by group.exact="cn=itpeople,ou=groups,dc=example,dc=com"
                     write
       by *          none
# ACL2
access to attrs=carlicense,homepostaladdress,homephone
       by self       write
       by group.exact="cn=hrpeople,ou=groups,dc=example,dc=com"
                     write
       by *          none
# ACL3
access to *
       by self       write
       by group.exact="cn=hrpeople,ou=groups,dc=example,dc=com"
                     write
       by users      read
       by *          none

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM