使用 OpenLDAP 集中管理用戶帳號

Linux-PAM 和 OpenLDAP 簡介

Linux-PAM 簡介

Linux-PAM (Linux 系統的可插入式認證模塊) 是一套共享函數庫,它表示一種性能健碩而且靈活方便的用戶級認證方式,允許系統管理員來決定應用程序如何識別用戶,即不需要 (重寫和) 重新編譯一個 (支持 PAM 的) 應用,就可以切換它所用的認證機制。目前,Linux-PAM 已經成爲 Linux、BSD 和其它一些 Unix 操作系統的首選認證方式,特別是在 Linux 上,幾乎所有的 daemon 和一些與授權有關的命令都通過 PAM 來進行驗證。

Linux-PAM 主要是由一組共享庫文件(share libraries, 也就是.so 文件)和一些配置文件組成。當用戶請求服務時,具有 PAM 認證功能的應用程序將與這些.so 文件進行交互,以此判斷是否可以授權給發起請求的用戶來使用服務,比如 su、vsftp、httpd 等。如果認證成功,那麼用戶便可以使用該服務或命令;如果認證失敗,用戶將不能使用該服務,同時,PAM 將向指定的 log 文件寫入警告信息。PAM 不依賴於任何應用或服務,用戶完全可以升級這些應用或服務而不必管 PAM 的共享庫的更新或升級,反之亦然。所以它非常的靈活。

PAM 的認證過程是通過對一些服務或應用的配置文件來控制的。在 Linux 上,PAM 配置信息通常位於目錄 /etc/pam.d,但是 UNIX 系統把所有的配置都放在/etc/pam.conf 文件裏。對於使用 PAM 的各項服務,/etc/pam.d 目錄中都有一個對應的配置文件,PAM 的配置文件是一系列的單行配置命令構成,每行配置都說明一種在操作系統上使用的特殊 PAM 模塊。

其一般格式爲:

[service] module-type control-flag module-path [arguments]

PAM 配置文件中的字段包括:

  • service: 指定服務/應用程序的名稱,如 telnet、login、ftp 等(默認值爲 OTHER)。

  • module-type: 爲 service 字段中的服務/應用程序指定模塊類型,模塊類型有四種類型(auth/account/session/password)。

  • control-flag: 指定了"配置段"裏的模塊應該怎麼相互作用,可以理解爲對 PAM 認證的流程控制,它可以獲取諸如 requisite、required、sufficient 和 optional 之類的值。

  • module-path: 指定實現模塊的庫對象的路徑名稱。最好使用絕對路徑,缺省路徑一般是/lib/security 或/lib64/security。

  • arguments:指定可以傳遞給服務模塊的選項或參數(可選字段)。

PAM 框架將按照配置文件中列出的條目順序調用相應的模塊,這取決於每個條目允許的 control_flag 的值。control_flag 指定了"配置段"裏的模塊應該怎麼相互作用,生成該配置段的最終結果。control_flag 值包括:

  • required:表示這一模塊的認證是必須成功的,如果認證失敗,認證過程不會即刻終止,PAM 將繼續下一個同類型的模塊認證。

  • requisite:與 required 類似,只是如果認證失敗,認證過程將立即終止。

  • sufficient:表示如果認證成功,那麼對這一類的模塊認證是充足的,其它的模塊將不會再檢驗。

  • optional:表示這一模塊認證是可選的,也不會對認證成功或失敗產生影響。

  • include:類似於 DNS 的 include。表示將包括其他的一些認證,這樣可以建立一個分離式的配置文件管理機制。

清單 1. PAM 配置文件的示例:
/etc/pam.d/login
#%PAM-1.0
auth          requisite      pam_nologin.so
auth          [user_unknown=ignore success=ok ignore=ignore auth_err=die default=bad]pam_securetty.so
auth          include        common-auth
account      include        common-account
password     include        common-password
session      required       pam_loginuid.so
session      include        common-session
session      required       pam_lastlog.so nowtmp
session      optional       pam_mail.so standard

PAM 配置文件來源於 SUSE Linux Enterprise Server11 操作系統。對於 PAM 的結構有了基本的瞭解,我們來看看 PAM 是如果控制 login 的,從上至下對於 login 的 PAM 配置文件的流程控制爲:

  • login 的第一行 pam_nologin 模塊檢查有沒有/etc/nologin 文件,如果有這個文件,除非是 root 用戶,否則該模塊就立即中止登陸。

  • 繼續第二項 auth 認證,第二行以方括號括起來的 key/value 值的組合用來表示 control_flag 的值,pam_securetty.so 模塊確保 root 用戶只能從文件/etc/securetty 裏列出的那些終端登陸到系統裏,限制 root 用戶在特殊設備上登陸。

  • 繼續第三項 auth 認證,具體的驗證規則包含在 common-auth 中。

  • 繼續第四項 account 認證,具體的驗證規則包含在 common-account 中

  • 繼續第五項 password 認證,具體的驗證規則在 common-password 中。

  • 繼續第六項 session 的驗證。注意:pam_loginuid.so 模塊用來設置 loginuid 過程屬性,其他的 session 驗證過程,請參照 control-flag 的說明,不再一一贅述。

OpenLDAP 簡介

OpenLDAP 是輕型目錄訪問協議(Lightweight Directory Access Protocol,LDAP)的自由和開源的實現,是最常用的目錄服務之一。在 Linux 的髮型版本中提供的 OpenLDAP 軟件按照客戶機/服務器模式實現了輕量級目錄訪問協議(LDAP)。

LDAP 目錄以樹狀的層次結構來存儲數據(這很類同於 DNS),最頂層即根部稱作"基準 DN",形如"dc=mydomain, dc=org"或者"o= mydomain.org",在根目錄的下面有很多的文件和目錄,爲了把這些大量的數據從邏輯上分開,LDAP 像其它的目錄服務協議一樣使用 OU (Organization Unit),可以用來表示公司內部機構,如部門等,也可以用來表示設備、人員等。同時 OU 還可以有子 OU,用來表示更爲細緻的分類。

Linux 系統配置 OpenLDAP

本文使用 OpenLDAP 2.4.30 來構建 LDAP 的服務器和客戶機。操作系統使用 SUSE Linux Enterprise Server11。用戶可以從 OpenLDAP 下載頁http://www.openldap.org/software/download/或者ftp://ftp.openldap.org/pub/OpenLDAP/下載 OpenLDAP 軟件到/usr/local,解壓 OpenLDAP,並進入 OpenLDAP 的最外層目錄,編譯並安裝 LDAP。

清單 2. 編譯及安裝 OpenLDAP 示例
#tarzxvfopenldap-stable-20120311.tgz
#cd /usr/local/openldap-2.4.30
#./configure withwrappers
Please "make depend" to build dependencies
#make depend
#make
#make test
#make install

OpenLDAP 依賴於一些第三方軟件包,因此安裝配置 OpenLDAP 之前需要首先安裝第三方軟件包。執行"make install"命令要求用戶有超級用戶權限。安裝成功後,可以配置 OpenLDAP 的服務器端和客戶端。

配置 OpenLDAP 服務器

OpenLDAP 安裝成功後,用戶會在/usr/local/etc/openldap 找到配置文件 slapd.conf。/usr/local/etc/openldap/slapd.conf 是 OpenLDAP 服務器最重要的配置文件,配置權限、口令、數據庫類型和數據庫位置等等。slapd.conf 文件中包括一系列全局配置選項,它們作爲一個整體應用到 slapd 上面,後面是包含數據庫特有信息的數據庫後端定義。空行和以 "#" 字符開頭的註釋行都會被忽略。

清單 3. slapd.conf 示例:
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/rfc2307bis.schema
include         /etc/openldap/schema/yast.schema

# Define global ACLs to disable default read access.

# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral       ldap://root.openldap.org

pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd/slapd.args

# Load dynamic backend modules:
# modulepath    /usr/lib/openldap/modules
# moduleload    back_bdb.la
# moduleload    back_hdb.la
# moduleload    back_ldap.la

# Sample security restrictions
#       Require integrity protection (prevent hijacking)
#       Require 112-bit (3DES or better) encryption for updates
#       Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64

# Sample access control policy:
#       Root DSE: allow anyone to read it
#       Subschema (sub)entry DSE: allow anyone to read it
#       Other DSEs:
#               Allow self write access to user password
#               Allow anonymous users to authenticate
#               Allow read access to everything else
#       Directives needed to implement policy:
access to dn.base=""
        by * read

access to dn.base="cn=Subschema"
        by * read

access to attrs=userPassword,userPKCS12
        by self write
        by * auth

access to attrs=shadowLastChange
        by self write
        by * read

access to *
        by * read
#######################################################################
# BDB database definitions
#######################################################################

database        bdb
suffix          "dc=my-domain,dc=com"
rootdn          "cn=Manager,dc=my-domain,dc=com"
# Cleartext passwords, especially for the rootdn, should
# be avoid.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw          secret
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory       /var/lib/ldap
# Indices to maintain
index   objectClass     eq

下面解釋一下配置文件中的設置:

database bdb

定義使用的後端數據存儲方式,數據庫格式默認採用 Berkeley DB。其後可以跟的值有 bdb、ldbm、passwd 和 shell。bdb 指使用 Berkley DB 4 數據庫。

suffix "dc=my-domain,dc=com"

suffix 是"LDAP 基準名",它是 LDAP 名字空間在這裏的根。設置想要創建的子樹的根的 DN(distinguished name),將 my-domain 替換成用戶實際使用的 domain。

rootdn "cn=Manager,dc=my-domain,dc=com"

設置管理 LDAP 目錄的超級用戶的 DN。這個用戶名不要出現在"/etc/passwd"文件裏。

rootpw secret

設置這個數據庫的超級用戶的口令驗證方式。也就是上面"rootdn"設置的用戶的口令。千萬不要用明文進行口令驗證,一定要用加密的口令,可以使用的加密方式有:CRYPT、MD5、SMD5、SHA 和 SSHA。

directory var/lib/ldap

設置 LDAP 數據庫和索引文件所在的目錄。在安裝階段指定 LDAP 的後臺數據庫。

access to dn.base=""

by * read

access to dn.base="cn=Subschema"

by * read

…...

用來定義訪問控制列表。

attrs=userPassword #指定"密碼"屬性
by self write #用戶自己可更改
by * auth #所有訪問者需要通過認證

到現在爲止,服務器基本就配置完成,在啓動 slapd 之前可以使用 slaptest 測試一下,slaptest 在/usr/sbin 目錄下。出現 config file testing succeeed 就表示配置沒有問題了。

清單 4. 測試 OpenLDAP 配置:
#/usr/sbin/slaptest
bdb_monitor_db_open: monitoring disabled; configure monitor database to enable
config file testing succeeded
清單 5. 啓動 OpenLDAP:
#/usr/local/openldap/libexec/slapd
[email protected] ldomain:/usr/local/src/openldap-2.4.30/servers/slapd

可以用 ps -aux 查看,或用以下命令查詢服務器,測試服務啓動是否成功:

ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts

如果命令執行成功,返回一些信息,則說明服務器正常運行了。如果啓動不成功,它會提示一些出錯信息,多數是 slapd.conf 配置出錯。仔細覈查一下配置文件。如果 OpenLDAP 配置爲非匿名訪問,請在 ldapsearch 命令中加入-D 和-w 參數。

配置 OpenLDAP 客戶機

手工配置 OpenLDAP 客戶機,編輯/etc/openldap/ldap.conf。

清單 6. ldap.conf 示例:
TLS_REQCERT never
URI ldap://localhost:389
base dc=base,dc=com
binddn cn=manager,dc=base,dc=com
bindpw crypt{ae2ec15710d547a0}
searchfilter (&(uid=%v)(objectclass=person))
pam_login_attribute uid
ldap_version 3
timelimit 30
bind_timelimit 30
pam_lookup_policy yes

URI :訪問LDAP serverURI,默認端口爲389;啓用SSL/TLS時,使用ldaps://host,端口爲636

base :指定默認的base DN

binddn: 指定默認的bind DN

bindpw: 認證用戶的密碼,建議使用密文。

基於 PAM 的 LDAP 用戶身份驗證

基於 PAM 的 LDAP 身份驗證要想正常的工作,還需要配置其他服務:系統命名服務和身份驗證服務。

系統命名服務(NSS)需要配置爲使用 LDAP 來解析諸如用戶和組帳號之類的資源,即將用戶的 uid 解析爲用戶名。由於未來用戶都存儲在 LDAP 目錄中,因此係統需要配置成同時對 /etc/passwd 文件和 LDAP 目錄中的帳號進行解析。這種功能是通過 /usr/lib/libnss_ldap.so 庫提供的。

身份驗證服務是實際執行 LDAP 驗證用戶身份的服務。Linux-PAM 提供了本地 Linux 身份驗證服務。基於 PAM 的 LDAP 身份認證首先在本地的 /etc/passwd 文件檢查用戶帳號,如果用戶在/etc/passwd 中存在,則 PAM LDAP 模塊可以將身份驗證重定向到 LDAP 目錄上。並進行密碼的校驗,/lib/security/pam_ldap.so PAM 模塊提供了 LDAP 身份驗證功能。如果用戶在/etc/passwd 中不存在,則對 LDAP 服務器進行檢查,用戶在 LDAP 上存在,且用戶所在的組有權限登錄 Linux 操作系統,則 PAM 身份認證程序自動在 Linux 操作系統上創建同名的用戶,並將用戶加入默認的組。以後用戶只需要在 LDAP 上維護,不需要在 Linux 操作系統上維護。從而減輕了管理員的維護工作,也是用戶免去了記錄多個用戶 ID 和密碼的煩惱。

圖 1. 基於 PAM 的 LDAP 身份驗證流程

基於 PAM 的 LDAP 身份驗證流程

PAM 身份驗證服務程序

Linux 系統成功配置 OpenLDAP 後,爲了與 PAM 集成統一管理用戶,需要開發 PAM 相關的 so 文件實現用戶的身份驗證,在本文中 so 文件命名爲 pam_ldap_union.so。當 LDAP 用戶首次登陸 Linux terminal 時,首先判斷用戶在 Linux 操作系統中是否存在。如果用戶在操作系統中存在,則直接返回 PAM_SUCCESS。如果用戶不存在,則查詢 OpenLDAP server。如果用戶在 OpenLDAP server 存在,並且用戶所在的組具有登陸 Linux 操作系統的權限,則在本地創建同名的用戶,並給用戶分配相應的權限。

清單 7. pam_ldap_union.so 代碼示例
//判斷用戶在 Linux 操作系統中是否存在。用戶存在,直接返回 PAM_SUCCESS;否則,查詢 OpenLDAP server。
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv)
{
  
rc = pam_get_user(pamh, &user, NULL);// the user name is in the authentication handle – pamh

rc = pam_get_item(pamh, PAM_SERVICE, (const void**)&service);// get current user service.

localuser = getpwnam(user); // get user from /etc/passwd
if ( localuser != NULL ) {
    	return PAM_SUCCESS;
    }
  ……
}

//從文件/etc/openldap/ldap.conf 獲取 binddn 的 bindpw 值,作爲 ldapsearch 命令的參數。
FILE *fp = fopen("/etc/openldap/ldap.conf", "r");
int rc=0;
char ldapsearch[300];

//通過 ldapsearch 命令查詢當前用戶是否在 LDAP server 中。
sprintf(ldapsearch, "/usr/bin/ldapsearch -x -D \"%s\" -w \"%s\" cn=%s | grep \"=%s,\" 2>&1", 
     binddn, bindpw, group, user);
rc = system(ldapsearch);
if(rc == 0){
    printf ("pam_ldap_union: user %s found in LDAP directory", user);
    break;
}else {
    printf("pam_ldap_union: user %s not found in LDAP directory ,local account will not be created", 
    user, user);
    if(i == 5){
        return(PAM_AUTH_ERR);
    }
}

char useradd[100];
char *homeDir = "-m";
char *primarygroup = "-g users";
char *supplgroup = "-G \'\'";
char *shell = "-s /bin/smrsh";

//如果用戶在 LDAP server 中,通過 useradd 命令在 Linux 操作系統創建同名用戶。
sprintf(useradd, "/usr/sbin/useradd %s %s %s %s %s >/dev/null 2>&1", homeDir, primarygroup, 
    supplgroup, shell, user);

rc = system(useradd);

if ( rc != 0 ) {
    printf("pam_ldap_union: useradd command failed with return code %d", rc);
}
return PAM_SUCCESS;

PAM 身份驗證配置

要讓 PAM 身份驗證服務使用 OpenLDAP 服務器中的用戶,將 pam_ldap 和 pam_ldap_union 加入到 PAM 配置文件/etc/pam.d/login 中,/etc/pam.d/login 中包含了 common-auth、common-account、common-password。將 pam_ldap 和 pam_ldap_union 按照以下方式加入到相應配置文件中。

清單 8. login 文件清單
#%PAM-1.0
auth    requisite      pam_nologin.so
auth    [user_unknown=ignore success=ok ignore=ignore auth_err=die default=bad] 
   pam_securetty.so
auth       include        common-auth
account   include        common-account
password include        common-password
session  required       pam_loginuid.so
session  include        common-session
session  required       pam_lastlog.so nowtmp
session  optional       pam_mail.so standard
清單 9. common-auth 文件清單
auth required pam_tally2.so onerr=fail deny=20 unlock_time=3600 silent
auth required  /lib/security/pam_ldap_union.so
auth sufficient /lib/security/pam_ldap.so config=/etc/openldap/ldap.conf 
   ignore_authinfo_unavail ignore_unknown_user
auth required  pam_unix_auth.so try_first_pass delay    #nullok set_setrpc
清單 10. common-account 文件清單:
account required     pam_tally2.so
account required     pam_unix_acct.so
account sufficient   /lib/security/pam_ldap.so config=/etc/openldap/ldap.conf
清單 11. common-password 文件清單
Password required    pam_cracklib.so type=#
password sufficient  /lib/security/pam_ldap.so config=/etc/openldap/ldap.conf  use_authtok
password required    pam_unix_passwd.so   use_first_pass sha512
清單 12. common-session 文件清單
session required        pam_limits.so
session required        pam_unix_session.so debug # none or trace
session optional        pam_umask.so

LDAP 用戶的統一管理

經過以上 PAM 程序的開發和配置,LDAP 用戶以後可以直接登陸 Linux 操作系統。企業中的用戶只需要記錄一套用戶名和密碼,就可以登錄企業其他應用服務。當 LDAP server 上的用戶出現新增、修改、刪除等變化時,用戶可以開發一套腳本,實現 Linux 操作系統和 LDAP server 上用戶的同步。主要使用的命令如下:

新增用戶使用的命令:

LDAP:ldapadd,例如 ldapadd -x -D <bindDN> -w <password>

Linux:useradd,例如 useradd –m –g <group> -s <shell> <name>

修改用戶使用的命令:

LDAP:ldapmodify 或者 ldappasswd,ldappasswd 用於設置密碼。

Linux:usermod,修改用戶相關信息。

刪除用戶使用的命令:

LDAP:ldapdelete,例如 ldapdelete -x -D <bindDN> -w secret <userinfo>

Linux:userdel <username>

用戶也可以不開發此類腳本,這樣在操作系統上會存在一些冗餘的用戶,但是不影響用戶的登陸,凡是在 LDAP server 上作廢的用戶,是無法在操作系統上登陸的。

基於 PAM 的 LDAP 用戶統一管理的應用

隨着企業業務的不斷髮展,企業的信息系統隨之增加,用戶信息相對分散,爲保障系統的安全正常使用和信息的一致性,需要將分散的用戶信息整合集中進行統一管理,LDAP 是用戶首選的用戶管理工具,由 LDAP 統一管理企業的所有用戶,能夠快速構建出符合企業自身用戶信息管理的需求,消除應用系統間用戶信息孤島,實現人員集中管理和企業各級分散的授權管理,形成人員和應用統一入口、統一管理。Linux-PAM 與 LDAP 的集成,可以用來管理企業的 Linux 服務器的用戶。LDAP 服務器上有非常多的用戶,屬於不同組的用戶具有不同的權限,只要將用戶添加到相應的組,用戶便有權限登陸操作系統或維護企業的 Linux 操作系統服務器,雖然用戶可以在 LDAP 上維護,但是用戶的權限信息還是維護在各自的應用系統上。在一些擁有幾十萬員工和以及擁有數以千計的服務器的企業中,這種應用能夠簡化管理員的維護工作,也能免去用戶繁瑣的記錄多套用戶名和密碼的煩惱。

原文出自:https://www.ibm.com/developerworks/cn/linux/1406_liulz_pamopenldap/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章