LDAP学习笔记之十:OpenLDAP 主机控制策略
一、主机控制策略实现方式
针对 OpenLDAP 实现主机控制有两种方式。一种通过系统自身的 access 模块实现用户登录主机限制,但配置比较复杂、缺乏灵活性。另一种则通过 OpenLDAP 服务端自身定义的 schema、objectClass 以及添加用户条目属性。并结合客户端的参数配置,从而实现主机登录控制。此方式管理简单、灵活性强。
二、通过 Linux-PAM 模块实现控制
1.Linux-PAM 组织架构
默认登录 UNIX/Linux 机器时,均通过系统自带的 PAM 模块来验证登录者身份的合法性以及密码的正确性来实现系统的登录。Linux-PAM 组织架构图如下
+----------------+
| application: X |
+----------------+ / +----------+ +================+
| authentication-[---->--\--] Linux- |--<--| PAM config file|
| + [----<--/--] PAM | |================|
|[conversation()][--+ \ | | | X auth .. a.so |
+----------------+ | / +-n--n-----+ | X auth .. b.so |
| | | __| | | _____/
| service user | A | | |____,-----'
| | | V A
+----------------+ +------|-----|---------+ -----+------+
+---u-----u----+ | | |
| auth.... |--[ a ]--[ b ]--[ c ]
+--------------+
| acct.... |--[ b ]--[ d ]
+--------------+
| password |--[ b ]--[ c ]
+--------------+
| session |--[ e ]--[ c ]
+--------------+
2.PAM 配置文件语法讲解
PAM 配置文件路径
$ ls /etc/pam.conf # 旧版
$ ls /etc/pam.d/* # 新版
PAM 模块路径如下:
$ ls /lib64/security/ # x86_64
$ ls /lib/security/ # x86_32
系统的默认配置文件如下:
/etc/pam.d/system-auth #https://www.cnblogs.com/kevingrace/p/8671964.html 可以参考这篇文章
三、通过Access 控制用户实战演练
1.Access 模块功能概要
pam_access 主要用于控制登录访问机器,默认使用 /etc/security/access.conf 配置文件实现各种访问控制限制。但要使用 access.conf 配置文件,必须在 /etc/pam.d/login 文件中加载 pam_access.so 模块,否则修改 access.conf 不会生效
2.Access 配置语法
pam_access.so 验证模块主要根据 access.conf 配置文件中限制的条件进行过滤,access.conf 配置文件格式如下
permission: user : origin
各参数的含义如下:
permission:通过 “+” 和 “-” 实现; “+” 代表运行动作,“-” 代表拒绝动作。可以通过 EXCEPT 实现拒绝所有,运行部分登录。
user:代表允许的或拒绝的用户以及用户组;可以通过 “all” 代表所有用户。
origin:代表用户登录的目标,例如 local 代表本地,console 代表控制台,all 代表所有以及定义网络等
3.通过 Access 控制用户实战演练
加载 pam_access.so 模块(需要限制用户登录的客户端机器上)
要加载 pam_access.so 模块,首先编辑 /etc/pam.d/sshd 文件。然后搜索并定位 account,添加如下:(新添加的 account 要设置最前面否则可能会失效)
[root@ldap01 ~]# vim /etc/pam.d/sshd
#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_access.so #添加pam_access模块,新添加的 account 要设置最前面否则可能会失效
account required pam_nologin.so
account include password-auth
password include password-auth
配置访问规则
[root@client01 ~]# vim /etc/security/access.conf #限制登录的主机上添加
-:ldap1:ALL #以ldap1用户为例,禁止ldap1用户登录客户端192.168.1.132机器
验证
[root@client01 ~]# ssh ldap1@192.168.1.132
ldap1@192.168.1.132's password:
Permission denied, please try again.
[root@client01 ~]# tail /var/log/secure
Apr 23 00:02:01 client01 sshd[38953]: fatal: Access denied for user ldap5 by PAM account configuration [preauth]
Apr 24 22:27:33 client01 sshd[46999]: Accepted password for root from 192.168.1.1 port 1366 ssh2
Apr 24 22:27:33 client01 sshd[46999]: pam_unix(sshd:session): session opened for user root by (uid=0)
Apr 24 22:37:34 client01 sshd[47514]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=client01.pwb.com user=ldap1
如果要拒绝或运行多个用户登录系统,可以通过在 OpenLDAP 服务端上将用户加入到指定的组中,然后在 access.conf 配置文件中限制拒绝或运行即可,因为所有验证都通过 OpenLDAP 服务读取信息。
通过 pam_access.so 模块,从 ssh 登录以及 IP 地址方式限制了用户登录主机,但无法限制从控制台登录,所以建议根据当前需求进行选择。
四、OpenLDAP 服务端主机控制规则
提供自定义模块并调整主机配置即可实现 OpenLDAP 用户登录权限限制。
1.定义 olcModuleList 对象
#通过以下命令定义 olcModuleList 对象。(请查看是否有 /etc/openldap/slapd.d/cn=config/cn=module\{0}.ldif 文件,如果有则忽略定义 olcModuleList 和模块路径的添加 )
$ cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
EOF
2.添加模块路径
$ cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module{0},cn=config
changetype: modify
add: olcModulePath
olcModulePath: /usr/lib64/openldap/ #有则忽略
EOF
3.定义主机控制模块
[root@ldap01 ~]# cat << EOF | ldapmodify -c -Y EXTERNAL -Q -H ldapi:///
dn: cn=module{0},cn=config
add: olcModuleLoad
olcModuleLoad: dynlist.la
EOF
modifying entry "cn=module{0},cn=config"
4.定义主机 objectClass 对象
[root@ldap01 ~]# cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: olcOverlay=dynlist,olcDatabase={2}hdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcDynamicList
olcOverlay: dynlist
olcDlAttrSet: inetOrgPerson labeledURI
EOF
5.定义 ldapns 的 schema 规范
[root@ldap01 ~]# cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=ldapns,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: ldapns
olcAttributeTypes: {0}( 1.3.6.1.4.1.5322.17.2.1 NAME 'authorizedService' DESC 'IANA GSS-API authorized service name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
olcAttributeTypes: {1}( 1.3.6.1.4.1.5322.17.2.2 NAME 'loginStatus' DESC 'Currently logged in sessions for a user' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch ORDERING caseIgnoreOrderingMatch SYNTAX OMsDirectoryString )
olcObjectClasses: {0}( 1.3.6.1.4.1.5322.17.1.1 NAME 'authorizedServiceObject' DESC 'Auxiliary object class for adding authorizedService attribute' SUP top AUXILIARY MAY authorizedService )
olcObjectClasses: {1}( 1.3.6.1.4.1.5322.17.1.2 NAME 'hostObject' DESC 'Auxiliary object class for adding host attribute' SUP top AUXILIARY MAY host )
olcObjectClasses: {2}( 1.3.6.1.4.1.5322.17.1.3 NAME 'loginStatusObject' DESC 'Auxiliary object class for login status attribute' SUP top AUXILIARY MAY loginStatus )
EOF
6.定义主机列表组
要定义举止列表组(ou),可以添加 ou 为 servers, 并在 servers 下添加子 ou(apphost 和 dbahost),然后将应用系统列表加入到 apphost 组中,将数据库系统加入到 dbahost 组中,从而以组为目录树单位限制不同用户登录不同系统。例如,应用用户只允许登录应用系统(JBOSS、Tomcat、Nginx、openStack 等)以及监控系统(Cacti、Nagios、Zabbix 等),数据库用户只允许登录数据库系统(Oracle、MySQL、MariaDB 等),这样就对用户登录不同系统进行了限制。
为了限制用户登录的系统,使用组进行的形式进行划分。例如,以项目名称为单位划分组,然后将每个项目的机器加入到每个组中,在添加用户时指定 objectClass 对象为 hostObject,并添加 host 和 labeldURI 数据及值即可。具体命令如下:
[root@ldap01 ~]# cat << EOF | ldapadd -x -D "cn=admin,dc=ldap01,dc=pwb,dc=com" -w 123456 -H ldap://ldap01.pwb.com dn: ou=servers,dc=ldap01,dc=pwb,dc=com objectClass: organizationalUnit ou: servers dn: ou=apphost,ou=servers,dc=ldap01,dc=pwb,dc=com objectClass: organizationalUnit objectClass: hostObject ou: apphost host: client01.pwb.com EOF
在添加 ou 时,添加了 objectClass 作为 hostObject 类型,添加了 host 属性,并将client01.pwb.com主机添加至 apphost 组
7.定义用户组
将用户添加至不同的组中,从而以组为单位限制主机登录。例如用户组:appteam,用户app_user1,具体步骤如下
添加用户组
cat << EOF | ldapadd -x -D "cn=admin,dc=ldap01,dc=pwb,dc=com" -w 123456 -H ldap://ldap01.pwb.com dn: cn=appteam,ou=Group,dc=ldap01,dc=pwb,dc=com objectClass: posixGroup cn: appteam gidNumber: 10010 EOF
添加用户,并添加到apphost组中
[root@ldap01 ~]# cat add_user.ldif dn: uid=app_user1,ou=People,dc=ldap01,dc=pwb,dc=com uid: app_user1 cn: app_user1 sn: app objectClass: person objectClass: posixAccount objectClass: top objectClass: shadowAccount objectClass: inetOrgPerson #labeledURL需要添加inetOrgPerson objectClass userPassword: 123456 shadowLastChange: 19096 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/bash uidNumber: 1010 gidNumber: 10010 #注意此处的GID homeDirectory: /home/app_user1 labeledURI: ldap:///ou=apphost,ou=servers,dc=ldap01,dc=pwb,dc=com?host [root@ldap01 ~]# ldapadd -x -D "cn=admin,dc=ldap01,dc=pwb,dc=com" -w 123456 -H ldap://ldap01.pwb.com -f add_user.ldif
检验
[root@ldap01 ~]# ldapsearch -x -D "cn=admin,dc=ldap01,dc=pwb,dc=com" -w 123456 -H ldap://ldap01.pwb.com -b "uid=app_user1,ou=People,dc=ldap01,dc=pwb,dc=com" # extended LDIF # # LDAPv3 # base <uid=app_user1,ou=People,dc=ldap01,dc=pwb,dc=com> with scope subtree # filter: (objectclass=*) # requesting: ALL # # app_user1, People, ldap01.pwb.com dn: uid=app_user1,ou=People,dc=ldap01,dc=pwb,dc=com uid: app_user1 cn: app_user1 sn: app objectClass: person objectClass: posixAccount objectClass: top objectClass: shadowAccount objectClass: inetOrgPerson userPassword:: e1NTSEF9STZZcjZhV0FOdTh6UkpUNEV5eVB2Y3dGUzNmeCtRMnU= shadowLastChange: 19096 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/bash uidNumber: 1010 gidNumber: 10010 homeDirectory: /home/app_user1 labeledURI: ldap:///ou=apphost,ou=servers,dc=ldap01,dc=pwb,dc=com?host host: client01.pwb.com [root@ldap01 ~]# ldapsearch -x -D "cn=admin,dc=ldap01,dc=pwb,dc=com" -w 123456 -H ldap://ldap01.pwb.com "host=client01.pwb.com" # extended LDIF # # LDAPv3 # base <dc=ldap01,dc=pwb,dc=com> (default) with scope subtree # filter: host=client01.pwb.com # requesting: ALL # # jboss, People, ldap01.pwb.com dn: uid=jboss,ou=People,dc=ldap01,dc=pwb,dc=com objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: jboss uid: jboss uidNumber: 20006 gidNumber: 10005 userPassword:: amJvc3M= homeDirectory: /home/jboss loginShell: /bin/bash host: client01.pwb.com # apphost, servers, ldap01.pwb.com dn: ou=apphost,ou=servers,dc=ldap01,dc=pwb,dc=com objectClass: organizationalUnit objectClass: hostObject ou: apphost host: client01.pwb.com # search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 2
[root@ldap01 ~]# grep olcDbIndex /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif [root@ldap01 ~]# cat << EOF | ldapadd -Y EXTERNAL -H ldapi:/// # Add indexes dn: olcDatabase={2}hdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: host eq EOF
客户端验证:
加载 LDAP 主机控制规则
centos6: $ cat >> /etc/pam_ldap.conf << EOF pam_check_host_attr yes EOF centos7: cat >> /etc/nslcd.conf << EOF pam_authz_search (&(objectClass=posixAccount)(uid=\$username)(|(host=\$hostname)(host=\$fqdn)(host=\\\*))) EOF $ systemctl restart nslcd #重启nslcd服务