Page tree

如需转载请标注内容地址为: https://wiki.shileizcc.com/confluence/pages/viewpage.action?pageId=40566794

Skip to end of metadata
Go to start of metadata

未经允许不得转载

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 。

  • No labels

6 Comments

  1. 你好,我根据以上示例规则配置好 服务端以及客户端之后,并不能实现切换到其他用户。请问作者使用的是那个版本?

    我这里只有当 

    sudoCommand: /usr/bin/su

    sudoRunAsUser: ALL

    时才可以使用 sudo su root / sudo su oracle

    1. 版本忘记了,你可以排查系统日志以及切换用户时请求 LDAP 的日志。

  2. 您好,想请教您一个问题~

    如果通过这样来实现sudo的权限控制,那只要把一个用户赋予了sudo权限,那他在能登陆的所有服务器上是不是都有sudo权限了,请问这个要怎么控制呢?我只想设置他在某台服务器上有这个权限。

    1. sudo 的属性里面有个叫 sudoHost 的这个是定义主机名的,我的文档里面都是 ALL 你可以独立一个组添加哪个主机名(hostname)可以执行添加进去即可。

      1. 好的,谢谢~

        再请教您一个问题,posixAccount类型的user,如果他在不同服务器上的groups不完全相同的话,这种要怎么设置呢?

        我现在的使用情况是:user会指定一个gid,然后其他group通过把user添加到posixgroup的memberUid中来指定。

        然后存在一个情况:例如Bob在服务器A上属于 groupA,  groupB, 在服务器B上只属于groupB;但是为了能在服务器A上指定groupA,B, 用户Bob必须添加到他们的memberUid中,那在服务器B上,Bob也是属于两个组。

        要如何限制在服务器B上bob只属于一个组呢?

        1. 我没这种需求也不清楚,逻辑上也做不到,我不清楚有什么方法让 pam 知道当前的机器上 group 与其他机器有差异区分。