未经允许不得转载
OpenLDAP Sudo 权限讲解
Sudo 常见的属性介绍
Sudo 常见的属性有以下几个
sudoCommand:可执行的二进制命令,如 useradd、userdel、mount、umount 等。
sudoHost:可在哪些机器上执行 sudoCommand 定义的 BASH 命令。
sudoNotAfter:起始时间 sudo 规则匹配。
sudoNotBefore:结束时间 sudo 规则匹配。
sudoOption:定义超过自身权限及切换至其他用户时,是否需要输入当前用户密码。
sudoOrder:sudo 规则执行顺序,其属性是一个整数。
sudoRole:定义的规则。
sudoRunAs:可切换到定义的用户身份下执行 BASH 命令。
sudoRunAsGroup:可切换到定义所属组并具有该组的权限。
sudoRunAsUser:定义可切换至哪些用户下执行命令。
sudoUser:限制哪些用户或哪些组内的成员具有 sudo 相关规则。
通过本地 Sudo 规则实现 OpenLDAP 用户提权匹配
要通过本地 Sudo 实现 OpenLDAP 用户提权,可按以下步骤操作。
1)通过以下代码,配置客户端加入 OpenLDAP 服务端实现用户验证。
$ authconfig --enableldap --enableldapauth --enablemkhomedir --enableforcelegacy --disablesssd --disablesssdauth --disableldaptls --enablelocauthorize --ldapserver=47.94.86.245 --ldapbasedn="dc=shileizcc,dc=com" --enableshadow --update
2)通过以下代码,验证 shilei 用户是否具有添加用户权限。
$ sudo /usr/sbin/useradd test We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. [sudo] password for shilei: shilei 不在 sudoers 文件中。此事将被报告。
默认 sudo 提权使用本地 sudoers 文件进行查找匹配,如果指定其他获取方式,则需要添加 sudoers 属性并指定验证类型。从以上结果不难发现,当 OpenLDAP shilei 用户没有权限创建用户及切换到 appman 权限,因为普通用户不具备套在管理员指令的权限。
3)自定义 sudo 规则。
- 通过用户级别实现 sudo 提权,关于用户级别和组级别定义。
- 通过本地 sudoers 文件实现用户提权,命令如下。建议使用 visudo 指令修改,原因是 visudo 本身有自我语法检测功能。当存在错误语法时,visudo 提示并建议修改匹配。
$ cat >> /etc/sudoers << EOF shilei ALL=NOPASSWD:/bin/su *appman*,/usr/sbin/useradd,/usr/sbin/userdel chengcheng ALL=NOPASSWD:/bin/su *oracle*,/bin/su *grid* EOF
- 通过组级别实现 sudo 提权。
- 在生产环境中配置 sudo 实现用户提权,命令如下。无论使用本地 sudoers 文件还是基于 OpenLDAP 服务端提升用户权限,都建议使用组的方式进行定义,以方便管理。
$ cat >> /etc/sudoers << EOF User_Alias APPTEAM = shilei APPTEAM ALL=NOPASSWD:/bin/su *appman*,/usr/sbin/useradd,/usr/sbin/userdel User_Alias DBTEAM=shilei DBTEAM ALL=NOPASSWD:/bin/su *oracle*,/bin/su *grid* EOF
以上 sudo 配置中,shilei 用户具有切换到 appman 用户且具有维护本地系统用户的管理权限,如添加、删除本地系统用户。chengcheng 用户具有切换到 oracle 和 grid 用户的权限,但不能执行超出本身命令范围以外的指令。
4)客户端再次验证 sudo 权限,命令如下:
$ sudo /usr/sbin/useradd sudouser $ sudouser uid=1010(sudouser) gid=1010(sudouser) 组=1010(sudouser) $ sudo su - appman
从上述得知,当前 shilei 用户具有添加和删除用户的权限,以及切换到 appman 用户并以 appman 身份执行操作的权限。以上管理 sudo 的配置,往往也在系统中限制用户的权限。
在 OpenLDAP 服务端实现用户权限控制
要在 OpenLDAP 服务端实现用户权限控制,实施步骤如下。
- 导入 sudo schema
- 定义 sudo 规则条目及 sudo 组
- 用户加入 sudo 组,集成 sudo 权限
- 命令添加及修改
- 图形化管理界面配置
- 客户端配置加入 OpenLDAP 服务端
- 客户端识别 sudo 策略及验证用户权限
1)在 OpenLDAP 服务端中引入 sudo schema 规则。
在 OpenLDAP 服务端中,schema 是 LDAP 中一个重要组成部分,它类似于数据库的模式定义,LDAP 的 schema 定义了 LDAP 目录树所应遵循的结构和规则。比如,一个 objectClass 具有哪些属性,这些属性又具有什么结构特点等相关定义,哪些属性是必须的,哪些属性是非必需的。所以 schema 给 LDAP 提供了规范,属性等信息的识别方式,哪些对象可以被 LDAP 服务识别都是由 schema 来定义的。
OpenLDAP 的默认 schema 中不包含 sudo 所需要的数据结构,这是需要自行导入 sudo schema 文件。通过 rpm -ql sudo 来获取 sudo 管理 schema 的存放路径,将 schema 文件复制到 /etc/openldap/schema 目录下并通过 include 在 slapd.conf 中引用此 schema 文件,然后转换为 ldif 格式,通过 OpenLDAP 相关指令进行转换并导入后方可使用。具体命令如下所示。
$ rpm -ql sudo | grep OpenLDAP /usr/share/doc/sudo-1.8.19p2/schema.OpenLDAP $ cp /usr/share/doc/sudo-1.8.19p2/schema.OpenLDAP /etc/openldap/schema/sudo.schema $ restorecon /etc/openldap/schema/sudo.schema $ mkdir ~/sudo $ echo "include /etc/openldap/schema/sudo.schema" > ~/sudo/sudoSchema.conf $ slapcat -f ~/sudo/sudoSchema.conf -F /tmp/ -n0 -s "cn={0}sudo,cn=schema,cn=config" > ~/sudo/sudo.ldif $ sed -i "s/{0}sudo/{13}sudo/" ~/sudo/sudo.ldif $ head -n-8 ~/sudo/sudo.ldif > ~/sudo/sudo-config.ldif $ cat ~/sudo/sudo-config.ldif dn: cn={13}sudo,cn=schema,cn=config objectClass: olcSchemaConfig cn: {13}sudo olcAttributeTypes: {0}( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s ) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5Substrin gsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {1}( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s ) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5Substring sMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {2}( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Com mand(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4 .1.1466.115.121.1.26 ) olcAttributeTypes: {3}( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User( s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3 .6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {4}( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Opti ons(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466 .115.121.1.26 ) olcAttributeTypes: {5}( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'U ser(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1. 1466.115.121.1.26 ) olcAttributeTypes: {6}( 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: {7}( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'S tart of time interval for which the entry is valid' EQUALITY generalizedTim eMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.12 1.1.24 ) olcAttributeTypes: {8}( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'En d of time interval for which the entry is valid' EQUALITY generalizedTimeMa tch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1 .24 ) olcAttributeTypes: {9}( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an i nteger to order the sudoRole entries' EQUALITY integerMatch ORDERING intege rOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) olcObjectClasses: {0}( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' DESC 'Sudoer Entries' SUP top STRUCTURAL MUST cn MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ su doNotBefore $ sudoNotAfter $ description ) )
2)通过 ldapadd 添加,sudu 所产生的 ldif 文件导入数据库,命令如下:
$ cat ~/sudo/sudo-config.ldif | ldapadd -Y EXTERNAL -H ldapi:/// SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn={13}sudo,cn=schema,cn=config"
不难发现此指令成功添加了一个新条目 cn={13}sudo,cn=schema,cn=config。
注:如果出现如下提示:
$ cat ~/sudo/sudo-config.ldif | ldapadd -Y EXTERNAL -H ldapi:/// SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 adding new entry "cn={12}sudo,cn=schema,cn=config" ldap_add: Server is unwilling to perform (53) additional info: operation requires sibling renumbering
请修改 13 编号为其他数值,如果无法确定请查看目录下是否有重复的:
$ ls /etc/openldap/slapd.d/cn\=config/cn\=schema cn={0}core.ldif cn={11}pmi.ldif cn={1}cosine.ldif cn={3}collective.ldif cn={5}duaconf.ldif cn={7}inetorgperson.ldif cn={9}misc.ldif cn={10}openldap.ldif cn={12}ppolicy.ldif cn={2}nis.ldif cn={4}corba.ldif cn={6}dyngroup.ldif cn={8}java.ldif
3)再次检查 OpenLDAP 数据库目录中 schema 产生的文件,命令如下:
$ ls /etc/openldap/slapd.d/cn\=config/cn\=schema cn={0}core.ldif cn={11}pmi.ldif cn={13}sudo.ldif cn={2}nis.ldif cn={4}corba.ldif cn={6}dyngroup.ldif cn={8}java.ldif cn={10}openldap.ldif cn={12}ppolicy.ldif cn={1}cosine.ldif cn={3}collective.ldif cn={5}duaconf.ldif cn={7}inetorgperson.ldif cn={9}misc.ldif
不难发现,当前目录多了一个关于 sudo 的配置文件 cn={13}sudo.ldif 文件,并且在 schema 目录下会存在 sudo.schema 文件。
4)查看 sudo schema 所支持的对象类型,命令如下:
$ ldapsearch -LLLY EXTERNAL -H ldapi:/// -b cn={13}sudo,cn=schema,cn=config | grep NAME | awk '{print $4,$5}' | sort SASL/EXTERNAL authentication started SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth SASL SSF: 0 NAME 'sudoCommand' NAME 'sudoHost' NAME 'sudoNotAfter' NAME 'sudoNotBefore' NAME 'sudoOption' NAME 'sudoOrder' NAME 'sudoRole' NAME 'sudoRunAs' NAME 'sudoRunAsGroup' NAME 'sudoRunAsUser' NAME 'sudoUser'
5)在 OpenLDAP 目录树中创建 suers 条目。
sudoers 的配置信息存放在 ou=suders 的子树中,默认 OpenLDAP 用户没有指定 sudo 规则,OpenLDAP 首先在目录树中寻找条目 cn=default,如果找到,那么所有 sudoOption 属性都会被解析为全局默认值,这类似于服务端中查询一个 sudo 用户权限时一般有两到三次查询。第一次查询解析全局配置,第二次查询匹配用户名或者用户所在的组(特殊标签 ALL 也在此次查询中匹配),如果没有找到相关匹配项,则发出第三次查询,此次查询返回所有包含用户组的条目并检查该用户是否存在于这些组中。接下来创建 OpenLDAP 的 suders 子树。具体命令如下:
$ cat << EOF | ldapadd -D "cn=admin,dc=shileizcc,dc=com" -w 123456 -H ldap://shileizcc.com dn: ou=sudoers,dc=shileizcc,dc=com objectCLass: top objectClass: organizationalUnit ou: sudoers dn: cn=defaults,ou=sudoers,dc=shileizcc,dc=com objectClass: sudoRole objectCLass: top cn: defaults description: Default sudoOption's go here sudoOption: requiretty sudoOption: !visiblepw sudoOption: always_set_home sudoOption: env_reset sudoOption: env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" sudoOption: env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" sudoOption: env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES" sudoOption: env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" sudoOption: env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" sudoOption: secure_path=/sbin:/bin:/usr/sbin:/usr/bin dn: cn=%dba,ou=sudoers,dc=shileizcc,dc=com objectClass: sudoRole objectCLass: top cn: %dba sudoUser: %dba sudoHost: ALL sudoRunAsUser: oracle sudoRunAsUser: grid sudoOption: !authenticate sudoCommand: /bin/bash dn: cn=%app,ou=sudoers,dc=shileizcc,dc=com objectClass: sudoRole objectCLass: top cn: %app sudoUser: %app sudoHost: ALL sudoRunAsUser: appman sudoOption: !authenticate sudoCommand: /bin/bash dn: cn=%admin,ou=sudoers,dc=shileizcc,dc=com objectClass: sudoRole objectCLass: top cn: %admin sudoUser: %admin sudoHost: ALL sudoRunAsUser: oracle sudoRunAsUser: grid sudoOption: authenticate sudoCommand: /bin/rm sudoCommand: /bin/rmdir sudoCommand: /bin/chmod sudoCommand: /bin/chown sudoCommand: /bin/dd sudoCommand: /bin/mv sudoCommand: /bin/cp sudoCommand: /sbin/fsck* sudoCommand: /sbin/*remove sudoCommand: /usr/bin/chattr sudoCommand: /sbin/mkfs* sudoCommand: !/usr/bin/passwd sudoOrder: 0 dn: cn=%limit,ou=sudoers,dc=shileizcc,dc=com objectClass: sudoRole objectClass: top cn: %limit sudoUser: %limit sudoHost: limit.shileizcc.com sudoCommand: /usr/bin/chattr sudoRunAsUser: ALL sudoOption: !authenticate dn: cn=%manager,ou=sudoers,dc=shileizcc,dc=com objectClass: sudoRole objectClass: top cn: %manager sudoUser: ALL sudoHost: ALL sudoCommand: /bin/bash sudoRunAsUser: ALL sudoOption: !authenticate EOF adding new entry "ou=sudoers,dc=shileizcc,dc=com" adding new entry "cn=defaults,ou=sudoers,dc=shileizcc,dc=com" adding new entry "cn=%dba,ou=sudoers,dc=shileizcc,dc=com" adding new entry "cn=%app,ou=sudoers,dc=shileizcc,dc=com" adding new entry "cn=%admin,ou=sudoers,dc=shileizcc,dc=com" adding new entry "cn=%limit,ou=sudoers,dc=shileizcc,dc=com" adding new entry "cn=%manager,ou=sudoers,dc=shileizcc,dc=com"
从以上操作,不难发现 app 组可以 sudo 切换到系统 appman 用户下,而且也不需要输入验证密码,同理 admin 组里面的用户只能通过 sudo 执行允许的命令,其他越权命令不允许执行。dba 组里面的用户可以通过 sudo 命令切换到系统 oracle 和 grid 用户下,且不需要输入验证密码。limit 组里面的用户只允许在 limit.shileizcc.com 机器上通过 sudo 执行一条命令,且不需要输入杨峥密码,其他任何机器都不能使用 sudo 命令执行命令。manager 组里面的用户可以在任何主机上执行 sudo 命令,没有任何显示,如果要求 OpenLDAP 用户提示密码,值需要将 “!authenticate” 中的感叹号去掉即可。
注意:manager 组会导致所有的用户都具有免密码可用 sudo 的所有权限,所以仅供测试使用。
manager 的 sudoUser 会造成所有 User 都有 Sudo 免密权限。
6)添加 OpenLDAP 用户到 app 和 manager 组中。
此 app 和 manager 组类似于 /etc/sudoers 文件中的 User_Alias app|manager 字段,但在 sudoers 配置是组必须大写,否则会提示 visudo >> /etc/sudoers:syntax error near line xx 错误,且需要编辑和修改:
$ cat << EOF | ldapadd -D "cn=admin,dc=shileizcc,dc=com" -H ldap://shileizcc.com -w 123456 dn: ou=groups,dc=shileizcc,dc=com ou: groups objectClass: top objectClass: organizationalUnit dn: ou=people,dc=shileizcc,dc=com ou: people objectClass: top objectClass: organizationalUnit dn: cn=app,ou=groups,dc=shileizcc,dc=com objectClass: posixGroup cn: app gidNumber: 10005 dn: cn=manager,ou=groups,dc=shileizcc,dc=com objectClass: posixGroup cn: manager gidNumber: 10006 dn: uid=jboss,ou=people,dc=shileizcc,dc=com objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: jboss uid: jboss uidNumber: 20006 gidNumber: 10005 userPassword: jboss homeDirectory: /home/jboss loginShell: /bin/bash dn: uid=manager01,ou=people,dc=shileizcc,dc=com objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: manager01 uid: manager01 uidNumber: 20007 gidNumber: 10006 userPassword: manager01 homeDirectory: /home/manager01 loginShell: /bin/bash EOF adding new entry "ou=groups,dc=shileizcc,dc=com" adding new entry "cn=app,ou=groups,dc=shileizcc,dc=com" adding new entry "cn=manager,ou=groups,dc=shileizcc,dc=com" adding new entry "uid=jboss,ou=people,dc=shileizcc,dc=com" adding new entry "uid=manager01,ou=people,dc=shileizcc,dc=com"
7)通过 ldapsearch 查看 jboss 用户及 app 组相关信息,命令如下:
$ ldapsearch -x -LLL uid=jboss dn: uid=jboss,ou=people,dc=shileizcc,dc=com objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: jboss uid: jboss uidNumber: 20006 gidNumber: 10005 userPassword:: amJvc3M= homeDirectory: /home/jboss loginShell: /bin/bash $ ldapsearch -x -LLL cn=app dn: cn=app,ou=groups,dc=shileizcc,dc=com objectClass: posixGroup cn: app gidNumber: 10005
8)通过 Web UI 管理界面查看 OpenLDAP 用户目录树 sudo 规则:
9)添加索引:
$ cat << EOF | ldapadd -Y EXTERNAL -H ldapi:/// # Add indexes dn: olcDatabase={2}hdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: sudoUser eq EOF
The current time to create this page is and the end time is ,Document status is STABLE ,Write a version of the interface V1.1.0 。
6 Comments
Joker
你好,我根据以上示例规则配置好 服务端以及客户端之后,并不能实现切换到其他用户。请问作者使用的是那个版本?
我这里只有当
sudoCommand: /usr/bin/su
sudoRunAsUser: ALL
时才可以使用 sudo su root / sudo su oracle
Jones Shi
版本忘记了,你可以排查系统日志以及切换用户时请求 LDAP 的日志。
megan
您好,想请教您一个问题~
如果通过这样来实现sudo的权限控制,那只要把一个用户赋予了sudo权限,那他在能登陆的所有服务器上是不是都有sudo权限了,请问这个要怎么控制呢?我只想设置他在某台服务器上有这个权限。
Jones Shi
sudo 的属性里面有个叫 sudoHost 的这个是定义主机名的,我的文档里面都是 ALL 你可以独立一个组添加哪个主机名(hostname)可以执行添加进去即可。
megan
好的,谢谢~
再请教您一个问题,posixAccount类型的user,如果他在不同服务器上的groups不完全相同的话,这种要怎么设置呢?
我现在的使用情况是:user会指定一个gid,然后其他group通过把user添加到posixgroup的memberUid中来指定。
然后存在一个情况:例如Bob在服务器A上属于 groupA, groupB, 在服务器B上只属于groupB;但是为了能在服务器A上指定groupA,B, 用户Bob必须添加到他们的memberUid中,那在服务器B上,Bob也是属于两个组。
要如何限制在服务器B上bob只属于一个组呢?
Jones Shi
我没这种需求也不清楚,逻辑上也做不到,我不清楚有什么方法让 pam 知道当前的机器上 group 与其他机器有差异区分。