+86 135 410 16684Mon. - Fri. 10:00-22:00

OpenLDAP构建统一认证之项目实战

OpenLDAP构建统一认证之项目实战

OpenLDAP构建统一认证之项目实战

OpenLDAP构建统一认证之项目实战

背景

问题

登录服务器的账号分散在所有的机器上,这样就带来两个问题:

  1. 维护成本高,需要专门在playbook里定义用户权限
  2. 没有明确的权限划分
  3. 不便于和其他系统(如Google Apps)对接

需求

  1. 数据集中管理
  2. 根据用户组控制用户的登陆权限
  3. 控制用户的sudo权限,只有operation有sudo的权限
  4. 自动创建家目录
  5. Web管理界面

原则

  • 尽可能少的涉及组件,减少维护成本
  • 尽可能的不入侵系统配置,便于恢复

配置

服务端

OpenLDAP安装配置

 

LAM安装配置

 

管理账号

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=com

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=admin,dc=example,dc=com

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}1Ahx2TU+7DrRzk6eJMNIk2pPaxKsS+Om # generated by ldappasswd

使配置生效

ldapmodify -Y EXTERNAL -H ldapi:/// -f example.ldif

ssh公钥

为了配合客户端支持ssh的公钥登陆,我们需要为LDAP Server添加openssh-lpk的schema,由于最新的OpenLDAP都是olc模式来管理服务器配置,所以所有的schema需要通过 LDIF的通用格式导入,这里我找到了一个能和sssd以及LAM配合的schema:

dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
    DESC 'MANDATORY: OpenSSH Public key'
    EQUALITY octetStringMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
    DESC 'MANDATORY: OpenSSH LPK objectclass'
    MAY ( sshPublicKey $ uid )
    )

然后导入该schema

ldapadd -Y EXTERNAL -H ldapi:/// -f openssh-lpk.ldif

然后给LAM添加上ssh key的模块即可用来管理public key

sudo权限

和ssh公钥一样,sudo权限也需要添加相应的schema,如下的LDIF是我根据官方的schema转换而来的。

dn: cn=sudoRole,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: sudoRole
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1
   NAME 'sudoUser'
   DESC 'User(s) who may  run sudo'
   EQUALITY caseExactIA5Match
   SUBSTR caseExactIA5SubstringsMatch
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2
   NAME 'sudoHost'
   DESC 'Host(s) who may run sudo'
   EQUALITY caseExactIA5Match
   SUBSTR caseExactIA5SubstringsMatch
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3
   NAME 'sudoCommand'
   DESC 'Command(s) to be executed by sudo'
   EQUALITY caseExactIA5Match
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4
   NAME 'sudoRunAs'
   DESC 'User(s) impersonated by sudo'
   EQUALITY caseExactIA5Match
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5
   NAME 'sudoOption'
   DESC 'Options(s) followed by sudo'
   EQUALITY caseExactIA5Match
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6
   NAME 'sudoRunAsUser'
   DESC 'User(s) impersonated by sudo'
   EQUALITY caseExactIA5Match
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7
   NAME 'sudoRunAsGroup'
   DESC 'Group(s) impersonated by sudo'
   EQUALITY caseExactIA5Match
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.8
   NAME 'sudoNotBefore'
   DESC 'Start of time interval for which the entry is valid'
   EQUALITY generalizedTimeMatch
   ORDERING generalizedTimeOrderingMatch
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.9
   NAME 'sudoNotAfter'
   DESC 'End of time interval for which the entry is valid'
   EQUALITY generalizedTimeMatch
   ORDERING generalizedTimeOrderingMatch
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.10
    NAME 'sudoOrder'
    DESC 'an integer to order the sudoRole entries'
    EQUALITY integerMatch
    ORDERING integerOrderingMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
   DESC 'Sudoer Entries'
   MUST ( cn )
   MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $ sudoOrder $ description ))

然后导入该schema:

ldapadd -Y EXTERNAL -H ldapi:/// -f sudoers.ldif

由于LAM的sudo管理模块是收费的,所以只能自己手动添加sudo策略,示例LDIF文件如下:

dn: ou=sudoers,dc=example,dc=com
objectClass: top
objectclass: organizationalUnit
ou: sudoers

dn: cn=operation,ou=sudoers,dc=example,dc=com
objectClass: top
objectClass: sudoRole
cn: operation
sudoUser: %operation
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
sudoOption: !authenticate

导入该配置:

ldapadd -D 'cn=admin,dc=example,dc=com' -W -H ldapi:/// -f sudo.ldif

ACL配置

该配置主要是允许用户修改自己的密码

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: to attr=userPassword by self =xw by anonymous auth by * none

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: to * by * read

导入该配置:

ldapmodify -Y EXTERNAL -H ldapi:/// -f acl.ldif

客户端(手动)

NSS交由sssd管理

编辑/etc/nsswitch.conf

passwd:         compat sss
group:          compat sss
shadow:         compat sss

hosts:          files dns
networks:       files

protocols:      db files
services:       db files

ethers:         db files
rpc:            db files

netgroup:       nis sss
sudoers:        files sss
automount:  files sss

配置PAM

配置PAM主要为了解决两个问题,一个是用户认证走SSSD,另一个是自动创建用户家目录。

CentOS系统编辑/etc/pam.d/system-auth

auth        sufficient    pam_sss.so use_first_pass
account     [default=bad success=ok user_unknown=ignore] pam_sss.so
password    sufficient    pam_sss.so use_authtok
session     optional      pam_sss.so

然后执行如下命令开启自动创建家目录

authconfig --enablemkhomedir --update

注意 此配置需要关闭SELinux

Ubuntu系统无需配置,sssd已经帮我们做了。除了为了能自动创建家目录,需添加如下行到/etc/pam.d/common-session即可

session required        pam_mkhomedir.so umask=0022 skel=/etc/skel

配置SSSD

编辑/etc/sssd/sssd.conf

[sssd]
config_file_version = 2
services = nss, pam, ssh, sudo
domains = example
debug_level = 3

[nss]
filter_users = root,ldap,named,avahi,haldaemon,dbus,radiusd,news,nscd

[domain/example]
debug_level = 9
ldap_id_use_start_tls = True
ldap_tls_reqcert = never
cache_credentials = True
ldap_schema = rfc2307
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
ldap_uri = ldaps://dir.example.com
ldap_search_base = dc=example,dc=com
ldap_user_ssh_public_key = sshPublicKey
sudo_provider = ldap
ldap_sudo_search_base = ou=sudoers,dc=example,dc=com
access_provider = simple
simple_allow_groups = operation,login

配置SSHD

编辑/etc/ssh/sshd_config

AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys

客户端(Ansible)

具体请参考我的这个Ansible Role

参考链接

  • http://www.zytrax.com/books/ldap/ch6/slapd-config.html
  • https://wiki.gentoo.org/wiki/Centralized_authentication_using_OpenLDAP
  • http://www.openldap.org/doc/admin24/
  • http://web.mit.edu/kerberos/krb5-latest/doc/admin/index.html
  • http://serverfault.com/questions/653792/ssh-key-authentication-using-ldap
  • http://vaab.blog.kal.fr/2010/03/06/how-to-add-a-schema-in-openldap-24/
  • http://www.ossramblings.com/using-ldap-to-store-ssh-public-keys-with-sssd
  • https://lists.fedorahosted.org/pipermail/sssd-users/2013-March/000456.html
  • http://linux.die.net/man/5/sudoers.ldap
  • https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Identity_Management_Guide/users.html#homedir-pammod
  • http://support.hp.com/us-en/document/c03737146
  • http://thornelabs.net/2013/01/28/linux-restrict-server-login-via-ldap-groups.html