For anyone using LDAP authentication on Linux hosts, controlling who can be SUDO on VMs via LDAP makes it much easier, control becomes centralised and not host to host, imagine doing this with hundreds or thousands of hosts?
In this post I will show how to create the SUDO schema in OpenLDAP and the specific configuration on clients (VMs). For this, the premise is that the VMs are already using LDAP authentication (Explained in another post) and SSSD.
sudo-ldap
First step, install sudo-ldap:
export SUDO_FORCE_REMOVE=yes
apt install -y sudo-ldap
Check if the SUDO schema is already available in the OpenLDAP installation.
$ find /usr/share/doc/ -iname schema.openldap
/usr/share/doc/sudo-ldap/schema.OpenLDAP
Then copy the file to the OpenLDAP schema folder.
cp /usr/share/doc/sudo-ldap/schema.OpenLDAP /etc/ldap/schema/sudo.schema
Now to create the structure of the SUDO LDIF file, we will have to create a structure of temporary folders, files can be deleted, but it will be necessary to generate and change some files.
mkdir -p /work/ldap-sudo/config
cd /work/ldap-sudo
echo "include /etc/ldap/schema/sudo.schema" > ldapsudo.conf
cd /work/ldap-sudo/config
Run slaptest pointing to the file created in the previous step. The file is nothing more than a simple conf that includes the SUDO schema.
slaptest -f ../ldapsudo.conf -F .
You will notice that slaptest will create a folder and file structure, as shown below:
.
├── config
│ ├── cn=config
│ │ ├── cn=schema
│ │ │ └── cn={0}sudo.ldif
│ │ ├── cn=schema.ldif
│ │ ├── olcDatabase={0}config.ldif
│ │ └── olcDatabase={-1}frontend.ldif
│ └── cn=config.ldif
└── ldapsudo.conf
Let’s work with the file created for the sudo schema:
vi cn\=config/cn\=schema/cn\=\{0\}sudo.ldif
Remove the first lines (2), which are commented (not necessary).
Change the lines below:
From:
dn: cn={0}sudo
objectClass: olcSchemaConfig
cn: {0}sudo
To:
dn: cn=sudo,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: sudo
Also remove the last lines, from structuralObjectClass downwards:
structuralObjectClass: olcSchemaConfig
entryUUID: 431580bc-67ab-103e-932b-a1c41a5943c1
creatorsName: cn=config
createTimestamp: 20240224215609Z
entryCSN: 20240224215609.360408Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20240224215609Z
In the end, the file must have +/- this structure.
dn: cn=sudo,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: 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 caseExactIA5SubstringsMa
tch 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 caseExactIA5SubstringsMat
ch 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 'Comma
nd(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1
466.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 'Option
s(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 'Use
r(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 'Gr
oup(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.14
66.115.121.1.26 )
olcAttributeTypes: {7}( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Sta
rt of time interval for which the entry is valid' EQUALITY generalizedTimeMat
ch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
)
olcAttributeTypes: {8}( 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: {9}( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an int
eger to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrd
eringMatch 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 En
tries' SUP top STRUCTURAL MUST cn MAY ( sudoUser $ sudoHost $ sudoCommand $ s
udoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotB
efore $ sudoNotAfter $ description ) )
Then, import the schema:
$ ldapadd -Q -Y EXTERNAL -H ldapi:/// -f 'cn=config/cn=schema/cn={0}sudo.ldif'
adding new entry "cn=sudo,cn=schema,cn=config"
After importing the schema, it is necessary to enable sudoUser and sudoHost.
cat << EOL > /work/ldap-sudo/ldap-sudo.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: sudoUser,sudoHost pres,eq
EOL
ldapadd -Y EXTERNAL -H ldapi:/// -f /work/ldap-sudo/ldap-sudo.ldif
Check if they are all being indexed.
$ slapcat -n 0 | grep olcDbIndex
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcDbIndex: sudoUser,sudoHost pres,eq
Sudoers OU
To control users who may be Sudores, I will just use the previously created group “ou=AdminGroups,dc=ldap,dc=devops-db,dc=info“, in a more complex environment, subgroups should help.
cat << EOL > /work/ldap-sudo/sudoers_defaults.ldif
dn: cn=defaults,ou=AdminGroups,dc=ldap,dc=devops-db,dc=info
objectClass: top
objectClass: sudoRole
cn: defaults
sudoOption: !visiblepw
sudoOption: !authenticate
sudoOption: always_set_home
sudoOption: match_group_by_gid
sudoOption: always_query_group_plugin
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: env_keep+=SSH_AUTH_SOCK
sudoOption: secure_path = /sbin:/bin:/usr/sbin:/usr/bin
dn: cn=sudo,ou=AdminGroups,dc=ldap,dc=devops-db,dc=info
objectClass: top
objectClass: sudoRole
cn: sudo
sudoUser: fbranco
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
EOL
The options above are automatically applied to the Host for the authenticated user, there is a simple table with the options for this sudoOption.
/etc/sudoers | LDAP Sudoers |
---|---|
NOPASSWD | !authenticate |
PASSWD | authenticate |
NOEXEC | noexec |
EXEC | !noexec |
SETENV | setenv |
NOSETENV | !setenv |
LOG_INPUT | log_input |
NOLOG_INPUT | !log_input |
LOG_OUTPUT | log_output |
NOLOG_OUTPUT | !log_output |
Import the defaults:
$ ldapadd -v -x -H ldaps://ldap.devops-db.info:636 -f /work/ldap-sudo/sudoers_defaults.ldif -D "cn=admin,dc=ldap,dc=devops-db,dc=info" -w "JbBmKx#lK@ZX4*amqd5l"
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=defaults,ou=AdminGroups,dc=ldap,dc=devops-db,dc=info"
adding new entry "cn=sudo,ou=AdminGroups,dc=ldap,dc=devops-db,dc=info"
To add other users in SUDO, use the example below.
cat > add-otheruser.ldif << 'EOL'
dn: cn=sudo,ou=AdminGroups,dc=ldap,dc=devops-db,dc=info
changetype: modify
add: sudoUser
sudoUser: otheruser
EOL
ldapmodify -Y EXTERNAL -H ldapi:/// -f add-otheruser.ldif
At this point, the Schema has been created, enabled and the permissions to the group have been made.
Configuration on the Client
As mentioned above, this part of the configuration on clients/VMs/Hosts is only to be validated and applied to Sudos according to LDAP, all LDAP configuration on VMs must already be ready and functional with SSSD.
Install the SSD lib to handle the Sudo:
apt-get install -y libsss-sudo
Add the following line to the SSSD configuration file, it is the sarch base for the sudoers group we created above.
vi /etc/sssd/sssd.conf
ldap_sudo_search_base = ou=AdminGroups,dc=ldap,dc=devops-db,dc=info
In the same sense, add the search base in the ldap configuration file.
vi /etc/ldap/ldap.conf
sudoers_base ou=AdminGroups,dc=ldap,dc=devops-db,dc=info
Reconfigure and restart SSSD.
chmod 600 -R /etc/sssd
systemctl restart sssd
systemctl status sssd
Test access and permissions.
vagrant@srv-hostldap-01:~$ su fbranco
Password:
fbranco@srv-hostldap-01:/home/vagrant$ sudo -s
root@srv-hostldap-01:/home/vagrant#
Leave a Reply